Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci-2.6.23
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci-2.6.23
Commits
783b581f
Commit
783b581f
authored
Oct 03, 2005
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ARM: OMAP: Add MMC support for 24xx
Add MMC support for 24xx
parent
f311c822
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
108 additions
and
28 deletions
+108
-28
drivers/mmc/omap.c
drivers/mmc/omap.c
+108
-28
No files found.
drivers/mmc/omap.c
View file @
783b581f
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
*
*
* Copyright (C) 2004 Nokia Corporation
* Copyright (C) 2004 Nokia Corporation
* Written by Tuukka Tikkanen and Juha Yrjl <juha.yrjola@nokia.com>
* Written by Tuukka Tikkanen and Juha Yrjl <juha.yrjola@nokia.com>
*
Pin multiplexing and Innovator support
by Tony Lindgren <tony@atomide.com>
*
Misc hacks here and there
by Tony Lindgren <tony@atomide.com>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* it under the terms of the GNU General Public License version 2 as
...
@@ -42,6 +42,7 @@
...
@@ -42,6 +42,7 @@
#include <asm/arch/mux.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
#include <asm/arch/fpga.h>
#include <asm/arch/tps65010.h>
#include <asm/arch/tps65010.h>
#include <asm/arch/menelaus.h>
#include <asm/hardware/clock.h>
#include <asm/hardware/clock.h>
...
@@ -71,10 +72,12 @@ struct mmc_omap_host {
...
@@ -71,10 +72,12 @@ struct mmc_omap_host {
struct
mmc_host
*
mmc
;
struct
mmc_host
*
mmc
;
struct
device
*
dev
;
struct
device
*
dev
;
unsigned
char
id
;
/* 16xx chips have 2 MMC blocks */
unsigned
char
id
;
/* 16xx chips have 2 MMC blocks */
struct
clk
*
clk
;
struct
clk
*
iclk
;
struct
clk
*
fclk
;
void
__iomem
*
base
;
void
__iomem
*
base
;
int
irq
;
int
irq
;
unsigned
char
bus_mode
;
unsigned
char
bus_mode
;
unsigned
char
hw_bus_mode
;
unsigned
int
sg_len
;
unsigned
int
sg_len
;
int
sg_idx
;
int
sg_idx
;
...
@@ -168,6 +171,19 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
...
@@ -168,6 +171,19 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
resptype
=
0
;
resptype
=
0
;
cmdtype
=
0
;
cmdtype
=
0
;
/*
* On 24xx we may have external MMC transceiver on Menelaus.
* In that case we need to manually toggle between open-drain
* and push-pull states.
*/
if
(
omap_has_menelaus
()
&&
(
host
->
bus_mode
!=
host
->
hw_bus_mode
))
{
if
(
host
->
bus_mode
==
MMC_BUSMODE_OPENDRAIN
)
menelaus_mmc_opendrain
(
1
);
else
menelaus_mmc_opendrain
(
0
);
host
->
hw_bus_mode
=
host
->
bus_mode
;
}
/* Protocol layer does not provide response type,
/* Protocol layer does not provide response type,
* but our hardware needs to know exact type, not just size!
* but our hardware needs to know exact type, not just size!
*/
*/
...
@@ -223,7 +239,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
...
@@ -223,7 +239,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
if
(
host
->
data
&&
!
(
host
->
data
->
flags
&
MMC_DATA_WRITE
))
if
(
host
->
data
&&
!
(
host
->
data
->
flags
&
MMC_DATA_WRITE
))
cmdreg
|=
1
<<
15
;
cmdreg
|=
1
<<
15
;
clk_use
(
host
->
clk
);
clk_use
(
host
->
f
clk
);
OMAP_MMC_WRITE
(
host
->
base
,
CTO
,
200
);
OMAP_MMC_WRITE
(
host
->
base
,
CTO
,
200
);
OMAP_MMC_WRITE
(
host
->
base
,
ARGL
,
cmd
->
arg
&
0xffff
);
OMAP_MMC_WRITE
(
host
->
base
,
ARGL
,
cmd
->
arg
&
0xffff
);
...
@@ -257,7 +273,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
...
@@ -257,7 +273,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
}
}
host
->
data
=
NULL
;
host
->
data
=
NULL
;
host
->
sg_len
=
0
;
host
->
sg_len
=
0
;
clk_unuse
(
host
->
clk
);
clk_unuse
(
host
->
f
clk
);
/* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing
/* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing
* dozens of requests until the card finishes writing data.
* dozens of requests until the card finishes writing data.
...
@@ -361,7 +377,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
...
@@ -361,7 +377,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
if
(
host
->
data
==
NULL
||
cmd
->
error
!=
MMC_ERR_NONE
)
{
if
(
host
->
data
==
NULL
||
cmd
->
error
!=
MMC_ERR_NONE
)
{
DBG
(
"MMC%d: End request, err %x
\n
"
,
host
->
id
,
cmd
->
error
);
DBG
(
"MMC%d: End request, err %x
\n
"
,
host
->
id
,
cmd
->
error
);
host
->
mrq
=
NULL
;
host
->
mrq
=
NULL
;
clk_unuse
(
host
->
clk
);
clk_unuse
(
host
->
f
clk
);
mmc_request_done
(
host
->
mmc
,
cmd
->
mrq
);
mmc_request_done
(
host
->
mmc
,
cmd
->
mrq
);
}
}
}
}
...
@@ -597,6 +613,26 @@ static void mmc_omap_switch_timer(unsigned long arg)
...
@@ -597,6 +613,26 @@ static void mmc_omap_switch_timer(unsigned long arg)
schedule_work
(
&
host
->
switch_work
);
schedule_work
(
&
host
->
switch_work
);
}
}
/* FIXME: Handle card insertion and removal properly. Maybe use a mask
* for MMC state? */
static
void
mmc_omap_switch_callback
(
unsigned
long
data
,
u8
mmc_mask
)
{
struct
mmc_omap_host
*
host
=
(
struct
mmc_omap_host
*
)
data
;
if
(
machine_is_omap_h4
())
{
if
(
mmc_mask
&
0x1
)
printk
(
"XXX card in slot 1
\n
"
);
if
(
mmc_mask
&
0x2
)
printk
(
"XXX card in slot 2
\n
"
);
}
else
{
/* Assume card detect connected to cover switch */
if
(
mmc_mask
&
0x2
)
printk
(
"XXX cover open
\n
"
);
else
printk
(
"XXX cover closed
\n
"
);
}
}
static
void
mmc_omap_switch_handler
(
void
*
data
)
static
void
mmc_omap_switch_handler
(
void
*
data
)
{
{
struct
mmc_omap_host
*
host
=
(
struct
mmc_omap_host
*
)
data
;
struct
mmc_omap_host
*
host
=
(
struct
mmc_omap_host
*
)
data
;
...
@@ -1001,7 +1037,10 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
...
@@ -1001,7 +1037,10 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
else
if
(
machine_is_omap_h3
())
else
if
(
machine_is_omap_h3
())
/* GPIO 4 of TPS65010 sends SD_EN signal */
/* GPIO 4 of TPS65010 sends SD_EN signal */
tps65010_set_gpio_out_value
(
GPIO4
,
HIGH
);
tps65010_set_gpio_out_value
(
GPIO4
,
HIGH
);
else
else
if
(
cpu_is_omap24xx
())
{
u16
reg
=
OMAP_MMC_READ
(
host
->
base
,
CON
);
OMAP_MMC_WRITE
(
host
->
base
,
CON
,
reg
|
(
1
<<
11
));
}
else
if
(
host
->
power_pin
>=
0
)
if
(
host
->
power_pin
>=
0
)
omap_set_gpio_dataout
(
host
->
power_pin
,
1
);
omap_set_gpio_dataout
(
host
->
power_pin
,
1
);
}
else
{
}
else
{
...
@@ -1011,7 +1050,10 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
...
@@ -1011,7 +1050,10 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
tps65010_set_gpio_out_value
(
GPIO3
,
LOW
);
tps65010_set_gpio_out_value
(
GPIO3
,
LOW
);
else
if
(
machine_is_omap_h3
())
else
if
(
machine_is_omap_h3
())
tps65010_set_gpio_out_value
(
GPIO4
,
LOW
);
tps65010_set_gpio_out_value
(
GPIO4
,
LOW
);
else
else
if
(
cpu_is_omap24xx
())
{
u16
reg
=
OMAP_MMC_READ
(
host
->
base
,
CON
);
OMAP_MMC_WRITE
(
host
->
base
,
CON
,
reg
&
~
(
1
<<
11
));
}
else
if
(
host
->
power_pin
>=
0
)
if
(
host
->
power_pin
>=
0
)
omap_set_gpio_dataout
(
host
->
power_pin
,
0
);
omap_set_gpio_dataout
(
host
->
power_pin
,
0
);
}
}
...
@@ -1027,17 +1069,15 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
...
@@ -1027,17 +1069,15 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host
->
id
,
ios
->
clock
,
ios
->
bus_mode
,
ios
->
power_mode
,
host
->
id
,
ios
->
clock
,
ios
->
bus_mode
,
ios
->
power_mode
,
ios
->
vdd
/
100
,
ios
->
vdd
%
100
);
ios
->
vdd
/
100
,
ios
->
vdd
%
100
);
if
(
ios
->
power_mode
==
MMC_POWER_UP
&&
ios
->
clock
<
400000
)
{
if
(
ios
->
power_mode
==
MMC_POWER_UP
&&
ios
->
clock
<
400000
)
/* Fix for broken stack */
realclock
=
400000
;
/* Fix for broken stack */
realclock
=
400000
;
else
}
else
{
realclock
=
ios
->
clock
;
realclock
=
ios
->
clock
;
}
if
(
ios
->
clock
==
0
)
{
if
(
ios
->
clock
==
0
)
dsor
=
0
;
dsor
=
0
;
}
else
{
else
{
int
func_clk_rate
=
clk_get_rate
(
host
->
clk
);
int
func_clk_rate
=
clk_get_rate
(
host
->
f
clk
);
dsor
=
func_clk_rate
/
realclock
;
dsor
=
func_clk_rate
/
realclock
;
if
(
dsor
<
1
)
if
(
dsor
<
1
)
...
@@ -1065,7 +1105,16 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
...
@@ -1065,7 +1105,16 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
host
->
bus_mode
=
ios
->
bus_mode
;
host
->
bus_mode
=
ios
->
bus_mode
;
clk_use
(
host
->
clk
);
if
(
omap_has_menelaus
())
{
if
(
host
->
bus_mode
==
MMC_BUSMODE_OPENDRAIN
)
menelaus_mmc_opendrain
(
1
);
else
menelaus_mmc_opendrain
(
0
);
}
host
->
hw_bus_mode
=
host
->
bus_mode
;
clk_use
(
host
->
fclk
);
/* On insanely high arm_per frequencies something sometimes
/* On insanely high arm_per frequencies something sometimes
* goes somehow out of sync, and the POW bit is not being set,
* goes somehow out of sync, and the POW bit is not being set,
* which results in the while loop below getting stuck.
* which results in the while loop below getting stuck.
...
@@ -1080,7 +1129,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
...
@@ -1080,7 +1129,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
while
(
0
==
(
OMAP_MMC_READ
(
host
->
base
,
STAT
)
&
1
));
while
(
0
==
(
OMAP_MMC_READ
(
host
->
base
,
STAT
)
&
1
));
OMAP_MMC_WRITE
(
host
->
base
,
STAT
,
1
);
OMAP_MMC_WRITE
(
host
->
base
,
STAT
,
1
);
}
}
clk_unuse
(
host
->
clk
);
clk_unuse
(
host
->
f
clk
);
}
}
static
struct
mmc_host_ops
mmc_omap_ops
=
{
static
struct
mmc_host_ops
mmc_omap_ops
=
{
...
@@ -1124,9 +1173,22 @@ static int __init mmc_omap_probe(struct device *dev)
...
@@ -1124,9 +1173,22 @@ static int __init mmc_omap_probe(struct device *dev)
host
->
dma_timer
.
data
=
(
unsigned
long
)
host
;
host
->
dma_timer
.
data
=
(
unsigned
long
)
host
;
host
->
id
=
pdev
->
id
;
host
->
id
=
pdev
->
id
;
host
->
clk
=
clk_get
(
dev
,
(
host
->
id
==
1
)
?
"mmc1_ck"
:
"mmc2_ck"
);
if
(
IS_ERR
(
host
->
clk
))
{
if
(
cpu_is_omap24xx
())
{
ret
=
PTR_ERR
(
host
->
clk
);
host
->
iclk
=
clk_get
(
dev
,
"mmc_ick"
);
if
(
IS_ERR
(
host
->
iclk
))
goto
out
;
clk_use
(
host
->
iclk
);
}
if
(
!
cpu_is_omap24xx
())
host
->
fclk
=
clk_get
(
dev
,
(
host
->
id
==
1
)
?
"mmc1_ck"
:
"mmc2_ck"
);
else
host
->
fclk
=
clk_get
(
dev
,
"mmc_fck"
);
if
(
IS_ERR
(
host
->
fclk
))
{
ret
=
PTR_ERR
(
host
->
fclk
);
goto
out
;
goto
out
;
}
}
...
@@ -1140,6 +1202,10 @@ static int __init mmc_omap_probe(struct device *dev)
...
@@ -1140,6 +1202,10 @@ static int __init mmc_omap_probe(struct device *dev)
host
->
switch_pin
=
minfo
->
switch_pin
;
host
->
switch_pin
=
minfo
->
switch_pin
;
host
->
wp_pin
=
minfo
->
wp_pin
;
host
->
wp_pin
=
minfo
->
wp_pin
;
/* FIXME: Remove once DMA works on 24xx */
if
(
cpu_is_omap24xx
())
host
->
use_dma
=
0
;
else
host
->
use_dma
=
1
;
host
->
use_dma
=
1
;
host
->
dma_ch
=
-
1
;
host
->
dma_ch
=
-
1
;
...
@@ -1218,13 +1284,22 @@ static int __init mmc_omap_probe(struct device *dev)
...
@@ -1218,13 +1284,22 @@ static int __init mmc_omap_probe(struct device *dev)
if
(
mmc_omap_enable_poll
&&
mmc_omap_cover_is_open
(
host
))
if
(
mmc_omap_enable_poll
&&
mmc_omap_cover_is_open
(
host
))
schedule_work
(
&
host
->
switch_work
);
schedule_work
(
&
host
->
switch_work
);
}
}
/* FIXME: Add callback function for card detection */
printk
(
"XXX host: 0x%08x
\n
"
,
&
host
);
if
(
omap_has_menelaus
())
menelaus_mmc_register
(
mmc_omap_switch_callback
,
&
host
);
no_switch:
no_switch:
return
0
;
return
0
;
out:
out:
/* FIXME: Free other resources too. */
/* FIXME: Free other resources too. */
if
(
host
)
{
if
(
host
)
{
if
(
host
->
clk
&&
!
IS_ERR
(
host
->
clk
))
if
(
host
->
iclk
&&
!
IS_ERR
(
host
->
iclk
))
clk_put
(
host
->
clk
);
clk_put
(
host
->
iclk
);
if
(
host
->
fclk
&&
!
IS_ERR
(
host
->
fclk
))
clk_put
(
host
->
fclk
);
mmc_free_host
(
host
->
mmc
);
mmc_free_host
(
host
->
mmc
);
}
}
return
ret
;
return
ret
;
...
@@ -1253,11 +1328,16 @@ static int __exit mmc_omap_remove(struct device *dev)
...
@@ -1253,11 +1328,16 @@ static int __exit mmc_omap_remove(struct device *dev)
del_timer_sync
(
&
host
->
switch_timer
);
del_timer_sync
(
&
host
->
switch_timer
);
flush_scheduled_work
();
flush_scheduled_work
();
}
}
if
(
host
->
clk
&&
!
IS_ERR
(
host
->
clk
))
if
(
host
->
iclk
&&
!
IS_ERR
(
host
->
iclk
))
clk_put
(
host
->
clk
);
clk_put
(
host
->
iclk
);
if
(
host
->
fclk
&&
!
IS_ERR
(
host
->
fclk
))
clk_put
(
host
->
fclk
);
mmc_free_host
(
host
->
mmc
);
mmc_free_host
(
host
->
mmc
);
}
}
if
(
omap_has_menelaus
())
menelaus_mmc_remove
();
release_mem_region
(
pdev
->
resource
[
0
].
start
,
release_mem_region
(
pdev
->
resource
[
0
].
start
,
pdev
->
resource
[
0
].
end
-
pdev
->
resource
[
0
].
start
+
1
);
pdev
->
resource
[
0
].
end
-
pdev
->
resource
[
0
].
start
+
1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment