Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
4f27f0ab
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4f27f0ab
编写于
4月 20, 2011
作者:
W
Wolfgang Denk
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.denx.de/u-boot-mmc
上级
8c4734e9
8511cd84
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
616 addition
and
50 deletion
+616
-50
common/Makefile
common/Makefile
+1
-0
common/cmd_mmc.c
common/cmd_mmc.c
+2
-1
common/cmd_mmc_spi.c
common/cmd_mmc_spi.c
+88
-0
drivers/mmc/Makefile
drivers/mmc/Makefile
+1
-0
drivers/mmc/fsl_esdhc.c
drivers/mmc/fsl_esdhc.c
+3
-3
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+219
-43
drivers/mmc/mmc_spi.c
drivers/mmc/mmc_spi.c
+280
-0
drivers/spi/cf_spi.c
drivers/spi/cf_spi.c
+11
-3
include/mmc.h
include/mmc.h
+11
-0
未找到文件。
common/Makefile
浏览文件 @
4f27f0ab
...
...
@@ -118,6 +118,7 @@ COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
COBJS-$(CONFIG_CMD_MII)
+=
cmd_mii.o
COBJS-$(CONFIG_CMD_MISC)
+=
cmd_misc.o
COBJS-$(CONFIG_CMD_MMC)
+=
cmd_mmc.o
COBJS-$(CONFIG_CMD_MMC_SPI)
+=
cmd_mmc_spi.o
COBJS-$(CONFIG_MP)
+=
cmd_mp.o
COBJS-$(CONFIG_CMD_MTDPARTS)
+=
cmd_mtdparts.o
COBJS-$(CONFIG_CMD_NAND)
+=
cmd_nand.o
...
...
common/cmd_mmc.c
浏览文件 @
4f27f0ab
...
...
@@ -104,7 +104,8 @@ static void print_mmcinfo(struct mmc *mmc)
(
mmc
->
version
>>
4
)
&
0xf
,
mmc
->
version
&
0xf
);
printf
(
"High Capacity: %s
\n
"
,
mmc
->
high_capacity
?
"Yes"
:
"No"
);
printf
(
"Capacity: %lld
\n
"
,
mmc
->
capacity
);
puts
(
"Capacity: "
);
print_size
(
mmc
->
capacity
,
"
\n
"
);
printf
(
"Bus Width: %d-bit
\n
"
,
mmc
->
bus_width
);
}
...
...
common/cmd_mmc_spi.c
0 → 100644
浏览文件 @
4f27f0ab
/*
* Command for mmc_spi setup.
*
* Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <mmc.h>
#include <spi.h>
#ifndef CONFIG_MMC_SPI_BUS
# define CONFIG_MMC_SPI_BUS 0
#endif
#ifndef CONFIG_MMC_SPI_CS
# define CONFIG_MMC_SPI_CS 1
#endif
/* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */
#ifndef CONFIG_MMC_SPI_SPEED
# define CONFIG_MMC_SPI_SPEED 25000000
#endif
/* MMC and SD specs only seem to care that sampling is on the
* rising edge ... meaning SPI modes 0 or 3. So either SPI mode
* should be legit. We'll use mode 0 since the steady state is 0,
* which is appropriate for hotplugging, unless the platform data
* specify mode 3 (if hardware is not compatible to mode 0).
*/
#ifndef CONFIG_MMC_SPI_MODE
# define CONFIG_MMC_SPI_MODE SPI_MODE_0
#endif
static
int
do_mmc_spi
(
cmd_tbl_t
*
cmdtp
,
int
flag
,
int
argc
,
char
*
const
argv
[])
{
uint
bus
=
CONFIG_MMC_SPI_BUS
;
uint
cs
=
CONFIG_MMC_SPI_CS
;
uint
speed
=
CONFIG_MMC_SPI_SPEED
;
uint
mode
=
CONFIG_MMC_SPI_MODE
;
char
*
endp
;
struct
mmc
*
mmc
;
if
(
argc
<
2
)
goto
usage
;
cs
=
simple_strtoul
(
argv
[
1
],
&
endp
,
0
);
if
(
*
argv
[
1
]
==
0
||
(
*
endp
!=
0
&&
*
endp
!=
':'
))
goto
usage
;
if
(
*
endp
==
':'
)
{
if
(
endp
[
1
]
==
0
)
goto
usage
;
bus
=
cs
;
cs
=
simple_strtoul
(
endp
+
1
,
&
endp
,
0
);
if
(
*
endp
!=
0
)
goto
usage
;
}
if
(
argc
>=
3
)
{
speed
=
simple_strtoul
(
argv
[
2
],
&
endp
,
0
);
if
(
*
argv
[
2
]
==
0
||
*
endp
!=
0
)
goto
usage
;
}
if
(
argc
>=
4
)
{
mode
=
simple_strtoul
(
argv
[
3
],
&
endp
,
16
);
if
(
*
argv
[
3
]
==
0
||
*
endp
!=
0
)
goto
usage
;
}
if
(
!
spi_cs_is_valid
(
bus
,
cs
))
{
printf
(
"Invalid SPI bus %u cs %u
\n
"
,
bus
,
cs
);
return
1
;
}
mmc
=
mmc_spi_init
(
bus
,
cs
,
speed
,
mode
);
if
(
!
mmc
)
{
printf
(
"Failed to create MMC Device
\n
"
);
return
1
;
}
printf
(
"%s: %d at %u:%u hz %u mode %u
\n
"
,
mmc
->
name
,
mmc
->
block_dev
.
dev
,
bus
,
cs
,
speed
,
mode
);
return
0
;
usage:
cmd_usage
(
cmdtp
);
return
1
;
}
U_BOOT_CMD
(
mmc_spi
,
4
,
0
,
do_mmc_spi
,
"mmc_spi setup"
,
"[bus:]cs [hz] [mode] - setup mmc_spi device"
);
drivers/mmc/Makefile
浏览文件 @
4f27f0ab
...
...
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o
COBJS-$(CONFIG_FSL_ESDHC)
+=
fsl_esdhc.o
COBJS-$(CONFIG_GENERIC_MMC)
+=
mmc.o
COBJS-$(CONFIG_GENERIC_ATMEL_MCI)
+=
gen_atmel_mci.o
COBJS-$(CONFIG_MMC_SPI)
+=
mmc_spi.o
COBJS-$(CONFIG_MXC_MMC)
+=
mxcmmc.o
COBJS-$(CONFIG_OMAP3_MMC)
+=
omap3_mmc.o
COBJS-$(CONFIG_OMAP_HSMMC)
+=
omap_hsmmc.o
...
...
drivers/mmc/fsl_esdhc.c
浏览文件 @
4f27f0ab
...
...
@@ -332,11 +332,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
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
...
...
drivers/mmc/mmc.c
浏览文件 @
4f27f0ab
...
...
@@ -30,9 +30,13 @@
#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
;
...
...
@@ -45,7 +49,100 @@ int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
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
;
#ifdef CONFIG_MMC_TRACE
int
status
;
#endif
cmd
.
cmdidx
=
MMC_CMD_SEND_STATUS
;
cmd
.
resp_type
=
MMC_RSP_R1
;
cmd
.
cmdarg
=
0
;
cmd
.
flags
=
0
;
do
{
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
else
if
(
cmd
.
response
[
0
]
&
MMC_STATUS_RDY_FOR_DATA
)
break
;
udelay
(
1000
);
if
(
cmd
.
response
[
0
]
&
MMC_STATUS_MASK
)
{
printf
(
"Status Error: 0x%08X
\n
"
,
cmd
.
response
[
0
]);
return
COMM_ERR
;
}
}
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
)
...
...
@@ -82,6 +179,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
{
struct
mmc_cmd
cmd
;
struct
mmc_data
data
;
int
timeout
=
1000
;
if
((
start
+
blkcnt
)
>
mmc
->
block_dev
.
lba
)
{
printf
(
"MMC: block number 0x%lx exceeds max(0x%lx)
\n
"
,
...
...
@@ -112,7 +210,10 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
return
0
;
}
if
(
blkcnt
>
1
)
{
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
*/
if
(
!
mmc_host_is_spi
(
mmc
)
&&
blkcnt
>
1
)
{
cmd
.
cmdidx
=
MMC_CMD_STOP_TRANSMISSION
;
cmd
.
cmdarg
=
0
;
cmd
.
resp_type
=
MMC_RSP_R1b
;
...
...
@@ -121,6 +222,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
printf
(
"mmc fail to send stop cmd
\n
"
);
return
0
;
}
/* Waiting for the ready status */
mmc_send_status
(
mmc
,
timeout
);
}
return
blkcnt
;
...
...
@@ -139,11 +243,8 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
return
0
;
do
{
/*
* The 65535 constraint comes from some hardware has
* only 16 bit width block number counter
*/
cur
=
(
blocks_todo
>
65535
)
?
65535
:
blocks_todo
;
cur
=
(
blocks_todo
>
CONFIG_SYS_MMC_MAX_BLK_COUNT
)
?
CONFIG_SYS_MMC_MAX_BLK_COUNT
:
blocks_todo
;
if
(
mmc_write_blocks
(
mmc
,
start
,
cur
,
src
)
!=
cur
)
return
0
;
blocks_todo
-=
cur
;
...
...
@@ -158,6 +259,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
{
struct
mmc_cmd
cmd
;
struct
mmc_data
data
;
int
timeout
=
1000
;
if
(
blkcnt
>
1
)
cmd
.
cmdidx
=
MMC_CMD_READ_MULTIPLE_BLOCK
;
...
...
@@ -189,6 +291,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
printf
(
"mmc fail to send stop cmd
\n
"
);
return
0
;
}
/* Waiting for the ready status */
mmc_send_status
(
mmc
,
timeout
);
}
return
blkcnt
;
...
...
@@ -215,11 +320,8 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
return
0
;
do
{
/*
* The 65535 constraint comes from some hardware has
* only 16 bit width block number counter
*/
cur
=
(
blocks_todo
>
65535
)
?
65535
:
blocks_todo
;
cur
=
(
blocks_todo
>
CONFIG_SYS_MMC_MAX_BLK_COUNT
)
?
CONFIG_SYS_MMC_MAX_BLK_COUNT
:
blocks_todo
;
if
(
mmc_read_blocks
(
mmc
,
dst
,
start
,
cur
)
!=
cur
)
return
0
;
blocks_todo
-=
cur
;
...
...
@@ -280,7 +382,8 @@ sd_send_op_cond(struct mmc *mmc)
* how to manage low voltages SD card is not yet
* specified.
*/
cmd
.
cmdarg
=
mmc
->
voltages
&
0xff8000
;
cmd
.
cmdarg
=
mmc_host_is_spi
(
mmc
)
?
0
:
(
mmc
->
voltages
&
0xff8000
);
if
(
mmc
->
version
==
SD_VERSION_2
)
cmd
.
cmdarg
|=
OCR_HCS
;
...
...
@@ -299,6 +402,18 @@ sd_send_op_cond(struct mmc *mmc)
if
(
mmc
->
version
!=
SD_VERSION_2
)
mmc
->
version
=
SD_VERSION_1_0
;
if
(
mmc_host_is_spi
(
mmc
))
{
/* read OCR for spi */
cmd
.
cmdidx
=
MMC_CMD_SPI_READ_OCR
;
cmd
.
resp_type
=
MMC_RSP_R3
;
cmd
.
cmdarg
=
0
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
}
mmc
->
ocr
=
cmd
.
response
[
0
];
mmc
->
high_capacity
=
((
mmc
->
ocr
&
OCR_HCS
)
==
OCR_HCS
);
...
...
@@ -309,17 +424,33 @@ sd_send_op_cond(struct mmc *mmc)
int
mmc_send_op_cond
(
struct
mmc
*
mmc
)
{
int
timeout
=
1000
;
int
timeout
=
1000
0
;
struct
mmc_cmd
cmd
;
int
err
;
/* Some cards seem to need this */
mmc_go_idle
(
mmc
);
/* Asking to the card its capabilities */
cmd
.
cmdidx
=
MMC_CMD_SEND_OP_COND
;
cmd
.
resp_type
=
MMC_RSP_R3
;
cmd
.
cmdarg
=
0
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
udelay
(
1000
);
do
{
cmd
.
cmdidx
=
MMC_CMD_SEND_OP_COND
;
cmd
.
resp_type
=
MMC_RSP_R3
;
cmd
.
cmdarg
=
OCR_HCS
|
mmc
->
voltages
;
cmd
.
cmdarg
=
(
mmc_host_is_spi
(
mmc
)
?
0
:
(
mmc
->
voltages
&
(
cmd
.
response
[
0
]
&
OCR_VOLTAGE_MASK
))
|
(
cmd
.
response
[
0
]
&
OCR_ACCESS_MODE
));
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
...
...
@@ -333,6 +464,18 @@ int mmc_send_op_cond(struct mmc *mmc)
if
(
timeout
<=
0
)
return
UNUSABLE_ERR
;
if
(
mmc_host_is_spi
(
mmc
))
{
/* read OCR for spi */
cmd
.
cmdidx
=
MMC_CMD_SPI_READ_OCR
;
cmd
.
resp_type
=
MMC_RSP_R3
;
cmd
.
cmdarg
=
0
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
}
mmc
->
version
=
MMC_VERSION_UNKNOWN
;
mmc
->
ocr
=
cmd
.
response
[
0
];
...
...
@@ -369,15 +512,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
int
mmc_switch
(
struct
mmc
*
mmc
,
u8
set
,
u8
index
,
u8
value
)
{
struct
mmc_cmd
cmd
;
int
timeout
=
1000
;
int
ret
;
cmd
.
cmdidx
=
MMC_CMD_SWITCH
;
cmd
.
resp_type
=
MMC_RSP_R1b
;
cmd
.
cmdarg
=
(
MMC_SWITCH_MODE_WRITE_BYTE
<<
24
)
|
(
index
<<
16
)
|
(
value
<<
8
);
(
index
<<
16
)
|
(
value
<<
8
);
cmd
.
flags
=
0
;
return
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
ret
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
/* Waiting for the ready status */
mmc_send_status
(
mmc
,
timeout
);
return
ret
;
}
int
mmc_change_freq
(
struct
mmc
*
mmc
)
...
...
@@ -388,6 +539,9 @@ int mmc_change_freq(struct mmc *mmc)
mmc
->
card_caps
=
0
;
if
(
mmc_host_is_spi
(
mmc
))
return
0
;
/* Only version 4 supports high-speed */
if
(
mmc
->
version
<
MMC_VERSION_4
)
return
0
;
...
...
@@ -399,9 +553,6 @@ int mmc_change_freq(struct mmc *mmc)
if
(
err
)
return
err
;
if
(
ext_csd
[
212
]
||
ext_csd
[
213
]
||
ext_csd
[
214
]
||
ext_csd
[
215
])
mmc
->
high_capacity
=
1
;
cardtype
=
ext_csd
[
196
]
&
0xf
;
err
=
mmc_switch
(
mmc
,
EXT_CSD_CMD_SET_NORMAL
,
EXT_CSD_HS_TIMING
,
1
);
...
...
@@ -461,6 +612,9 @@ int sd_change_freq(struct mmc *mmc)
mmc
->
card_caps
=
0
;
if
(
mmc_host_is_spi
(
mmc
))
return
0
;
/* Read the SCR to find out if this card supports higher speeds */
cmd
.
cmdidx
=
MMC_CMD_APP_CMD
;
cmd
.
resp_type
=
MMC_RSP_R1
;
...
...
@@ -512,6 +666,9 @@ retry_scr:
break
;
}
if
(
mmc
->
scr
[
0
]
&
SD_DATA_4BIT
)
mmc
->
card_caps
|=
MMC_MODE_4BIT
;
/* Version 1.0 doesn't support switching */
if
(
mmc
->
version
==
SD_VERSION_1_0
)
return
0
;
...
...
@@ -529,9 +686,6 @@ retry_scr:
break
;
}
if
(
mmc
->
scr
[
0
]
&
SD_DATA_4BIT
)
mmc
->
card_caps
|=
MMC_MODE_4BIT
;
/* If high-speed isn't supported, we return */
if
(
!
(
__be32_to_cpu
(
switch_status
[
3
])
&
SD_HIGHSPEED_SUPPORTED
))
return
0
;
...
...
@@ -549,7 +703,7 @@ retry_scr:
/* frequency bases */
/* divided by 10 to be nice to platforms without floating point */
int
fbase
[]
=
{
static
const
int
fbase
[]
=
{
10000
,
100000
,
1000000
,
...
...
@@ -559,7 +713,7 @@ int fbase[] = {
/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
* to platforms without floating point.
*/
int
multipliers
[]
=
{
static
const
int
multipliers
[]
=
{
0
,
/* reserved */
10
,
12
,
...
...
@@ -610,9 +764,24 @@ int mmc_startup(struct mmc *mmc)
u64
cmult
,
csize
;
struct
mmc_cmd
cmd
;
char
ext_csd
[
512
];
int
timeout
=
1000
;
#ifdef CONFIG_MMC_SPI_CRC_ON
if
(
mmc_host_is_spi
(
mmc
))
{
/* enable CRC check for spi */
cmd
.
cmdidx
=
MMC_CMD_SPI_CRC_ON_OFF
;
cmd
.
resp_type
=
MMC_RSP_R1
;
cmd
.
cmdarg
=
1
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
}
#endif
/* Put the Card in Identify Mode */
cmd
.
cmdidx
=
MMC_CMD_ALL_SEND_CID
;
cmd
.
cmdidx
=
mmc_host_is_spi
(
mmc
)
?
MMC_CMD_SEND_CID
:
MMC_CMD_ALL_SEND_CID
;
/* cmd not supported in spi */
cmd
.
resp_type
=
MMC_RSP_R2
;
cmd
.
cmdarg
=
0
;
cmd
.
flags
=
0
;
...
...
@@ -629,18 +798,20 @@ int mmc_startup(struct mmc *mmc)
* For SD cards, get the Relatvie Address.
* This also puts the cards into Standby State
*/
cmd
.
cmdidx
=
SD_CMD_SEND_RELATIVE_ADDR
;
cmd
.
cmdarg
=
mmc
->
rca
<<
16
;
cmd
.
resp_type
=
MMC_RSP_R6
;
cmd
.
flags
=
0
;
if
(
!
mmc_host_is_spi
(
mmc
))
{
/* cmd not supported in spi */
cmd
.
cmdidx
=
SD_CMD_SEND_RELATIVE_ADDR
;
cmd
.
cmdarg
=
mmc
->
rca
<<
16
;
cmd
.
resp_type
=
MMC_RSP_R6
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
if
(
err
)
return
err
;
if
(
IS_SD
(
mmc
))
mmc
->
rca
=
(
cmd
.
response
[
0
]
>>
16
)
&
0xffff
;
if
(
IS_SD
(
mmc
))
mmc
->
rca
=
(
cmd
.
response
[
0
]
>>
16
)
&
0xffff
;
}
/* Get the Card-Specific Data */
cmd
.
cmdidx
=
MMC_CMD_SEND_CSD
;
...
...
@@ -650,6 +821,9 @@ int mmc_startup(struct mmc *mmc)
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
/* Waiting for the ready status */
mmc_send_status
(
mmc
,
timeout
);
if
(
err
)
return
err
;
...
...
@@ -716,14 +890,16 @@ int mmc_startup(struct mmc *mmc)
mmc
->
write_bl_len
=
512
;
/* Select the card, and put it into Transfer Mode */
cmd
.
cmdidx
=
MMC_CMD_SELECT_CARD
;
cmd
.
resp_type
=
MMC_RSP_R1b
;
cmd
.
cmdarg
=
mmc
->
rca
<<
16
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
!
mmc_host_is_spi
(
mmc
))
{
/* cmd not supported in spi */
cmd
.
cmdidx
=
MMC_CMD_SELECT_CARD
;
cmd
.
resp_type
=
MMC_RSP_R1b
;
cmd
.
cmdarg
=
mmc
->
rca
<<
16
;
cmd
.
flags
=
0
;
err
=
mmc_send_cmd
(
mmc
,
&
cmd
,
NULL
);
if
(
err
)
return
err
;
if
(
err
)
return
err
;
}
if
(
!
IS_SD
(
mmc
)
&&
(
mmc
->
version
>=
MMC_VERSION_4
))
{
/* check ext_csd version and capacity */
...
...
drivers/mmc/mmc_spi.c
0 → 100644
浏览文件 @
4f27f0ab
/*
* generic mmc spi driver
*
* Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <malloc.h>
#include <part.h>
#include <mmc.h>
#include <spi.h>
#include <crc.h>
#include <linux/crc7.h>
#include <linux/byteorder/swab.h>
/* MMC/SD in SPI mode reports R1 status always */
#define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
#define R1_SPI_COM_CRC (1 << 3)
#define R1_SPI_ERASE_SEQ (1 << 4)
#define R1_SPI_ADDRESS (1 << 5)
#define R1_SPI_PARAMETER (1 << 6)
/* R1 bit 7 is always zero, reuse this bit for error */
#define R1_SPI_ERROR (1 << 7)
/* Response tokens used to ack each block written: */
#define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f)
#define SPI_RESPONSE_ACCEPTED ((2 << 1)|1)
#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
/* Read and write blocks start with these tokens and end with crc;
* on error, read tokens act like a subset of R2_SPI_* values.
*/
#define SPI_TOKEN_SINGLE 0xfe
/* single block r/w, multiblock read */
#define SPI_TOKEN_MULTI_WRITE 0xfc
/* multiblock write */
#define SPI_TOKEN_STOP_TRAN 0xfd
/* terminate multiblock write */
/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
#define MMC_SPI_CMD(x) (0x40 | (x & 0x3f))
/* bus capability */
#define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
#define MMC_SPI_MIN_CLOCK 400000
/* 400KHz to meet MMC spec */
/* timeout value */
#define CTOUT 8
#define RTOUT 3000000
/* 1 sec */
#define WTOUT 3000000
/* 1 sec */
static
uint
mmc_spi_sendcmd
(
struct
mmc
*
mmc
,
ushort
cmdidx
,
u32
cmdarg
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
u8
cmdo
[
7
];
u8
r1
;
int
i
;
cmdo
[
0
]
=
0xff
;
cmdo
[
1
]
=
MMC_SPI_CMD
(
cmdidx
);
cmdo
[
2
]
=
cmdarg
>>
24
;
cmdo
[
3
]
=
cmdarg
>>
16
;
cmdo
[
4
]
=
cmdarg
>>
8
;
cmdo
[
5
]
=
cmdarg
;
cmdo
[
6
]
=
(
crc7
(
0
,
&
cmdo
[
1
],
5
)
<<
1
)
|
0x01
;
spi_xfer
(
spi
,
sizeof
(
cmdo
)
*
8
,
cmdo
,
NULL
,
0
);
for
(
i
=
0
;
i
<
CTOUT
;
i
++
)
{
spi_xfer
(
spi
,
1
*
8
,
NULL
,
&
r1
,
0
);
if
(
i
&&
(
r1
&
0x80
)
==
0
)
/* r1 response */
break
;
}
debug
(
"%s:cmd%d resp%d %x
\n
"
,
__func__
,
cmdidx
,
i
,
r1
);
return
r1
;
}
static
uint
mmc_spi_readdata
(
struct
mmc
*
mmc
,
void
*
xbuf
,
u32
bcnt
,
u32
bsize
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
u8
*
buf
=
xbuf
;
u8
r1
;
u16
crc
;
int
i
;
while
(
bcnt
--
)
{
for
(
i
=
0
;
i
<
RTOUT
;
i
++
)
{
spi_xfer
(
spi
,
1
*
8
,
NULL
,
&
r1
,
0
);
if
(
r1
!=
0xff
)
/* data token */
break
;
}
debug
(
"%s:tok%d %x
\n
"
,
__func__
,
i
,
r1
);
if
(
r1
==
SPI_TOKEN_SINGLE
)
{
spi_xfer
(
spi
,
bsize
*
8
,
NULL
,
buf
,
0
);
spi_xfer
(
spi
,
2
*
8
,
NULL
,
&
crc
,
0
);
#ifdef CONFIG_MMC_SPI_CRC_ON
if
(
swab16
(
cyg_crc16
(
buf
,
bsize
))
!=
crc
)
{
debug
(
"%s: CRC error
\n
"
,
mmc
->
name
);
r1
=
R1_SPI_COM_CRC
;
break
;
}
#endif
r1
=
0
;
}
else
{
r1
=
R1_SPI_ERROR
;
break
;
}
buf
+=
bsize
;
}
return
r1
;
}
static
uint
mmc_spi_writedata
(
struct
mmc
*
mmc
,
const
void
*
xbuf
,
u32
bcnt
,
u32
bsize
,
int
multi
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
const
u8
*
buf
=
xbuf
;
u8
r1
;
u16
crc
;
u8
tok
[
2
];
int
i
;
tok
[
0
]
=
0xff
;
tok
[
1
]
=
multi
?
SPI_TOKEN_MULTI_WRITE
:
SPI_TOKEN_SINGLE
;
while
(
bcnt
--
)
{
#ifdef CONFIG_MMC_SPI_CRC_ON
crc
=
swab16
(
cyg_crc16
((
u8
*
)
buf
,
bsize
));
#endif
spi_xfer
(
spi
,
2
*
8
,
tok
,
NULL
,
0
);
spi_xfer
(
spi
,
bsize
*
8
,
buf
,
NULL
,
0
);
spi_xfer
(
spi
,
2
*
8
,
&
crc
,
NULL
,
0
);
for
(
i
=
0
;
i
<
CTOUT
;
i
++
)
{
spi_xfer
(
spi
,
1
*
8
,
NULL
,
&
r1
,
0
);
if
((
r1
&
0x10
)
==
0
)
/* response token */
break
;
}
debug
(
"%s:tok%d %x
\n
"
,
__func__
,
i
,
r1
);
if
(
SPI_MMC_RESPONSE_CODE
(
r1
)
==
SPI_RESPONSE_ACCEPTED
)
{
for
(
i
=
0
;
i
<
WTOUT
;
i
++
)
{
/* wait busy */
spi_xfer
(
spi
,
1
*
8
,
NULL
,
&
r1
,
0
);
if
(
i
&&
r1
==
0xff
)
{
r1
=
0
;
break
;
}
}
if
(
i
==
WTOUT
)
{
debug
(
"%s:wtout %x
\n
"
,
__func__
,
r1
);
r1
=
R1_SPI_ERROR
;
break
;
}
}
else
{
debug
(
"%s: err %x
\n
"
,
__func__
,
r1
);
r1
=
R1_SPI_COM_CRC
;
break
;
}
buf
+=
bsize
;
}
if
(
multi
&&
bcnt
==
-
1
)
{
/* stop multi write */
tok
[
1
]
=
SPI_TOKEN_STOP_TRAN
;
spi_xfer
(
spi
,
2
*
8
,
tok
,
NULL
,
0
);
for
(
i
=
0
;
i
<
WTOUT
;
i
++
)
{
/* wait busy */
spi_xfer
(
spi
,
1
*
8
,
NULL
,
&
r1
,
0
);
if
(
i
&&
r1
==
0xff
)
{
r1
=
0
;
break
;
}
}
if
(
i
==
WTOUT
)
{
debug
(
"%s:wstop %x
\n
"
,
__func__
,
r1
);
r1
=
R1_SPI_ERROR
;
}
}
return
r1
;
}
static
int
mmc_spi_request
(
struct
mmc
*
mmc
,
struct
mmc_cmd
*
cmd
,
struct
mmc_data
*
data
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
u8
r1
;
int
i
;
int
ret
=
0
;
debug
(
"%s:cmd%d %x %x %x
\n
"
,
__func__
,
cmd
->
cmdidx
,
cmd
->
resp_type
,
cmd
->
cmdarg
,
cmd
->
flags
);
spi_claim_bus
(
spi
);
spi_cs_activate
(
spi
);
r1
=
mmc_spi_sendcmd
(
mmc
,
cmd
->
cmdidx
,
cmd
->
cmdarg
);
if
(
r1
==
0xff
)
{
/* no response */
ret
=
NO_CARD_ERR
;
goto
done
;
}
else
if
(
r1
&
R1_SPI_COM_CRC
)
{
ret
=
COMM_ERR
;
goto
done
;
}
else
if
(
r1
&
~
R1_SPI_IDLE
)
{
/* other errors */
ret
=
TIMEOUT
;
goto
done
;
}
else
if
(
cmd
->
resp_type
==
MMC_RSP_R2
)
{
r1
=
mmc_spi_readdata
(
mmc
,
cmd
->
response
,
1
,
16
);
for
(
i
=
0
;
i
<
4
;
i
++
)
cmd
->
response
[
i
]
=
swab32
(
cmd
->
response
[
i
]);
debug
(
"r128 %x %x %x %x
\n
"
,
cmd
->
response
[
0
],
cmd
->
response
[
1
],
cmd
->
response
[
2
],
cmd
->
response
[
3
]);
}
else
if
(
!
data
)
{
switch
(
cmd
->
cmdidx
)
{
case
SD_CMD_APP_SEND_OP_COND
:
case
MMC_CMD_SEND_OP_COND
:
cmd
->
response
[
0
]
=
(
r1
&
R1_SPI_IDLE
)
?
0
:
OCR_BUSY
;
break
;
case
SD_CMD_SEND_IF_COND
:
case
MMC_CMD_SPI_READ_OCR
:
spi_xfer
(
spi
,
4
*
8
,
NULL
,
cmd
->
response
,
0
);
cmd
->
response
[
0
]
=
swab32
(
cmd
->
response
[
0
]);
debug
(
"r32 %x
\n
"
,
cmd
->
response
[
0
]);
break
;
}
}
else
{
debug
(
"%s:data %x %x %x
\n
"
,
__func__
,
data
->
flags
,
data
->
blocks
,
data
->
blocksize
);
if
(
data
->
flags
==
MMC_DATA_READ
)
r1
=
mmc_spi_readdata
(
mmc
,
data
->
dest
,
data
->
blocks
,
data
->
blocksize
);
else
if
(
data
->
flags
==
MMC_DATA_WRITE
)
r1
=
mmc_spi_writedata
(
mmc
,
data
->
src
,
data
->
blocks
,
data
->
blocksize
,
(
cmd
->
cmdidx
==
MMC_CMD_WRITE_MULTIPLE_BLOCK
));
if
(
r1
&
R1_SPI_COM_CRC
)
ret
=
COMM_ERR
;
else
if
(
r1
)
/* other errors */
ret
=
TIMEOUT
;
}
done:
spi_cs_deactivate
(
spi
);
spi_release_bus
(
spi
);
return
ret
;
}
static
void
mmc_spi_set_ios
(
struct
mmc
*
mmc
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
debug
(
"%s: clock %u
\n
"
,
__func__
,
mmc
->
clock
);
if
(
mmc
->
clock
)
spi_set_speed
(
spi
,
mmc
->
clock
);
}
static
int
mmc_spi_init_p
(
struct
mmc
*
mmc
)
{
struct
spi_slave
*
spi
=
mmc
->
priv
;
mmc
->
clock
=
0
;
spi_set_speed
(
spi
,
MMC_SPI_MIN_CLOCK
);
spi_claim_bus
(
spi
);
/* cs deactivated for 100+ clock */
spi_xfer
(
spi
,
18
*
8
,
NULL
,
NULL
,
0
);
spi_release_bus
(
spi
);
return
0
;
}
struct
mmc
*
mmc_spi_init
(
uint
bus
,
uint
cs
,
uint
speed
,
uint
mode
)
{
struct
mmc
*
mmc
;
mmc
=
malloc
(
sizeof
(
*
mmc
));
if
(
!
mmc
)
return
NULL
;
memset
(
mmc
,
0
,
sizeof
(
*
mmc
));
mmc
->
priv
=
spi_setup_slave
(
bus
,
cs
,
speed
,
mode
);
if
(
!
mmc
->
priv
)
{
free
(
mmc
);
return
NULL
;
}
sprintf
(
mmc
->
name
,
"MMC_SPI"
);
mmc
->
send_cmd
=
mmc_spi_request
;
mmc
->
set_ios
=
mmc_spi_set_ios
;
mmc
->
init
=
mmc_spi_init_p
;
mmc
->
host_caps
=
MMC_MODE_SPI
;
mmc
->
voltages
=
MMC_SPI_VOLTAGE
;
mmc
->
f_max
=
speed
;
mmc
->
f_min
=
MMC_SPI_MIN_CLOCK
;
mmc
->
block_dev
.
part_type
=
PART_TYPE_DOS
;
mmc_register
(
mmc
);
return
mmc
;
}
drivers/spi/cf_spi.c
浏览文件 @
4f27f0ab
...
...
@@ -49,6 +49,14 @@ extern void cfspi_release_bus(uint bus, uint cs);
DECLARE_GLOBAL_DATA_PTR
;
#ifndef CONFIG_SPI_IDLE_VAL
#if defined(CONFIG_SPI_MMC)
#define CONFIG_SPI_IDLE_VAL 0xFFFF
#else
#define CONFIG_SPI_IDLE_VAL 0x0
#endif
#endif
#if defined(CONFIG_CF_DSPI)
/* DSPI specific mode */
#define SPI_MODE_MOD 0x00200000
...
...
@@ -145,7 +153,7 @@ int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
}
if
(
din
!=
NULL
)
{
cfspi_tx
(
ctrl
,
0
);
cfspi_tx
(
ctrl
,
CONFIG_SPI_IDLE_VAL
);
if
(
cfslave
->
charbit
==
16
)
*
spi_rd16
++
=
cfspi_rx
();
else
...
...
@@ -169,7 +177,7 @@ int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
}
if
(
din
!=
NULL
)
{
cfspi_tx
(
ctrl
,
0
);
cfspi_tx
(
ctrl
,
CONFIG_SPI_IDLE_VAL
);
if
(
cfslave
->
charbit
==
16
)
*
spi_rd16
=
cfspi_rx
();
else
...
...
@@ -177,7 +185,7 @@ int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
}
}
else
{
/* dummy read */
cfspi_tx
(
ctrl
,
0
);
cfspi_tx
(
ctrl
,
CONFIG_SPI_IDLE_VAL
);
cfspi_rx
();
}
...
...
include/mmc.h
浏览文件 @
4f27f0ab
...
...
@@ -44,6 +44,7 @@
#define MMC_MODE_HS_52MHz 0x010
#define MMC_MODE_4BIT 0x100
#define MMC_MODE_8BIT 0x200
#define MMC_MODE_SPI 0x400
#define SD_DATA_4BIT 0x00040000
...
...
@@ -75,6 +76,8 @@
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
#define MMC_CMD_APP_CMD 55
#define MMC_CMD_SPI_READ_OCR 58
#define MMC_CMD_SPI_CRC_ON_OFF 59
#define SD_CMD_SEND_RELATIVE_ADDR 3
#define SD_CMD_SWITCH_FUNC 6
...
...
@@ -93,6 +96,12 @@
#define OCR_BUSY 0x80000000
#define OCR_HCS 0x40000000
#define OCR_VOLTAGE_MASK 0x007FFF80
#define OCR_ACCESS_MODE 0x60000000
#define MMC_STATUS_MASK (~0x0206BF7F)
#define MMC_STATUS_RDY_FOR_DATA (1<<8)
#define MMC_STATUS_CURR_STATE (0xf<<9)
#define MMC_VDD_165_195 0x00000080
/* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100
/* VDD voltage 2.0 ~ 2.1 */
...
...
@@ -291,6 +300,8 @@ int board_mmc_getcd(u8 *cd, struct mmc *mmc);
#ifdef CONFIG_GENERIC_MMC
int
atmel_mci_init
(
void
*
regs
);
#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
struct
mmc
*
mmc_spi_init
(
uint
bus
,
uint
cs
,
uint
speed
,
uint
mode
);
#else
int
mmc_legacy_init
(
int
verbose
);
#endif
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录