Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Sami Nurmenniemi
u-boot-stm32
Commits
586667b4
Commit
586667b4
authored
Sep 15, 2017
by
Alexander Dyachenko
Committed by
Sergei Poselenov
Sep 28, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RM 1947: Copy the newer mmc and fsl_esdhc drivers from the Vybrid U-Boot repository
(cherry picked from commit 85502fd1becd71b365b71f4a8fd308ae4953025e)
parent
bdf130d6
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
914 additions
and
241 deletions
+914
-241
drivers/mmc/fsl_esdhc.c
drivers/mmc/fsl_esdhc.c
+213
-58
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+520
-151
include/asm-arm/cache.h
include/asm-arm/cache.h
+11
-0
include/common.h
include/common.h
+66
-0
include/config_defaults.h
include/config_defaults.h
+1
-0
include/fsl_esdhc.h
include/fsl_esdhc.h
+19
-2
include/mmc.h
include/mmc.h
+81
-30
include/part.h
include/part.h
+3
-0
No files found.
drivers/mmc/fsl_esdhc.c
View file @
586667b4
/*
* Copyright 2007, Freescale Semiconductor, Inc
* Copyright 2007,
2010-2012
Freescale Semiconductor, Inc
* Andy Fleming
*
* Based vaguely on the pxa mmc code:
...
...
@@ -58,7 +58,8 @@ struct fsl_esdhc {
uint
autoc12err
;
uint
hostcapblt
;
uint
wml
;
char
reserved1
[
8
];
uint
mixctrl
;
char
reserved1
[
4
];
uint
fevt
;
char
reserved2
[
168
];
uint
hostver
;
...
...
@@ -72,11 +73,16 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
uint
xfertyp
=
0
;
if
(
data
)
{
xfertyp
|=
XFERTYP_DPSEL
|
XFERTYP_DMAEN
;
xfertyp
|=
XFERTYP_DPSEL
;
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
xfertyp
|=
XFERTYP_DMAEN
;
#endif
if
(
data
->
blocks
>
1
)
{
xfertyp
|=
XFERTYP_MSBSEL
;
xfertyp
|=
XFERTYP_BCEN
;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
xfertyp
|=
XFERTYP_AC12EN
;
#endif
}
if
(
data
->
flags
&
MMC_DATA_READ
)
...
...
@@ -94,42 +100,139 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
else
if
(
cmd
->
resp_type
&
MMC_RSP_PRESENT
)
xfertyp
|=
XFERTYP_RSPTYP_48
;
#ifdef CONFIG_MX53
if
(
cmd
->
cmdidx
==
MMC_CMD_STOP_TRANSMISSION
)
xfertyp
|=
XFERTYP_CMDTYP_ABORT
;
#endif
return
XFERTYP_CMD
(
cmd
->
cmdidx
)
|
xfertyp
;
}
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
/*
* PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
*/
static
void
esdhc_pio_read_write
(
struct
mmc
*
mmc
,
struct
mmc_data
*
data
)
{
struct
fsl_esdhc_cfg
*
cfg
=
mmc
->
priv
;
struct
fsl_esdhc
*
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
uint
blocks
;
char
*
buffer
;
uint
databuf
;
uint
size
;
uint
irqstat
;
uint
timeout
;
if
(
data
->
flags
&
MMC_DATA_READ
)
{
blocks
=
data
->
blocks
;
buffer
=
data
->
dest
;
while
(
blocks
)
{
timeout
=
PIO_TIMEOUT
;
size
=
data
->
blocksize
;
irqstat
=
esdhc_read32
(
&
regs
->
irqstat
);
while
(
!
(
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_BREN
)
&&
--
timeout
);
if
(
timeout
<=
0
)
{
printf
(
"
\n
Data Read Failed in PIO Mode."
);
return
;
}
while
(
size
&&
(
!
(
irqstat
&
IRQSTAT_TC
)))
{
#ifndef CONFIG_VYBRID
udelay
(
100
);
/* Wait before last byte transfer complete */
#endif
irqstat
=
esdhc_read32
(
&
regs
->
irqstat
);
databuf
=
in_le32
(
&
regs
->
datport
);
*
((
uint
*
)
buffer
)
=
databuf
;
buffer
+=
4
;
size
-=
4
;
}
blocks
--
;
}
}
else
{
blocks
=
data
->
blocks
;
buffer
=
(
char
*
)
data
->
src
;
while
(
blocks
)
{
timeout
=
PIO_TIMEOUT
;
size
=
data
->
blocksize
;
irqstat
=
esdhc_read32
(
&
regs
->
irqstat
);
while
(
!
(
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_BWEN
)
&&
--
timeout
);
if
(
timeout
<=
0
)
{
printf
(
"
\n
Data Write Failed in PIO Mode."
);
return
;
}
while
(
size
&&
(
!
(
irqstat
&
IRQSTAT_TC
)))
{
udelay
(
100
);
/* Wait before last byte transfer complete */
databuf
=
*
((
uint
*
)
buffer
);
buffer
+=
4
;
size
-=
4
;
irqstat
=
esdhc_read32
(
&
regs
->
irqstat
);
out_le32
(
&
regs
->
datport
,
databuf
);
}
blocks
--
;
}
}
}
#endif
static
int
esdhc_setup_data
(
struct
mmc
*
mmc
,
struct
mmc_data
*
data
)
{
uint
wml_value
;
int
timeout
;
struct
fsl_esdhc_cfg
*
cfg
=
(
struct
fsl_esdhc_cfg
*
)
mmc
->
priv
;
struct
fsl_esdhc
*
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
uint
wml_value
;
wml_value
=
data
->
blocksize
/
4
;
if
(
data
->
flags
&
MMC_DATA_READ
)
{
if
(
wml_value
>
0x10
)
wml_value
=
0x10
;
wml_value
=
0x100000
|
wml_value
;
if
(
wml_value
>
WML_RD_WML_MAX
)
wml_value
=
WML_RD_WML_MAX_VAL
;
esdhc_clrsetbits32
(
&
regs
->
wml
,
WML_RD_WML_MASK
,
wml_value
);
esdhc_write32
(
&
regs
->
dsaddr
,
(
u32
)
data
->
dest
);
}
else
{
if
(
wml_value
>
0x80
)
wml_value
=
0x80
;
if
(
wml_value
>
WML_WR_WML_MAX
)
wml_value
=
WML_WR_WML_MAX_VAL
;
if
((
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_WPSPL
)
==
0
)
{
printf
(
"
\n
The SD card is locked. Can not write to a locked card.
\n\n
"
);
return
TIMEOUT
;
}
wml_value
=
wml_value
<<
16
|
0x10
;
esdhc_clrsetbits32
(
&
regs
->
wml
,
WML_WR_WML_MASK
,
wml_value
<<
16
);
esdhc_write32
(
&
regs
->
dsaddr
,
(
u32
)
data
->
src
);
}
esdhc_write32
(
&
regs
->
wml
,
wml_value
);
#else
/* CONFIG_SYS_FSL_ESDHC_USE_PIO */
if
(
!
(
data
->
flags
&
MMC_DATA_READ
))
{
if
((
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_WPSPL
)
==
0
)
{
printf
(
"
\n
The SD card is locked. "
"Can not write to a locked card.
\n\n
"
);
return
TIMEOUT
;
}
esdhc_write32
(
&
regs
->
dsaddr
,
(
u32
)
data
->
src
);
}
else
esdhc_write32
(
&
regs
->
dsaddr
,
(
u32
)
data
->
dest
);
#endif
/* CONFIG_SYS_FSL_ESDHC_USE_PIO */
esdhc_write32
(
&
regs
->
blkattr
,
data
->
blocks
<<
16
|
data
->
blocksize
);
/* Calculate the timeout period for data transactions */
timeout
=
fls
(
mmc
->
tran_speed
/
10
)
-
1
;
/*
* 1)Timeout period = (2^(timeout+13)) SD Clock cycles
* 2)Timeout period should be minimum 0.250sec as per SD Card spec
* So, Number of SD Clock cycles for 0.25sec should be minimum
* (SD Clock/sec * 0.25 sec) SD Clock cycles
* = (mmc->tran_speed * 1/4) SD Clock cycles
* As 1) >= 2)
* => (2^(timeout+13)) >= mmc->tran_speed * 1/4
* Taking log2 both the sides
* => timeout + 13 >= log2(mmc->tran_speed/4)
* Rounding up to next power of 2
* => timeout + 13 = log2(mmc->tran_speed/4) + 1
* => timeout + 13 = fls(mmc->tran_speed/4)
*/
timeout
=
fls
(
mmc
->
tran_speed
/
4
);
timeout
-=
13
;
if
(
timeout
>
14
)
...
...
@@ -138,6 +241,11 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
if
(
timeout
<
0
)
timeout
=
0
;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
if
((
timeout
==
4
)
||
(
timeout
==
8
)
||
(
timeout
==
12
))
timeout
++
;
#endif
esdhc_clrsetbits32
(
&
regs
->
sysctl
,
SYSCTL_TIMEOUT_MASK
,
timeout
<<
16
);
return
0
;
...
...
@@ -156,6 +264,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
struct
fsl_esdhc_cfg
*
cfg
=
(
struct
fsl_esdhc_cfg
*
)
mmc
->
priv
;
volatile
struct
fsl_esdhc
*
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
if
(
cmd
->
cmdidx
==
MMC_CMD_STOP_TRANSMISSION
)
return
0
;
#endif
esdhc_write32
(
&
regs
->
irqstat
,
-
1
);
sync
();
...
...
@@ -189,8 +302,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Send the command */
esdhc_write32
(
&
regs
->
cmdarg
,
cmd
->
cmdarg
);
#if defined(CONFIG_FSL_USDHC)
esdhc_write32
(
&
regs
->
mixctrl
,
(
esdhc_read32
(
&
regs
->
mixctrl
)
&
0xFFFFFF80
)
|
(
xfertyp
&
0x7F
));
esdhc_write32
(
&
regs
->
xfertyp
,
xfertyp
&
0xFFFF0000
);
#else
esdhc_write32
(
&
regs
->
xfertyp
,
xfertyp
);
#endif
/* Wait for the command to complete */
while
(
!
(
esdhc_read32
(
&
regs
->
irqstat
)
&
IRQSTAT_CC
))
;
...
...
@@ -221,16 +339,20 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Wait until all of the blocks are transferred */
if
(
data
)
{
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_pio_read_write
(
mmc
,
data
);
#else
do
{
irqstat
=
esdhc_read32
(
&
regs
->
irqstat
);
if
(
irqstat
&
DATA_ERR
)
return
COMM_ERR
;
if
(
irqstat
&
IRQSTAT_DTOE
)
return
TIMEOUT
;
if
(
irqstat
&
DATA_ERR
)
return
COMM_ERR
;
}
while
(
!
(
irqstat
&
IRQSTAT_TC
)
&&
(
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_DLA
));
#endif
}
esdhc_write32
(
&
regs
->
irqstat
,
-
1
);
...
...
@@ -265,18 +387,13 @@ void set_sysctl(struct mmc *mmc, uint clock)
clk
=
(
pre_div
<<
8
)
|
(
div
<<
4
);
/* On imx the clock must be stopped before changing frequency */
if
(
cfg
->
clk_enable
)
esdhc_clrbits32
(
&
regs
->
sysctl
,
SYSCTL_CKEN
);
esdhc_clrsetbits32
(
&
regs
->
sysctl
,
SYSCTL_CLOCK_MASK
,
clk
);
udelay
(
10000
);
clk
=
SYSCTL_PEREN
;
/* On imx systems the clock must be explicitely enabled */
if
(
cfg
->
clk_enable
)
clk
|=
SYSCTL_CKEN
;
clk
=
SYSCTL_PEREN
|
SYSCTL_CKEN
;
esdhc_setbits32
(
&
regs
->
sysctl
,
clk
);
}
...
...
@@ -304,12 +421,6 @@ static int esdhc_init(struct mmc *mmc)
struct
fsl_esdhc_cfg
*
cfg
=
(
struct
fsl_esdhc_cfg
*
)
mmc
->
priv
;
struct
fsl_esdhc
*
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
int
timeout
=
1000
;
int
ret
=
0
;
u8
card_absent
;
/* Enable cache snooping */
if
(
cfg
&&
!
cfg
->
no_snoop
)
esdhc_write32
(
&
regs
->
scr
,
0x00000040
);
/* Reset the entire host controller */
esdhc_write32
(
&
regs
->
sysctl
,
SYSCTL_RSTA
);
...
...
@@ -318,10 +429,17 @@ static int esdhc_init(struct mmc *mmc)
while
((
esdhc_read32
(
&
regs
->
sysctl
)
&
SYSCTL_RSTA
)
&&
--
timeout
)
udelay
(
1000
);
/* Enable cache snooping */
if
(
cfg
&&
!
cfg
->
no_snoop
)
{
asm
volatile
(
""
:::
"memory"
);
esdhc_write32
(
&
regs
->
scr
,
0x00000040
);
}
esdhc_write32
(
&
regs
->
sysctl
,
SYSCTL_HCKEN
|
SYSCTL_IPGEN
);
/* Set the initial clock speed */
set_sysctl
(
mmc
,
400000
);
mmc_set_clock
(
mmc
,
400000
);
/* Disable the BRR and BWR bits in IRQSTAT */
esdhc_clrbits32
(
&
regs
->
irqstaten
,
IRQSTATEN_BRR
|
IRQSTATEN_BWR
);
...
...
@@ -332,50 +450,81 @@ static int esdhc_init(struct mmc *mmc)
/* Set timout to the maximum value */
esdhc_clrsetbits32
(
&
regs
->
sysctl
,
SYSCTL_TIMEOUT_MASK
,
14
<<
16
);
/* Check if there is a callback for detecting the card */
if
(
board_mmc_getcd
(
&
card_absent
,
mmc
))
{
timeout
=
1000
;
while
(
!
(
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_CINS
)
&&
--
timeout
)
return
0
;
}
static
int
esdhc_getcd
(
struct
mmc
*
mmc
)
{
struct
fsl_esdhc_cfg
*
cfg
=
(
struct
fsl_esdhc_cfg
*
)
mmc
->
priv
;
struct
fsl_esdhc
*
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
int
timeout
=
1000
;
while
(
!
(
esdhc_read32
(
&
regs
->
prsstat
)
&
PRSSTAT_CINS
)
&&
--
timeout
)
udelay
(
1000
);
if
(
timeout
<=
0
)
ret
=
NO_CARD_ERR
;
}
else
{
if
(
card_absent
)
ret
=
NO_CARD_ERR
;
}
return
timeout
>
0
;
}
static
void
esdhc_reset
(
struct
fsl_esdhc
*
regs
)
{
unsigned
long
timeout
=
100
;
/* wait max 100 ms */
/* reset the controller */
esdhc_write32
(
&
regs
->
sysctl
,
SYSCTL_RSTA
);
return
ret
;
/* hardware clears the bit when it is done */
while
((
esdhc_read32
(
&
regs
->
sysctl
)
&
SYSCTL_RSTA
)
&&
--
timeout
)
udelay
(
1000
);
if
(
!
timeout
)
printf
(
"MMC/SD: Reset never completed.
\n
"
);
}
int
fsl_esdhc_initialize
(
bd_t
*
bis
,
struct
fsl_esdhc_cfg
*
cfg
)
{
struct
fsl_esdhc
*
regs
;
struct
mmc
*
mmc
;
u32
caps
;
u32
caps
,
voltage_
caps
;
if
(
!
cfg
)
return
-
1
;
mmc
=
malloc
(
sizeof
(
struct
mmc
));
sprintf
(
mmc
->
name
,
"FSL_
E
SDHC"
);
sprintf
(
mmc
->
name
,
"FSL_SDHC"
);
regs
=
(
struct
fsl_esdhc
*
)
cfg
->
esdhc_base
;
/* First reset the eSDHC controller */
esdhc_reset
(
regs
);
mmc
->
priv
=
cfg
;
mmc
->
send_cmd
=
esdhc_send_cmd
;
mmc
->
set_ios
=
esdhc_set_ios
;
mmc
->
init
=
esdhc_init
;
mmc
->
getcd
=
esdhc_getcd
;
voltage_caps
=
0
;
caps
=
regs
->
hostcapblt
;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
caps
=
caps
&
~
(
ESDHC_HOSTCAPBLT_SRS
|
ESDHC_HOSTCAPBLT_VS18
|
ESDHC_HOSTCAPBLT_VS30
);
#endif
if
(
caps
&
ESDHC_HOSTCAPBLT_VS18
)
mmc
->
voltages
|=
MMC_VDD_165_195
;
voltage
_cap
s
|=
MMC_VDD_165_195
;
if
(
caps
&
ESDHC_HOSTCAPBLT_VS30
)
mmc
->
voltages
|=
MMC_VDD_29_30
|
MMC_VDD_30_31
;
voltage
_cap
s
|=
MMC_VDD_29_30
|
MMC_VDD_30_31
;
if
(
caps
&
ESDHC_HOSTCAPBLT_VS33
)
mmc
->
voltages
|=
MMC_VDD_32_33
|
MMC_VDD_33_34
;
voltage_caps
|=
MMC_VDD_32_33
|
MMC_VDD_33_34
;
#ifdef CONFIG_SYS_SD_VOLTAGE
mmc
->
voltages
=
CONFIG_SYS_SD_VOLTAGE
;
#else
mmc
->
voltages
=
MMC_VDD_32_33
|
MMC_VDD_33_34
;
#endif
if
((
mmc
->
voltages
&
voltage_caps
)
==
0
)
{
printf
(
"voltage not supported by controller
\n
"
);
return
-
1
;
}
mmc
->
host_caps
=
MMC_MODE_4BIT
|
MMC_MODE_8BIT
;
...
...
@@ -383,8 +532,9 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
mmc
->
host_caps
|=
MMC_MODE_HS_52MHz
|
MMC_MODE_HS
;
mmc
->
f_min
=
400000
;
mmc
->
f_max
=
MIN
(
gd
->
sdhc_clk
,
5
0
000000
);
mmc
->
f_max
=
MIN
(
gd
->
sdhc_clk
,
5
2
000000
);
mmc
->
b_max
=
0
;
mmc_register
(
mmc
);
return
0
;
...
...
@@ -397,6 +547,9 @@ int fsl_esdhc_mmc_init(bd_t *bis)
cfg
=
malloc
(
sizeof
(
struct
fsl_esdhc_cfg
));
memset
(
cfg
,
0
,
sizeof
(
struct
fsl_esdhc_cfg
));
cfg
->
esdhc_base
=
CONFIG_SYS_FSL_ESDHC_ADDR
;
#ifdef CONFIG_ESDHC_NO_SNOOP
cfg
->
no_snoop
=
1
;
#endif
return
fsl_esdhc_initialize
(
bis
,
cfg
);
}
...
...
@@ -404,17 +557,19 @@ int fsl_esdhc_mmc_init(bd_t *bis)
void
fdt_fixup_esdhc
(
void
*
blob
,
bd_t
*
bd
)
{
const
char
*
compat
=
"fsl,esdhc"
;
const
char
*
status
=
"okay"
;
#ifdef CONFIG_FSL_ESDHC_PIN_MUX
if
(
!
hwconfig
(
"esdhc"
))
{
status
=
"disabled"
;
goto
out
;
do_fixup_by_compat
(
blob
,
compat
,
"status"
,
"disabled"
,
8
+
1
,
1
);
return
;
}
#endif
do_fixup_by_compat_u32
(
blob
,
compat
,
"clock-frequency"
,
gd
->
sdhc_clk
,
1
);
out:
do_fixup_by_compat
(
blob
,
compat
,
"status"
,
status
,
strlen
(
status
)
+
1
,
1
);
do_fixup_by_compat
(
blob
,
compat
,
"status"
,
"okay"
,
4
+
1
,
1
);
}
#endif
drivers/mmc/mmc.c
View file @
586667b4
...
...
@@ -30,22 +30,124 @@
#include <part.h>
#include <malloc.h>
#include <linux/list.h>
#include <mmc.h>
#include <div64.h>
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
#endif
static
struct
list_head
mmc_devices
;
static
int
cur_dev_num
=
-
1
;
int
__board_mmc_getcd
(
u8
*
cd
,
struct
mmc
*
mmc
)
{
int
__board_mmc_getcd
(
struct
mmc
*
mmc
)
{
return
-
1
;
}
int
board_mmc_getcd
(
u8
*
cd
,
struct
mmc
*
mmc
)
__attribute__
((
weak
,
int
board_mmc_getcd
(
struct
mmc
*
mmc
)
__attribute__
((
weak
,
alias
(
"__board_mmc_getcd"
)));
int
mmc_send_cmd
(
struct
mmc
*
mmc
,
struct
mmc_cmd
*
cmd
,
struct
mmc_data
*
data
)
{
#ifdef CONFIG_MMC_TRACE
int
ret
;
int
i
;
u8
*
ptr
;
printf
(
"CMD_SEND:%d
\n
"
,
cmd
->
cmdidx
);
printf
(
"
\t\t
ARG
\t\t\t
0x%08X
\n
"
,
cmd
->
cmdarg
);
printf
(
"
\t\t
FLAG
\t\t\t
%d
\n
"
,
cmd
->
flags
);
ret
=
mmc
->
send_cmd
(
mmc
,
cmd
,
data
);
switch
(
cmd
->
resp_type
)
{
case
MMC_RSP_NONE
:
printf
(
"
\t\t
MMC_RSP_NONE
\n
"
);
break
;
case
MMC_RSP_R1
:
printf
(
"
\t\t
MMC_RSP_R1,5,6,7
\t
0x%08X
\n
"
,
cmd
->
response
[
0
]);
break
;
case
MMC_RSP_R1b
:
printf
(
"
\t\t
MMC_RSP_R1b
\t\t
0x%08X
\n
"
,
cmd
->
response
[
0
]);
break
;
case
MMC_RSP_R2
:
printf
(
"
\t\t
MMC_RSP_R2
\t\t
0x%08X
\n
"
,
cmd
->
response
[
0
]);
printf
(
"
\t\t
\t\t
0x%08X
\n
"
,
cmd
->
response
[
1
]);
printf
(
"
\t\t
\t\t
0x%08X
\n
"
,
cmd
->
response
[
2
]);
printf
(
"
\t\t
\t\t
0x%08X
\n
"
,
cmd
->
response
[
3
]);
printf
(
"
\n
"
);
printf
(
"
\t\t\t\t\t
DUMPING DATA
\n
"
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
int
j
;
printf
(
"
\t\t\t\t\t
%03d - "
,
i
*
4
);
ptr
=
&
cmd
->
response
[
i
];
ptr
+=
3
;
for
(
j
=
0
;
j
<
4
;
j
++
)
printf
(
"%02X "
,
*
ptr
--
);
printf
(
"
\n
"
);
}
break
;
case
MMC_RSP_R3
:
printf
(
"
\t\t
MMC_RSP_R3,4
\t\t
0x%08X
\n
"
,
cmd
->
response
[
0
]);
break
;
default:
printf
(
"
\t\t
ERROR MMC rsp not supported
\n
"
);
break
;
}
return
ret
;
#else
return
mmc
->
send_cmd
(
mmc
,
cmd
,
data
);
#endif
}
int
mmc_send_status
(
struct
mmc
*
mmc
,
int
timeout
)
{
struct
mmc_cmd
cmd
;
int
err
,
retries
=
5
;
#ifdef CONFIG_MMC_TRACE
int
status
;
#endif
cmd
.
cmdidx
=
MMC_CMD_SEND_STATUS
;
cmd
.
resp_type
=
MMC_RSP_R1
;
if
(
!
mmc_host_is_spi
(
mmc
))
cmd
.
cmdarg
=
mmc
->
rca
<<
16
;
cmd
.
flags
=
0
;
do
{
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
!
err
)
{
if
((
cmd
.
response
[
0
]
&
MMC_STATUS_RDY_FOR_DATA
)
&&
(
cmd
.
response
[
0
]
&
MMC_STATUS_CURR_STATE
)
!=
MMC_STATE_PRG
)
break
;
else
if
(
cmd
.
response
[
0
]
&
MMC_STATUS_MASK
)
{
printf
(
"Status Error: 0x%08X
\n
"
,
cmd
.
response
[
0
]);
return
COMM_ERR
;
}
}
else
if
(
--
retries
<
0
)
return
err
;
udelay
(
1000
);
}
while
(
timeout
--
);
#ifdef CONFIG_MMC_TRACE
status
=
(
cmd
.
response
[
0
]
&
MMC_STATUS_CURR_STATE
)
>>
9
;
printf
(
"CURR STATE:%d
\n
"
,
status
);
#endif
if
(
!
timeout
)
{
printf
(
"Timeout waiting card ready
\n
"
);
return
TIMEOUT
;
}
return
0
;
}
int
mmc_set_blocklen
(
struct
mmc
*
mmc
,
int
len
)
...
...
@@ -77,26 +179,99 @@ struct mmc *find_mmc_device(int dev_num)
return
NULL
;
}
static
ulong
mmc_bwrite
(
int
dev_num
,
ulong
start
,
lbaint_t
blkcnt
,
const
void
*
src
)
static
ulong
mmc_erase_t
(
struct
mmc
*
mmc
,
ulong
start
,
lbaint_t
blkcnt
)
{
struct
mmc_cmd
cmd
;
struct
mmc_data
data
;
int
err
;
int
stoperr
=
0
;
ulong
end
;
int
err
,
start_cmd
,
end_cmd
;
if
(
mmc
->
high_capacity
)
end
=
start
+
blkcnt
-
1
;
else
{
end
=
(
start
+
blkcnt
-
1
)
*
mmc
->
write_bl_len
;
start
*=
mmc
->
write_bl_len
;
}
if
(
IS_SD
(
mmc
))
{
start_cmd
=
SD_CMD_ERASE_WR_BLK_START
;
end_cmd
=
SD_CMD_ERASE_WR_BLK_END
;
}
else
{
start_cmd
=
MMC_CMD_ERASE_GROUP_START
;
end_cmd
=
MMC_CMD_ERASE_GROUP_END
;
}
cmd
.
cmdidx
=
start_cmd
;
cmd
.
cmdarg
=
start
;
cmd
.
resp_type
=
MMC_RSP_R1
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
goto
err_out
;
cmd
.
cmdidx
=
end_cmd
;
cmd
.
cmdarg
=
end
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
goto
err_out
;
cmd
.
cmdidx
=
MMC_CMD_ERASE
;
cmd
.
cmdarg
=
SECURE_ERASE
;
cmd
.
resp_type
=
MMC_RSP_R1b
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
goto
err_out
;
return
0
;