diff options
Diffstat (limited to 'include/linux/mmc/sh_mmcif.h')
-rw-r--r-- | include/linux/mmc/sh_mmcif.h | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h index aafe832f18aa..d4a2ebbdab4b 100644 --- a/include/linux/mmc/sh_mmcif.h +++ b/include/linux/mmc/sh_mmcif.h | |||
@@ -14,6 +14,9 @@ | |||
14 | #ifndef __SH_MMCIF_H__ | 14 | #ifndef __SH_MMCIF_H__ |
15 | #define __SH_MMCIF_H__ | 15 | #define __SH_MMCIF_H__ |
16 | 16 | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
17 | /* | 20 | /* |
18 | * MMCIF : CE_CLK_CTRL [19:16] | 21 | * MMCIF : CE_CLK_CTRL [19:16] |
19 | * 1000 : Peripheral clock / 512 | 22 | * 1000 : Peripheral clock / 512 |
@@ -36,4 +39,162 @@ struct sh_mmcif_plat_data { | |||
36 | u32 ocr; | 39 | u32 ocr; |
37 | }; | 40 | }; |
38 | 41 | ||
42 | #define MMCIF_CE_CMD_SET 0x00000000 | ||
43 | #define MMCIF_CE_ARG 0x00000008 | ||
44 | #define MMCIF_CE_ARG_CMD12 0x0000000C | ||
45 | #define MMCIF_CE_CMD_CTRL 0x00000010 | ||
46 | #define MMCIF_CE_BLOCK_SET 0x00000014 | ||
47 | #define MMCIF_CE_CLK_CTRL 0x00000018 | ||
48 | #define MMCIF_CE_BUF_ACC 0x0000001C | ||
49 | #define MMCIF_CE_RESP3 0x00000020 | ||
50 | #define MMCIF_CE_RESP2 0x00000024 | ||
51 | #define MMCIF_CE_RESP1 0x00000028 | ||
52 | #define MMCIF_CE_RESP0 0x0000002C | ||
53 | #define MMCIF_CE_RESP_CMD12 0x00000030 | ||
54 | #define MMCIF_CE_DATA 0x00000034 | ||
55 | #define MMCIF_CE_INT 0x00000040 | ||
56 | #define MMCIF_CE_INT_MASK 0x00000044 | ||
57 | #define MMCIF_CE_HOST_STS1 0x00000048 | ||
58 | #define MMCIF_CE_HOST_STS2 0x0000004C | ||
59 | #define MMCIF_CE_VERSION 0x0000007C | ||
60 | |||
61 | extern inline u32 sh_mmcif_readl(void __iomem *addr, int reg) | ||
62 | { | ||
63 | return readl(addr + reg); | ||
64 | } | ||
65 | |||
66 | extern inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) | ||
67 | { | ||
68 | writel(val, addr + reg); | ||
69 | } | ||
70 | |||
71 | #define SH_MMCIF_BBS 512 /* boot block size */ | ||
72 | |||
73 | extern inline void sh_mmcif_boot_cmd_send(void __iomem *base, | ||
74 | unsigned long cmd, unsigned long arg) | ||
75 | { | ||
76 | sh_mmcif_writel(base, MMCIF_CE_INT, 0); | ||
77 | sh_mmcif_writel(base, MMCIF_CE_ARG, arg); | ||
78 | sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd); | ||
79 | } | ||
80 | |||
81 | extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) | ||
82 | { | ||
83 | unsigned long tmp; | ||
84 | int cnt; | ||
85 | |||
86 | for (cnt = 0; cnt < 1000000; cnt++) { | ||
87 | tmp = sh_mmcif_readl(base, MMCIF_CE_INT); | ||
88 | if (tmp & mask) { | ||
89 | sh_mmcif_writel(base, MMCIF_CE_INT, tmp & ~mask); | ||
90 | return 0; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | return -1; | ||
95 | } | ||
96 | |||
97 | extern inline int sh_mmcif_boot_cmd(void __iomem *base, | ||
98 | unsigned long cmd, unsigned long arg) | ||
99 | { | ||
100 | sh_mmcif_boot_cmd_send(base, cmd, arg); | ||
101 | return sh_mmcif_boot_cmd_poll(base, 0x00010000); | ||
102 | } | ||
103 | |||
104 | extern inline int sh_mmcif_boot_do_read_single(void __iomem *base, | ||
105 | unsigned int block_nr, | ||
106 | unsigned long *buf) | ||
107 | { | ||
108 | int k; | ||
109 | |||
110 | /* CMD13 - Status */ | ||
111 | sh_mmcif_boot_cmd(base, 0x0d400000, 0x00010000); | ||
112 | |||
113 | if (sh_mmcif_readl(base, MMCIF_CE_RESP0) != 0x0900) | ||
114 | return -1; | ||
115 | |||
116 | /* CMD17 - Read */ | ||
117 | sh_mmcif_boot_cmd(base, 0x11480000, block_nr * SH_MMCIF_BBS); | ||
118 | if (sh_mmcif_boot_cmd_poll(base, 0x00100000) < 0) | ||
119 | return -1; | ||
120 | |||
121 | for (k = 0; k < (SH_MMCIF_BBS / 4); k++) | ||
122 | buf[k] = sh_mmcif_readl(base, MMCIF_CE_DATA); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | extern inline int sh_mmcif_boot_do_read(void __iomem *base, | ||
128 | unsigned long first_block, | ||
129 | unsigned long nr_blocks, | ||
130 | void *buf) | ||
131 | { | ||
132 | unsigned long k; | ||
133 | int ret = 0; | ||
134 | |||
135 | /* CMD16 - Set the block size */ | ||
136 | sh_mmcif_boot_cmd(base, 0x10400000, SH_MMCIF_BBS); | ||
137 | |||
138 | for (k = 0; !ret && k < nr_blocks; k++) | ||
139 | ret = sh_mmcif_boot_do_read_single(base, first_block + k, | ||
140 | buf + (k * SH_MMCIF_BBS)); | ||
141 | |||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | extern inline void sh_mmcif_boot_init(void __iomem *base) | ||
146 | { | ||
147 | unsigned long tmp; | ||
148 | |||
149 | /* reset */ | ||
150 | tmp = sh_mmcif_readl(base, MMCIF_CE_VERSION); | ||
151 | sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp | 0x80000000); | ||
152 | sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp & ~0x80000000); | ||
153 | |||
154 | /* byte swap */ | ||
155 | sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, 0x00010000); | ||
156 | |||
157 | /* Set block size in MMCIF hardware */ | ||
158 | sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS); | ||
159 | |||
160 | /* Enable the clock, set it to Bus clock/256 (about 325Khz)*/ | ||
161 | sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01072fff); | ||
162 | |||
163 | /* CMD0 */ | ||
164 | sh_mmcif_boot_cmd(base, 0x00000040, 0); | ||
165 | |||
166 | /* CMD1 - Get OCR */ | ||
167 | do { | ||
168 | sh_mmcif_boot_cmd(base, 0x01405040, 0x40300000); /* CMD1 */ | ||
169 | } while ((sh_mmcif_readl(base, MMCIF_CE_RESP0) & 0x80000000) | ||
170 | != 0x80000000); | ||
171 | |||
172 | /* CMD2 - Get CID */ | ||
173 | sh_mmcif_boot_cmd(base, 0x02806040, 0); | ||
174 | |||
175 | /* CMD3 - Set card relative address */ | ||
176 | sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); | ||
177 | } | ||
178 | |||
179 | extern inline void sh_mmcif_boot_slurp(void __iomem *base, | ||
180 | unsigned char *buf, | ||
181 | unsigned long no_bytes) | ||
182 | { | ||
183 | unsigned long tmp; | ||
184 | |||
185 | /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */ | ||
186 | sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01012fff); | ||
187 | |||
188 | /* CMD9 - Get CSD */ | ||
189 | sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000); | ||
190 | |||
191 | /* CMD7 - Select the card */ | ||
192 | sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000); | ||
193 | |||
194 | tmp = no_bytes / SH_MMCIF_BBS; | ||
195 | tmp += (no_bytes % SH_MMCIF_BBS) ? 1 : 0; | ||
196 | |||
197 | sh_mmcif_boot_do_read(base, 512, tmp, buf); | ||
198 | } | ||
199 | |||
39 | #endif /* __SH_MMCIF_H__ */ | 200 | #endif /* __SH_MMCIF_H__ */ |