Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
rt-thread
提交
41597e87
R
rt-thread
项目概览
BaiXuePrincess
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
41597e87
编写于
6月 20, 2015
作者:
W
weety
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add mmc and emmc drivers.
上级
562ac32e
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
834 addition
and
26 deletion
+834
-26
components/drivers/include/drivers/mmc.h
components/drivers/include/drivers/mmc.h
+206
-0
components/drivers/include/drivers/mmcsd_card.h
components/drivers/include/drivers/mmcsd_card.h
+1
-0
components/drivers/sdio/SConscript
components/drivers/sdio/SConscript
+1
-0
components/drivers/sdio/block_dev.c
components/drivers/sdio/block_dev.c
+3
-10
components/drivers/sdio/mmc.c
components/drivers/sdio/mmc.c
+586
-0
components/drivers/sdio/mmcsd_core.c
components/drivers/sdio/mmcsd_core.c
+37
-16
未找到文件。
components/drivers/include/drivers/mmc.h
0 → 100644
浏览文件 @
41597e87
/*
* File : mmc.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2015-06-15 hichard first version
*/
#ifndef __MMC_H__
#define __MMC_H__
#include <rtthread.h>
#include <drivers/mmcsd_host.h>
#ifdef __cplusplus
extern
"C"
{
#endif
/*
* EXT_CSD fields
*/
#define EXT_CSD_FLUSH_CACHE 32
/* W */
#define EXT_CSD_CACHE_CTRL 33
/* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34
/* R/W */
#define EXT_CSD_PACKED_FAILURE_INDEX 35
/* RO */
#define EXT_CSD_PACKED_CMD_STATUS 36
/* RO */
#define EXT_CSD_EXP_EVENTS_STATUS 54
/* RO, 2 bytes */
#define EXT_CSD_EXP_EVENTS_CTRL 56
/* R/W, 2 bytes */
#define EXT_CSD_DATA_SECTOR_SIZE 61
/* R */
#define EXT_CSD_GP_SIZE_MULT 143
/* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156
/* R/W */
#define EXT_CSD_PARTITION_SUPPORT 160
/* RO */
#define EXT_CSD_HPI_MGMT 161
/* R/W */
#define EXT_CSD_RST_N_FUNCTION 162
/* R/W */
#define EXT_CSD_BKOPS_EN 163
/* R/W */
#define EXT_CSD_BKOPS_START 164
/* W */
#define EXT_CSD_SANITIZE_START 165
/* W */
#define EXT_CSD_WR_REL_PARAM 166
/* RO */
#define EXT_CSD_RPMB_MULT 168
/* RO */
#define EXT_CSD_BOOT_WP 173
/* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175
/* R/W */
#define EXT_CSD_PART_CONFIG 179
/* R/W */
#define EXT_CSD_ERASED_MEM_CONT 181
/* RO */
#define EXT_CSD_BUS_WIDTH 183
/* R/W */
#define EXT_CSD_HS_TIMING 185
/* R/W */
#define EXT_CSD_POWER_CLASS 187
/* R/W */
#define EXT_CSD_REV 192
/* RO */
#define EXT_CSD_STRUCTURE 194
/* RO */
#define EXT_CSD_CARD_TYPE 196
/* RO */
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198
/* RO */
#define EXT_CSD_PART_SWITCH_TIME 199
/* RO */
#define EXT_CSD_PWR_CL_52_195 200
/* RO */
#define EXT_CSD_PWR_CL_26_195 201
/* RO */
#define EXT_CSD_PWR_CL_52_360 202
/* RO */
#define EXT_CSD_PWR_CL_26_360 203
/* RO */
#define EXT_CSD_SEC_CNT 212
/* RO, 4 bytes */
#define EXT_CSD_S_A_TIMEOUT 217
/* RO */
#define EXT_CSD_REL_WR_SEC_C 222
/* RO */
#define EXT_CSD_HC_WP_GRP_SIZE 221
/* RO */
#define EXT_CSD_ERASE_TIMEOUT_MULT 223
/* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224
/* RO */
#define EXT_CSD_BOOT_MULT 226
/* RO */
#define EXT_CSD_SEC_TRIM_MULT 229
/* RO */
#define EXT_CSD_SEC_ERASE_MULT 230
/* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT 231
/* RO */
#define EXT_CSD_TRIM_MULT 232
/* RO */
#define EXT_CSD_PWR_CL_200_195 236
/* RO */
#define EXT_CSD_PWR_CL_200_360 237
/* RO */
#define EXT_CSD_PWR_CL_DDR_52_195 238
/* RO */
#define EXT_CSD_PWR_CL_DDR_52_360 239
/* RO */
#define EXT_CSD_BKOPS_STATUS 246
/* RO */
#define EXT_CSD_POWER_OFF_LONG_TIME 247
/* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248
/* RO */
#define EXT_CSD_CACHE_SIZE 249
/* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253
/* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498
/* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499
/* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500
/* RO */
#define EXT_CSD_MAX_PACKED_READS 501
/* RO */
#define EXT_CSD_BKOPS_SUPPORT 502
/* RO */
#define EXT_CSD_HPI_FEATURES 503
/* RO */
/*
* EXT_CSD field definitions
*/
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
#define EXT_CSD_CMD_SET_SECURE (1<<1)
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0)
/* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1)
/* Card can run at 52MHz */
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
EXT_CSD_CARD_TYPE_HS_52)
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2)
/* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3)
/* Card can run at 52MHz */
/* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
| EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4)
/* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5)
/* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6)
/* Card can run at 200MHz DDR, 1.8V */
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7)
/* Card can run at 200MHz DDR, 1.2V */
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0
/* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1
/* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2
/* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4 5
/* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6
/* Card is in 8 bit DDR mode */
#define EXT_CSD_TIMING_BC 0
/* Backwards compatility */
#define EXT_CSD_TIMING_HS 1
/* High speed */
#define EXT_CSD_TIMING_HS200 2
/* HS200 */
#define EXT_CSD_TIMING_HS400 3
/* HS400 */
#define EXT_CSD_SEC_ER_EN BIT(0)
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
#define EXT_CSD_SEC_SANITIZE BIT(6)
/* v4.5 only */
#define EXT_CSD_RST_N_EN_MASK 0x3
#define EXT_CSD_RST_N_ENABLED 1
/* RST_n is enabled on card */
#define EXT_CSD_NO_POWER_NOTIFICATION 0
#define EXT_CSD_POWER_ON 1
#define EXT_CSD_POWER_OFF_SHORT 2
#define EXT_CSD_POWER_OFF_LONG 3
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0
/* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F
/* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
/*
* EXCEPTION_EVENT_STATUS field
*/
#define EXT_CSD_URGENT_BKOPS BIT(0)
#define EXT_CSD_DYNCAP_NEEDED BIT(1)
#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2)
#define EXT_CSD_PACKED_FAILURE BIT(3)
#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0)
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
/*
* BKOPS status level
*/
#define EXT_CSD_BKOPS_LEVEL_2 0x2
/*
* MMC_SWITCH access modes
*/
#define MMC_SWITCH_MODE_CMD_SET 0x00
/* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01
/* Set bits which are 1 in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02
/* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03
/* Set target to value */
/*
* extern function
*/
rt_err_t
mmc_send_op_cond
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
ocr
,
rt_uint32_t
*
rocr
);
rt_int32_t
init_mmc
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
ocr
);
#ifdef __cplusplus
}
#endif
#endif
components/drivers/include/drivers/mmcsd_card.h
浏览文件 @
41597e87
...
...
@@ -153,6 +153,7 @@ struct rt_mmcsd_card {
rt_uint32_t
max_data_rate
;
/* max data transfer rate */
rt_uint32_t
card_capacity
;
/* card capacity, unit:KB */
rt_uint32_t
card_blksize
;
/* card block size */
rt_uint32_t
erase_size
;
/* erase size in sectors */
rt_uint16_t
card_type
;
#define CARD_TYPE_MMC 0
/* MMC card */
#define CARD_TYPE_SD 1
/* SD card */
...
...
components/drivers/sdio/SConscript
浏览文件 @
41597e87
...
...
@@ -7,6 +7,7 @@ block_dev.c
mmcsd_core.c
sd.c
sdio.c
mmc.c
"""
)
# The set of source files associated with this SConscript file.
...
...
components/drivers/sdio/block_dev.c
浏览文件 @
41597e87
...
...
@@ -149,7 +149,7 @@ static rt_err_t rt_mmcsd_req_blk(struct rt_mmcsd_card *card,
}
else
{
req
.
stop
=
NULL
;
req
.
stop
=
RT_
NULL
;
r_cmd
=
READ_SINGLE_BLOCK
;
w_cmd
=
WRITE_BLOCK
;
}
...
...
@@ -408,15 +408,8 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
blk_dev
->
geometry
.
bytes_per_sector
=
1
<<
9
;
blk_dev
->
geometry
.
block_size
=
card
->
card_blksize
;
if
(
card
->
flags
&
CARD_FLAG_SDHC
)
{
blk_dev
->
geometry
.
sector_count
=
(
card
->
csd
.
c_size
+
1
)
*
1024
;
}
else
{
blk_dev
->
geometry
.
sector_count
=
card
->
card_capacity
*
1024
/
512
;
}
blk_dev
->
geometry
.
sector_count
=
card
->
card_capacity
*
(
1024
/
512
);
rt_device_register
(
&
blk_dev
->
dev
,
"sd0"
,
RT_DEVICE_FLAG_RDWR
|
RT_DEVICE_FLAG_REMOVABLE
|
RT_DEVICE_FLAG_STANDALONE
);
...
...
components/drivers/sdio/mmc.c
0 → 100644
浏览文件 @
41597e87
/*
* File : mmc.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2015-06-15 hichard first version
*/
#include <drivers/mmcsd_core.h>
#include <drivers/mmc.h>
static
const
rt_uint32_t
tran_unit
[]
=
{
10000
,
100000
,
1000000
,
10000000
,
0
,
0
,
0
,
0
};
static
const
rt_uint8_t
tran_value
[]
=
{
0
,
10
,
12
,
13
,
15
,
20
,
25
,
30
,
35
,
40
,
45
,
50
,
55
,
60
,
70
,
80
,
};
static
const
rt_uint32_t
tacc_uint
[]
=
{
1
,
10
,
100
,
1000
,
10000
,
100000
,
1000000
,
10000000
,
};
static
const
rt_uint8_t
tacc_value
[]
=
{
0
,
10
,
12
,
13
,
15
,
20
,
25
,
30
,
35
,
40
,
45
,
50
,
55
,
60
,
70
,
80
,
};
rt_inline
rt_uint32_t
GET_BITS
(
rt_uint32_t
*
resp
,
rt_uint32_t
start
,
rt_uint32_t
size
)
{
const
rt_int32_t
__size
=
size
;
const
rt_uint32_t
__mask
=
(
__size
<
32
?
1
<<
__size
:
0
)
-
1
;
const
rt_int32_t
__off
=
3
-
((
start
)
/
32
);
const
rt_int32_t
__shft
=
(
start
)
&
31
;
rt_uint32_t
__res
;
__res
=
resp
[
__off
]
>>
__shft
;
if
(
__size
+
__shft
>
32
)
__res
|=
resp
[
__off
-
1
]
<<
((
32
-
__shft
)
%
32
);
return
__res
&
__mask
;
}
/*
* Given a 128-bit response, decode to our card CSD structure.
*/
static
rt_int32_t
mmcsd_parse_csd
(
struct
rt_mmcsd_card
*
card
)
{
rt_uint32_t
a
,
b
;
struct
rt_mmcsd_csd
*
csd
=
&
card
->
csd
;
rt_uint32_t
*
resp
=
card
->
resp_csd
;
/*
* We only understand CSD structure v1.1 and v1.2.
* v1.2 has extra information in bits 15, 11 and 10.
* We also support eMMC v4.4 & v4.41.
*/
csd
->
csd_structure
=
GET_BITS
(
resp
,
126
,
2
);
if
(
csd
->
csd_structure
==
0
)
{
rt_kprintf
(
"unrecognised CSD structure version %d
\n
"
,
csd
->
csd_structure
);
return
-
RT_ERROR
;
}
csd
->
taac
=
GET_BITS
(
resp
,
112
,
8
);
csd
->
nsac
=
GET_BITS
(
resp
,
104
,
8
);
csd
->
tran_speed
=
GET_BITS
(
resp
,
96
,
8
);
csd
->
card_cmd_class
=
GET_BITS
(
resp
,
84
,
12
);
csd
->
rd_blk_len
=
GET_BITS
(
resp
,
80
,
4
);
csd
->
rd_blk_part
=
GET_BITS
(
resp
,
79
,
1
);
csd
->
wr_blk_misalign
=
GET_BITS
(
resp
,
78
,
1
);
csd
->
rd_blk_misalign
=
GET_BITS
(
resp
,
77
,
1
);
csd
->
dsr_imp
=
GET_BITS
(
resp
,
76
,
1
);
csd
->
c_size
=
GET_BITS
(
resp
,
62
,
12
);
csd
->
c_size_mult
=
GET_BITS
(
resp
,
47
,
3
);
csd
->
r2w_factor
=
GET_BITS
(
resp
,
26
,
3
);
csd
->
wr_blk_len
=
GET_BITS
(
resp
,
22
,
4
);
csd
->
wr_blk_partial
=
GET_BITS
(
resp
,
21
,
1
);
csd
->
csd_crc
=
GET_BITS
(
resp
,
1
,
7
);
card
->
card_blksize
=
1
<<
csd
->
rd_blk_len
;
card
->
tacc_clks
=
csd
->
nsac
*
100
;
card
->
tacc_ns
=
(
tacc_uint
[
csd
->
taac
&
0x07
]
*
tacc_value
[(
csd
->
taac
&
0x78
)
>>
3
]
+
9
)
/
10
;
card
->
max_data_rate
=
tran_unit
[
csd
->
tran_speed
&
0x07
]
*
tran_value
[(
csd
->
tran_speed
&
0x78
)
>>
3
];
if
(
csd
->
wr_blk_len
>=
9
)
{
a
=
GET_BITS
(
resp
,
42
,
5
);
b
=
GET_BITS
(
resp
,
37
,
5
);
card
->
erase_size
=
(
a
+
1
)
*
(
b
+
1
);
card
->
erase_size
<<=
csd
->
wr_blk_len
-
9
;
}
return
0
;
}
/*
* Read extended CSD.
*/
static
int
mmc_get_ext_csd
(
struct
rt_mmcsd_card
*
card
,
rt_uint8_t
**
new_ext_csd
)
{
void
*
ext_csd
;
struct
rt_mmcsd_req
req
;
struct
rt_mmcsd_cmd
cmd
;
struct
rt_mmcsd_data
data
;
*
new_ext_csd
=
RT_NULL
;
if
(
GET_BITS
(
card
->
resp_cid
,
122
,
4
)
<
4
)
return
0
;
/*
* As the ext_csd is so large and mostly unused, we don't store the
* raw block in mmc_card.
*/
ext_csd
=
rt_malloc
(
512
);
if
(
!
ext_csd
)
{
rt_kprintf
(
"alloc memory failed when get ext csd
\n
"
);
return
-
RT_ENOMEM
;
}
rt_memset
(
&
req
,
0
,
sizeof
(
struct
rt_mmcsd_req
));
rt_memset
(
&
cmd
,
0
,
sizeof
(
struct
rt_mmcsd_cmd
));
rt_memset
(
&
data
,
0
,
sizeof
(
struct
rt_mmcsd_data
));
req
.
cmd
=
&
cmd
;
req
.
data
=
&
data
;
cmd
.
cmd_code
=
SEND_EXT_CSD
;
cmd
.
arg
=
0
;
/* NOTE HACK: the RESP_SPI_R1 is always correct here, but we
* rely on callers to never use this with "native" calls for reading
* CSD or CID. Native versions of those commands use the R2 type,
* not R1 plus a data block.
*/
cmd
.
flags
=
RESP_SPI_R1
|
RESP_R1
|
CMD_ADTC
;
data
.
blksize
=
512
;
data
.
blks
=
1
;
data
.
flags
=
DATA_DIR_READ
;
data
.
buf
=
ext_csd
;
/*
* Some cards require longer data read timeout than indicated in CSD.
* Address this by setting the read timeout to a "reasonably high"
* value. For the cards tested, 300ms has proven enough. If necessary,
* this value can be increased if other problematic cards require this.
*/
data
.
timeout_ns
=
300000000
;
data
.
timeout_clks
=
0
;
mmcsd_send_request
(
card
->
host
,
&
req
);
if
(
cmd
.
err
)
return
cmd
.
err
;
if
(
data
.
err
)
return
data
.
err
;
*
new_ext_csd
=
ext_csd
;
return
0
;
}
/*
* Decode extended CSD.
*/
static
int
mmc_parse_ext_csd
(
struct
rt_mmcsd_card
*
card
,
rt_uint8_t
*
ext_csd
)
{
card
->
flags
|=
CARD_FLAG_HIGHSPEED
;
card
->
hs_max_data_rate
=
200000000
;
card
->
card_capacity
=
*
((
rt_uint32_t
*
)
&
ext_csd
[
EXT_CSD_SEC_CNT
]);
card
->
card_capacity
*=
card
->
card_blksize
;
card
->
card_capacity
>>=
10
;
/* unit:KB */
rt_kprintf
(
"emmc card capacity %d KB
\n
"
,
card
->
card_capacity
);
return
0
;
}
/**
* mmc_switch - modify EXT_CSD register
* @card: the MMC card associated with the data transfer
* @set: cmd set values
* @index: EXT_CSD register index
* @value: value to program into EXT_CSD register
*
* Modifies the EXT_CSD register for selected card.
*/
static
int
mmc_switch
(
struct
rt_mmcsd_card
*
card
,
rt_uint8_t
set
,
rt_uint8_t
index
,
rt_uint8_t
value
)
{
int
err
;
struct
rt_mmcsd_host
*
host
=
card
->
host
;
struct
rt_mmcsd_cmd
cmd
=
{
0
};
cmd
.
cmd_code
=
SWITCH
;
cmd
.
arg
=
(
MMC_SWITCH_MODE_WRITE_BYTE
<<
24
)
|
(
index
<<
16
)
|
(
value
<<
8
)
|
set
;
cmd
.
flags
=
RESP_SPI_R1
|
RESP_R1
|
CMD_AC
;
err
=
mmcsd_send_cmd
(
host
,
&
cmd
,
3
);
if
(
err
)
return
err
;
return
0
;
}
static
int
mmc_compare_ext_csds
(
struct
rt_mmcsd_card
*
card
,
rt_uint8_t
*
ext_csd
,
rt_uint32_t
bus_width
)
{
rt_uint8_t
*
bw_ext_csd
;
int
err
;
if
(
bus_width
==
MMCSD_BUS_WIDTH_1
)
return
0
;
err
=
mmc_get_ext_csd
(
card
,
&
bw_ext_csd
);
if
(
err
||
bw_ext_csd
==
RT_NULL
)
{
err
=
-
RT_ERROR
;
goto
out
;
}
/* only compare read only fields */
err
=
!
((
ext_csd
[
EXT_CSD_PARTITION_SUPPORT
]
==
bw_ext_csd
[
EXT_CSD_PARTITION_SUPPORT
])
&&
(
ext_csd
[
EXT_CSD_ERASED_MEM_CONT
]
==
bw_ext_csd
[
EXT_CSD_ERASED_MEM_CONT
])
&&
(
ext_csd
[
EXT_CSD_REV
]
==
bw_ext_csd
[
EXT_CSD_REV
])
&&
(
ext_csd
[
EXT_CSD_STRUCTURE
]
==
bw_ext_csd
[
EXT_CSD_STRUCTURE
])
&&
(
ext_csd
[
EXT_CSD_CARD_TYPE
]
==
bw_ext_csd
[
EXT_CSD_CARD_TYPE
])
&&
(
ext_csd
[
EXT_CSD_S_A_TIMEOUT
]
==
bw_ext_csd
[
EXT_CSD_S_A_TIMEOUT
])
&&
(
ext_csd
[
EXT_CSD_HC_WP_GRP_SIZE
]
==
bw_ext_csd
[
EXT_CSD_HC_WP_GRP_SIZE
])
&&
(
ext_csd
[
EXT_CSD_ERASE_TIMEOUT_MULT
]
==
bw_ext_csd
[
EXT_CSD_ERASE_TIMEOUT_MULT
])
&&
(
ext_csd
[
EXT_CSD_HC_ERASE_GRP_SIZE
]
==
bw_ext_csd
[
EXT_CSD_HC_ERASE_GRP_SIZE
])
&&
(
ext_csd
[
EXT_CSD_SEC_TRIM_MULT
]
==
bw_ext_csd
[
EXT_CSD_SEC_TRIM_MULT
])
&&
(
ext_csd
[
EXT_CSD_SEC_ERASE_MULT
]
==
bw_ext_csd
[
EXT_CSD_SEC_ERASE_MULT
])
&&
(
ext_csd
[
EXT_CSD_SEC_FEATURE_SUPPORT
]
==
bw_ext_csd
[
EXT_CSD_SEC_FEATURE_SUPPORT
])
&&
(
ext_csd
[
EXT_CSD_TRIM_MULT
]
==
bw_ext_csd
[
EXT_CSD_TRIM_MULT
])
&&
(
ext_csd
[
EXT_CSD_SEC_CNT
+
0
]
==
bw_ext_csd
[
EXT_CSD_SEC_CNT
+
0
])
&&
(
ext_csd
[
EXT_CSD_SEC_CNT
+
1
]
==
bw_ext_csd
[
EXT_CSD_SEC_CNT
+
1
])
&&
(
ext_csd
[
EXT_CSD_SEC_CNT
+
2
]
==
bw_ext_csd
[
EXT_CSD_SEC_CNT
+
2
])
&&
(
ext_csd
[
EXT_CSD_SEC_CNT
+
3
]
==
bw_ext_csd
[
EXT_CSD_SEC_CNT
+
3
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_52_195
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_52_195
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_26_195
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_26_195
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_52_360
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_52_360
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_26_360
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_26_360
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_200_195
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_200_195
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_200_360
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_200_360
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_DDR_52_195
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_DDR_52_195
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_DDR_52_360
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_DDR_52_360
])
&&
(
ext_csd
[
EXT_CSD_PWR_CL_DDR_200_360
]
==
bw_ext_csd
[
EXT_CSD_PWR_CL_DDR_200_360
]));
if
(
err
)
err
=
-
RT_ERROR
;
out:
rt_free
(
bw_ext_csd
);
return
err
;
}
/*
* Select the bus width amoung 4-bit and 8-bit(SDR).
* If the bus width is changed successfully, return the selected width value.
* Zero is returned instead of error value if the wide width is not supported.
*/
static
int
mmc_select_bus_width
(
struct
rt_mmcsd_card
*
card
,
rt_uint8_t
*
ext_csd
)
{
rt_uint32_t
ext_csd_bits
[]
=
{
EXT_CSD_BUS_WIDTH_8
,
EXT_CSD_BUS_WIDTH_4
,
EXT_CSD_BUS_WIDTH_1
};
rt_uint32_t
bus_widths
[]
=
{
MMCSD_BUS_WIDTH_8
,
MMCSD_BUS_WIDTH_4
,
MMCSD_BUS_WIDTH_1
};
struct
rt_mmcsd_host
*
host
=
card
->
host
;
unsigned
idx
,
bus_width
=
0
;
int
err
=
0
;
if
(
GET_BITS
(
card
->
resp_cid
,
122
,
4
)
<
4
)
return
0
;
/*
* Unlike SD, MMC cards dont have a configuration register to notify
* supported bus width. So bus test command should be run to identify
* the supported bus width or compare the ext csd values of current
* bus width and ext csd values of 1 bit mode read earlier.
*/
for
(
idx
=
0
;
idx
<
sizeof
(
bus_widths
)
/
sizeof
(
rt_uint32_t
);
idx
++
)
{
/*
* Host is capable of 8bit transfer, then switch
* the device to work in 8bit transfer mode. If the
* mmc switch command returns error then switch to
* 4bit transfer mode. On success set the corresponding
* bus width on the host.
*/
err
=
mmc_switch
(
card
,
EXT_CSD_CMD_SET_NORMAL
,
EXT_CSD_BUS_WIDTH
,
ext_csd_bits
[
idx
]);
if
(
err
)
continue
;
bus_width
=
bus_widths
[
idx
];
mmcsd_set_bus_width
(
host
,
bus_width
);
mmcsd_delay_ms
(
20
);
//delay 10ms
err
=
mmc_compare_ext_csds
(
card
,
ext_csd
,
bus_width
);
if
(
!
err
)
{
err
=
bus_width
;
break
;
}
else
{
switch
(
ext_csd_bits
[
idx
]){
case
0
:
rt_kprintf
(
"switch to bus width 1 bit failed
\n
"
);
break
;
case
1
:
rt_kprintf
(
"switch to bus width 4 bit failed
\n
"
);
break
;
case
2
:
rt_kprintf
(
"switch to bus width 8 bit failed
\n
"
);
break
;
default:
break
;
}
}
}
return
err
;
}
rt_err_t
mmc_send_op_cond
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
ocr
,
rt_uint32_t
*
rocr
)
{
struct
rt_mmcsd_cmd
cmd
;
rt_uint32_t
i
;
rt_err_t
err
=
RT_EOK
;
rt_memset
(
&
cmd
,
0
,
sizeof
(
struct
rt_mmcsd_cmd
));
cmd
.
cmd_code
=
SEND_OP_COND
;
cmd
.
arg
=
controller_is_spi
(
host
)
?
0
:
ocr
;
cmd
.
flags
=
RESP_SPI_R1
|
RESP_R3
|
CMD_BCR
;
for
(
i
=
100
;
i
;
i
--
)
{
err
=
mmcsd_send_cmd
(
host
,
&
cmd
,
3
);
if
(
err
)
break
;
/* if we're just probing, do a single pass */
if
(
ocr
==
0
)
break
;
/* otherwise wait until reset completes */
if
(
controller_is_spi
(
host
))
{
if
(
!
(
cmd
.
resp
[
0
]
&
R1_SPI_IDLE
))
break
;
}
else
{
if
(
cmd
.
resp
[
0
]
&
CARD_BUSY
)
break
;
}
err
=
-
RT_ETIMEOUT
;
mmcsd_delay_ms
(
10
);
//delay 10ms
}
if
(
rocr
&&
!
controller_is_spi
(
host
))
*
rocr
=
cmd
.
resp
[
0
];
return
err
;
}
static
rt_err_t
mmc_set_card_addr
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
rca
)
{
rt_err_t
err
;
struct
rt_mmcsd_cmd
cmd
;
rt_memset
(
&
cmd
,
0
,
sizeof
(
struct
rt_mmcsd_cmd
));
cmd
.
cmd_code
=
SET_RELATIVE_ADDR
;
cmd
.
arg
=
rca
<<
16
;
cmd
.
flags
=
RESP_R1
|
CMD_AC
;
err
=
mmcsd_send_cmd
(
host
,
&
cmd
,
3
);
if
(
err
)
return
err
;
return
0
;
}
static
rt_int32_t
mmcsd_mmc_init_card
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
ocr
)
{
struct
rt_mmcsd_card
*
card
;
rt_int32_t
err
;
rt_uint32_t
resp
[
4
];
rt_uint32_t
rocr
;
rt_uint32_t
max_data_rate
;
rt_uint8_t
*
ext_csd
=
RT_NULL
;
mmcsd_go_idle
(
host
);
/* The extra bit indicates that we support high capacity */
err
=
mmc_send_op_cond
(
host
,
ocr
|
(
1
<<
30
),
&
rocr
);
if
(
err
)
goto
err
;
if
(
controller_is_spi
(
host
))
{
err
=
mmcsd_spi_use_crc
(
host
,
1
);
if
(
err
)
goto
err1
;
}
if
(
controller_is_spi
(
host
))
err
=
mmcsd_get_cid
(
host
,
resp
);
else
err
=
mmcsd_all_get_cid
(
host
,
resp
);
if
(
err
)
goto
err
;
card
=
rt_malloc
(
sizeof
(
struct
rt_mmcsd_card
));
if
(
!
card
)
{
rt_kprintf
(
"malloc card failed
\n
"
);
err
=
-
RT_ENOMEM
;
goto
err
;
}
rt_memset
(
card
,
0
,
sizeof
(
struct
rt_mmcsd_card
));
card
->
card_type
=
CARD_TYPE_MMC
;
card
->
host
=
host
;
card
->
rca
=
1
;
rt_memcpy
(
card
->
resp_cid
,
resp
,
sizeof
(
card
->
resp_cid
));
/*
* For native busses: get card RCA and quit open drain mode.
*/
if
(
!
controller_is_spi
(
host
))
{
err
=
mmc_set_card_addr
(
host
,
card
->
rca
);
if
(
err
)
goto
err1
;
mmcsd_set_bus_mode
(
host
,
MMCSD_BUSMODE_PUSHPULL
);
}
err
=
mmcsd_get_csd
(
card
,
card
->
resp_csd
);
if
(
err
)
goto
err1
;
err
=
mmcsd_parse_csd
(
card
);
if
(
err
)
goto
err1
;
if
(
!
controller_is_spi
(
host
))
{
err
=
mmcsd_select_card
(
card
);
if
(
err
)
goto
err1
;
}
/*
* Fetch and process extended CSD.
*/
err
=
mmc_get_ext_csd
(
card
,
&
ext_csd
);
if
(
err
)
goto
err1
;
err
=
mmc_parse_ext_csd
(
card
,
ext_csd
);
if
(
err
)
goto
err1
;
/* If doing byte addressing, check if required to do sector
* addressing. Handle the case of <2GB cards needing sector
* addressing. See section 8.1 JEDEC Standard JED84-A441;
* ocr register has bit 30 set for sector addressing.
*/
if
(
!
(
card
->
flags
&
CARD_FLAG_SDHC
)
&&
(
rocr
&
(
1
<<
30
)))
card
->
flags
|=
CARD_FLAG_SDHC
;
/* set bus speed */
max_data_rate
=
(
unsigned
int
)
-
1
;
if
(
card
->
flags
&
CARD_FLAG_HIGHSPEED
)
{
if
(
max_data_rate
>
card
->
hs_max_data_rate
)
max_data_rate
=
card
->
hs_max_data_rate
;
}
else
if
(
max_data_rate
>
card
->
max_data_rate
)
{
max_data_rate
=
card
->
max_data_rate
;
}
mmcsd_set_clock
(
host
,
max_data_rate
);
/*switch bus width*/
mmc_select_bus_width
(
card
,
ext_csd
);
host
->
card
=
card
;
rt_free
(
ext_csd
);
return
0
;
err1:
rt_free
(
card
);
err:
return
err
;
}
/*
* Starting point for mmc card init.
*/
rt_int32_t
init_mmc
(
struct
rt_mmcsd_host
*
host
,
rt_uint32_t
ocr
)
{
rt_int32_t
err
;
rt_uint32_t
current_ocr
;
/*
* We need to get OCR a different way for SPI.
*/
if
(
controller_is_spi
(
host
))
{
err
=
mmcsd_spi_read_ocr
(
host
,
0
,
&
ocr
);
if
(
err
)
goto
err
;
}
current_ocr
=
mmcsd_select_voltage
(
host
,
ocr
);
/*
* Can we support the voltage(s) of the card(s)?
*/
if
(
!
current_ocr
)
{
err
=
-
RT_ERROR
;
goto
err
;
}
/*
* Detect and init the card.
*/
err
=
mmcsd_mmc_init_card
(
host
,
current_ocr
);
if
(
err
)
goto
err
;
mmcsd_host_unlock
(
host
);
err
=
rt_mmcsd_blk_probe
(
host
->
card
);
if
(
err
)
goto
remove_card
;
mmcsd_host_lock
(
host
);
return
0
;
remove_card:
mmcsd_host_lock
(
host
);
rt_mmcsd_blk_remove
(
host
->
card
);
rt_free
(
host
->
card
);
host
->
card
=
RT_NULL
;
err:
rt_kprintf
(
"init SD card failed
\n
"
);
return
err
;
}
components/drivers/sdio/mmcsd_core.c
浏览文件 @
41597e87
...
...
@@ -25,6 +25,7 @@
#include <rtthread.h>
#include <drivers/mmcsd_core.h>
#include <drivers/sd.h>
#include <drivers/mmc.h>
#ifndef RT_MMCSD_STACK_SIZE
#define RT_MMCSD_STACK_SIZE 1024
...
...
@@ -60,22 +61,29 @@ void mmcsd_req_complete(struct rt_mmcsd_host *host)
void
mmcsd_send_request
(
struct
rt_mmcsd_host
*
host
,
struct
rt_mmcsd_req
*
req
)
{
req
->
cmd
->
err
=
0
;
req
->
cmd
->
mrq
=
req
;
if
(
req
->
data
)
{
req
->
cmd
->
data
=
req
->
data
;
req
->
data
->
err
=
0
;
req
->
data
->
mrq
=
req
;
if
(
req
->
stop
)
{
req
->
data
->
stop
=
req
->
stop
;
req
->
stop
->
err
=
0
;
req
->
stop
->
mrq
=
req
;
}
}
host
->
ops
->
request
(
host
,
req
);
rt_sem_take
(
&
host
->
sem_ack
,
RT_WAITING_FOREVER
);
do
{
req
->
cmd
->
retries
--
;
req
->
cmd
->
err
=
0
;
req
->
cmd
->
mrq
=
req
;
if
(
req
->
data
)
{
req
->
cmd
->
data
=
req
->
data
;
req
->
data
->
err
=
0
;
req
->
data
->
mrq
=
req
;
if
(
req
->
stop
)
{
req
->
data
->
stop
=
req
->
stop
;
req
->
stop
->
err
=
0
;
req
->
stop
->
mrq
=
req
;
}
}
host
->
ops
->
request
(
host
,
req
);
rt_sem_take
(
&
host
->
sem_ack
,
RT_WAITING_FOREVER
);
}
while
(
req
->
cmd
->
err
&&
req
->
cmd
->
retries
);
}
rt_int32_t
mmcsd_send_cmd
(
struct
rt_mmcsd_host
*
host
,
...
...
@@ -86,6 +94,7 @@ rt_int32_t mmcsd_send_cmd(struct rt_mmcsd_host *host,
rt_memset
(
&
req
,
0
,
sizeof
(
struct
rt_mmcsd_req
));
rt_memset
(
cmd
->
resp
,
0
,
sizeof
(
cmd
->
resp
));
cmd
->
retries
=
retries
;
req
.
cmd
=
cmd
;
cmd
->
data
=
RT_NULL
;
...
...
@@ -626,6 +635,18 @@ void mmcsd_detect(void *param)
mmcsd_host_unlock
(
host
);
continue
;
}
/*
* detect mmc card
*/
err
=
mmc_send_op_cond
(
host
,
0
,
&
ocr
);
if
(
!
err
)
{
if
(
init_mmc
(
host
,
ocr
))
mmcsd_power_off
(
host
);
mmcsd_host_unlock
(
host
);
continue
;
}
mmcsd_host_unlock
(
host
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录