OpenWrt – Diff between revs 2 and 3
?pathlinks?
Rev 2 | Rev 3 | |||
---|---|---|---|---|
Line 32... | Line 32... | |||
32 | * have been modified by MediaTek Inc. All revisions are subject to any receiver's |
32 | * have been modified by MediaTek Inc. All revisions are subject to any receiver's |
|
33 | * applicable license agreements with MediaTek Inc. |
33 | * applicable license agreements with MediaTek Inc. |
|
34 | */ |
34 | */ |
|
Line 35... | Line 35... | |||
35 | |
35 | |
|
36 | #include <linux/module.h> |
36 | #include <linux/module.h> |
|
37 | #include <linux/delay.h> |
37 | #include <linux/moduleparam.h> |
|
38 | #include <linux/dma-mapping.h> |
38 | #include <linux/init.h> |
|
- | 39 | #include <linux/spinlock.h> |
||
- | 40 | #include <linux/timer.h> |
||
- | 41 | #include <linux/ioport.h> |
||
39 | #include <linux/spinlock.h> |
42 | #include <linux/device.h> |
|
40 | #include <linux/platform_device.h> |
43 | #include <linux/platform_device.h> |
|
41 | #include <linux/interrupt.h> |
- | ||
- | 44 | #include <linux/interrupt.h> |
||
- | 45 | #include <linux/delay.h> |
||
- | 46 | #include <linux/blkdev.h> |
||
42 | |
47 | #include <linux/slab.h> |
|
- | 48 | #include <linux/mmc/host.h> |
||
- | 49 | #include <linux/mmc/card.h> |
||
43 | #include <linux/mmc/host.h> |
50 | #include <linux/mmc/core.h> |
|
44 | #include <linux/mmc/mmc.h> |
51 | #include <linux/mmc/mmc.h> |
|
45 | #include <linux/mmc/sd.h> |
52 | #include <linux/mmc/sd.h> |
|
- | 53 | #include <linux/mmc/sdio.h> |
||
Line -... | Line 54... | |||
- | 54 | #include <linux/dma-mapping.h> |
||
46 | #include <linux/mmc/sdio.h> |
55 | |
|
47 | |
- | ||
48 | #include <asm/mach-ralink/ralink_regs.h> |
56 | /* +++ by chhung */ |
|
- | 57 | #include <linux/types.h> |
||
49 | |
58 | #include <linux/kernel.h> |
|
50 | #include "board.h" |
59 | #include <linux/version.h> |
|
- | 60 | #include <linux/pm.h> |
||
- | 61 | #include <linux/of.h> |
||
- | 62 | |
||
- | 63 | #define MSDC_SMPL_FALLING (1) |
||
- | 64 | #define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ |
||
- | 65 | #define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ |
||
- | 66 | #define MSDC_REMOVABLE (1 << 5) /* removable slot */ |
||
Line 51... | Line 67... | |||
51 | #include "dbg.h" |
67 | #define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ |
|
52 | #include "mt6575_sd.h" |
68 | #define MSDC_HIGHSPEED (1 << 7) |
|
53 | |
69 | |
|
54 | //#define IRQ_SDC 14 //MT7620 /*FIXME*/ |
70 | //#define IRQ_SDC 14 //MT7620 /*FIXME*/ |
|
Line 59... | Line 75... | |||
59 | #define RALINK_SYSCTL_BASE 0xb0000000 |
75 | #define RALINK_SYSCTL_BASE 0xb0000000 |
|
60 | #define RALINK_MSDC_BASE 0xb0130000 |
76 | #define RALINK_MSDC_BASE 0xb0130000 |
|
61 | #endif |
77 | #endif |
|
62 | #define IRQ_SDC 22 /*FIXME*/ |
78 | #define IRQ_SDC 22 /*FIXME*/ |
|
Line -... | Line 79... | |||
- | 79 | |
||
- | 80 | #include <asm/dma.h> |
||
- | 81 | /* end of +++ */ |
||
- | 82 | |
||
- | 83 | |
||
- | 84 | #include <asm/mach-ralink/ralink_regs.h> |
||
- | 85 | |
||
- | 86 | #if 0 /* --- by chhung */ |
||
- | 87 | #include <mach/board.h> |
||
- | 88 | #include <mach/mt6575_devs.h> |
||
- | 89 | #include <mach/mt6575_typedefs.h> |
||
- | 90 | #include <mach/mt6575_clock_manager.h> |
||
- | 91 | #include <mach/mt6575_pm_ldo.h> |
||
- | 92 | //#include <mach/mt6575_pll.h> |
||
- | 93 | //#include <mach/mt6575_gpio.h> |
||
- | 94 | //#include <mach/mt6575_gpt_sw.h> |
||
- | 95 | #include <asm/tcm.h> |
||
- | 96 | // #include <mach/mt6575_gpt.h> |
||
- | 97 | #endif /* end of --- */ |
||
- | 98 | |
||
- | 99 | #include "mt6575_sd.h" |
||
- | 100 | #include "dbg.h" |
||
- | 101 | |
||
- | 102 | /* +++ by chhung */ |
||
- | 103 | #include "board.h" |
||
- | 104 | /* end of +++ */ |
||
- | 105 | |
||
- | 106 | #if 0 /* --- by chhung */ |
||
- | 107 | #define isb() __asm__ __volatile__ ("" : : : "memory") |
||
- | 108 | #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ |
||
- | 109 | : : "r" (0) : "memory") |
||
- | 110 | #define dmb() __asm__ __volatile__ ("" : : : "memory") |
||
- | 111 | #endif /* end of --- */ |
||
63 | |
112 | |
|
Line -... | Line 113... | |||
- | 113 | #define DRV_NAME "mtk-sd" |
||
- | 114 | |
||
64 | #define DRV_NAME "mtk-sd" |
115 | #define HOST_MAX_NUM (1) /* +/- by chhung */ |
|
65 | |
116 | |
|
66 | #if defined(CONFIG_SOC_MT7620) |
117 | #if defined (CONFIG_SOC_MT7620) |
|
67 | #define HOST_MAX_MCLK (48000000) /* +/- by chhung */ |
118 | #define HOST_MAX_MCLK (48000000) /* +/- by chhung */ |
|
68 | #elif defined(CONFIG_SOC_MT7621) |
119 | #elif defined (CONFIG_SOC_MT7621) |
|
69 | #define HOST_MAX_MCLK (50000000) /* +/- by chhung */ |
120 | #define HOST_MAX_MCLK (50000000) /* +/- by chhung */ |
|
Line 70... | Line 121... | |||
70 | #endif |
121 | #endif |
|
Line 77... | Line 128... | |||
77 | #define GPIO_PULL_DOWN (0) |
128 | #define GPIO_PULL_DOWN (0) |
|
78 | #define GPIO_PULL_UP (1) |
129 | #define GPIO_PULL_UP (1) |
|
Line 79... | Line 130... | |||
79 | |
130 | |
|
80 | #if 0 /* --- by chhung */ |
131 | #if 0 /* --- by chhung */ |
|
81 | #define MSDC_CLKSRC_REG (0xf100000C) |
132 | #define MSDC_CLKSRC_REG (0xf100000C) |
|
82 | #define PDN_REG (0xF1000010) |
133 | #define PDN_REG (0xF1000010) |
|
Line 83... | Line 134... | |||
83 | #endif /* end of --- */ |
134 | #endif /* end of --- */ |
|
84 | |
135 | |
|
Line 85... | Line 136... | |||
85 | #define DEFAULT_DEBOUNCE (8) /* 8 cycles */ |
136 | #define DEFAULT_DEBOUNCE (8) /* 8 cycles */ |
|
86 | #define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ |
137 | #define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ |
|
Line 87... | Line 138... | |||
87 | |
138 | |
|
Line 88... | Line 139... | |||
88 | #define CMD_TIMEOUT (HZ / 10) /* 100ms */ |
139 | #define CMD_TIMEOUT (HZ/10) /* 100ms */ |
|
89 | #define DAT_TIMEOUT (HZ / 2 * 5) /* 500ms x5 */ |
140 | #define DAT_TIMEOUT (HZ/2 * 5) /* 500ms x5 */ |
|
90 | |
141 | |
|
Line 91... | Line 142... | |||
91 | #define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ |
142 | #define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ |
|
92 | |
143 | |
|
93 | #define MAX_GPD_NUM (1 + 1) /* one null gpd */ |
144 | #define MAX_GPD_NUM (1 + 1) /* one null gpd */ |
|
94 | #define MAX_BD_NUM (1024) |
145 | #define MAX_BD_NUM (1024) |
|
- | 146 | #define MAX_BD_PER_GPD (MAX_BD_NUM) |
||
- | 147 | |
||
Line 95... | Line 148... | |||
95 | #define MAX_BD_PER_GPD (MAX_BD_NUM) |
148 | #define MAX_HW_SGMTS (MAX_BD_NUM) |
|
Line 96... | Line 149... | |||
96 | |
149 | #define MAX_PHY_SGMTS (MAX_BD_NUM) |
|
97 | #define MAX_HW_SGMTS (MAX_BD_NUM) |
150 | #define MAX_SGMT_SZ (MAX_DMA_CNT) |
|
Line 107... | Line 160... | |||
107 | //#define PERI_MSDC2_PDN (17) |
160 | //#define PERI_MSDC2_PDN (17) |
|
108 | //#define PERI_MSDC3_PDN (18) |
161 | //#define PERI_MSDC3_PDN (18) |
|
Line 109... | Line 162... | |||
109 | |
162 | |
|
110 | #if 0 /* --- by chhung */ |
163 | #if 0 /* --- by chhung */ |
|
111 | /* gate means clock power down */ |
164 | /* gate means clock power down */ |
|
112 | static int g_clk_gate = 0; |
165 | static int g_clk_gate = 0; |
|
113 | #define msdc_gate_clock(id) \ |
166 | #define msdc_gate_clock(id) \ |
|
114 | do { \ |
167 | do { \ |
|
115 | g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \ |
168 | g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \ |
|
116 | } while (0) |
169 | } while(0) |
|
117 | /* not like power down register. 1 means clock on. */ |
170 | /* not like power down register. 1 means clock on. */ |
|
118 | #define msdc_ungate_clock(id) \ |
171 | #define msdc_ungate_clock(id) \ |
|
119 | do { \ |
172 | do { \ |
|
120 | g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \ |
173 | g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \ |
|
Line 121... | Line 174... | |||
121 | } while (0) |
174 | } while(0) |
|
122 | |
175 | |
|
123 | // do we need sync object or not |
176 | // do we need sync object or not |
|
124 | void msdc_clk_status(int *status) |
177 | void msdc_clk_status(int * status) |
|
125 | { |
178 | { |
|
126 | *status = g_clk_gate; |
179 | *status = g_clk_gate; |
|
Line 127... | Line 180... | |||
127 | } |
180 | } |
|
128 | #endif /* end of --- */ |
181 | #endif /* end of --- */ |
|
129 | |
182 | |
|
- | 183 | /* +++ by chhung */ |
||
- | 184 | struct msdc_hw msdc0_hw = { |
||
- | 185 | .clk_src = 0, |
||
- | 186 | .cmd_edge = MSDC_SMPL_FALLING, |
||
- | 187 | .data_edge = MSDC_SMPL_FALLING, |
||
- | 188 | .clk_drv = 4, |
||
- | 189 | .cmd_drv = 4, |
||
130 | /* +++ by chhung */ |
190 | .dat_drv = 4, |
|
131 | struct msdc_hw msdc0_hw = { |
191 | .data_pins = 4, |
|
- | 192 | .data_offset = 0, |
||
- | 193 | .flags = MSDC_SYS_SUSPEND | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, |
||
- | 194 | // .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE, |
||
- | 195 | }; |
||
- | 196 | |
||
- | 197 | static struct resource mtk_sd_resources[] = { |
||
- | 198 | [0] = { |
||
- | 199 | .start = RALINK_MSDC_BASE, |
||
- | 200 | .end = RALINK_MSDC_BASE+0x3fff, |
||
- | 201 | .flags = IORESOURCE_MEM, |
||
- | 202 | }, |
||
- | 203 | [1] = { |
||
- | 204 | .start = IRQ_SDC, /*FIXME*/ |
||
132 | .clk_src = 0, |
205 | .end = IRQ_SDC, /*FIXME*/ |
|
Line -... | Line 206... | |||
- | 206 | .flags = IORESOURCE_IRQ, |
||
- | 207 | }, |
||
- | 208 | }; |
||
- | 209 | |
||
- | 210 | static struct platform_device mtk_sd_device = { |
||
- | 211 | .name = "mtk-sd", |
||
133 | .flags = MSDC_CD_PIN_EN | MSDC_REMOVABLE, |
212 | .id = 0, |
|
Line 134... | Line 213... | |||
134 | // .flags = MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE, |
213 | .num_resources = ARRAY_SIZE(mtk_sd_resources), |
|
135 | }; |
214 | .resource = mtk_sd_resources, |
|
136 | |
215 | }; |
|
137 | /* end of +++ */ |
216 | /* end of +++ */ |
|
138 | |
217 | |
|
139 | static int msdc_rsp[] = { |
218 | static int msdc_rsp[] = { |
|
140 | 0, /* RESP_NONE */ |
219 | 0, /* RESP_NONE */ |
|
141 | 1, /* RESP_R1 */ |
220 | 1, /* RESP_R1 */ |
|
142 | 2, /* RESP_R2 */ |
221 | 2, /* RESP_R2 */ |
|
143 | 3, /* RESP_R3 */ |
222 | 3, /* RESP_R3 */ |
|
144 | 4, /* RESP_R4 */ |
223 | 4, /* RESP_R4 */ |
|
Line -... | Line 224... | |||
- | 224 | 1, /* RESP_R5 */ |
||
- | 225 | 1, /* RESP_R6 */ |
||
- | 226 | 1, /* RESP_R7 */ |
||
- | 227 | 7, /* RESP_R1b */ |
||
- | 228 | }; |
||
- | 229 | |
||
- | 230 | /* For Inhanced DMA */ |
||
- | 231 | #define msdc_init_gpd_ex(gpd,extlen,cmd,arg,blknum) \ |
||
- | 232 | do { \ |
||
- | 233 | ((gpd_t*)gpd)->extlen = extlen; \ |
||
- | 234 | ((gpd_t*)gpd)->cmd = cmd; \ |
||
- | 235 | ((gpd_t*)gpd)->arg = arg; \ |
||
- | 236 | ((gpd_t*)gpd)->blknum = blknum; \ |
||
- | 237 | }while(0) |
||
- | 238 | |
||
- | 239 | #define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \ |
||
- | 240 | do { \ |
||
- | 241 | BUG_ON(dlen > 0xFFFFUL); \ |
||
145 | 1, /* RESP_R5 */ |
242 | ((bd_t*)bd)->blkpad = blkpad; \ |
|
146 | 1, /* RESP_R6 */ |
243 | ((bd_t*)bd)->dwpad = dwpad; \ |
|
147 | 1, /* RESP_R7 */ |
244 | ((bd_t*)bd)->ptr = (void*)dptr; \ |
|
148 | 7, /* RESP_R1b */ |
245 | ((bd_t*)bd)->buflen = dlen; \ |
|
149 | }; |
246 | }while(0) |
|
150 | |
247 | |
|
- | 248 | #define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) |
||
Line 151... | Line 249... | |||
151 | #define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) |
249 | #define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) |
|
- | 250 | #define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v)) |
||
Line 152... | Line 251... | |||
152 | #define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) |
251 | #define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v)) |
|
153 | #define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v)) |
252 | #define msdc_fifo_read32() sdr_read32(MSDC_RXDATA) |
|
154 | #define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v)) |
253 | #define msdc_fifo_read8() sdr_read8(MSDC_RXDATA) |
|
155 | #define msdc_fifo_read32() sdr_read32(MSDC_RXDATA) |
254 | |
|
156 | #define msdc_fifo_read8() sdr_read8(MSDC_RXDATA) |
255 | |
|
157 | |
- | ||
158 | #define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO) |
256 | #define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO) |
|
159 | |
257 | #define msdc_dma_off() sdr_set_bits(MSDC_CFG, MSDC_CFG_PIO) |
|
160 | #define msdc_retry(expr, retry, cnt) \ |
258 | |
|
161 | do { \ |
259 | #define msdc_retry(expr,retry,cnt) \ |
|
162 | int backup = cnt; \ |
260 | do { \ |
|
163 | while (retry) { \ |
261 | int backup = cnt; \ |
|
164 | if (!(expr)) \ |
262 | while (retry) { \ |
|
- | 263 | if (!(expr)) break; \ |
||
165 | break; \ |
264 | if (cnt-- == 0) { \ |
|
166 | if (cnt-- == 0) { \ |
265 | retry--; mdelay(1); cnt = backup; \ |
|
167 | retry--; mdelay(1); cnt = backup; \ |
266 | } \ |
|
168 | } \ |
- | ||
169 | } \ |
267 | } \ |
|
- | 268 | WARN_ON(retry == 0); \ |
||
170 | WARN_ON(retry == 0); \ |
269 | } while(0) |
|
171 | } while (0) |
270 | |
|
172 | |
271 | #if 0 /* --- by chhung */ |
|
- | 272 | #define msdc_reset() \ |
||
- | 273 | do { \ |
||
- | 274 | int retry = 3, cnt = 1000; \ |
||
- | 275 | sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ |
||
- | 276 | dsb(); \ |
||
- | 277 | msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ |
||
- | 278 | } while(0) |
||
Line 173... | Line 279... | |||
173 | static void msdc_reset_hw(struct msdc_host *host) |
279 | #else |
|
174 | { |
280 | #define msdc_reset() \ |
|
175 | void __iomem *base = host->base; |
281 | do { \ |
|
176 | |
282 | int retry = 3, cnt = 1000; \ |
|
177 | sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); |
283 | sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ |
|
Line 178... | Line 284... | |||
178 | while (sdr_read32(MSDC_CFG) & MSDC_CFG_RST) |
284 | msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ |
|
179 | cpu_relax(); |
285 | } while(0) |
|
180 | } |
286 | #endif /* end of +/- */ |
|
181 | |
287 | |
|
182 | #define msdc_clr_int() \ |
288 | #define msdc_clr_int() \ |
|
183 | do { \ |
289 | do { \ |
|
Line 184... | Line 290... | |||
184 | volatile u32 val = sdr_read32(MSDC_INT); \ |
290 | volatile u32 val = sdr_read32(MSDC_INT); \ |
|
185 | sdr_write32(MSDC_INT, val); \ |
291 | sdr_write32(MSDC_INT, val); \ |
|
186 | } while (0) |
292 | } while(0) |
|
187 | |
293 | |
|
188 | #define msdc_clr_fifo() \ |
294 | #define msdc_clr_fifo() \ |
|
189 | do { \ |
295 | do { \ |
|
190 | int retry = 3, cnt = 1000; \ |
296 | int retry = 3, cnt = 1000; \ |
|
191 | sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ |
297 | sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ |
|
192 | msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ |
298 | msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ |
|
193 | } while (0) |
299 | } while(0) |
|
Line 194... | Line 300... | |||
194 | |
300 | |
|
195 | #define msdc_irq_save(val) \ |
301 | #define msdc_irq_save(val) \ |
|
196 | do { \ |
302 | do { \ |
|
197 | val = sdr_read32(MSDC_INTEN); \ |
303 | val = sdr_read32(MSDC_INTEN); \ |
|
198 | sdr_clr_bits(MSDC_INTEN, val); \ |
304 | sdr_clr_bits(MSDC_INTEN, val); \ |
|
199 | } while (0) |
305 | } while(0) |
|
Line 200... | Line 306... | |||
200 | |
306 | |
|
201 | #define msdc_irq_restore(val) \ |
307 | #define msdc_irq_restore(val) \ |
|
202 | do { \ |
308 | do { \ |
|
203 | sdr_set_bits(MSDC_INTEN, val); \ |
309 | sdr_set_bits(MSDC_INTEN, val); \ |
|
204 | } while (0) |
310 | } while(0) |
|
205 | |
311 | |
|
206 | /* clock source for host: global */ |
312 | /* clock source for host: global */ |
|
207 | #if defined(CONFIG_SOC_MT7620) |
313 | #if defined (CONFIG_SOC_MT7620) |
|
208 | static u32 hclks[] = {48000000}; /* +/- by chhung */ |
314 | static u32 hclks[] = {48000000}; /* +/- by chhung */ |
|
209 | #elif defined(CONFIG_SOC_MT7621) |
315 | #elif defined (CONFIG_SOC_MT7621) |
|
210 | static u32 hclks[] = {50000000}; /* +/- by chhung */ |
316 | static u32 hclks[] = {50000000}; /* +/- by chhung */ |
|
211 | #endif |
317 | #endif |
|
212 | |
318 | |
|
213 | //============================================ |
319 | //============================================ |
|
Line 214... | Line 320... | |||
214 | // the power for msdc host controller: global |
320 | // the power for msdc host controller: global |
|
215 | // always keep the VMC on. |
321 | // always keep the VMC on. |
|
216 | //============================================ |
322 | //============================================ |
|
217 | #define msdc_vcore_on(host) \ |
323 | #define msdc_vcore_on(host) \ |
|
218 | do { \ |
324 | do { \ |
|
219 | INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \ |
325 | INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \ |
|
220 | (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ |
326 | (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ |
|
221 | } while (0) |
327 | } while (0) |
|
222 | #define msdc_vcore_off(host) \ |
328 | #define msdc_vcore_off(host) \ |
|
223 | do { \ |
329 | do { \ |
|
224 | INIT_MSG("[-]VMC ref. count<%d>", --host->pwr_ref); \ |
330 | INIT_MSG("[-]VMC ref. count<%d>", --host->pwr_ref); \ |
|
225 | (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ |
331 | (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ |
|
Line 226... | Line 332... | |||
226 | } while (0) |
332 | } while (0) |
|
227 | |
333 | |
|
Line 228... | Line 334... | |||
228 | //==================================== |
334 | //==================================== |
|
229 | // the vdd output for card: global |
335 | // the vdd output for card: global |
|
230 | // always keep the VMCH on. |
336 | // always keep the VMCH on. |
|
231 | //==================================== |
337 | //==================================== |
|
232 | #define msdc_vdd_on(host) \ |
338 | #define msdc_vdd_on(host) \ |
|
Line 233... | Line 339... | |||
233 | do { \ |
339 | do { \ |
|
234 | (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ |
340 | (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ |
|
235 | } while (0) |
341 | } while (0) |
|
Line 236... | Line 342... | |||
236 | #define msdc_vdd_off(host) \ |
342 | #define msdc_vdd_off(host) \ |
|
237 | do { \ |
343 | do { \ |
|
238 | (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ |
344 | (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ |
|
239 | } while (0) |
345 | } while (0) |
|
240 | |
346 | |
|
241 | #define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY) |
347 | #define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY) |
|
242 | #define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY) |
348 | #define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY) |
|
243 | |
349 | |
|
244 | #define sdc_send_cmd(cmd, arg) \ |
350 | #define sdc_send_cmd(cmd,arg) \ |
|
245 | do { \ |
351 | do { \ |
|
246 | sdr_write32(SDC_ARG, (arg)); \ |
352 | sdr_write32(SDC_ARG, (arg)); \ |
|
247 | sdr_write32(SDC_CMD, (cmd)); \ |
353 | sdr_write32(SDC_CMD, (cmd)); \ |
|
248 | } while (0) |
354 | } while(0) |
|
Line 249... | Line 355... | |||
249 | |
355 | |
|
250 | // can modify to read h/w register. |
356 | // can modify to read h/w register. |
|
251 | //#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1); |
357 | //#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1); |
|
252 | #define is_card_present(h) (((struct msdc_host *)(h))->card_inserted) |
- | ||
253 | |
- | ||
254 | /* +++ by chhung */ |
358 | #define is_card_present(h) (((struct msdc_host*)(h))->card_inserted) |
|
255 | #ifndef __ASSEMBLY__ |
359 | |
|
256 | #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) |
360 | /* +++ by chhung */ |
|
257 | #else |
361 | #ifndef __ASSEMBLY__ |
|
258 | #define PHYSADDR(a) ((a) & 0x1fffffff) |
362 | #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) |
|
259 | #endif |
363 | #else |
|
260 | /* end of +++ */ |
364 | #define PHYSADDR(a) ((a) & 0x1fffffff) |
|
261 | static unsigned int msdc_do_command(struct msdc_host *host, |
365 | #endif |
|
262 | struct mmc_command *cmd, |
366 | /* end of +++ */ |
|
263 | int tune, |
367 | static unsigned int msdc_do_command(struct msdc_host *host, |
|
264 | unsigned long timeout); |
368 | struct mmc_command *cmd, |
|
265 | |
369 | int tune, |
|
266 | static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd); |
370 | unsigned long timeout); |
|
267 | |
371 | |
|
268 | #ifdef MT6575_SD_DEBUG |
372 | static int msdc_tune_cmdrsp(struct msdc_host*host,struct mmc_command *cmd); |
|
269 | static void msdc_dump_card_status(struct msdc_host *host, u32 status) |
373 | |
|
270 | { |
374 | #ifdef MT6575_SD_DEBUG |
|
271 | /* N_MSG is currently a no-op */ |
375 | static void msdc_dump_card_status(struct msdc_host *host, u32 status) |
|
272 | #if 0 |
- | ||
273 | static char *state[] = { |
376 | { |
|
274 | "Idle", /* 0 */ |
377 | static char *state[] = { |
|
275 | "Ready", /* 1 */ |
378 | "Idle", /* 0 */ |
|
276 | "Ident", /* 2 */ |
379 | "Ready", /* 1 */ |
|
277 | "Stby", /* 3 */ |
380 | "Ident", /* 2 */ |
|
278 | "Tran", /* 4 */ |
381 | "Stby", /* 3 */ |
|
279 | "Data", /* 5 */ |
382 | "Tran", /* 4 */ |
|
280 | "Rcv", /* 6 */ |
383 | "Data", /* 5 */ |
|
281 | "Prg", /* 7 */ |
384 | "Rcv", /* 6 */ |
|
282 | "Dis", /* 8 */ |
385 | "Prg", /* 7 */ |
|
283 | "Reserved", /* 9 */ |
386 | "Dis", /* 8 */ |
|
284 | "Reserved", /* 10 */ |
387 | "Reserved", /* 9 */ |
|
285 | "Reserved", /* 11 */ |
388 | "Reserved", /* 10 */ |
|
286 | "Reserved", /* 12 */ |
389 | "Reserved", /* 11 */ |
|
287 | "Reserved", /* 13 */ |
390 | "Reserved", /* 12 */ |
|
288 | "Reserved", /* 14 */ |
391 | "Reserved", /* 13 */ |
|
289 | "I/O mode", /* 15 */ |
392 | "Reserved", /* 14 */ |
|
290 | }; |
393 | "I/O mode", /* 15 */ |
|
291 | #endif |
394 | }; |
|
292 | if (status & R1_OUT_OF_RANGE) |
395 | if (status & R1_OUT_OF_RANGE) |
|
293 | N_MSG(RSP, "[CARD_STATUS] Out of Range"); |
396 | N_MSG(RSP, "[CARD_STATUS] Out of Range"); |
|
294 | if (status & R1_ADDRESS_ERROR) |
397 | if (status & R1_ADDRESS_ERROR) |
|
295 | N_MSG(RSP, "[CARD_STATUS] Address Error"); |
398 | N_MSG(RSP, "[CARD_STATUS] Address Error"); |
|
296 | if (status & R1_BLOCK_LEN_ERROR) |
399 | if (status & R1_BLOCK_LEN_ERROR) |
|
297 | N_MSG(RSP, "[CARD_STATUS] Block Len Error"); |
400 | N_MSG(RSP, "[CARD_STATUS] Block Len Error"); |
|
298 | if (status & R1_ERASE_SEQ_ERROR) |
401 | if (status & R1_ERASE_SEQ_ERROR) |
|
299 | N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); |
402 | N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); |
|
300 | if (status & R1_ERASE_PARAM) |
403 | if (status & R1_ERASE_PARAM) |
|
301 | N_MSG(RSP, "[CARD_STATUS] Erase Param"); |
404 | N_MSG(RSP, "[CARD_STATUS] Erase Param"); |
|
302 | if (status & R1_WP_VIOLATION) |
405 | if (status & R1_WP_VIOLATION) |
|
303 | N_MSG(RSP, "[CARD_STATUS] WP Violation"); |
406 | N_MSG(RSP, "[CARD_STATUS] WP Violation"); |
|
304 | if (status & R1_CARD_IS_LOCKED) |
407 | if (status & R1_CARD_IS_LOCKED) |
|
305 | N_MSG(RSP, "[CARD_STATUS] Card is Locked"); |
408 | N_MSG(RSP, "[CARD_STATUS] Card is Locked"); |
|
306 | if (status & R1_LOCK_UNLOCK_FAILED) |
409 | if (status & R1_LOCK_UNLOCK_FAILED) |
|
307 | N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); |
410 | N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); |
|
308 | if (status & R1_COM_CRC_ERROR) |
411 | if (status & R1_COM_CRC_ERROR) |
|
309 | N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); |
412 | N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); |
|
310 | if (status & R1_ILLEGAL_COMMAND) |
413 | if (status & R1_ILLEGAL_COMMAND) |
|
311 | N_MSG(RSP, "[CARD_STATUS] Illegal Command"); |
414 | N_MSG(RSP, "[CARD_STATUS] Illegal Command"); |
|
312 | if (status & R1_CARD_ECC_FAILED) |
415 | if (status & R1_CARD_ECC_FAILED) |
|
313 | N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); |
416 | N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); |
|
314 | if (status & R1_CC_ERROR) |
417 | if (status & R1_CC_ERROR) |
|
315 | N_MSG(RSP, "[CARD_STATUS] CC Error"); |
418 | N_MSG(RSP, "[CARD_STATUS] CC Error"); |
|
316 | if (status & R1_ERROR) |
419 | if (status & R1_ERROR) |
|
317 | N_MSG(RSP, "[CARD_STATUS] Error"); |
420 | N_MSG(RSP, "[CARD_STATUS] Error"); |
|
318 | if (status & R1_UNDERRUN) |
421 | if (status & R1_UNDERRUN) |
|
319 | N_MSG(RSP, "[CARD_STATUS] Underrun"); |
422 | N_MSG(RSP, "[CARD_STATUS] Underrun"); |
|
Line 320... | Line 423... | |||
320 | if (status & R1_OVERRUN) |
423 | if (status & R1_OVERRUN) |
|
321 | N_MSG(RSP, "[CARD_STATUS] Overrun"); |
424 | N_MSG(RSP, "[CARD_STATUS] Overrun"); |
|
322 | if (status & R1_CID_CSD_OVERWRITE) |
425 | if (status & R1_CID_CSD_OVERWRITE) |
|
323 | N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); |
426 | N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); |
|
324 | if (status & R1_WP_ERASE_SKIP) |
427 | if (status & R1_WP_ERASE_SKIP) |
|
325 | N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); |
428 | N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); |
|
326 | if (status & R1_CARD_ECC_DISABLED) |
429 | if (status & R1_CARD_ECC_DISABLED) |
|
327 | N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); |
430 | N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); |
|
328 | if (status & R1_ERASE_RESET) |
431 | if (status & R1_ERASE_RESET) |
|
329 | N_MSG(RSP, "[CARD_STATUS] Erase Reset"); |
432 | N_MSG(RSP, "[CARD_STATUS] Erase Reset"); |
|
330 | if (status & R1_READY_FOR_DATA) |
433 | if (status & R1_READY_FOR_DATA) |
|
331 | N_MSG(RSP, "[CARD_STATUS] Ready for Data"); |
434 | N_MSG(RSP, "[CARD_STATUS] Ready for Data"); |
|
332 | if (status & R1_SWITCH_ERROR) |
435 | if (status & R1_SWITCH_ERROR) |
|
333 | N_MSG(RSP, "[CARD_STATUS] Switch error"); |
436 | N_MSG(RSP, "[CARD_STATUS] Switch error"); |
|
334 | if (status & R1_APP_CMD) |
437 | if (status & R1_APP_CMD) |
|
335 | N_MSG(RSP, "[CARD_STATUS] App Command"); |
438 | N_MSG(RSP, "[CARD_STATUS] App Command"); |
|
336 | |
439 | |
|
337 | N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); |
440 | N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); |
|
338 | } |
441 | } |
|
339 | |
442 | |
|
340 | static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) |
443 | static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) |
|
341 | { |
444 | { |
|
342 | if (resp & (1 << 7)) |
445 | if (resp & (1 << 7)) |
|
343 | N_MSG(RSP, "[OCR] Low Voltage Range"); |
446 | N_MSG(RSP, "[OCR] Low Voltage Range"); |
|
344 | if (resp & (1 << 15)) |
447 | if (resp & (1 << 15)) |
|
345 | N_MSG(RSP, "[OCR] 2.7-2.8 volt"); |
448 | N_MSG(RSP, "[OCR] 2.7-2.8 volt"); |
|
346 | if (resp & (1 << 16)) |
449 | if (resp & (1 << 16)) |
|
347 | N_MSG(RSP, "[OCR] 2.8-2.9 volt"); |
450 | N_MSG(RSP, "[OCR] 2.8-2.9 volt"); |
|
348 | if (resp & (1 << 17)) |
451 | if (resp & (1 << 17)) |
|
349 | N_MSG(RSP, "[OCR] 2.9-3.0 volt"); |
452 | N_MSG(RSP, "[OCR] 2.9-3.0 volt"); |
|
350 | if (resp & (1 << 18)) |
453 | if (resp & (1 << 18)) |
|
Line 351... | Line 454... | |||
351 | N_MSG(RSP, "[OCR] 3.0-3.1 volt"); |
454 | N_MSG(RSP, "[OCR] 3.0-3.1 volt"); |
|
352 | if (resp & (1 << 19)) |
455 | if (resp & (1 << 19)) |
|
353 | N_MSG(RSP, "[OCR] 3.1-3.2 volt"); |
456 | N_MSG(RSP, "[OCR] 3.1-3.2 volt"); |
|
354 | if (resp & (1 << 20)) |
457 | if (resp & (1 << 20)) |
|
355 | N_MSG(RSP, "[OCR] 3.2-3.3 volt"); |
458 | N_MSG(RSP, "[OCR] 3.2-3.3 volt"); |
|
356 | if (resp & (1 << 21)) |
459 | if (resp & (1 << 21)) |
|
357 | N_MSG(RSP, "[OCR] 3.3-3.4 volt"); |
460 | N_MSG(RSP, "[OCR] 3.3-3.4 volt"); |
|
358 | if (resp & (1 << 22)) |
461 | if (resp & (1 << 22)) |
|
359 | N_MSG(RSP, "[OCR] 3.4-3.5 volt"); |
462 | N_MSG(RSP, "[OCR] 3.4-3.5 volt"); |
|
360 | if (resp & (1 << 23)) |
463 | if (resp & (1 << 23)) |
|
Line 361... | Line 464... | |||
361 | N_MSG(RSP, "[OCR] 3.5-3.6 volt"); |
464 | N_MSG(RSP, "[OCR] 3.5-3.6 volt"); |
|
362 | if (resp & (1 << 24)) |
465 | if (resp & (1 << 24)) |
|
363 | N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)"); |
466 | N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)"); |
|
364 | if (resp & (1 << 30)) |
- | ||
365 | N_MSG(RSP, "[OCR] Card Capacity Status (CCS)"); |
467 | if (resp & (1 << 30)) |
|
366 | if (resp & (1 << 31)) |
468 | N_MSG(RSP, "[OCR] Card Capacity Status (CCS)"); |
|
367 | N_MSG(RSP, "[OCR] Card Power Up Status (Idle)"); |
469 | if (resp & (1 << 31)) |
|
368 | else |
470 | N_MSG(RSP, "[OCR] Card Power Up Status (Idle)"); |
|
369 | N_MSG(RSP, "[OCR] Card Power Up Status (Busy)"); |
471 | else |
|
370 | } |
472 | N_MSG(RSP, "[OCR] Card Power Up Status (Busy)"); |
|
371 | |
473 | } |
|
372 | static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) |
474 | |
|
373 | { |
475 | static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) |
|
374 | u32 status = (((resp >> 15) & 0x1) << 23) | |
476 | { |
|
375 | (((resp >> 14) & 0x1) << 22) | |
477 | u32 status = (((resp >> 15) & 0x1) << 23) | |
|
376 | (((resp >> 13) & 0x1) << 19) | |
478 | (((resp >> 14) & 0x1) << 22) | |
|
377 | (resp & 0x1fff); |
479 | (((resp >> 13) & 0x1) << 19) | |
|
378 | |
480 | (resp & 0x1fff); |
|
Line 379... | Line 481... | |||
379 | N_MSG(RSP, "[RCA] 0x%.4x", resp >> 16); |
481 | |
|
380 | msdc_dump_card_status(host, status); |
482 | N_MSG(RSP, "[RCA] 0x%.4x", resp >> 16); |
|
381 | } |
483 | msdc_dump_card_status(host, status); |
|
Line 382... | Line 484... | |||
382 | |
484 | } |
|
383 | static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) |
485 | |
|
384 | { |
486 | static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) |
|
385 | u32 flags = (resp >> 8) & 0xFF; |
487 | { |
|
- | 488 | u32 flags = (resp >> 8) & 0xFF; |
||
- | 489 | char *state[] = {"DIS", "CMD", "TRN", "RFU"}; |
||
- | 490 | |
||
- | 491 | if (flags & (1 << 7)) |
||
- | 492 | N_MSG(RSP, "[IO] COM_CRC_ERR"); |
||
- | 493 | if (flags & (1 << 6)) |
||
- | 494 | N_MSG(RSP, "[IO] Illgal command"); |
||
- | 495 | if (flags & (1 << 3)) |
||
- | 496 | N_MSG(RSP, "[IO] Error"); |
||
- | 497 | if (flags & (1 << 2)) |
||
- | 498 | N_MSG(RSP, "[IO] RFU"); |
||
- | 499 | if (flags & (1 << 1)) |
||
- | 500 | N_MSG(RSP, "[IO] Function number error"); |
||
- | 501 | if (flags & (1 << 0)) |
||
- | 502 | N_MSG(RSP, "[IO] Out of range"); |
||
- | 503 | |
||
- | 504 | N_MSG(RSP, "[IO] State: %s, Data:0x%x", state[(resp >> 12) & 0x3], resp & 0xFF); |
||
- | 505 | } |
||
- | 506 | #endif |
||
- | 507 | |
||
Line 386... | Line -... | |||
386 | #if 0 |
- | ||
387 | char *state[] = {"DIS", "CMD", "TRN", "RFU"}; |
508 | static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) |
|
Line 388... | Line 509... | |||
388 | #endif |
509 | { |
|
389 | if (flags & (1 << 7)) |
- | ||
- | 510 | u32 base = host->base; |
||
- | 511 | u32 timeout, clk_ns; |
||
390 | N_MSG(RSP, "[IO] COM_CRC_ERR"); |
512 | |
|
391 | if (flags & (1 << 6)) |
513 | host->timeout_ns = ns; |
|
- | 514 | host->timeout_clks = clks; |
||
392 | N_MSG(RSP, "[IO] Illgal command"); |
515 | |
|
Line 393... | Line 516... | |||
393 | if (flags & (1 << 3)) |
516 | clk_ns = 1000000000UL / host->sclk; |
|
Line -... | Line 517... | |||
- | 517 | timeout = ns / clk_ns + clks; |
||
394 | N_MSG(RSP, "[IO] Error"); |
518 | timeout = timeout >> 16; /* in 65536 sclk cycle unit */ |
|
- | 519 | timeout = timeout > 1 ? timeout - 1 : 0; |
||
395 | if (flags & (1 << 2)) |
520 | timeout = timeout > 255 ? 255 : timeout; |
|
- | 521 | |
||
396 | N_MSG(RSP, "[IO] RFU"); |
522 | sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout); |
|
Line -... | Line 523... | |||
- | 523 | |
||
- | 524 | N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles", |
||
- | 525 | ns, clks, timeout + 1); |
||
- | 526 | } |
||
- | 527 | |
||
397 | if (flags & (1 << 1)) |
528 | /* msdc_eirq_sdio() will be called when EIRQ(for WIFI) */ |
|
398 | N_MSG(RSP, "[IO] Function number error"); |
529 | static void msdc_eirq_sdio(void *data) |
|
399 | if (flags & (1 << 0)) |
530 | { |
|
400 | N_MSG(RSP, "[IO] Out of range"); |
531 | struct msdc_host *host = (struct msdc_host *)data; |
|
- | 532 | |
||
- | 533 | N_MSG(INT, "SDIO EINT"); |
||
401 | |
534 | |
|
402 | N_MSG(RSP, "[IO] State: %s, Data:0x%x", state[(resp >> 12) & 0x3], resp & 0xFF); |
535 | mmc_signal_sdio_irq(host->mmc); |
|
403 | } |
536 | } |
|
404 | #endif |
537 | |
|
Line 405... | Line 538... | |||
405 | |
538 | /* msdc_eirq_cd will not be used! We not using EINT for card detection. */ |
|
Line -... | Line 539... | |||
- | 539 | static void msdc_eirq_cd(void *data) |
||
- | 540 | { |
||
- | 541 | struct msdc_host *host = (struct msdc_host *)data; |
||
406 | static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) |
542 | |
|
407 | { |
543 | N_MSG(INT, "CD EINT"); |
|
408 | void __iomem *base = host->base; |
544 | |
|
409 | u32 timeout, clk_ns; |
545 | #if 0 |
|
410 | |
546 | tasklet_hi_schedule(&host->card_tasklet); |
|
- | 547 | #else |
||
- | 548 | schedule_delayed_work(&host->card_delaywork, HZ); |
||
- | 549 | #endif |
||
Line 411... | Line 550... | |||
411 | host->timeout_ns = ns; |
550 | } |
|
412 | host->timeout_clks = clks; |
551 | |
|
413 | |
552 | #if 0 |
|
414 | clk_ns = 1000000000UL / host->sclk; |
553 | static void msdc_tasklet_card(unsigned long arg) |
|
415 | timeout = ns / clk_ns + clks; |
554 | { |
|
416 | timeout = timeout >> 16; /* in 65536 sclk cycle unit */ |
555 | struct msdc_host *host = (struct msdc_host *)arg; |
|
417 | timeout = timeout > 1 ? timeout - 1 : 0; |
556 | #else |
|
- | 557 | static void msdc_tasklet_card(struct work_struct *work) |
||
418 | timeout = timeout > 255 ? 255 : timeout; |
558 | { |
|
419 | |
559 | struct msdc_host *host = (struct msdc_host *)container_of(work, |
|
420 | sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout); |
560 | struct msdc_host, card_delaywork.work); |
|
421 | |
561 | #endif |
|
422 | N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles", |
562 | struct msdc_hw *hw = host->hw; |
|
423 | ns, clks, timeout + 1); |
563 | u32 base = host->base; |
|
424 | } |
564 | u32 inserted; |
|
425 | |
565 | u32 status = 0; |
|
426 | static void msdc_tasklet_card(struct work_struct *work) |
566 | //u32 change = 0; |
|
427 | { |
567 | |
|
428 | struct msdc_host *host = (struct msdc_host *)container_of(work, |
568 | spin_lock(&host->lock); |
|
429 | struct msdc_host, card_delaywork.work); |
569 | |
|
Line 430... | Line 570... | |||
430 | void __iomem *base = host->base; |
570 | if (hw->get_cd_status) { // NULL |
|
431 | u32 inserted; |
571 | inserted = hw->get_cd_status(); |
|
Line 432... | Line 572... | |||
432 | u32 status = 0; |
572 | } else { |
|
433 | //u32 change = 0; |
573 | status = sdr_read32(MSDC_PS); |
|
434 | |
574 | if (cd_active_low) |
|
435 | spin_lock(&host->lock); |
575 | inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; |
|
436 | |
576 | else |
|
Line 437... | Line 577... | |||
437 | status = sdr_read32(MSDC_PS); |
577 | inserted = (status & MSDC_PS_CDSTS) ? 1 : 0; |
|
438 | if (cd_active_low) |
578 | } |
|
439 | inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; |
579 | if (host->mmc->caps & MMC_CAP_NEEDS_POLL) |
|
440 | else |
580 | inserted = 1; |
|
441 | inserted = (status & MSDC_PS_CDSTS) ? 1 : 0; |
581 | |
|
442 | |
582 | #if 0 |
|
443 | #if 0 |
583 | change = host->card_inserted ^ inserted; |
|
444 | change = host->card_inserted ^ inserted; |
584 | host->card_inserted = inserted; |
|
445 | host->card_inserted = inserted; |
585 | |
|
446 | |
586 | if (change && !host->suspend) { |
|
447 | if (change && !host->suspend) { |
587 | if (inserted) { |
|
448 | if (inserted) |
588 | host->mmc->f_max = HOST_MAX_MCLK; // work around |
|
449 | host->mmc->f_max = HOST_MAX_MCLK; // work around |
589 | } |
|
450 | mmc_detect_change(host->mmc, msecs_to_jiffies(20)); |
590 | mmc_detect_change(host->mmc, msecs_to_jiffies(20)); |
|
451 | } |
591 | } |
|
452 | #else /* Make sure: handle the last interrupt */ |
592 | #else /* Make sure: handle the last interrupt */ |
|
453 | host->card_inserted = inserted; |
593 | host->card_inserted = inserted; |
|
454 | |
594 | |
|
455 | if (!host->suspend) { |
595 | if (!host->suspend) { |
|
456 | host->mmc->f_max = HOST_MAX_MCLK; |
596 | host->mmc->f_max = HOST_MAX_MCLK; |
|
457 | mmc_detect_change(host->mmc, msecs_to_jiffies(20)); |
597 | mmc_detect_change(host->mmc, msecs_to_jiffies(20)); |
|
Line 458... | Line 598... | |||
458 | } |
598 | } |
|
459 | |
599 | |
|
460 | IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed"); |
600 | IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed"); |
|
461 | #endif |
601 | #endif |
|
462 | |
602 | |
|
463 | spin_unlock(&host->lock); |
603 | spin_unlock(&host->lock); |
|
464 | } |
604 | } |
|
465 | |
605 | |
|
466 | #if 0 /* --- by chhung */ |
606 | #if 0 /* --- by chhung */ |
|
467 | /* For E2 only */ |
607 | /* For E2 only */ |
|
468 | static u8 clk_src_bit[4] = { |
608 | static u8 clk_src_bit[4] = { |
|
469 | 0, 3, 5, 7 |
609 | 0, 3, 5, 7 |
|
470 | }; |
610 | }; |
|
471 | |
611 | |
|
472 | static void msdc_select_clksrc(struct msdc_host *host, unsigned char clksrc) |
612 | static void msdc_select_clksrc(struct msdc_host* host, unsigned char clksrc) |
|
473 | { |
613 | { |
|
474 | u32 val; |
614 | u32 val; |
|
475 | void __iomem *base = host->base; |
615 | u32 base = host->base; |
|
476 | |
616 | |
|
- | 617 | BUG_ON(clksrc > 3); |
||
- | 618 | INIT_MSG("set clock source to <%d>", clksrc); |
||
- | 619 | |
||
- | 620 | val = sdr_read32(MSDC_CLKSRC_REG); |
||
- | 621 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
||
- | 622 | val &= ~(0x3 << clk_src_bit[host->id]); |
||
- | 623 | val |= clksrc << clk_src_bit[host->id]; |
||
- | 624 | } else { |
||
- | 625 | val &= ~0x3; val |= clksrc; |
||
- | 626 | } |
||
477 | BUG_ON(clksrc > 3); |
627 | sdr_write32(MSDC_CLKSRC_REG, val); |
|
478 | INIT_MSG("set clock source to <%d>", clksrc); |
628 | |
|
479 | |
629 | host->hclk = hclks[clksrc]; |
|
480 | val = sdr_read32(MSDC_CLKSRC_REG); |
630 | host->hw->clk_src = clksrc; |
|
481 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
631 | } |
|
482 | val &= ~(0x3 << clk_src_bit[host->id]); |
632 | #endif /* end of --- */ |
|
483 | val |= clksrc << clk_src_bit[host->id]; |
633 | |
|
484 | } else { |
634 | static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) |
|
485 | val &= ~0x3; val |= clksrc; |
635 | { |
|
486 | } |
636 | //struct msdc_hw *hw = host->hw; |
|
487 | sdr_write32(MSDC_CLKSRC_REG, val); |
637 | u32 base = host->base; |
|
488 | |
638 | u32 mode; |
|
489 | host->hclk = hclks[clksrc]; |
639 | u32 flags; |
|
490 | host->hw->clk_src = clksrc; |
640 | u32 div; |
|
491 | } |
641 | u32 sclk; |
|
492 | #endif /* end of --- */ |
642 | u32 hclk = host->hclk; |
|
493 | |
643 | //u8 clksrc = hw->clk_src; |
|
494 | static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) |
644 | |
|
495 | { |
645 | if (!hz) { // set mmc system clock to 0 ? |
|
496 | //struct msdc_hw *hw = host->hw; |
646 | //ERR_MSG("set mclk to 0!!!"); |
|
497 | void __iomem *base = host->base; |
647 | msdc_reset(); |
|
498 | u32 mode; |
648 | return; |
|
499 | u32 flags; |
649 | } |
|
500 | u32 div; |
650 | |
|
501 | u32 sclk; |
651 | msdc_irq_save(flags); |
|
502 | u32 hclk = host->hclk; |
652 | |
|
503 | //u8 clksrc = hw->clk_src; |
653 | #if defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7628_FPGA) |
|
504 | |
654 | mode = 0x0; /* use divisor */ |
|
505 | if (!hz) { // set mmc system clock to 0 ? |
655 | if (hz >= (hclk >> 1)) { |
|
506 | //ERR_MSG("set mclk to 0!!!"); |
656 | div = 0; /* mean div = 1/2 */ |
|
507 | msdc_reset_hw(host); |
- | ||
508 | return; |
657 | sclk = hclk >> 1; /* sclk = clk / 2 */ |
|
509 | } |
658 | } else { |
|
510 | |
659 | div = (hclk + ((hz << 2) - 1)) / (hz << 2); |
|
511 | msdc_irq_save(flags); |
660 | sclk = (hclk >> 2) / div; |
|
512 | |
661 | } |
|
513 | if (ddr) { |
662 | #else |
|
514 | mode = 0x2; /* ddr mode and use divisor */ |
663 | if (ddr) { |
|
515 | if (hz >= (hclk >> 2)) { |
664 | mode = 0x2; /* ddr mode and use divisor */ |
|
Line 516... | Line 665... | |||
516 | div = 1; /* mean div = 1/4 */ |
665 | if (hz >= (hclk >> 2)) { |
|
517 | sclk = hclk >> 2; /* sclk = clk / 4 */ |
666 | div = 1; /* mean div = 1/4 */ |
|
Line 518... | Line 667... | |||
518 | } else { |
667 | sclk = hclk >> 2; /* sclk = clk / 4 */ |
|
519 | div = (hclk + ((hz << 2) - 1)) / (hz << 2); |
668 | } else { |
|
520 | sclk = (hclk >> 2) / div; |
669 | div = (hclk + ((hz << 2) - 1)) / (hz << 2); |
|
521 | } |
670 | sclk = (hclk >> 2) / div; |
|
522 | } else if (hz >= hclk) { /* bug fix */ |
671 | } |
|
Line 523... | Line 672... | |||
523 | mode = 0x1; /* no divisor and divisor is ignored */ |
672 | } else if (hz >= hclk) { /* bug fix */ |
|
524 | div = 0; |
673 | mode = 0x1; /* no divisor and divisor is ignored */ |
|
525 | sclk = hclk; |
674 | div = 0; |
|
526 | } else { |
675 | sclk = hclk; |
|
527 | mode = 0x0; /* use divisor */ |
676 | } else { |
|
528 | if (hz >= (hclk >> 1)) { |
677 | mode = 0x0; /* use divisor */ |
|
529 | div = 0; /* mean div = 1/2 */ |
678 | if (hz >= (hclk >> 1)) { |
|
530 | sclk = hclk >> 1; /* sclk = clk / 2 */ |
679 | div = 0; /* mean div = 1/2 */ |
|
531 | } else { |
680 | sclk = hclk >> 1; /* sclk = clk / 2 */ |
|
532 | div = (hclk + ((hz << 2) - 1)) / (hz << 2); |
681 | } else { |
|
533 | sclk = (hclk >> 2) / div; |
682 | div = (hclk + ((hz << 2) - 1)) / (hz << 2); |
|
534 | } |
683 | sclk = (hclk >> 2) / div; |
|
535 | } |
684 | } |
|
536 | |
685 | } |
|
537 | /* set clock mode and divisor */ |
686 | #endif |
|
538 | sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode); |
687 | /* set clock mode and divisor */ |
|
539 | sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div); |
688 | sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode); |
|
Line 540... | Line 689... | |||
540 | |
689 | sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div); |
|
541 | /* wait clock stable */ |
690 | |
|
542 | while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB)) |
691 | /* wait clock stable */ |
|
543 | cpu_relax(); |
692 | while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB)); |
|
544 | |
693 | |
|
545 | host->sclk = sclk; |
694 | host->sclk = sclk; |
|
546 | host->mclk = hz; |
695 | host->mclk = hz; |
|
547 | msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need? |
696 | msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need? |
|
548 | |
697 | |
|
549 | INIT_MSG("================"); |
698 | INIT_MSG("================"); |
|
550 | INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz / 1000, hclk / 1000, sclk / 1000); |
699 | INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz/1000, hclk/1000, sclk/1000); |
|
551 | INIT_MSG("================"); |
700 | INIT_MSG("================"); |
|
552 | |
701 | |
|
553 | msdc_irq_restore(flags); |
702 | msdc_irq_restore(flags); |
|
554 | } |
703 | } |
|
555 | |
704 | |
|
556 | /* Fix me. when need to abort */ |
705 | /* Fix me. when need to abort */ |
|
557 | static void msdc_abort_data(struct msdc_host *host) |
706 | static void msdc_abort_data(struct msdc_host *host) |
|
558 | { |
707 | { |
|
559 | void __iomem *base = host->base; |
708 | u32 base = host->base; |
|
560 | struct mmc_command *stop = host->mrq->stop; |
709 | struct mmc_command *stop = host->mrq->stop; |
|
561 | |
710 | |
|
562 | ERR_MSG("Need to Abort."); |
711 | ERR_MSG("Need to Abort. dma<%d>", host->dma_xfer); |
|
563 | |
712 | |
|
564 | msdc_reset_hw(host); |
713 | msdc_reset(); |
|
565 | msdc_clr_fifo(); |
714 | msdc_clr_fifo(); |
|
566 | msdc_clr_int(); |
715 | msdc_clr_int(); |
|
567 | |
716 | |
|
568 | // need to check FIFO count 0 ? |
717 | // need to check FIFO count 0 ? |
|
569 | |
718 | |
|
570 | if (stop) { /* try to stop, but may not success */ |
719 | if (stop) { /* try to stop, but may not success */ |
|
571 | ERR_MSG("stop when abort CMD<%d>", stop->opcode); |
720 | ERR_MSG("stop when abort CMD<%d>", stop->opcode); |
|
572 | (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT); |
721 | (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT); |
|
573 | } |
722 | } |
|
574 | |
723 | |
|
575 | //if (host->mclk >= 25000000) { |
724 | //if (host->mclk >= 25000000) { |
|
576 | // msdc_set_mclk(host, 0, host->mclk >> 1); |
725 | // msdc_set_mclk(host, 0, host->mclk >> 1); |
|
577 | //} |
726 | //} |
|
578 | } |
727 | } |
|
579 | |
728 | |
|
580 | #if 0 /* --- by chhung */ |
729 | #if 0 /* --- by chhung */ |
|
581 | static void msdc_pin_config(struct msdc_host *host, int mode) |
730 | static void msdc_pin_config(struct msdc_host *host, int mode) |
|
582 | { |
731 | { |
|
583 | struct msdc_hw *hw = host->hw; |
732 | struct msdc_hw *hw = host->hw; |
|
Line 584... | Line 733... | |||
584 | void __iomem *base = host->base; |
733 | u32 base = host->base; |
|
585 | int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; |
734 | int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; |
|
586 | |
735 | |
|
587 | /* Config WP pin */ |
736 | /* Config WP pin */ |
|
588 | if (hw->flags & MSDC_WP_PIN_EN) { |
737 | if (hw->flags & MSDC_WP_PIN_EN) { |
|
589 | if (hw->config_gpio_pin) /* NULL */ |
738 | if (hw->config_gpio_pin) /* NULL */ |
|
590 | hw->config_gpio_pin(MSDC_WP_PIN, pull); |
739 | hw->config_gpio_pin(MSDC_WP_PIN, pull); |
|
591 | } |
740 | } |
|
592 | |
741 | |
|
593 | switch (mode) { |
742 | switch (mode) { |
|
594 | case MSDC_PIN_PULL_UP: |
743 | case MSDC_PIN_PULL_UP: |
|
595 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */ |
744 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */ |
|
596 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ |
745 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ |
|
597 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1); |
746 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1); |
|
598 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); |
747 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); |
|
- | 748 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1); |
||
599 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1); |
749 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); |
|
600 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); |
750 | break; |
|
Line 601... | Line 751... | |||
601 | break; |
751 | case MSDC_PIN_PULL_DOWN: |
|
602 | case MSDC_PIN_PULL_DOWN: |
752 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ |
|
603 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ |
753 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */ |
|
604 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */ |
754 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); |
|
Line 605... | Line 755... | |||
605 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); |
755 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1); |
|
606 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1); |
756 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); |
|
607 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); |
757 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1); |
|
608 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1); |
758 | break; |
|
609 | break; |
759 | case MSDC_PIN_PULL_NONE: |
|
610 | case MSDC_PIN_PULL_NONE: |
760 | default: |
|
611 | default: |
761 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ |
|
612 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ |
762 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ |
|
613 | //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ |
763 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); |
|
614 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); |
764 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); |
|
Line 615... | Line 765... | |||
615 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); |
765 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); |
|
616 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); |
766 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); |
|
617 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); |
767 | break; |
|
Line 618... | Line 768... | |||
618 | break; |
768 | } |
|
619 | } |
769 | |
|
620 | |
770 | N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", |
|
621 | N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", |
771 | mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP); |
|
622 | mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP); |
772 | } |
|
623 | } |
773 | |
|
624 | |
774 | void msdc_pin_reset(struct msdc_host *host, int mode) |
|
625 | void msdc_pin_reset(struct msdc_host *host, int mode) |
775 | { |
|
Line 626... | Line 776... | |||
626 | { |
776 | struct msdc_hw *hw = (struct msdc_hw *)host->hw; |
|
627 | struct msdc_hw *hw = (struct msdc_hw *)host->hw; |
777 | u32 base = host->base; |
|
628 | void __iomem *base = host->base; |
778 | int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; |
|
Line 629... | Line 779... | |||
629 | int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; |
779 | |
|
630 | |
780 | /* Config reset pin */ |
|
- | 781 | if (hw->flags & MSDC_RST_PIN_EN) { |
||
- | 782 | if (hw->config_gpio_pin) /* NULL */ |
||
- | 783 | hw->config_gpio_pin(MSDC_RST_PIN, pull); |
||
631 | /* Config reset pin */ |
784 | |
|
- | 785 | if (mode == MSDC_PIN_PULL_UP) { |
||
632 | if (hw->flags & MSDC_RST_PIN_EN) { |
786 | sdr_clr_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); |
|
633 | if (hw->config_gpio_pin) /* NULL */ |
787 | } else { |
|
- | 788 | sdr_set_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); |
||
- | 789 | } |
||
- | 790 | } |
||
634 | hw->config_gpio_pin(MSDC_RST_PIN, pull); |
791 | } |
|
- | 792 | |
||
635 | |
793 | static void msdc_core_power(struct msdc_host *host, int on) |
|
636 | if (mode == MSDC_PIN_PULL_UP) |
794 | { |
|
637 | sdr_clr_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); |
795 | N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", |
|
638 | else |
796 | on ? "on" : "off", "core", host->core_power, on); |
|
Line 639... | Line 797... | |||
639 | sdr_set_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); |
797 | |
|
640 | } |
798 | if (on && host->core_power == 0) { |
|
641 | } |
799 | msdc_vcore_on(host); |
|
Line 642... | Line 800... | |||
642 | |
800 | host->core_power = 1; |
|
643 | static void msdc_core_power(struct msdc_host *host, int on) |
801 | msleep(1); |
|
644 | { |
802 | } else if (!on && host->core_power == 1) { |
|
645 | N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", |
803 | msdc_vcore_off(host); |
|
646 | on ? "on" : "off", "core", host->core_power, on); |
804 | host->core_power = 0; |
|
647 | |
805 | msleep(1); |
|
648 | if (on && host->core_power == 0) { |
806 | } |
|
649 | msdc_vcore_on(host); |
807 | } |
|
650 | host->core_power = 1; |
808 | |
|
651 | msleep(1); |
809 | static void msdc_host_power(struct msdc_host *host, int on) |
|
Line 652... | Line 810... | |||
652 | } else if (!on && host->core_power == 1) { |
810 | { |
|
653 | msdc_vcore_off(host); |
811 | N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host"); |
|
654 | host->core_power = 0; |
812 | |
|
655 | msleep(1); |
813 | if (on) { |
|
656 | } |
814 | //msdc_core_power(host, 1); // need do card detection. |
|
657 | } |
815 | msdc_pin_reset(host, MSDC_PIN_PULL_UP); |
|
658 | |
816 | } else { |
|
659 | static void msdc_host_power(struct msdc_host *host, int on) |
817 | msdc_pin_reset(host, MSDC_PIN_PULL_DOWN); |
|
660 | { |
818 | //msdc_core_power(host, 0); |
|
Line 661... | Line 819... | |||
661 | N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host"); |
819 | } |
|
662 | |
820 | } |
|
663 | if (on) { |
821 | |
|
664 | //msdc_core_power(host, 1); // need do card detection. |
822 | static void msdc_card_power(struct msdc_host *host, int on) |
|
665 | msdc_pin_reset(host, MSDC_PIN_PULL_UP); |
823 | { |
|
666 | } else { |
824 | N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card"); |
|
667 | msdc_pin_reset(host, MSDC_PIN_PULL_DOWN); |
825 | |
|
668 | //msdc_core_power(host, 0); |
826 | if (on) { |
|
669 | } |
827 | msdc_pin_config(host, MSDC_PIN_PULL_UP); |
|
670 | } |
828 | if (host->hw->ext_power_on) { |
|
671 | |
829 | host->hw->ext_power_on(); |
|
672 | static void msdc_card_power(struct msdc_host *host, int on) |
830 | } else { |
|
673 | { |
831 | //msdc_vdd_on(host); // need todo card detection. |
|
674 | N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card"); |
832 | } |
|
675 | |
833 | msleep(1); |
|
676 | if (on) { |
834 | } else { |
|
677 | msdc_pin_config(host, MSDC_PIN_PULL_UP); |
835 | if (host->hw->ext_power_off) { |
|
- | 836 | host->hw->ext_power_off(); |
||
- | 837 | } else { |
||
- | 838 | //msdc_vdd_off(host); |
||
- | 839 | } |
||
- | 840 | msdc_pin_config(host, MSDC_PIN_PULL_DOWN); |
||
- | 841 | msleep(1); |
||
- | 842 | } |
||
678 | //msdc_vdd_on(host); // need todo card detection. |
843 | } |
|
679 | msleep(1); |
844 | |
|
680 | } else { |
845 | static void msdc_set_power_mode(struct msdc_host *host, u8 mode) |
|
681 | //msdc_vdd_off(host); |
846 | { |
|
682 | msdc_pin_config(host, MSDC_PIN_PULL_DOWN); |
847 | N_MSG(CFG, "Set power mode(%d)", mode); |
|
683 | msleep(1); |
848 | |
|
684 | } |
849 | if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { |
|
685 | } |
850 | msdc_host_power(host, 1); |
|
686 | |
851 | msdc_card_power(host, 1); |
|
687 | static void msdc_set_power_mode(struct msdc_host *host, u8 mode) |
852 | } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { |
|
688 | { |
853 | msdc_card_power(host, 0); |
|
689 | N_MSG(CFG, "Set power mode(%d)", mode); |
854 | msdc_host_power(host, 0); |
|
690 | |
855 | } |
|
691 | if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { |
856 | host->power_mode = mode; |
|
692 | msdc_host_power(host, 1); |
857 | } |
|
- | 858 | #endif /* end of --- */ |
||
- | 859 | |
||
- | 860 | #ifdef CONFIG_PM |
||
- | 861 | /* |
||
- | 862 | register as callback function of WIFI(combo_sdio_register_pm) . |
||
- | 863 | can called by msdc_drv_suspend/resume too. |
||
- | 864 | */ |
||
- | 865 | static void msdc_pm(pm_message_t state, void *data) |
||
693 | msdc_card_power(host, 1); |
866 | { |
|
694 | } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { |
867 | struct msdc_host *host = (struct msdc_host *)data; |
|
695 | msdc_card_power(host, 0); |
868 | int evt = state.event; |
|
Line 696... | Line 869... | |||
696 | msdc_host_power(host, 0); |
869 | |
|
697 | } |
870 | if (evt == PM_EVENT_USER_RESUME || evt == PM_EVENT_USER_SUSPEND) { |
|
698 | host->power_mode = mode; |
871 | INIT_MSG("USR_%s: suspend<%d> power<%d>", |
|
Line 788... | Line -... | |||
788 | case MMC_RSP_R1B: |
- | ||
789 | resp = RESP_R1B; |
- | ||
790 | break; |
- | ||
791 | case MMC_RSP_R2: |
- | ||
792 | resp = RESP_R2; |
- | ||
793 | break; |
- | ||
794 | case MMC_RSP_R3: |
- | ||
795 | resp = RESP_R3; |
- | ||
796 | break; |
- | ||
797 | case MMC_RSP_NONE: |
- | ||
798 | default: |
- | ||
799 | resp = RESP_NONE; |
- | ||
800 | break; |
- | ||
801 | } |
- | ||
802 | } |
- | ||
803 | |
- | ||
804 | cmd->error = 0; |
- | ||
805 | /* rawcmd : |
- | ||
806 | * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | |
- | ||
807 | * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode |
- | ||
808 | */ |
- | ||
809 | rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; |
- | ||
810 | |
- | ||
811 | if (opcode == MMC_READ_MULTIPLE_BLOCK) { |
- | ||
812 | rawcmd |= (2 << 11); |
- | ||
813 | } else if (opcode == MMC_READ_SINGLE_BLOCK) { |
- | ||
814 | rawcmd |= (1 << 11); |
- | ||
815 | } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) { |
- | ||
816 | rawcmd |= ((2 << 11) | (1 << 13)); |
- | ||
817 | } else if (opcode == MMC_WRITE_BLOCK) { |
- | ||
818 | rawcmd |= ((1 << 11) | (1 << 13)); |
- | ||
819 | } else if (opcode == SD_IO_RW_EXTENDED) { |
- | ||
820 | if (cmd->data->flags & MMC_DATA_WRITE) |
- | ||
821 | rawcmd |= (1 << 13); |
- | ||
822 | if (cmd->data->blocks > 1) |
- | ||
823 | rawcmd |= (2 << 11); |
- | ||
824 | else |
- | ||
825 | rawcmd |= (1 << 11); |
- | ||
826 | } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) { |
- | ||
827 | rawcmd |= (1 << 14); |
- | ||
828 | } else if ((opcode == SD_APP_SEND_SCR) || |
- | ||
829 | (opcode == SD_APP_SEND_NUM_WR_BLKS) || |
- | ||
830 | (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || |
- | ||
831 | (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || |
- | ||
832 | (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) { |
- | ||
833 | rawcmd |= (1 << 11); |
- | ||
834 | } else if (opcode == MMC_STOP_TRANSMISSION) { |
- | ||
835 | rawcmd |= (1 << 14); |
- | ||
836 | rawcmd &= ~(0x0FFF << 16); |
- | ||
837 | } |
- | ||
838 | |
- | ||
839 | N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode, rawcmd, cmd->arg); |
- | ||
840 | |
- | ||
841 | tmo = jiffies + timeout; |
- | ||
842 | |
- | ||
843 | if (opcode == MMC_SEND_STATUS) { |
- | ||
844 | for (;;) { |
- | ||
845 | if (!sdc_is_cmd_busy()) |
- | ||
846 | break; |
- | ||
847 | |
- | ||
848 | if (time_after(jiffies, tmo)) { |
- | ||
849 | ERR_MSG("XXX cmd_busy timeout: before CMD<%d>", opcode); |
- | ||
850 | cmd->error = -ETIMEDOUT; |
- | ||
851 | msdc_reset_hw(host); |
- | ||
852 | goto end; |
- | ||
853 | } |
- | ||
854 | } |
- | ||
855 | } else { |
- | ||
856 | for (;;) { |
1028 | }else { |
|
857 | if (!sdc_is_busy()) |
1029 | for (;;) { |
|
Line 858... | Line 1030... | |||
858 | break; |
1030 | if (!sdc_is_busy()) |
|
859 | if (time_after(jiffies, tmo)) { |
1031 | break; |
|
860 | ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", opcode); |
1032 | if (time_after(jiffies, tmo)) { |
|
861 | cmd->error = -ETIMEDOUT; |
1033 | ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", opcode); |
|
862 | msdc_reset_hw(host); |
1034 | cmd->error = (unsigned int)-ETIMEDOUT; |
|
863 | goto end; |
1035 | msdc_reset(); |
|
864 | } |
1036 | goto end; |
|
865 | } |
1037 | } |
|
866 | } |
1038 | } |
|
867 | |
1039 | } |
|
868 | //BUG_ON(in_interrupt()); |
1040 | |
|
869 | host->cmd = cmd; |
1041 | //BUG_ON(in_interrupt()); |
|
870 | host->cmd_rsp = resp; |
1042 | host->cmd = cmd; |
|
871 | |
1043 | host->cmd_rsp = resp; |
|
872 | init_completion(&host->cmd_done); |
1044 | |
|
873 | |
1045 | init_completion(&host->cmd_done); |
|
874 | sdr_set_bits(MSDC_INTEN, wints); |
1046 | |
|
875 | sdc_send_cmd(rawcmd, cmd->arg); |
1047 | sdr_set_bits(MSDC_INTEN, wints); |
|
876 | |
1048 | sdc_send_cmd(rawcmd, cmd->arg); |
|
877 | end: |
1049 | |
|
878 | return cmd->error; |
1050 | end: |
|
879 | } |
1051 | return cmd->error; |
|
880 | |
1052 | } |
|
881 | static unsigned int msdc_command_resp(struct msdc_host *host, |
1053 | |
|
882 | struct mmc_command *cmd, |
1054 | static unsigned int msdc_command_resp(struct msdc_host *host, |
|
883 | int tune, |
1055 | struct mmc_command *cmd, |
|
884 | unsigned long timeout) |
1056 | int tune, |
|
885 | __must_hold(&host->lock) |
1057 | unsigned long timeout) |
|
886 | { |
1058 | { |
|
887 | void __iomem *base = host->base; |
1059 | u32 base = host->base; |
|
888 | u32 opcode = cmd->opcode; |
1060 | u32 opcode = cmd->opcode; |
|
889 | //u32 rawcmd; |
1061 | //u32 rawcmd; |
|
890 | u32 resp; |
1062 | u32 resp; |
|
891 | u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | |
1063 | u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | |
|
892 | MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | |
1064 | MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | |
|
893 | MSDC_INT_ACMD19_DONE; |
1065 | MSDC_INT_ACMD19_DONE; |
|
894 | |
1066 | |
|
895 | resp = host->cmd_rsp; |
1067 | resp = host->cmd_rsp; |
|
896 | |
1068 | |
|
- | 1069 | BUG_ON(in_interrupt()); |
||
897 | BUG_ON(in_interrupt()); |
1070 | //init_completion(&host->cmd_done); |
|
898 | //init_completion(&host->cmd_done); |
1071 | //sdr_set_bits(MSDC_INTEN, wints); |
|
899 | //sdr_set_bits(MSDC_INTEN, wints); |
1072 | |
|
900 | |
1073 | spin_unlock(&host->lock); |
|
901 | spin_unlock(&host->lock); |
1074 | if(!wait_for_completion_timeout(&host->cmd_done, 10*timeout)){ |
|
902 | if (!wait_for_completion_timeout(&host->cmd_done, 10 * timeout)) { |
1075 | ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg); |
|
903 | ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg); |
1076 | cmd->error = (unsigned int)-ETIMEDOUT; |
|
904 | cmd->error = -ETIMEDOUT; |
1077 | msdc_reset(); |
|
905 | msdc_reset_hw(host); |
1078 | } |
|
906 | } |
1079 | spin_lock(&host->lock); |
|
907 | spin_lock(&host->lock); |
1080 | |
|
908 | |
1081 | sdr_clr_bits(MSDC_INTEN, wints); |
|
909 | sdr_clr_bits(MSDC_INTEN, wints); |
1082 | host->cmd = NULL; |
|
910 | host->cmd = NULL; |
1083 | |
|
911 | |
1084 | //end: |
|
912 | //end: |
1085 | #ifdef MT6575_SD_DEBUG |
|
913 | #ifdef MT6575_SD_DEBUG |
1086 | switch (resp) { |
|
914 | switch (resp) { |
1087 | case RESP_NONE: |
|
915 | case RESP_NONE: |
1088 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp); |
|
- | 1089 | break; |
||
- | 1090 | case RESP_R2: |
||
- | 1091 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", |
||
- | 1092 | opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], |
||
- | 1093 | cmd->resp[2], cmd->resp[3]); |
||
- | 1094 | break; |
||
- | 1095 | default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ |
||
- | 1096 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", |
||
- | 1097 | opcode, cmd->error, resp, cmd->resp[0]); |
||
- | 1098 | if (cmd->error == 0) { |
||
- | 1099 | switch (resp) { |
||
- | 1100 | case RESP_R1: |
||
- | 1101 | case RESP_R1B: |
||
- | 1102 | msdc_dump_card_status(host, cmd->resp[0]); |
||
- | 1103 | break; |
||
- | 1104 | case RESP_R3: |
||
916 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp); |
1105 | msdc_dump_ocr_reg(host, cmd->resp[0]); |
|
- | 1106 | break; |
||
917 | break; |
1107 | case RESP_R5: |
|
- | 1108 | msdc_dump_io_resp(host, cmd->resp[0]); |
||
- | 1109 | break; |
||
- | 1110 | case RESP_R6: |
||
- | 1111 | msdc_dump_rca_resp(host, cmd->resp[0]); |
||
- | 1112 | break; |
||
- | 1113 | } |
||
- | 1114 | } |
||
- | 1115 | break; |
||
- | 1116 | } |
||
- | 1117 | #endif |
||
- | 1118 | |
||
- | 1119 | /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */ |
||
- | 1120 | |
||
- | 1121 | if (!tune) { |
||
- | 1122 | return cmd->error; |
||
- | 1123 | } |
||
- | 1124 | |
||
- | 1125 | /* memory card CRC */ |
||
- | 1126 | if(host->hw->flags & MSDC_REMOVABLE && cmd->error == (unsigned int)(-EIO) ) { |
||
- | 1127 | if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ |
||
- | 1128 | msdc_abort_data(host); |
||
- | 1129 | } else { |
||
- | 1130 | /* do basic: reset*/ |
||
- | 1131 | msdc_reset(); |
||
- | 1132 | msdc_clr_fifo(); |
||
- | 1133 | msdc_clr_int(); |
||
- | 1134 | } |
||
918 | case RESP_R2: |
1135 | cmd->error = msdc_tune_cmdrsp(host,cmd); |
|
Line -... | Line 1136... | |||
- | 1136 | } |
||
919 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", |
1137 | |
|
920 | opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], |
- | ||
- | 1138 | // check DAT0 |
||
921 | cmd->resp[2], cmd->resp[3]); |
1139 | /* if (resp == RESP_R1B) { |
|
922 | break; |
1140 | while ((sdr_read32(MSDC_PS) & 0x10000) != 0x10000); |
|
923 | default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ |
1141 | } */ |
|
924 | N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", |
1142 | /* CMD12 Error Handle */ |
|
- | 1143 | |
||
- | 1144 | return cmd->error; |
||
925 | opcode, cmd->error, resp, cmd->resp[0]); |
1145 | } |
|
- | 1146 | |
||
- | 1147 | static unsigned int msdc_do_command(struct msdc_host *host, |
||
- | 1148 | struct mmc_command *cmd, |
||
- | 1149 | int tune, |
||
- | 1150 | unsigned long timeout) |
||
926 | if (cmd->error == 0) { |
1151 | { |
|
- | 1152 | if (msdc_command_start(host, cmd, tune, timeout)) |
||
- | 1153 | goto end; |
||
- | 1154 | |
||
- | 1155 | if (msdc_command_resp(host, cmd, tune, timeout)) |
||
- | 1156 | goto end; |
||
- | 1157 | |
||
- | 1158 | end: |
||
- | 1159 | |
||
- | 1160 | N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); |
||
- | 1161 | return cmd->error; |
||
- | 1162 | } |
||
- | 1163 | |
||
- | 1164 | /* The abort condition when PIO read/write |
||
927 | switch (resp) { |
1165 | tmo: |
|
- | 1166 | */ |
||
- | 1167 | static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo) |
||
- | 1168 | { |
||
- | 1169 | int ret = 0; |
||
- | 1170 | u32 base = host->base; |
||
- | 1171 | |
||
- | 1172 | if (atomic_read(&host->abort)) { |
||
- | 1173 | ret = 1; |
||
928 | case RESP_R1: |
1174 | } |
|
929 | case RESP_R1B: |
1175 | |
|
- | 1176 | if (time_after(jiffies, tmo)) { |
||
- | 1177 | data->error = (unsigned int)-ETIMEDOUT; |
||
- | 1178 | ERR_MSG("XXX PIO Data Timeout: CMD<%d>", host->mrq->cmd->opcode); |
||
- | 1179 | ret = 1; |
||
- | 1180 | } |
||
- | 1181 | |
||
- | 1182 | if(ret) { |
||
930 | msdc_dump_card_status(host, cmd->resp[0]); |
1183 | msdc_reset(); |
|
- | 1184 | msdc_clr_fifo(); |
||
- | 1185 | msdc_clr_int(); |
||
- | 1186 | ERR_MSG("msdc pio find abort"); |
||
- | 1187 | } |
||
- | 1188 | return ret; |
||
- | 1189 | } |
||
- | 1190 | |
||
Line -... | Line 1191... | |||
- | 1191 | /* |
||
- | 1192 | Need to add a timeout, or WDT timeout, system reboot. |
||
- | 1193 | */ |
||
- | 1194 | // pio mode data read/write |
||
- | 1195 | static int msdc_pio_read(struct msdc_host *host, struct mmc_data *data) |
||
- | 1196 | { |
||
- | 1197 | struct scatterlist *sg = data->sg; |
||
- | 1198 | u32 base = host->base; |
||
- | 1199 | u32 num = data->sg_len; |
||
- | 1200 | u32 *ptr; |
||
- | 1201 | u8 *u8ptr; |
||
- | 1202 | u32 left = 0; |
||
- | 1203 | u32 count, size = 0; |
||
- | 1204 | u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; |
||
- | 1205 | unsigned long tmo = jiffies + DAT_TIMEOUT; |
||
- | 1206 | |
||
- | 1207 | sdr_set_bits(MSDC_INTEN, wints); |
||
- | 1208 | while (num) { |
||
- | 1209 | left = sg_dma_len(sg); |
||
- | 1210 | ptr = sg_virt(sg); |
||
- | 1211 | while (left) { |
||
- | 1212 | if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() >= MSDC_FIFO_THD)) { |
||
- | 1213 | count = MSDC_FIFO_THD >> 2; |
||
- | 1214 | do { |
||
- | 1215 | *ptr++ = msdc_fifo_read32(); |
||
- | 1216 | } while (--count); |
||
- | 1217 | left -= MSDC_FIFO_THD; |
||
- | 1218 | } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() >= left) { |
||
- | 1219 | while (left > 3) { |
||
- | 1220 | *ptr++ = msdc_fifo_read32(); |
||
- | 1221 | left -= 4; |
||
- | 1222 | } |
||
- | 1223 | |
||
- | 1224 | u8ptr = (u8 *)ptr; |
||
- | 1225 | while(left) { |
||
- | 1226 | * u8ptr++ = msdc_fifo_read8(); |
||
- | 1227 | left--; |
||
- | 1228 | } |
||
- | 1229 | } |
||
- | 1230 | |
||
- | 1231 | if (msdc_pio_abort(host, data, tmo)) { |
||
- | 1232 | goto end; |
||
- | 1233 | } |
||
- | 1234 | } |
||
- | 1235 | size += sg_dma_len(sg); |
||
- | 1236 | sg = sg_next(sg); num--; |
||
- | 1237 | } |
||
- | 1238 | end: |
||
- | 1239 | data->bytes_xfered += size; |
||
- | 1240 | N_MSG(FIO, " PIO Read<%d>bytes", size); |
||
931 | break; |
1241 | |
|
- | 1242 | sdr_clr_bits(MSDC_INTEN, wints); |
||
- | 1243 | if(data->error) ERR_MSG("read pio data->error<%d> left<%d> size<%d>", data->error, left, size); |
||
- | 1244 | return data->error; |
||
932 | case RESP_R3: |
1245 | } |
|
933 | msdc_dump_ocr_reg(host, cmd->resp[0]); |
1246 | |
|
Line 934... | Line 1247... | |||
934 | break; |
1247 | /* please make sure won't using PIO when size >= 512 |
|
935 | case RESP_R5: |
1248 | which means, memory card block read/write won't using pio |
|
936 | msdc_dump_io_resp(host, cmd->resp[0]); |
1249 | then don't need to handle the CMD12 when data error. |
|
937 | break; |
1250 | */ |
|
938 | case RESP_R6: |
1251 | static int msdc_pio_write(struct msdc_host* host, struct mmc_data *data) |
|
Line 939... | Line 1252... | |||
939 | msdc_dump_rca_resp(host, cmd->resp[0]); |
1252 | { |
|
Line 940... | Line 1253... | |||
940 | break; |
1253 | u32 base = host->base; |
|
941 | } |
1254 | struct scatterlist *sg = data->sg; |
|
942 | } |
1255 | u32 num = data->sg_len; |
|
Line 943... | Line 1256... | |||
943 | break; |
1256 | u32 *ptr; |
|
944 | } |
1257 | u8 *u8ptr; |
|
945 | #endif |
1258 | u32 left; |
|
946 | |
1259 | u32 count, size = 0; |
|
- | 1260 | u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; |
||
- | 1261 | unsigned long tmo = jiffies + DAT_TIMEOUT; |
||
- | 1262 | |
||
- | 1263 | sdr_set_bits(MSDC_INTEN, wints); |
||
Line 947... | Line -... | |||
947 | /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */ |
- | ||
948 | |
- | ||
949 | if (!tune) |
- | ||
950 | return cmd->error; |
- | ||
951 | |
1264 | while (num) { |
|
952 | /* memory card CRC */ |
1265 | left = sg_dma_len(sg); |
|
Line 953... | Line 1266... | |||
953 | if (host->hw->flags & MSDC_REMOVABLE && cmd->error == -EIO) { |
1266 | ptr = sg_virt(sg); |
|
954 | if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ |
1267 | |
|
955 | msdc_abort_data(host); |
1268 | while (left) { |
|
956 | } else { |
1269 | if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { |
|
957 | /* do basic: reset*/ |
1270 | count = MSDC_FIFO_SZ >> 2; |
|
- | 1271 | do { |
||
- | 1272 | msdc_fifo_write32(*ptr); ptr++; |
||
- | 1273 | } while (--count); |
||
Line 958... | Line 1274... | |||
958 | msdc_reset_hw(host); |
1274 | left -= MSDC_FIFO_SZ; |
|
959 | msdc_clr_fifo(); |
1275 | } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { |
|
Line 960... | Line 1276... | |||
960 | msdc_clr_int(); |
1276 | while (left > 3) { |
|
961 | } |
1277 | msdc_fifo_write32(*ptr); ptr++; |
|
962 | cmd->error = msdc_tune_cmdrsp(host, cmd); |
- | ||
Line 963... | Line 1278... | |||
963 | } |
1278 | left -= 4; |
|
964 | |
- | ||
- | 1279 | } |
||
Line -... | Line 1280... | |||
- | 1280 | |
||
- | 1281 | u8ptr = (u8*)ptr; |
||
- | 1282 | while(left){ |
||
- | 1283 | msdc_fifo_write8(*u8ptr); u8ptr++; |
||
- | 1284 | left--; |
||
- | 1285 | } |
||
- | 1286 | } |
||
- | 1287 | |
||
- | 1288 | if (msdc_pio_abort(host, data, tmo)) { |
||
- | 1289 | goto end; |
||
- | 1290 | } |
||
- | 1291 | } |
||
- | 1292 | size += sg_dma_len(sg); |
||
- | 1293 | sg = sg_next(sg); num--; |
||
965 | // check DAT0 |
1294 | } |
|
- | 1295 | end: |
||
- | 1296 | data->bytes_xfered += size; |
||
- | 1297 | N_MSG(FIO, " PIO Write<%d>bytes", size); |
||
- | 1298 | if(data->error) ERR_MSG("write pio data->error<%d>", data->error); |
||
- | 1299 | |
||
- | 1300 | sdr_clr_bits(MSDC_INTEN, wints); |
||
- | 1301 | return data->error; |
||
- | 1302 | } |
||
- | 1303 | |
||
- | 1304 | #if 0 /* --- by chhung */ |
||
- | 1305 | // DMA resume / start / stop |
||
- | 1306 | static void msdc_dma_resume(struct msdc_host *host) |
||
- | 1307 | { |
||
- | 1308 | u32 base = host->base; |
||
- | 1309 | |
||
- | 1310 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1); |
||
- | 1311 | |
||
- | 1312 | N_MSG(DMA, "DMA resume"); |
||
- | 1313 | } |
||
- | 1314 | #endif /* end of --- */ |
||
- | 1315 | |
||
- | 1316 | static void msdc_dma_start(struct msdc_host *host) |
||
- | 1317 | { |
||
- | 1318 | u32 base = host->base; |
||
- | 1319 | u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; |
||
- | 1320 | |
||
- | 1321 | sdr_set_bits(MSDC_INTEN, wints); |
||
- | 1322 | //dsb(); /* --- by chhung */ |
||
- | 1323 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); |
||
- | 1324 | |
||
- | 1325 | N_MSG(DMA, "DMA start"); |
||
- | 1326 | } |
||
- | 1327 | |
||
- | 1328 | static void msdc_dma_stop(struct msdc_host *host) |
||
- | 1329 | { |
||
- | 1330 | u32 base = host->base; |
||
- | 1331 | //u32 retries=500; |
||
- | 1332 | u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; |
||
- | 1333 | |
||
- | 1334 | N_MSG(DMA, "DMA status: 0x%.8x",sdr_read32(MSDC_DMA_CFG)); |
||
- | 1335 | //while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); |
||
966 | /* if (resp == RESP_R1B) { |
1336 | |
|
- | 1337 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); |
||
Line 967... | Line 1338... | |||
967 | while ((sdr_read32(MSDC_PS) & 0x10000) != 0x10000); |
1338 | while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); |
|
968 | } */ |
1339 | |
|
969 | /* CMD12 Error Handle */ |
1340 | //dsb(); /* --- by chhung */ |
|
970 | |
1341 | sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */ |
|
971 | return cmd->error; |
- | ||
972 | } |
1342 | |
|
973 | |
1343 | N_MSG(DMA, "DMA stop"); |
|
- | 1344 | } |
||
974 | static unsigned int msdc_do_command(struct msdc_host *host, |
1345 | |
|
975 | struct mmc_command *cmd, |
1346 | #if 0 /* --- by chhung */ |
|
Line 976... | Line 1347... | |||
976 | int tune, |
1347 | /* dump a gpd list */ |
|
977 | unsigned long timeout) |
1348 | static void msdc_dma_dump(struct msdc_host *host, struct msdc_dma *dma) |
|
978 | { |
1349 | { |
|
979 | if (msdc_command_start(host, cmd, tune, timeout)) |
1350 | gpd_t *gpd = dma->gpd; |
|
- | 1351 | bd_t *bd = dma->bd; |
||
980 | goto end; |
1352 | bd_t *ptr; |
|
981 | |
1353 | int i = 0; |
|
- | 1354 | int p_to_v; |
||
982 | if (msdc_command_resp(host, cmd, tune, timeout)) |
1355 | |
|
983 | goto end; |
1356 | if (dma->mode != MSDC_MODE_DMA_DESC) { |
|
984 | |
1357 | return; |
|
985 | end: |
1358 | } |
|
986 | |
1359 | |
|
987 | N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); |
1360 | ERR_MSG("try to dump gpd and bd"); |
|
988 | return cmd->error; |
1361 | |
|
989 | } |
1362 | /* dump gpd */ |
|
990 | |
1363 | ERR_MSG(".gpd<0x%.8x> gpd_phy<0x%.8x>", (int)gpd, (int)dma->gpd_addr); |
|
991 | #if 0 /* --- by chhung */ |
1364 | ERR_MSG("...hwo <%d>", gpd->hwo ); |
|
992 | // DMA resume / start / stop |
1365 | ERR_MSG("...bdp <%d>", gpd->bdp ); |
|
993 | static void msdc_dma_resume(struct msdc_host *host) |
1366 | ERR_MSG("...chksum<0x%.8x>", gpd->chksum ); |
|
994 | { |
1367 | //ERR_MSG("...intr <0x%.8x>", gpd->intr ); |
|
995 | void __iomem *base = host->base; |
1368 | ERR_MSG("...next <0x%.8x>", (int)gpd->next ); |
|
996 | |
1369 | ERR_MSG("...ptr <0x%.8x>", (int)gpd->ptr ); |
|
997 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1); |
1370 | ERR_MSG("...buflen<0x%.8x>", gpd->buflen ); |
|
998 | |
1371 | //ERR_MSG("...extlen<0x%.8x>", gpd->extlen ); |
|
1090 | bd[j].dwpad = 0; |
1485 | |
|
1091 | bd[j].ptr = (void *)sg_dma_address(sg); |
1486 | default: |
|
1092 | bd[j].buflen = sg_dma_len(sg); |
1487 | break; |
|
1093 | |
1488 | } |
|
1094 | if (j == dma->sglen - 1) |
1489 | |
|
1095 | bd[j].eol = 1; /* the last bd */ |
1490 | N_MSG(DMA, "DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); |
|
1096 | else |
1491 | N_MSG(DMA, "DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); |
|
1097 | bd[j].eol = 0; |
1492 | N_MSG(DMA, "DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); |
|
1098 | |
1493 | |
|
1099 | bd[j].chksum = 0; /* checksume need to clear first */ |
1494 | return 0; |
|
1100 | bd[j].chksum = msdc_dma_calcs((u8 *)(&bd[j]), 16); |
1495 | } |
|
- | 1496 | |
||
1101 | } |
1497 | static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, |
|
1102 | |
1498 | struct scatterlist *sg, unsigned int sglen) |
|
1103 | sdr_set_field(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1); |
1499 | { |
|
1104 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, |
1500 | BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ |
|
1105 | MSDC_BRUST_64B); |
1501 | |
|
1106 | sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); |
1502 | dma->sg = sg; |
|
1107 | |
1503 | dma->flags = DMA_FLAG_EN_CHKSUM; |
|
1108 | sdr_write32(MSDC_DMA_SA, PHYSADDR((u32)dma->gpd_addr)); |
1504 | //dma->flags = DMA_FLAG_NONE; /* CHECKME */ |
|
1109 | break; |
1505 | dma->sglen = sglen; |
|
- | 1506 | dma->xfersz = host->xfer_size; |
||
- | 1507 | dma->burstsz = MSDC_BRUST_64B; |
||
- | 1508 | |
||
- | 1509 | if (sglen == 1 && sg_dma_len(sg) <= MAX_DMA_CNT) |
||
- | 1510 | dma->mode = MSDC_MODE_DMA_BASIC; |
||
- | 1511 | else |
||
- | 1512 | dma->mode = MSDC_MODE_DMA_DESC; |
||
- | 1513 | |
||
- | 1514 | N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, dma->xfersz); |
||
1110 | |
1515 | |
|
1111 | default: |
1516 | msdc_dma_config(host, dma); |
|
1112 | break; |
1517 | |
|
1113 | } |
1518 | /*if (dma->mode == MSDC_MODE_DMA_DESC) { |
|
1114 | |
1519 | //msdc_dma_dump(host, dma); |
|
1115 | N_MSG(DMA, "DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); |
1520 | } */ |
|
1116 | N_MSG(DMA, "DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); |
1521 | } |
|
1117 | N_MSG(DMA, "DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); |
1522 | |
|
1118 | |
1523 | /* set block number before send command */ |
|
1119 | } |
1524 | static void msdc_set_blknum(struct msdc_host *host, u32 blknum) |
|
1120 | |
1525 | { |
|
- | 1526 | u32 base = host->base; |
||
1121 | static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, |
1527 | |
|
1122 | struct scatterlist *sg, unsigned int sglen) |
1528 | sdr_write32(SDC_BLK_NUM, blknum); |
|
1123 | { |
1529 | } |
|
1124 | BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ |
1530 | |
|
1125 | |
1531 | static int msdc_do_request(struct mmc_host*mmc, struct mmc_request*mrq) |
|
1126 | dma->sg = sg; |
1532 | { |
|
1127 | dma->sglen = sglen; |
1533 | struct msdc_host *host = mmc_priv(mmc); |
|
1128 | |
1534 | struct mmc_command *cmd; |
|
1129 | dma->mode = MSDC_MODE_DMA_DESC; |
- | ||
1130 | |
1535 | struct mmc_data *data; |
|
1131 | N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, |
1536 | u32 base = host->base; |
|
1132 | host->xfer_size); |
- | ||
1133 | |
1537 | //u32 intsts = 0; |
|
1134 | msdc_dma_config(host, dma); |
1538 | unsigned int left=0; |
|
1135 | } |
1539 | int dma = 0, read = 1, dir = DMA_FROM_DEVICE, send_type=0; |
|
1136 | |
1540 | |
|
1137 | static int msdc_do_request(struct mmc_host *mmc, struct mmc_request *mrq) |
1541 | #define SND_DAT 0 |
|
1138 | __must_hold(&host->lock) |
1542 | #define SND_CMD 1 |
|
1139 | { |
1543 | |
|
1140 | struct msdc_host *host = mmc_priv(mmc); |
1544 | BUG_ON(mmc == NULL); |
|
1141 | struct mmc_command *cmd; |
1545 | BUG_ON(mrq == NULL); |
|
1142 | struct mmc_data *data; |
1546 | |
|
1143 | void __iomem *base = host->base; |
1547 | host->error = 0; |
|
1144 | //u32 intsts = 0; |
1548 | atomic_set(&host->abort, 0); |
|
1145 | int read = 1, send_type = 0; |
1549 | |
|
1146 | |
1550 | cmd = mrq->cmd; |
|
1147 | #define SND_DAT 0 |
1551 | data = mrq->cmd->data; |
|
1148 | #define SND_CMD 1 |
1552 | |
|
1149 | |
1553 | #if 0 /* --- by chhung */ |
|
1150 | BUG_ON(mmc == NULL); |
1554 | //if(host->id ==1){ |
|
1151 | BUG_ON(mrq == NULL); |
1555 | N_MSG(OPS, "enable clock!"); |
|
1152 | |
1556 | msdc_ungate_clock(host->id); |
|
1153 | host->error = 0; |
1557 | //} |
|
1154 | |
1558 | #endif /* end of --- */ |
|
1155 | cmd = mrq->cmd; |
1559 | |
|
1156 | data = mrq->cmd->data; |
1560 | if (!data) { |
|
1157 | |
1561 | send_type=SND_CMD; |
|
- | 1562 | if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { |
||
- | 1563 | goto done; |
||
- | 1564 | } |
||
- | 1565 | } else { |
||
- | 1566 | BUG_ON(data->blksz > HOST_MAX_BLKSZ); |
||
- | 1567 | send_type=SND_DAT; |
||
- | 1568 | |
||
- | 1569 | data->error = 0; |
||
- | 1570 | read = data->flags & MMC_DATA_READ ? 1 : 0; |
||
- | 1571 | host->data = data; |
||
- | 1572 | host->xfer_size = data->blocks * data->blksz; |
||
- | 1573 | host->blksz = data->blksz; |
||
- | 1574 | |
||
- | 1575 | /* deside the transfer mode */ |
||
- | 1576 | if (drv_mode[host->id] == MODE_PIO) { |
||
- | 1577 | host->dma_xfer = dma = 0; |
||
- | 1578 | } else if (drv_mode[host->id] == MODE_DMA) { |
||
- | 1579 | host->dma_xfer = dma = 1; |
||
- | 1580 | } else if (drv_mode[host->id] == MODE_SIZE_DEP) { |
||
- | 1581 | host->dma_xfer = dma = ((host->xfer_size >= dma_size[host->id]) ? 1 : 0); |
||
- | 1582 | } |
||
- | 1583 | |
||
- | 1584 | if (read) { |
||
- | 1585 | if ((host->timeout_ns != data->timeout_ns) || |
||
- | 1586 | (host->timeout_clks != data->timeout_clks)) { |
||
- | 1587 | msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); |
||
- | 1588 | } |
||
- | 1589 | } |
||
- | 1590 | |
||
- | 1591 | msdc_set_blknum(host, data->blocks); |
||
- | 1592 | //msdc_clr_fifo(); /* no need */ |
||
- | 1593 | |
||
- | 1594 | if (dma) { |
||
- | 1595 | msdc_dma_on(); /* enable DMA mode first!! */ |
||
- | 1596 | init_completion(&host->xfer_done); |
||
- | 1597 | |
||
- | 1598 | /* start the command first*/ |
||
- | 1599 | if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0) |
||
- | 1600 | goto done; |
||
- | 1601 | |
||
- | 1602 | dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
||
- | 1603 | (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); |
||
- | 1604 | msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); |
||
1158 | #if 0 /* --- by chhung */ |
1605 | |
|
1159 | //if(host->id ==1){ |
1606 | /* then wait command done */ |
|
1160 | N_MSG(OPS, "enable clock!"); |
1607 | if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) |
|
1161 | msdc_ungate_clock(host->id); |
1608 | goto done; |
|
1162 | //} |
1609 | |
|
- | 1610 | /* for read, the data coming too fast, then CRC error |
||
1163 | #endif /* end of --- */ |
1611 | start DMA no business with CRC. */ |
|
1164 | |
1612 | //init_completion(&host->xfer_done); |
|
Line 1165... | Line 1613... | |||
1165 | if (!data) { |
1613 | msdc_dma_start(host); |
|
1166 | send_type = SND_CMD; |
1614 | |
|
1167 | if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) |
1615 | spin_unlock(&host->lock); |
|
- | 1616 | if(!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)){ |
||
- | 1617 | ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz); |
||
- | 1618 | ERR_MSG(" DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); |
||
- | 1619 | ERR_MSG(" DMA_CA = 0x%x", sdr_read32(MSDC_DMA_CA)); |
||
- | 1620 | ERR_MSG(" DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); |
||
1168 | goto done; |
1621 | ERR_MSG(" DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); |
|
1169 | } else { |
1622 | data->error = (unsigned int)-ETIMEDOUT; |
|
1170 | BUG_ON(data->blksz > HOST_MAX_BLKSZ); |
1623 | |
|
1171 | send_type = SND_DAT; |
1624 | msdc_reset(); |
|
1172 | |
1625 | msdc_clr_fifo(); |
|
1173 | data->error = 0; |
1626 | msdc_clr_int(); |
|
1174 | read = data->flags & MMC_DATA_READ ? 1 : 0; |
1627 | } |
|
1175 | host->data = data; |
1628 | spin_lock(&host->lock); |
|
1176 | host->xfer_size = data->blocks * data->blksz; |
1629 | msdc_dma_stop(host); |
|
1177 | host->blksz = data->blksz; |
1630 | } else { |
|
1178 | |
1631 | /* Firstly: send command */ |
|
1179 | if (read) { |
1632 | if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { |
|
1180 | if ((host->timeout_ns != data->timeout_ns) || |
1633 | goto done; |
|
1181 | (host->timeout_clks != data->timeout_clks)) { |
1634 | } |
|
Line 1182... | Line 1635... | |||
1182 | msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); |
1635 | |
|
1183 | } |
1636 | /* Secondly: pio data phase */ |
|
1184 | } |
1637 | if (read) { |
|
1185 | |
1638 | if (msdc_pio_read(host, data)){ |
|
1186 | sdr_write32(SDC_BLK_NUM, data->blocks); |
1639 | goto done; |
|
1187 | //msdc_clr_fifo(); /* no need */ |
1640 | } |
|
1188 | |
1641 | } else { |
|
1189 | msdc_dma_on(); /* enable DMA mode first!! */ |
1642 | if (msdc_pio_write(host, data)) { |
|
1190 | init_completion(&host->xfer_done); |
1643 | goto done; |
|
1191 | |
1644 | } |
|
1192 | /* start the command first*/ |
1645 | } |
|
1193 | if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0) |
1646 | |
|
1194 | goto done; |
1647 | /* For write case: make sure contents in fifo flushed to device */ |
|
1195 | |
1648 | if (!read) { |
|
1196 | data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg, |
1649 | while (1) { |
|
1197 | data->sg_len, |
1650 | left=msdc_txfifocnt(); |
|
1198 | mmc_get_dma_dir(data)); |
1651 | if (left == 0) { |
|
1199 | msdc_dma_setup(host, &host->dma, data->sg, |
1652 | break; |
|
1200 | data->sg_count); |
1653 | } |
|
1201 | |
1654 | if (msdc_pio_abort(host, data, jiffies + DAT_TIMEOUT)) { |
|
1202 | /* then wait command done */ |
1655 | break; |
|
1203 | if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) |
1656 | /* Fix me: what about if data error, when stop ? how to? */ |
|
1204 | goto done; |
1657 | } |
|
1205 | |
1658 | } |
|
- | 1659 | } else { |
||
- | 1660 | /* Fix me: read case: need to check CRC error */ |
||
- | 1661 | } |
||
- | 1662 | |
||
Line 1206... | Line -... | |||
1206 | /* for read, the data coming too fast, then CRC error |
- | ||
1207 | start DMA no business with CRC. */ |
- | ||
1208 | //init_completion(&host->xfer_done); |
- | ||
1209 | msdc_dma_start(host); |
- | ||
1210 | |
1663 | /* For write case: SDCBUSY and Xfer_Comp will assert when DAT0 not busy. |
|
1211 | spin_unlock(&host->lock); |
- | ||
Line 1212... | Line -... | |||
1212 | if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) { |
- | ||
1213 | ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz); |
- | ||
1214 | ERR_MSG(" DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); |
1664 | For read case : SDCBUSY and Xfer_Comp will assert when last byte read out from FIFO. |
|
1215 | ERR_MSG(" DMA_CA = 0x%x", sdr_read32(MSDC_DMA_CA)); |
1665 | */ |
|
Line 1216... | Line 1666... | |||
1216 | ERR_MSG(" DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); |
1666 | |
|
1217 | ERR_MSG(" DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); |
1667 | /* try not to wait xfer_comp interrupt. |
|
1218 | data->error = -ETIMEDOUT; |
1668 | the next command will check SDC_BUSY. |
|
1219 | |
1669 | SDC_BUSY means xfer_comp assert |
|
1220 | msdc_reset_hw(host); |
1670 | */ |
|
1221 | msdc_clr_fifo(); |
1671 | |
|
1222 | msdc_clr_int(); |
1672 | } // PIO mode |
|
1223 | } |
1673 | |
|
1224 | spin_lock(&host->lock); |
1674 | /* Last: stop transfer */ |
|
1225 | msdc_dma_stop(host); |
1675 | if (data->stop){ |
|
1226 | |
1676 | if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) { |
|
1227 | /* Last: stop transfer */ |
1677 | goto done; |
|
1228 | if (data->stop) { |
1678 | } |
|
1229 | if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) |
1679 | } |
|
1230 | goto done; |
1680 | } |
|
1231 | } |
1681 | |
|
1232 | } |
1682 | done: |
|
1233 | |
1683 | if (data != NULL) { |
|
1234 | done: |
1684 | host->data = NULL; |
|
1235 | if (data != NULL) { |
1685 | host->dma_xfer = 0; |
|
1236 | host->data = NULL; |
1686 | if (dma != 0) { |
|
1237 | dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, |
1687 | msdc_dma_off(); |
|
1238 | mmc_get_dma_dir(data)); |
1688 | host->dma.used_bd = 0; |
|
1239 | host->blksz = 0; |
1689 | host->dma.used_gpd = 0; |
|
1240 | |
1690 | dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); |
|
1241 | #if 0 // don't stop twice! |
1691 | } |
|
1242 | if (host->hw->flags & MSDC_REMOVABLE && data->error) { |
1692 | host->blksz = 0; |
|
1243 | msdc_abort_data(host); |
1693 | |
|
1244 | /* reset in IRQ, stop command has issued. -> No need */ |
1694 | #if 0 // don't stop twice! |
|
1245 | } |
1695 | if(host->hw->flags & MSDC_REMOVABLE && data->error) { |
|
1246 | #endif |
1696 | msdc_abort_data(host); |
|
1247 | |
1697 | /* reset in IRQ, stop command has issued. -> No need */ |
|
1248 | N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>", cmd->opcode, (dma ? "dma" : "pio"), |
1698 | } |
|
1249 | (read ? "read " : "write"), data->blksz, data->blocks, data->error); |
1699 | #endif |
|
1250 | } |
1700 | |
|
1251 | |
1701 | N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio"), |
|
1252 | #if 0 /* --- by chhung */ |
1702 | (read ? "read ":"write") ,data->blksz, data->blocks, data->error); |
|
1253 | #if 1 |
1703 | } |
|
1254 | //if(host->id==1) { |
1704 | |
|
1255 | if (send_type == SND_CMD) { |
1705 | #if 0 /* --- by chhung */ |
|
1256 | if (cmd->opcode == MMC_SEND_STATUS) { |
1706 | #if 1 |
|
1257 | if ((cmd->resp[0] & CARD_READY_FOR_DATA) || (CARD_CURRENT_STATE(cmd->resp[0]) != 7)) { |
1707 | //if(host->id==1) { |
|
1258 | N_MSG(OPS, "disable clock, CMD13 IDLE"); |
1708 | if(send_type==SND_CMD) { |
|
1259 | msdc_gate_clock(host->id); |
1709 | if(cmd->opcode == MMC_SEND_STATUS) { |
|
1260 | } |
1710 | if((cmd->resp[0] & CARD_READY_FOR_DATA) ||(CARD_CURRENT_STATE(cmd->resp[0]) != 7)){ |
|
1261 | } else { |
1711 | N_MSG(OPS,"disable clock, CMD13 IDLE"); |
|
1262 | N_MSG(OPS, "disable clock, CMD<%d>", cmd->opcode); |
1712 | msdc_gate_clock(host->id); |
|
1263 | msdc_gate_clock(host->id); |
1713 | } |
|
1264 | } |
1714 | } else { |
|
1265 | } else { |
1715 | N_MSG(OPS,"disable clock, CMD<%d>", cmd->opcode); |
|
1266 | if (read) { |
1716 | msdc_gate_clock(host->id); |
|
1267 | N_MSG(OPS, "disable clock!!! Read CMD<%d>", cmd->opcode); |
1717 | } |
|
1268 | msdc_gate_clock(host->id); |
1718 | } else { |
|
1269 | } |
1719 | if(read) { |
|
1270 | } |
1720 | N_MSG(OPS,"disable clock!!! Read CMD<%d>",cmd->opcode); |
|
1271 | //} |
1721 | msdc_gate_clock(host->id); |
|
1272 | #else |
1722 | } |
|
1273 | msdc_gate_clock(host->id); |
1723 | } |
|
1274 | #endif |
1724 | //} |
|
1275 | #endif /* end of --- */ |
1725 | #else |
|
1276 | |
1726 | msdc_gate_clock(host->id); |
|
1277 | if (mrq->cmd->error) |
1727 | #endif |
|
1278 | host->error = 0x001; |
1728 | #endif /* end of --- */ |
|
1279 | if (mrq->data && mrq->data->error) |
1729 | |
|
1280 | host->error |= 0x010; |
1730 | if (mrq->cmd->error) host->error = 0x001; |
|
- | 1731 | if (mrq->data && mrq->data->error) host->error |= 0x010; |
||
1281 | if (mrq->stop && mrq->stop->error) |
1732 | if (mrq->stop && mrq->stop->error) host->error |= 0x100; |
|
1282 | host->error |= 0x100; |
1733 | |
|
1283 | |
1734 | //if (host->error) ERR_MSG("host->error<%d>", host->error); |
|
1284 | //if (host->error) ERR_MSG("host->error<%d>", host->error); |
1735 | |
|
1285 | |
1736 | return host->error; |
|
1286 | return host->error; |
1737 | } |
|
1287 | } |
1738 | |
|
1288 | |
1739 | static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) |
|
1289 | static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) |
1740 | { |
|
1290 | { |
1741 | struct mmc_command cmd; |
|
1291 | struct mmc_command cmd; |
1742 | struct mmc_request mrq; |
|
1292 | struct mmc_request mrq; |
1743 | u32 err; |
|
1293 | u32 err; |
1744 | |
|
1294 | |
1745 | memset(&cmd, 0, sizeof(struct mmc_command)); |
|
1295 | memset(&cmd, 0, sizeof(struct mmc_command)); |
1746 | cmd.opcode = MMC_APP_CMD; |
|
1296 | cmd.opcode = MMC_APP_CMD; |
1747 | #if 0 /* bug: we meet mmc->card is null when ACMD6 */ |
|
1297 | #if 0 /* bug: we meet mmc->card is null when ACMD6 */ |
1748 | cmd.arg = mmc->card->rca << 16; |
|
1298 | cmd.arg = mmc->card->rca << 16; |
1749 | #else |
|
Line 1299... | Line 1750... | |||
1299 | #else |
1750 | cmd.arg = host->app_cmd_arg; |
|
1300 | cmd.arg = host->app_cmd_arg; |
1751 | #endif |
|
1301 | #endif |
1752 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
|
1302 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
1753 | |
|
1303 | |
1754 | memset(&mrq, 0, sizeof(struct mmc_request)); |
|
1304 | memset(&mrq, 0, sizeof(struct mmc_request)); |
1755 | mrq.cmd = &cmd; cmd.mrq = &mrq; |
|
1305 | mrq.cmd = &cmd; cmd.mrq = &mrq; |
1756 | cmd.data = NULL; |
|
1306 | cmd.data = NULL; |
1757 | |
|
1307 | |
1758 | err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); |
|
1308 | err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); |
1759 | return err; |
|
1309 | return err; |
1760 | } |
|
1310 | } |
1761 | |
|
1311 | |
1762 | static int msdc_tune_cmdrsp(struct msdc_host*host, struct mmc_command *cmd) |
|
1312 | static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd) |
1763 | { |
|
1313 | { |
1764 | int result = -1; |
|
1314 | int result = -1; |
1765 | u32 base = host->base; |
|
1315 | void __iomem *base = host->base; |
1766 | u32 rsmpl, cur_rsmpl, orig_rsmpl; |
|
1316 | u32 rsmpl, cur_rsmpl, orig_rsmpl; |
1767 | u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly; |
|
1317 | u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly; |
1768 | u32 skip = 1; |
|
1318 | u32 skip = 1; |
1769 | |
|
1319 | |
1770 | /* ==== don't support 3.0 now ==== |
|
1320 | /* ==== don't support 3.0 now ==== |
1771 | 1: R_SMPL[1] |
|
1321 | 1: R_SMPL[1] |
1772 | 2: PAD_CMD_RESP_RXDLY[26:22] |
|
1322 | 2: PAD_CMD_RESP_RXDLY[26:22] |
1773 | ==========================*/ |
|
1323 | ==========================*/ |
1774 | |
|
1324 | |
1775 | // save the previous tune result |
|
1325 | // save the previous tune result |
1776 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl); |
|
1326 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, &orig_rsmpl); |
1777 | sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, orig_rrdly); |
|
1327 | sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, &orig_rrdly); |
1778 | |
|
1328 | |
1779 | rrdly = 0; |
|
1329 | rrdly = 0; |
1780 | do { |
|
1330 | do { |
1781 | for (rsmpl = 0; rsmpl < 2; rsmpl++) { |
|
1331 | for (rsmpl = 0; rsmpl < 2; rsmpl++) { |
1782 | /* Lv1: R_SMPL[1] */ |
|
1332 | /* Lv1: R_SMPL[1] */ |
1783 | cur_rsmpl = (orig_rsmpl + rsmpl) % 2; |
|
1333 | cur_rsmpl = (orig_rsmpl + rsmpl) % 2; |
1784 | if (skip == 1) { |
|
1334 | if (skip == 1) { |
1785 | skip = 0; |
|
1335 | skip = 0; |
1786 | continue; |
|
1336 | continue; |
1787 | } |
|
1337 | } |
1788 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl); |
|
1338 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl); |
1789 | |
|
1339 | |
- | ||
1340 | if (host->app_cmd) { |
1790 | if (host->app_cmd) { |
|
1341 | result = msdc_app_cmd(host->mmc, host); |
- | ||
1342 | if (result) { |
- | ||
1343 | ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", |
1791 | result = msdc_app_cmd(host->mmc, host); |
|
1344 | host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); |
1792 | if (result) { |
|
1345 | continue; |
1793 | ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", |
|
1346 | } |
1794 | host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); |
|
1347 | } |
1795 | continue; |
|
1348 | result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. |
1796 | } |
|
1349 | ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode, |
1797 | } |
|
1350 | (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); |
1798 | result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. |
|
1351 | |
1799 | ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode, |
|
1352 | if (result == 0) |
1800 | (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); |
|
1353 | return 0; |
- | ||
1354 | if (result != -EIO) { |
1801 | |
|
1355 | ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", cmd->opcode, result); |
1802 | if (result == 0) { |
|
1356 | return result; |
1803 | return 0; |
|
1357 | } |
1804 | } |
|
1358 | |
1805 | if (result != (unsigned int)(-EIO)) { |
|
1359 | /* should be EIO */ |
1806 | ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", cmd->opcode, result); |
|
1360 | if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ |
1807 | return result; |
|
1361 | msdc_abort_data(host); |
1808 | } |
|
1362 | } |
1809 | |
|
1363 | } |
1810 | /* should be EIO */ |
|
1364 | |
1811 | if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ |
|
1365 | /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ |
1812 | msdc_abort_data(host); |
|
1366 | cur_rrdly = (orig_rrdly + rrdly + 1) % 32; |
1813 | } |
|
1367 | sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); |
1814 | } |
|
1368 | } while (++rrdly < 32); |
1815 | |
|
1369 | |
1816 | /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ |
|
1370 | return result; |
1817 | cur_rrdly = (orig_rrdly + rrdly + 1) % 32; |
|
1371 | } |
1818 | sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); |
|
1372 | |
1819 | }while (++rrdly < 32); |
|
1373 | /* Support SD2.0 Only */ |
1820 | |
|
1374 | static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) |
1821 | return result; |
|
1375 | { |
1822 | } |
|
1376 | struct msdc_host *host = mmc_priv(mmc); |
1823 | |
|
1377 | void __iomem *base = host->base; |
1824 | /* Support SD2.0 Only */ |
|
1378 | u32 ddr = 0; |
1825 | static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) |
|
1379 | u32 dcrc = 0; |
1826 | { |
|
1380 | u32 rxdly, cur_rxdly0, cur_rxdly1; |
1827 | struct msdc_host *host = mmc_priv(mmc); |
|
1381 | u32 dsmpl, cur_dsmpl, orig_dsmpl; |
1828 | u32 base = host->base; |
|
1382 | u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; |
1829 | u32 ddr=0; |
|
1383 | u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; |
1830 | u32 dcrc=0; |
|
1384 | u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; |
1831 | u32 rxdly, cur_rxdly0, cur_rxdly1; |
|
1385 | u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; |
1832 | u32 dsmpl, cur_dsmpl, orig_dsmpl; |
|
1386 | int result = -1; |
1833 | u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; |
|
1387 | u32 skip = 1; |
1834 | u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; |
|
1388 | |
1835 | u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; |
|
1389 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl); |
1836 | u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; |
|
1390 | |
1837 | int result = -1; |
|
1391 | /* Tune Method 2. */ |
1838 | u32 skip = 1; |
|
1392 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); |
1839 | |
|
1393 | |
1840 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl); |
|
1394 | rxdly = 0; |
1841 | |
|
1395 | do { |
1842 | /* Tune Method 2. */ |
|
1396 | for (dsmpl = 0; dsmpl < 2; dsmpl++) { |
1843 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); |
|
1397 | cur_dsmpl = (orig_dsmpl + dsmpl) % 2; |
1844 | |
|
1398 | if (skip == 1) { |
1845 | rxdly = 0; |
|
1399 | skip = 0; |
1846 | do { |
|
1400 | continue; |
1847 | for (dsmpl = 0; dsmpl < 2; dsmpl++) { |
|
Line 1401... | Line 1848... | |||
1401 | } |
1848 | cur_dsmpl = (orig_dsmpl + dsmpl) % 2; |
|
1402 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); |
1849 | if (skip == 1) { |
|
Line 1403... | Line 1850... | |||
1403 | |
1850 | skip = 0; |
|
1404 | if (host->app_cmd) { |
1851 | continue; |
|
1405 | result = msdc_app_cmd(host->mmc, host); |
- | ||
1406 | if (result) { |
- | ||
Line -... | Line 1852... | |||
- | 1852 | } |
||
- | 1853 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); |
||
1407 | ERR_MSG("TUNE_BREAD app_cmd<%d> failed", host->mrq->cmd->opcode); |
1854 | |
|
1408 | continue; |
1855 | if (host->app_cmd) { |
|
1409 | } |
1856 | result = msdc_app_cmd(host->mmc, host); |
|
Line 1410... | Line 1857... | |||
1410 | } |
1857 | if (result) { |
|
1411 | result = msdc_do_request(mmc, mrq); |
1858 | ERR_MSG("TUNE_BREAD app_cmd<%d> failed", host->mrq->cmd->opcode); |
|
1412 | |
1859 | continue; |
|
1413 | sdr_get_field(SDC_DCRC_STS, |
1860 | } |
|
1414 | SDC_DCRC_STS_POS | SDC_DCRC_STS_NEG, |
- | ||
1415 | &dcrc); /* RO */ |
- | ||
1416 | if (!ddr) |
- | ||
1417 | dcrc &= ~SDC_DCRC_STS_NEG; |
- | ||
1418 | ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>", |
- | ||
1419 | (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, |
- | ||
1420 | sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl); |
- | ||
1421 | |
- | ||
1422 | /* Fix me: result is 0, but dcrc is still exist */ |
- | ||
1423 | if (result == 0 && dcrc == 0) { |
- | ||
1424 | goto done; |
- | ||
1425 | } else { |
- | ||
1426 | /* there is a case: command timeout, and data phase not processed */ |
- | ||
Line -... | Line 1861... | |||
- | 1861 | } |
||
- | 1862 | result = msdc_do_request(mmc,mrq); |
||
- | 1863 | |
||
- | 1864 | sdr_get_field(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc); /* RO */ |
||
- | 1865 | if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG; |
||
- | 1866 | ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>", |
||
- | 1867 | (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, |
||
- | 1868 | sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl); |
||
- | 1869 | |
||
- | 1870 | /* Fix me: result is 0, but dcrc is still exist */ |
||
- | 1871 | if (result == 0 && dcrc == 0) { |
||
- | 1872 | goto done; |
||
- | 1873 | } else { |
||
1427 | if (mrq->data->error != 0 && |
1874 | /* there is a case: command timeout, and data phase not processed */ |
|
1428 | mrq->data->error != -EIO) { |
1875 | if (mrq->data->error != 0 && mrq->data->error != (unsigned int)(-EIO)) { |
|
1429 | ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", |
1876 | ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", |
|
1430 | result, mrq->cmd->error, mrq->data->error); |
1877 | result, mrq->cmd->error, mrq->data->error); |
|
1431 | goto done; |
1878 | goto done; |
|
1432 | } |
1879 | } |
|
1433 | } |
1880 | } |
|
1434 | } |
1881 | } |
|
1435 | |
1882 | |
|
1436 | cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); |
1883 | cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); |
|
1437 | cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1); |
1884 | cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1); |
|
1438 | |
1885 | |
|
1439 | /* E1 ECO. YD: Reverse */ |
1886 | /* E1 ECO. YD: Reverse */ |
|
1440 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
1887 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
|
1441 | orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; |
1888 | orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; |
|
1442 | orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; |
1889 | orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; |
|
1443 | orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; |
1890 | orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; |
|
1444 | orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; |
1891 | orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; |
|
1445 | orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; |
1892 | orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; |
|
1446 | orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; |
1893 | orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; |
|
1447 | orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; |
1894 | orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; |
|
1448 | orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; |
1895 | orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; |
|
1449 | } else { |
1896 | } else { |
|
1450 | orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; |
1897 | orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; |
|
1451 | orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; |
1898 | orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; |
|
1452 | orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; |
1899 | orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; |
|
1453 | orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; |
1900 | orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; |
|
1454 | orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; |
1901 | orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; |
|
1455 | orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; |
1902 | orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; |
|
1456 | orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; |
1903 | orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; |
|
1457 | orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; |
1904 | orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; |
|
1458 | } |
1905 | } |
|
1459 | |
1906 | |
|
1460 | if (ddr) { |
1907 | if (ddr) { |
|
1461 | cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; |
1908 | cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; |
|
1462 | cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; |
1909 | cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; |
|
1463 | cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; |
1910 | cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; |
|
1464 | cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; |
1911 | cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; |
|
1465 | } else { |
1912 | } else { |
|
1466 | cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; |
1913 | cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; |
|
1467 | cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; |
1914 | cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; |
|
1468 | cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; |
1915 | cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; |
|
1469 | cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; |
1916 | cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; |
|
1470 | } |
1917 | } |
|
- | 1918 | cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; |
||
1471 | cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; |
1919 | cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; |
|
1472 | cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; |
1920 | cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; |
|
1473 | cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; |
1921 | cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; |
|
1474 | cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; |
1922 | |
|
1475 | |
1923 | cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); |
|
1476 | cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); |
1924 | cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); |
|
1477 | cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); |
1925 | |
|
1478 | |
1926 | sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); |
|
1479 | sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); |
1927 | sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1); |
|
1480 | sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1); |
1928 | |
|
1481 | |
1929 | } while (++rxdly < 32); |
|
1482 | } while (++rxdly < 32); |
1930 | |
|
1483 | |
1931 | done: |
|
1484 | done: |
1932 | return result; |
|
1485 | return result; |
1933 | } |
|
1486 | } |
1934 | |
|
1487 | |
1935 | static int msdc_tune_bwrite(struct mmc_host *mmc,struct mmc_request *mrq) |
|
1488 | static int msdc_tune_bwrite(struct mmc_host *mmc, struct mmc_request *mrq) |
1936 | { |
|
1489 | { |
1937 | struct msdc_host *host = mmc_priv(mmc); |
|
1490 | struct msdc_host *host = mmc_priv(mmc); |
1938 | u32 base = host->base; |
|
1491 | void __iomem *base = host->base; |
1939 | |
|
Line 1492... | Line 1940... | |||
1492 | |
1940 | u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly; |
|
1493 | u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly; |
1941 | u32 dsmpl, cur_dsmpl, orig_dsmpl; |
|
1494 | u32 dsmpl, cur_dsmpl, orig_dsmpl; |
1942 | u32 rxdly, cur_rxdly0; |
|
Line 1495... | Line 1943... | |||
1495 | u32 rxdly, cur_rxdly0; |
1943 | u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; |
|
1496 | u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; |
1944 | u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; |
|
1497 | u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; |
1945 | int result = -1; |
|
1498 | int result = -1; |
1946 | u32 skip = 1; |
|
1499 | u32 skip = 1; |
1947 | |
|
1500 | |
1948 | // MSDC_IOCON_DDR50CKD need to check. [Fix me] |
|
1501 | // MSDC_IOCON_DDR50CKD need to check. [Fix me] |
1949 | |
|
1502 | |
1950 | sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly); |
|
1503 | sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, &orig_wrrdly); |
1951 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl ); |
|
1504 | sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl); |
1952 | |
|
1505 | |
1953 | /* Tune Method 2. just DAT0 */ |
|
1506 | /* Tune Method 2. just DAT0 */ |
1954 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); |
|
1507 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); |
1955 | cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); |
|
1508 | cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); |
1956 | |
|
1509 | |
1957 | /* E1 ECO. YD: Reverse */ |
|
1510 | /* E1 ECO. YD: Reverse */ |
1958 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
|
1511 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
1959 | orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; |
|
1512 | orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; |
1960 | orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; |
|
1513 | orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; |
1961 | orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; |
|
1514 | orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; |
1962 | orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; |
|
1515 | orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; |
1963 | } else { |
|
1516 | } else { |
1964 | orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; |
|
1517 | orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; |
1965 | orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; |
|
1518 | orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; |
1966 | orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; |
|
- | 1967 | orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; |
||
1519 | orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; |
1968 | } |
|
1520 | orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; |
1969 | |
|
1521 | } |
1970 | rxdly = 0; |
|
Line 1522... | Line 1971... | |||
1522 | |
1971 | do { |
|
1523 | rxdly = 0; |
1972 | wrrdly = 0; |
|
1524 | do { |
1973 | do { |
|
1525 | wrrdly = 0; |
1974 | for (dsmpl = 0; dsmpl < 2; dsmpl++) { |
|
1526 | do { |
1975 | cur_dsmpl = (orig_dsmpl + dsmpl) % 2; |
|
1527 | for (dsmpl = 0; dsmpl < 2; dsmpl++) { |
1976 | if (skip == 1) { |
|
1528 | cur_dsmpl = (orig_dsmpl + dsmpl) % 2; |
1977 | skip = 0; |
|
1529 | if (skip == 1) { |
- | ||
1530 | skip = 0; |
1978 | continue; |
|
1531 | continue; |
1979 | } |
|
1532 | } |
1980 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); |
|
1533 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); |
1981 | |
|
1534 | |
1982 | if (host->app_cmd) { |
|
1535 | if (host->app_cmd) { |
1983 | result = msdc_app_cmd(host->mmc, host); |
|
1536 | result = msdc_app_cmd(host->mmc, host); |
1984 | if (result) { |
|
Line 1537... | Line 1985... | |||
1537 | if (result) { |
1985 | ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode); |
|
1538 | ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode); |
1986 | continue; |
|
1539 | continue; |
1987 | } |
|
1540 | } |
1988 | } |
|
1541 | } |
1989 | result = msdc_do_request(mmc,mrq); |
|
1542 | result = msdc_do_request(mmc, mrq); |
1990 | |
|
1543 | |
1991 | ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", |
|
1544 | ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", |
1992 | result == 0 ? "PASS" : "FAIL", |
|
1545 | result == 0 ? "PASS" : "FAIL", |
1993 | cur_dsmpl, cur_wrrdly, cur_rxdly0); |
|
1546 | cur_dsmpl, cur_wrrdly, cur_rxdly0); |
1994 | |
|
1547 | |
1995 | if (result == 0) { |
|
1548 | if (result == 0) { |
1996 | goto done; |
|
1549 | goto done; |
1997 | } |
|
1550 | } else { |
1998 | else { |
|
1551 | /* there is a case: command timeout, and data phase not processed */ |
1999 | /* there is a case: command timeout, and data phase not processed */ |
|
1552 | if (mrq->data->error != -EIO) { |
2000 | if (mrq->data->error != (unsigned int)(-EIO)) { |
|
1553 | ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", |
2001 | ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", |
|
- | 2002 | result, mrq->cmd->error, mrq->data->error); |
||
1554 | result, mrq->cmd->error, mrq->data->error); |
2003 | goto done; |
|
1555 | goto done; |
2004 | } |
|
1556 | } |
2005 | } |
|
1557 | } |
2006 | } |
|
1558 | } |
2007 | cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; |
|
1559 | cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; |
2008 | sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); |
|
1560 | sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); |
2009 | } while (++wrrdly < 32); |
|
1561 | } while (++wrrdly < 32); |
2010 | |
|
1562 | |
2011 | cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ |
|
1563 | cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ |
2012 | cur_dat1 = orig_dat1; |
|
Line 1564... | Line 2013... | |||
1564 | cur_dat1 = orig_dat1; |
2013 | cur_dat2 = orig_dat2; |
|
1565 | cur_dat2 = orig_dat2; |
2014 | cur_dat3 = orig_dat3; |
|
Line 1566... | Line 2015... | |||
1566 | cur_dat3 = orig_dat3; |
2015 | |
|
1567 | |
2016 | cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); |
|
1568 | cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); |
2017 | sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); |
|
1569 | sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); |
2018 | } while (++rxdly < 32); |
|
Line 1570... | Line 2019... | |||
1570 | } while (++rxdly < 32); |
2019 | |
|
1571 | |
2020 | done: |
|
1572 | done: |
2021 | return result; |
|
1573 | return result; |
2022 | } |
|
1574 | } |
2023 | |
|
- | 2024 | static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) |
||
- | 2025 | { |
||
- | 2026 | struct mmc_command cmd; |
||
- | 2027 | struct mmc_request mrq; |
||
- | 2028 | u32 err; |
||
- | 2029 | |
||
- | 2030 | memset(&cmd, 0, sizeof(struct mmc_command)); |
||
- | 2031 | cmd.opcode = MMC_SEND_STATUS; |
||
- | 2032 | if (mmc->card) { |
||
- | 2033 | cmd.arg = mmc->card->rca << 16; |
||
- | 2034 | } else { |
||
- | 2035 | ERR_MSG("cmd13 mmc card is null"); |
||
- | 2036 | cmd.arg = host->app_cmd_arg; |
||
- | 2037 | } |
||
- | 2038 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; |
||
- | 2039 | |
||
Line 1575... | Line 2040... | |||
1575 | |
2040 | memset(&mrq, 0, sizeof(struct mmc_request)); |
|
- | 2041 | mrq.cmd = &cmd; cmd.mrq = &mrq; |
||
1576 | static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) |
2042 | cmd.data = NULL; |
|
1577 | { |
2043 | |
|
1578 | struct mmc_command cmd; |
2044 | err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); |
|
1579 | struct mmc_request mrq; |
2045 | |
|
1580 | u32 err; |
2046 | if (status) { |
|
1581 | |
2047 | *status = cmd.resp[0]; |
|
1582 | memset(&cmd, 0, sizeof(struct mmc_command)); |
2048 | } |
|
- | 2049 | |
||
1583 | cmd.opcode = MMC_SEND_STATUS; |
2050 | return err; |
|
1584 | if (mmc->card) { |
2051 | } |
|
- | 2052 | |
||
- | 2053 | static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) |
||
Line 1585... | Line -... | |||
1585 | cmd.arg = mmc->card->rca << 16; |
- | ||
1586 | } else { |
- | ||
1587 | ERR_MSG("cmd13 mmc card is null"); |
2054 | { |
|
1588 | cmd.arg = host->app_cmd_arg; |
2055 | u32 err = 0; |
|
1589 | } |
2056 | u32 status = 0; |
|
- | 2057 | |
||
1590 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; |
2058 | do { |
|
1591 | |
2059 | err = msdc_get_card_status(mmc, host, &status); |
|
1592 | memset(&mrq, 0, sizeof(struct mmc_request)); |
2060 | if (err) return err; |
|
1593 | mrq.cmd = &cmd; cmd.mrq = &mrq; |
2061 | /* need cmd12? */ |
|
1594 | cmd.data = NULL; |
2062 | ERR_MSG("cmd<13> resp<0x%x>", status); |
|
1595 | |
2063 | } while (R1_CURRENT_STATE(status) == 7); |
|
1596 | err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); |
2064 | |
|
1597 | |
2065 | return err; |
|
1598 | if (status) |
2066 | } |
|
1599 | *status = cmd.resp[0]; |
2067 | |
|
1600 | |
2068 | /* failed when msdc_do_request */ |
|
1601 | return err; |
2069 | static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) |
|
Line 1602... | Line 2070... | |||
1602 | } |
2070 | { |
|
1603 | |
2071 | struct msdc_host *host = mmc_priv(mmc); |
|
1604 | static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) |
2072 | struct mmc_command *cmd; |
|
1605 | { |
2073 | struct mmc_data *data; |
|
1606 | u32 err = 0; |
2074 | //u32 base = host->base; |
|
1607 | u32 status = 0; |
2075 | int ret=0, read; |
|
1608 | |
2076 | |
|
1609 | do { |
2077 | cmd = mrq->cmd; |
|
1610 | err = msdc_get_card_status(mmc, host, &status); |
2078 | data = mrq->cmd->data; |
|
1611 | if (err) |
2079 | |
|
1612 | return err; |
2080 | read = data->flags & MMC_DATA_READ ? 1 : 0; |
|
1613 | /* need cmd12? */ |
2081 | |
|
1614 | ERR_MSG("cmd<13> resp<0x%x>", status); |
2082 | if (read) { |
|
1615 | } while (R1_CURRENT_STATE(status) == 7); |
2083 | if (data->error == (unsigned int)(-EIO)) { |
|
1616 | |
2084 | ret = msdc_tune_bread(mmc,mrq); |
|
1617 | return err; |
2085 | } |
|
1618 | } |
2086 | } else { |
|
- | 2087 | ret = msdc_check_busy(mmc, host); |
||
1619 | |
2088 | if (ret){ |
|
1620 | /* failed when msdc_do_request */ |
2089 | ERR_MSG("XXX cmd13 wait program done failed"); |
|
1621 | static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) |
2090 | return ret; |
|
1622 | { |
2091 | } |
|
1623 | struct msdc_host *host = mmc_priv(mmc); |
2092 | /* CRC and TO */ |
|
1624 | struct mmc_command *cmd; |
2093 | /* Fix me: don't care card status? */ |
|
1625 | struct mmc_data *data; |
2094 | ret = msdc_tune_bwrite(mmc,mrq); |
|
1626 | //u32 base = host->base; |
2095 | } |
|
1627 | int ret = 0, read; |
2096 | |
|
Line 1628... | Line 2097... | |||
1628 | |
2097 | return ret; |
|
1629 | cmd = mrq->cmd; |
2098 | } |
|
1630 | data = mrq->cmd->data; |
2099 | |
|
1631 | |
2100 | /* ops.request */ |
|
1632 | read = data->flags & MMC_DATA_READ ? 1 : 0; |
2101 | static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq) |
|
1633 | |
2102 | { |
|
1634 | if (read) { |
2103 | struct msdc_host *host = mmc_priv(mmc); |
|
- | 2104 | |
||
- | 2105 | //=== for sdio profile === |
||
- | 2106 | #if 0 /* --- by chhung */ |
||
- | 2107 | u32 old_H32, old_L32, new_H32, new_L32; |
||
- | 2108 | u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; |
||
- | 2109 | #endif /* end of --- */ |
||
- | 2110 | |
||
- | 2111 | if(host->mrq){ |
||
- | 2112 | ERR_MSG("XXX host->mrq<0x%.8x>", (int)host->mrq); |
||
- | 2113 | BUG(); |
||
- | 2114 | } |
||
- | 2115 | |
||
- | 2116 | if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { |
||
- | 2117 | ERR_MSG("cmd<%d> card<%d> power<%d>", mrq->cmd->opcode, is_card_present(host), host->power_mode); |
||
- | 2118 | mrq->cmd->error = (unsigned int)-ENOMEDIUM; |
||
- | 2119 | |
||
Line 1635... | Line -... | |||
1635 | if (data->error == -EIO) |
- | ||
1636 | ret = msdc_tune_bread(mmc, mrq); |
- | ||
1637 | } else { |
- | ||
1638 | ret = msdc_check_busy(mmc, host); |
- | ||
1639 | if (ret) { |
- | ||
1640 | ERR_MSG("XXX cmd13 wait program done failed"); |
- | ||
1641 | return ret; |
- | ||
1642 | } |
- | ||
1643 | /* CRC and TO */ |
- | ||
1644 | /* Fix me: don't care card status? */ |
- | ||
1645 | ret = msdc_tune_bwrite(mmc, mrq); |
- | ||
1646 | } |
- | ||
1647 | |
- | ||
1648 | return ret; |
- | ||
1649 | } |
- | ||
1650 | |
- | ||
1651 | /* ops.request */ |
2120 | #if 1 |
|
1652 | static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) |
2121 | mrq->done(mrq); // call done directly. |
|
Line 1653... | Line 2122... | |||
1653 | { |
2122 | #else |
|
1654 | struct msdc_host *host = mmc_priv(mmc); |
2123 | mrq->cmd->retries = 0; // please don't retry. |
|
1655 | |
2124 | mmc_request_done(mmc, mrq); |
|
1656 | //=== for sdio profile === |
2125 | #endif |
|
- | 2126 | |
||
1657 | #if 0 /* --- by chhung */ |
2127 | return; |
|
1658 | u32 old_H32, old_L32, new_H32, new_L32; |
2128 | } |
|
Line 1659... | Line 2129... | |||
1659 | u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; |
2129 | |
|
1660 | #endif /* end of --- */ |
2130 | /* start to process */ |
|
1661 | |
2131 | spin_lock(&host->lock); |
|
1662 | WARN_ON(host->mrq); |
2132 | #if 0 /* --- by chhung */ |
|
1663 | |
2133 | if (sdio_pro_enable) { //=== for sdio profile === |
|
1664 | /* start to process */ |
2134 | if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { |
|
1665 | spin_lock(&host->lock); |
2135 | GPT_GetCounter64(&old_L32, &old_H32); |
|
1666 | #if 0 /* --- by chhung */ |
2136 | } |
|
1667 | if (sdio_pro_enable) { //=== for sdio profile === |
2137 | } |
|
1668 | if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) |
2138 | #endif /* end of --- */ |
|
1669 | GPT_GetCounter64(&old_L32, &old_H32); |
2139 | |
|
1670 | } |
2140 | host->mrq = mrq; |
|
1671 | #endif /* end of --- */ |
2141 | |
|
1672 | |
2142 | if (msdc_do_request(mmc,mrq)) { |
|
1673 | host->mrq = mrq; |
2143 | if(host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error) { |
|
1674 | |
2144 | msdc_tune_request(mmc,mrq); |
|
1675 | if (msdc_do_request(mmc, mrq)) { |
2145 | } |
|
1676 | if (host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error) |
2146 | } |
|
1677 | msdc_tune_request(mmc, mrq); |
2147 | |
|
1678 | } |
2148 | /* ==== when request done, check if app_cmd ==== */ |
|
1679 | |
2149 | if (mrq->cmd->opcode == MMC_APP_CMD) { |
|
1680 | /* ==== when request done, check if app_cmd ==== */ |
2150 | host->app_cmd = 1; |
|
1681 | if (mrq->cmd->opcode == MMC_APP_CMD) { |
2151 | host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ |
|
1682 | host->app_cmd = 1; |
2152 | } else { |
|
1683 | host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ |
2153 | host->app_cmd = 0; |
|
1684 | } else { |
2154 | //host->app_cmd_arg = 0; |
|
1685 | host->app_cmd = 0; |
2155 | } |
|
1686 | //host->app_cmd_arg = 0; |
2156 | |
|
1687 | } |
2157 | host->mrq = NULL; |
|
1688 | |
2158 | |
|
1689 | host->mrq = NULL; |
2159 | #if 0 /* --- by chhung */ |
|
1690 | |
2160 | //=== for sdio profile === |
|
1691 | #if 0 /* --- by chhung */ |
2161 | if (sdio_pro_enable) { |
|
1692 | //=== for sdio profile === |
2162 | if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { |
|
1693 | if (sdio_pro_enable) { |
2163 | GPT_GetCounter64(&new_L32, &new_H32); |
|
1694 | if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { |
2164 | ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32); |
|
1695 | GPT_GetCounter64(&new_L32, &new_H32); |
2165 | |
|
1696 | ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32); |
2166 | opcode = mrq->cmd->opcode; |
|
1697 | |
2167 | if (mrq->cmd->data) { |
|
1698 | opcode = mrq->cmd->opcode; |
2168 | sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; |
|
1699 | if (mrq->cmd->data) { |
2169 | bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0 ; |
|
1700 | sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; |
2170 | } else { |
|
1701 | bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0; |
2171 | bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; |
|
1702 | } else { |
2172 | } |
|
1703 | bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; |
- | ||
1704 | } |
2173 | |
|
1705 | |
- | ||
1706 | if (!mrq->cmd->error) |
2174 | if (!mrq->cmd->error) { |
|
1707 | msdc_performance(opcode, sizes, bRx, ticks); |
2175 | msdc_performance(opcode, sizes, bRx, ticks); |
|
1708 | } |
2176 | } |
|
1709 | } |
2177 | } |
|
1710 | #endif /* end of --- */ |
2178 | } |
|
1711 | spin_unlock(&host->lock); |
2179 | #endif /* end of --- */ |
|
1712 | |
2180 | spin_unlock(&host->lock); |
|
1713 | mmc_request_done(mmc, mrq); |
2181 | |
|
1714 | |
2182 | mmc_request_done(mmc, mrq); |
|
1715 | return; |
2183 | |
|
1716 | } |
2184 | return; |
|
1717 | |
2185 | } |
|
Line 1718... | Line 2186... | |||
1718 | /* called by ops.set_ios */ |
2186 | |
|
1719 | static void msdc_set_buswidth(struct msdc_host *host, u32 width) |
2187 | /* called by ops.set_ios */ |
|
1720 | { |
2188 | static void msdc_set_buswidth(struct msdc_host *host, u32 width) |
|
1721 | void __iomem *base = host->base; |
2189 | { |
|
1722 | u32 val = sdr_read32(SDC_CFG); |
2190 | u32 base = host->base; |
|
1723 | |
2191 | u32 val = sdr_read32(SDC_CFG); |
|
1724 | val &= ~SDC_CFG_BUSWIDTH; |
2192 | |
|
1725 | |
2193 | val &= ~SDC_CFG_BUSWIDTH; |
|
1726 | switch (width) { |
2194 | |
|
1727 | default: |
2195 | switch (width) { |
|
1728 | case MMC_BUS_WIDTH_1: |
2196 | default: |
|
1729 | width = 1; |
2197 | case MMC_BUS_WIDTH_1: |
|
1730 | val |= (MSDC_BUS_1BITS << 16); |
2198 | width = 1; |
|
1731 | break; |
2199 | val |= (MSDC_BUS_1BITS << 16); |
|
1732 | case MMC_BUS_WIDTH_4: |
2200 | break; |
|
Line 1733... | Line 2201... | |||
1733 | val |= (MSDC_BUS_4BITS << 16); |
2201 | case MMC_BUS_WIDTH_4: |
|
1734 | break; |
2202 | val |= (MSDC_BUS_4BITS << 16); |
|
1735 | case MMC_BUS_WIDTH_8: |
2203 | break; |
|
1736 | val |= (MSDC_BUS_8BITS << 16); |
2204 | case MMC_BUS_WIDTH_8: |
|
1737 | break; |
2205 | val |= (MSDC_BUS_8BITS << 16); |
|
1738 | } |
2206 | break; |
|
1739 | |
2207 | } |
|
1740 | sdr_write32(SDC_CFG, val); |
2208 | |
|
1741 | |
2209 | sdr_write32(SDC_CFG, val); |
|
1742 | N_MSG(CFG, "Bus Width = %d", width); |
2210 | |
|
1743 | } |
2211 | N_MSG(CFG, "Bus Width = %d", width); |
|
1744 | |
2212 | } |
|
1745 | /* ops.set_ios */ |
2213 | |
|
1746 | static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
2214 | /* ops.set_ios */ |
|
1747 | { |
2215 | static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
|
1748 | struct msdc_host *host = mmc_priv(mmc); |
2216 | { |
|
1749 | void __iomem *base = host->base; |
2217 | struct msdc_host *host = mmc_priv(mmc); |
|
1750 | u32 ddr = 0; |
2218 | struct msdc_hw *hw=host->hw; |
|
1751 | |
2219 | u32 base = host->base; |
|
1752 | #ifdef MT6575_SD_DEBUG |
2220 | u32 ddr = 0; |
|
1753 | static char *vdd[] = { |
2221 | |
|
1754 | "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", |
2222 | #ifdef MT6575_SD_DEBUG |
|
1755 | "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", |
2223 | static char *vdd[] = { |
|
1756 | "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", |
2224 | "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", |
|
1757 | "3.40v", "3.50v", "3.60v" |
2225 | "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", |
|
1758 | }; |
2226 | "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", |
|
1759 | static char *power_mode[] = { |
2227 | "3.40v", "3.50v", "3.60v" |
|
1760 | "OFF", "UP", "ON" |
2228 | }; |
|
1761 | }; |
2229 | static char *power_mode[] = { |
|
1762 | static char *bus_mode[] = { |
2230 | "OFF", "UP", "ON" |
|
1763 | "UNKNOWN", "OPENDRAIN", "PUSHPULL" |
2231 | }; |
|
1764 | }; |
2232 | static char *bus_mode[] = { |
|
- | 2233 | "UNKNOWN", "OPENDRAIN", "PUSHPULL" |
||
- | 2234 | }; |
||
1765 | static char *timing[] = { |
2235 | static char *timing[] = { |
|
1766 | "LEGACY", "MMC_HS", "SD_HS" |
2236 | "LEGACY", "MMC_HS", "SD_HS" |
|
1767 | }; |
2237 | }; |
|
1768 | |
2238 | |
|
1769 | printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)", |
2239 | printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)", |
|
1770 | ios->clock / 1000, bus_mode[ios->bus_mode], |
2240 | ios->clock / 1000, bus_mode[ios->bus_mode], |
|
1771 | (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, |
2241 | (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, |
|
1772 | power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]); |
2242 | power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]); |
|
1773 | #endif |
2243 | #endif |
|
- | 2244 | |
||
- | 2245 | msdc_set_buswidth(host, ios->bus_width); |
||
- | 2246 | |
||
- | 2247 | /* Power control ??? */ |
||
- | 2248 | switch (ios->power_mode) { |
||
- | 2249 | case MMC_POWER_OFF: |
||
- | 2250 | case MMC_POWER_UP: |
||
- | 2251 | // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ |
||
- | 2252 | break; |
||
- | 2253 | case MMC_POWER_ON: |
||
- | 2254 | host->power_mode = MMC_POWER_ON; |
||
- | 2255 | break; |
||
- | 2256 | default: |
||
- | 2257 | break; |
||
- | 2258 | } |
||
- | 2259 | |
||
- | 2260 | /* Clock control */ |
||
- | 2261 | if (host->mclk != ios->clock) { |
||
- | 2262 | if(ios->clock > 25000000) { |
||
- | 2263 | //if (!(host->hw->flags & MSDC_REMOVABLE)) { |
||
- | 2264 | INIT_MSG("SD data latch edge<%d>", hw->data_edge); |
||
- | 2265 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge); |
||
- | 2266 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, hw->data_edge); |
||
- | 2267 | //} /* for tuning debug */ |
||
- | 2268 | } else { /* default value */ |
||
- | 2269 | sdr_write32(MSDC_IOCON, 0x00000000); |
||
- | 2270 | // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); |
||
1774 | |
2271 | sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward |
|
Line 1775... | Line 2272... | |||
1775 | msdc_set_buswidth(host, ios->bus_width); |
2272 | sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); |
|
1776 | |
2273 | // sdr_write32(MSDC_PAD_TUNE, 0x00000000); |
|
1777 | /* Power control ??? */ |
2274 | sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward |
|
1778 | switch (ios->power_mode) { |
2275 | } |
|
1779 | case MMC_POWER_OFF: |
2276 | msdc_set_mclk(host, ddr, ios->clock); |
|
- | 2277 | } |
||
1780 | case MMC_POWER_UP: |
2278 | } |
|
Line 1781... | Line 2279... | |||
1781 | // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ |
2279 | |
|
1782 | break; |
2280 | /* ops.get_ro */ |
|
1783 | case MMC_POWER_ON: |
2281 | static int msdc_ops_get_ro(struct mmc_host *mmc) |
|
1784 | host->power_mode = MMC_POWER_ON; |
2282 | { |
|
1785 | break; |
2283 | struct msdc_host *host = mmc_priv(mmc); |
|
1786 | default: |
2284 | u32 base = host->base; |
|
1787 | break; |
2285 | unsigned long flags; |
|
1788 | } |
2286 | int ro = 0; |
|
1789 | |
2287 | |
|
1790 | /* Clock control */ |
2288 | if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ |
|
1791 | if (host->mclk != ios->clock) { |
2289 | spin_lock_irqsave(&host->lock, flags); |
|
1792 | if (ios->clock > 25000000) { |
2290 | ro = (sdr_read32(MSDC_PS) >> 31); |
|
1793 | //if (!(host->hw->flags & MSDC_REMOVABLE)) { |
2291 | spin_unlock_irqrestore(&host->lock, flags); |
|
1794 | INIT_MSG("SD data latch edge<%d>", MSDC_SMPL_FALLING); |
2292 | } |
|
1795 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, |
2293 | return ro; |
|
1796 | MSDC_SMPL_FALLING); |
2294 | } |
|
1797 | sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, |
2295 | |
|
1798 | MSDC_SMPL_FALLING); |
2296 | /* ops.get_cd */ |
|
1799 | //} /* for tuning debug */ |
2297 | static int msdc_ops_get_cd(struct mmc_host *mmc) |
|
1800 | } else { /* default value */ |
2298 | { |
|
1801 | sdr_write32(MSDC_IOCON, 0x00000000); |
2299 | struct msdc_host *host = mmc_priv(mmc); |
|
1802 | // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); |
2300 | u32 base = host->base; |
|
1803 | sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward |
2301 | unsigned long flags; |
|
1804 | sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); |
2302 | int present = 1; |
|
1805 | // sdr_write32(MSDC_PAD_TUNE, 0x00000000); |
2303 | |
|
1806 | sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward |
2304 | /* for sdio, MSDC_REMOVABLE not set, always return 1 */ |
|
1807 | } |
- | ||
1808 | msdc_set_mclk(host, ddr, ios->clock); |
- | ||
1809 | } |
- | ||
1810 | } |
- | ||
1811 | |
- | ||
1812 | /* ops.get_ro */ |
- | ||
1813 | static int msdc_ops_get_ro(struct mmc_host *mmc) |
2305 | if (!(host->hw->flags & MSDC_REMOVABLE)) { |
|
1814 | { |
- | ||
1815 | struct msdc_host *host = mmc_priv(mmc); |
- | ||
1816 | void __iomem *base = host->base; |
- | ||
1817 | unsigned long flags; |
- | ||
1818 | int ro = 0; |
- | ||
1819 | |
- | ||
1820 | if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ |
2306 | /* For sdio, read H/W always get<1>, but may timeout some times */ |
|
1821 | spin_lock_irqsave(&host->lock, flags); |
- | ||
1822 | ro = (sdr_read32(MSDC_PS) >> 31); |
- | ||
1823 | spin_unlock_irqrestore(&host->lock, flags); |
- | ||
1824 | } |
- | ||
1825 | return ro; |
- | ||
1826 | } |
- | ||
1827 | |
- | ||
1828 | /* ops.get_cd */ |
- | ||
1829 | static int msdc_ops_get_cd(struct mmc_host *mmc) |
- | ||
1830 | { |
- | ||
1831 | struct msdc_host *host = mmc_priv(mmc); |
- | ||
1832 | void __iomem *base = host->base; |
- | ||
1833 | unsigned long flags; |
- | ||
1834 | int present = 1; |
- | ||
1835 | |
- | ||
1836 | /* for sdio, MSDC_REMOVABLE not set, always return 1 */ |
- | ||
1837 | if (!(host->hw->flags & MSDC_REMOVABLE)) { |
- | ||
1838 | /* For sdio, read H/W always get<1>, but may timeout some times */ |
- | ||
1839 | #if 1 |
- | ||
1840 | host->card_inserted = 1; |
- | ||
1841 | return 1; |
- | ||
1842 | #else |
- | ||
1843 | host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; |
- | ||
1844 | INIT_MSG("sdio ops_get_cd<%d>", host->card_inserted); |
- | ||
1845 | return host->card_inserted; |
- | ||
1846 | #endif |
- | ||
1847 | } |
- | ||
1848 | |
- | ||
1849 | /* MSDC_CD_PIN_EN set for card */ |
- | ||
1850 | if (host->hw->flags & MSDC_CD_PIN_EN) { |
- | ||
1851 | spin_lock_irqsave(&host->lock, flags); |
- | ||
1852 | #if 0 |
- | ||
1853 | present = host->card_inserted; /* why not read from H/W: Fix me*/ |
- | ||
1854 | #else |
- | ||
1855 | // CD |
- | ||
1856 | if (cd_active_low) |
- | ||
1857 | present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; |
- | ||
1858 | else |
- | ||
1859 | present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 1 : 0; |
- | ||
1860 | host->card_inserted = present; |
- | ||
1861 | #endif |
- | ||
1862 | spin_unlock_irqrestore(&host->lock, flags); |
- | ||
1863 | } else { |
- | ||
1864 | present = 0; /* TODO? Check DAT3 pins for card detection */ |
- | ||
1865 | } |
- | ||
1866 | |
- | ||
1867 | INIT_MSG("ops_get_cd return<%d>", present); |
- | ||
1868 | return present; |
- | ||
1869 | } |
- | ||
1870 | |
- | ||
1871 | static struct mmc_host_ops mt_msdc_ops = { |
- | ||
1872 | .request = msdc_ops_request, |
2307 | #if 1 |
|
1873 | .set_ios = msdc_ops_set_ios, |
- | ||
1874 | .get_ro = msdc_ops_get_ro, |
- | ||
1875 | .get_cd = msdc_ops_get_cd, |
- | ||
1876 | }; |
- | ||
1877 | |
- | ||
1878 | /*--------------------------------------------------------------------------*/ |
- | ||
1879 | /* interrupt handler */ |
2308 | host->card_inserted = 1; |
|
1880 | /*--------------------------------------------------------------------------*/ |
- | ||
1881 | static irqreturn_t msdc_irq(int irq, void *dev_id) |
- | ||
1882 | { |
- | ||
1883 | struct msdc_host *host = (struct msdc_host *)dev_id; |
- | ||
1884 | struct mmc_data *data = host->data; |
- | ||
1885 | struct mmc_command *cmd = host->cmd; |
- | ||
1886 | void __iomem *base = host->base; |
- | ||
1887 | |
- | ||
1888 | u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | |
- | ||
1889 | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | |
- | ||
1890 | MSDC_INT_ACMD19_DONE; |
- | ||
1891 | u32 datsts = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO; |
- | ||
1892 | |
- | ||
1893 | u32 intsts = sdr_read32(MSDC_INT); |
- | ||
1894 | u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts; |
- | ||
1895 | |
- | ||
1896 | sdr_write32(MSDC_INT, intsts); /* clear interrupts */ |
- | ||
1897 | /* MSG will cause fatal error */ |
- | ||
1898 | |
- | ||
1899 | /* card change interrupt */ |
- | ||
1900 | if (intsts & MSDC_INT_CDSC) { |
- | ||
1901 | if (host->mmc->caps & MMC_CAP_NEEDS_POLL) |
- | ||
1902 | return IRQ_HANDLED; |
- | ||
1903 | IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); |
- | ||
1904 | schedule_delayed_work(&host->card_delaywork, HZ); |
- | ||
1905 | /* tuning when plug card ? */ |
- | ||
1906 | } |
- | ||
1907 | |
- | ||
1908 | /* sdio interrupt */ |
- | ||
1909 | if (intsts & MSDC_INT_SDIOIRQ) { |
- | ||
1910 | IRQ_MSG("XXX MSDC_INT_SDIOIRQ"); /* seems not sdio irq */ |
- | ||
1911 | //mmc_signal_sdio_irq(host->mmc); |
- | ||
1912 | } |
2309 | return 1; |
|
- | 2310 | #else |
||
- | 2311 | host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; |
||
- | 2312 | INIT_MSG("sdio ops_get_cd<%d>", host->card_inserted); |
||
- | 2313 | return host->card_inserted; |
||
- | 2314 | #endif |
||
- | 2315 | } |
||
- | 2316 | |
||
- | 2317 | /* MSDC_CD_PIN_EN set for card */ |
||
- | 2318 | if (host->hw->flags & MSDC_CD_PIN_EN) { |
||
- | 2319 | spin_lock_irqsave(&host->lock, flags); |
||
- | 2320 | #if 0 |
||
- | 2321 | present = host->card_inserted; /* why not read from H/W: Fix me*/ |
||
- | 2322 | #else |
||
- | 2323 | // CD |
||
- | 2324 | if (cd_active_low) |
||
- | 2325 | present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; |
||
- | 2326 | else |
||
- | 2327 | present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 1 : 0; |
||
- | 2328 | if (host->mmc->caps & MMC_CAP_NEEDS_POLL) |
||
- | 2329 | present = 1; |
||
- | 2330 | host->card_inserted = present; |
||
- | 2331 | #endif |
||
- | 2332 | spin_unlock_irqrestore(&host->lock, flags); |
||
- | 2333 | } else { |
||
- | 2334 | present = 0; /* TODO? Check DAT3 pins for card detection */ |
||
- | 2335 | } |
||
- | 2336 | |
||
- | 2337 | INIT_MSG("ops_get_cd return<%d>", present); |
||
- | 2338 | return present; |
||
- | 2339 | } |
||
- | 2340 | |
||
- | 2341 | /* ops.enable_sdio_irq */ |
||
- | 2342 | static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable) |
||
- | 2343 | { |
||
- | 2344 | struct msdc_host *host = mmc_priv(mmc); |
||
- | 2345 | struct msdc_hw *hw = host->hw; |
||
- | 2346 | u32 base = host->base; |
||
- | 2347 | u32 tmp; |
||
- | 2348 | |
||
- | 2349 | if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */ |
||
- | 2350 | if (enable) { |
||
- | 2351 | hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */ |
||
- | 2352 | } else { |
||
- | 2353 | hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */ |
||
- | 2354 | } |
||
- | 2355 | } else { |
||
- | 2356 | ERR_MSG("XXX "); /* so never enter here */ |
||
- | 2357 | tmp = sdr_read32(SDC_CFG); |
||
- | 2358 | /* FIXME. Need to interrupt gap detection */ |
||
- | 2359 | if (enable) { |
||
- | 2360 | tmp |= (SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); |
||
- | 2361 | } else { |
||
- | 2362 | tmp &= ~(SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); |
||
- | 2363 | } |
||
- | 2364 | sdr_write32(SDC_CFG, tmp); |
||
- | 2365 | } |
||
- | 2366 | } |
||
- | 2367 | |
||
- | 2368 | static struct mmc_host_ops mt_msdc_ops = { |
||
- | 2369 | .request = msdc_ops_request, |
||
- | 2370 | .set_ios = msdc_ops_set_ios, |
||
- | 2371 | .get_ro = msdc_ops_get_ro, |
||
- | 2372 | .get_cd = msdc_ops_get_cd, |
||
- | 2373 | .enable_sdio_irq = msdc_ops_enable_sdio_irq, |
||
- | 2374 | }; |
||
- | 2375 | |
||
- | 2376 | /*--------------------------------------------------------------------------*/ |
||
- | 2377 | /* interrupt handler */ |
||
- | 2378 | /*--------------------------------------------------------------------------*/ |
||
- | 2379 | static irqreturn_t msdc_irq(int irq, void *dev_id) |
||
- | 2380 | { |
||
- | 2381 | struct msdc_host *host = (struct msdc_host *)dev_id; |
||
- | 2382 | struct mmc_data *data = host->data; |
||
- | 2383 | struct mmc_command *cmd = host->cmd; |
||
- | 2384 | u32 base = host->base; |
||
- | 2385 | |
||
- | 2386 | u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | |
||
- | 2387 | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | |
||
- | 2388 | MSDC_INT_ACMD19_DONE; |
||
- | 2389 | u32 datsts = MSDC_INT_DATCRCERR |MSDC_INT_DATTMO; |
||
- | 2390 | |
||
- | 2391 | u32 intsts = sdr_read32(MSDC_INT); |
||
- | 2392 | u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts; |
||
- | 2393 | |
||
- | 2394 | sdr_write32(MSDC_INT, intsts); /* clear interrupts */ |
||
- | 2395 | /* MSG will cause fatal error */ |
||
- | 2396 | |
||
- | 2397 | /* card change interrupt */ |
||
- | 2398 | if (intsts & MSDC_INT_CDSC){ |
||
- | 2399 | if (mtk_sw_poll) |
||
- | 2400 | return IRQ_HANDLED; |
||
- | 2401 | IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); |
||
- | 2402 | #if 0 /* ---/+++ by chhung: fix slot mechanical bounce issue */ |
||
- | 2403 | tasklet_hi_schedule(&host->card_tasklet); |
||
- | 2404 | #else |
||
- | 2405 | schedule_delayed_work(&host->card_delaywork, HZ); |
||
- | 2406 | #endif |
||
- | 2407 | /* tuning when plug card ? */ |
||
- | 2408 | } |
||
- | 2409 | |
||
- | 2410 | /* sdio interrupt */ |
||
- | 2411 | if (intsts & MSDC_INT_SDIOIRQ){ |
||
- | 2412 | IRQ_MSG("XXX MSDC_INT_SDIOIRQ"); /* seems not sdio irq */ |
||
- | 2413 | //mmc_signal_sdio_irq(host->mmc); |
||
- | 2414 | } |
||
- | 2415 | |
||
- | 2416 | /* transfer complete interrupt */ |
||
- | 2417 | if (data != NULL) { |
||
- | 2418 | if (inten & MSDC_INT_XFER_COMPL) { |
||
- | 2419 | data->bytes_xfered = host->dma.xfersz; |
||
- | 2420 | complete(&host->xfer_done); |
||
- | 2421 | } |
||
- | 2422 | |
||
Line -... | Line 2423... | |||
- | 2423 | if (intsts & datsts) { |
||
- | 2424 | /* do basic reset, or stop command will sdc_busy */ |
||
- | 2425 | msdc_reset(); |
||
1913 | |
2426 | msdc_clr_fifo(); |
|
1914 | /* transfer complete interrupt */ |
2427 | msdc_clr_int(); |
|
Line 1915... | Line 2428... | |||
1915 | if (data != NULL) { |
2428 | atomic_set(&host->abort, 1); /* For PIO mode exit */ |
|
1916 | if (inten & MSDC_INT_XFER_COMPL) { |
2429 | |
|
1917 | data->bytes_xfered = host->xfer_size; |
2430 | if (intsts & MSDC_INT_DATTMO){ |
|
1918 | complete(&host->xfer_done); |
2431 | IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode); |
|
1919 | } |
2432 | data->error = (unsigned int)-ETIMEDOUT; |
|
1920 | |
2433 | } |
|
1921 | if (intsts & datsts) { |
2434 | else if (intsts & MSDC_INT_DATCRCERR){ |
|
1922 | /* do basic reset, or stop command will sdc_busy */ |
2435 | IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS)); |
|
Line 1923... | Line 2436... | |||
1923 | msdc_reset_hw(host); |
2436 | data->error = (unsigned int)-EIO; |
|
1924 | msdc_clr_fifo(); |
2437 | } |
|
1925 | msdc_clr_int(); |
2438 | |
|
1926 | |
2439 | //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { |
|
1927 | if (intsts & MSDC_INT_DATTMO) { |
2440 | if (host->dma_xfer) { |
|
1928 | IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode); |
2441 | complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ |
|
1929 | data->error = -ETIMEDOUT; |
2442 | } /* PIO mode can't do complete, because not init */ |
|
1930 | } else if (intsts & MSDC_INT_DATCRCERR) { |
2443 | } |
|
1931 | IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS)); |
2444 | } |
|
1932 | data->error = -EIO; |
2445 | |
|
1933 | } |
2446 | /* command interrupts */ |
|
1934 | |
2447 | if ((cmd != NULL) && (intsts & cmdsts)) { |
|
Line 1935... | Line 2448... | |||
1935 | //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { |
2448 | if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || |
|
Line 1936... | Line 2449... | |||
1936 | complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ |
2449 | (intsts & MSDC_INT_ACMD19_DONE)) { |
|
- | 2450 | u32 *rsp = &cmd->resp[0]; |
||
- | 2451 | |
||
- | 2452 | switch (host->cmd_rsp) { |
||
1937 | } |
2453 | case RESP_NONE: |
|
1938 | } |
2454 | break; |
|
1939 | |
2455 | case RESP_R2: |
|
1940 | /* command interrupts */ |
2456 | *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2); |
|
1941 | if ((cmd != NULL) && (intsts & cmdsts)) { |
2457 | *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0); |
|
1942 | if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || |
2458 | break; |
|
1943 | (intsts & MSDC_INT_ACMD19_DONE)) { |
2459 | default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ |
|
1944 | u32 *rsp = &cmd->resp[0]; |
2460 | if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) { |
|
1945 | |
2461 | *rsp = sdr_read32(SDC_ACMD_RESP); |
|
1946 | switch (host->cmd_rsp) { |
2462 | } else { |
|
1947 | case RESP_NONE: |
2463 | *rsp = sdr_read32(SDC_RESP0); |
|
1948 | break; |
2464 | } |
|
1949 | case RESP_R2: |
2465 | break; |
|
- | 2466 | } |
||
- | 2467 | } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { |
||
- | 2468 | if(intsts & MSDC_INT_ACMDCRCERR){ |
||
- | 2469 | IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR",cmd->opcode); |
||
1950 | *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2); |
2470 | } |
|
1951 | *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0); |
2471 | else { |
|
1952 | break; |
2472 | IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR",cmd->opcode); |
|
1953 | default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ |
2473 | } |
|
1954 | if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) |
2474 | cmd->error = (unsigned int)-EIO; |
|
1955 | *rsp = sdr_read32(SDC_ACMD_RESP); |
2475 | } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { |
|
1956 | else |
2476 | if(intsts & MSDC_INT_ACMDTMO){ |
|
1957 | *rsp = sdr_read32(SDC_RESP0); |
2477 | IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO",cmd->opcode); |
|
1958 | break; |
2478 | } |
|
1959 | } |
2479 | else { |
|
1960 | } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { |
2480 | IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO",cmd->opcode); |
|
1961 | if (intsts & MSDC_INT_ACMDCRCERR) |
2481 | } |
|
1962 | IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR", cmd->opcode); |
2482 | cmd->error = (unsigned int)-ETIMEDOUT; |
|
- | 2483 | msdc_reset(); |
||
1963 | else |
2484 | msdc_clr_fifo(); |
|
Line 1964... | Line 2485... | |||
1964 | IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR", cmd->opcode); |
2485 | msdc_clr_int(); |
|
1965 | cmd->error = -EIO; |
2486 | } |
|
1966 | } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { |
2487 | complete(&host->cmd_done); |
|
1967 | if (intsts & MSDC_INT_ACMDTMO) |
2488 | } |
|
- | 2489 | |
||
Line 1968... | Line 2490... | |||
1968 | IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO", cmd->opcode); |
2490 | /* mmc irq interrupts */ |
|
1969 | else |
2491 | if (intsts & MSDC_INT_MMCIRQ) { |
|
1970 | IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO", cmd->opcode); |
2492 | printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS)); |
|
1971 | cmd->error = -ETIMEDOUT; |
2493 | } |
|
1972 | msdc_reset_hw(host); |
2494 | |
|
1973 | msdc_clr_fifo(); |
2495 | #ifdef MT6575_SD_DEBUG |
|
1974 | msdc_clr_int(); |
2496 | { |
|
1975 | } |
2497 | msdc_int_reg *int_reg = (msdc_int_reg*)&intsts; |
|
1976 | complete(&host->cmd_done); |
2498 | N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", |
|
1977 | } |
2499 | intsts, |
|
1978 | |
2500 | int_reg->mmcirq, |
|
1979 | /* mmc irq interrupts */ |
2501 | int_reg->cdsc, |
|
1980 | if (intsts & MSDC_INT_MMCIRQ) |
2502 | int_reg->atocmdrdy, |
|
1981 | printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS)); |
2503 | int_reg->atocmdtmo, |
|
1982 | |
2504 | int_reg->atocmdcrc, |
|
1983 | #ifdef MT6575_SD_DEBUG |
2505 | int_reg->atocmd19done); |
|
1984 | { |
2506 | N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", |
|
1985 | /* msdc_int_reg *int_reg = (msdc_int_reg*)&intsts;*/ |
2507 | intsts, |
|
1986 | N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", |
2508 | int_reg->sdioirq, |
|
1987 | intsts, |
2509 | int_reg->cmdrdy, |
|
1988 | int_reg->mmcirq, |
2510 | int_reg->cmdtmo, |
|
1989 | int_reg->cdsc, |
2511 | int_reg->rspcrc, |
|
1990 | int_reg->atocmdrdy, |
2512 | int_reg->csta); |
|
1991 | int_reg->atocmdtmo, |
2513 | N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", |
|
1992 | int_reg->atocmdcrc, |
2514 | intsts, |
|
1993 | int_reg->atocmd19done); |
2515 | int_reg->xfercomp, |
|
1994 | N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", |
2516 | int_reg->dxferdone, |
|
1995 | intsts, |
2517 | int_reg->dattmo, |
|
1996 | int_reg->sdioirq, |
2518 | int_reg->datcrc, |
|
1997 | int_reg->cmdrdy, |
2519 | int_reg->dmaqempty); |
|
1998 | int_reg->cmdtmo, |
2520 | |
|
1999 | int_reg->rspcrc, |
2521 | } |
|
2000 | int_reg->csta); |
2522 | #endif |
|
2001 | N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", |
2523 | |
|
2002 | intsts, |
2524 | return IRQ_HANDLED; |
|
2003 | int_reg->xfercomp, |
- | ||
2004 | int_reg->dxferdone, |
- | ||
2005 | int_reg->dattmo, |
- | ||
2006 | int_reg->datcrc, |
- | ||
2007 | int_reg->dmaqempty); |
- | ||
2008 | } |
- | ||
2009 | #endif |
- | ||
2010 | |
- | ||
2011 | return IRQ_HANDLED; |
- | ||
2012 | } |
- | ||
2013 | |
- | ||
2014 | /*--------------------------------------------------------------------------*/ |
2525 | } |
|
Line -... | Line 2526... | |||
- | 2526 | |
||
- | 2527 | /*--------------------------------------------------------------------------*/ |
||
- | 2528 | /* platform_driver members */ |
||
- | 2529 | /*--------------------------------------------------------------------------*/ |
||
- | 2530 | /* called by msdc_drv_probe/remove */ |
||
- | 2531 | static void msdc_enable_cd_irq(struct msdc_host *host, int enable) |
||
- | 2532 | { |
||
- | 2533 | struct msdc_hw *hw = host->hw; |
||
- | 2534 | u32 base = host->base; |
||
- | 2535 | |
||
- | 2536 | /* for sdio, not set */ |
||
2015 | /* platform_driver members */ |
2537 | if ((hw->flags & MSDC_CD_PIN_EN) == 0) { |
|
2016 | /*--------------------------------------------------------------------------*/ |
2538 | /* Pull down card detection pin since it is not avaiable */ |
|
2017 | /* called by msdc_drv_probe/remove */ |
2539 | /* |
|
2018 | static void msdc_enable_cd_irq(struct msdc_host *host, int enable) |
2540 | if (hw->config_gpio_pin) |
|
2019 | { |
2541 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); |
|
2020 | struct msdc_hw *hw = host->hw; |
2542 | */ |
|
2021 | void __iomem *base = host->base; |
2543 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
|
2022 | |
2544 | sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
|
2023 | /* for sdio, not set */ |
2545 | sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); |
|
2024 | if ((hw->flags & MSDC_CD_PIN_EN) == 0) { |
2546 | return; |
|
2025 | /* Pull down card detection pin since it is not avaiable */ |
2547 | } |
|
2026 | /* |
2548 | |
|
2027 | if (hw->config_gpio_pin) |
2549 | N_MSG(CFG, "CD IRQ Eanable(%d)", enable); |
|
Line 2028... | Line 2550... | |||
2028 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); |
2550 | |
|
2029 | */ |
2551 | if (enable) { |
|
2030 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
2552 | if (hw->enable_cd_eirq) { /* not set, never enter */ |
|
2031 | sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
2553 | hw->enable_cd_eirq(); |
|
2032 | sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); |
2554 | } else { |
|
2033 | return; |
2555 | /* card detection circuit relies on the core power so that the core power |
|
2034 | } |
2556 | * shouldn't be turned off. Here adds a reference count to keep |
|
2035 | |
2557 | * the core power alive. |
|
2036 | N_MSG(CFG, "CD IRQ Eanable(%d)", enable); |
2558 | */ |
|
2037 | |
2559 | //msdc_vcore_on(host); //did in msdc_init_hw() |
|
2038 | if (enable) { |
2560 | |
|
2039 | /* card detection circuit relies on the core power so that the core power |
2561 | if (hw->config_gpio_pin) /* NULL */ |
|
2040 | * shouldn't be turned off. Here adds a reference count to keep |
2562 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); |
|
2041 | * the core power alive. |
2563 | |
|
2042 | */ |
2564 | sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE); |
|
2043 | //msdc_vcore_on(host); //did in msdc_init_hw() |
2565 | sdr_set_bits(MSDC_PS, MSDC_PS_CDEN); |
|
2044 | |
2566 | sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
|
2045 | if (hw->config_gpio_pin) /* NULL */ |
2567 | sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */ |
|
2046 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); |
2568 | } |
|
2047 | |
2569 | } else { |
|
2048 | sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE); |
2570 | if (hw->disable_cd_eirq) { |
|
Line 2049... | Line 2571... | |||
2049 | sdr_set_bits(MSDC_PS, MSDC_PS_CDEN); |
2571 | hw->disable_cd_eirq(); |
|
2050 | sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
2572 | } else { |
|
Line 2051... | Line 2573... | |||
2051 | sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */ |
2573 | if (hw->config_gpio_pin) /* NULL */ |
|
Line 2052... | Line 2574... | |||
2052 | } else { |
2574 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); |
|
2053 | if (hw->config_gpio_pin) /* NULL */ |
2575 | |
|
Line 2054... | Line 2576... | |||
2054 | hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); |
2576 | sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); |
|
2055 | |
2577 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
|
2056 | sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); |
2578 | sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
|
2057 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
2579 | |
|
Line 2058... | Line 2580... | |||
2058 | sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); |
2580 | /* Here decreases a reference count to core power since card |
|
2059 | |
2581 | * detection circuit is shutdown. |
|
2060 | /* Here decreases a reference count to core power since card |
2582 | */ |
|
2061 | * detection circuit is shutdown. |
2583 | //msdc_vcore_off(host); |
|
2062 | */ |
2584 | } |
|
2063 | //msdc_vcore_off(host); |
2585 | } |
|
2064 | } |
2586 | } |
|
2065 | } |
2587 | |
|
Line 2066... | Line 2588... | |||
2066 | |
2588 | /* called by msdc_drv_probe */ |
|
2067 | /* called by msdc_drv_probe */ |
2589 | static void msdc_init_hw(struct msdc_host *host) |
|
2068 | static void msdc_init_hw(struct msdc_host *host) |
2590 | { |
|
2069 | { |
2591 | u32 base = host->base; |
|
2070 | void __iomem *base = host->base; |
2592 | struct msdc_hw *hw = host->hw; |
|
2071 | |
2593 | |
|
2072 | /* Power on */ |
2594 | /* Power on */ |
|
2073 | #if 0 /* --- by chhung */ |
2595 | #if 0 /* --- by chhung */ |
|
2074 | msdc_vcore_on(host); |
2596 | msdc_vcore_on(host); |
|
2075 | msdc_pin_reset(host, MSDC_PIN_PULL_UP); |
- | ||
2076 | msdc_select_clksrc(host, hw->clk_src); |
2597 | msdc_pin_reset(host, MSDC_PIN_PULL_UP); |
|
- | 2598 | msdc_select_clksrc(host, hw->clk_src); |
||
2077 | enable_clock(PERI_MSDC0_PDN + host->id, "SD"); |
2599 | enable_clock(PERI_MSDC0_PDN + host->id, "SD"); |
|
- | 2600 | msdc_vdd_on(host); |
||
- | 2601 | #endif /* end of --- */ |
||
- | 2602 | /* Configure to MMC/SD mode */ |
||
2078 | msdc_vdd_on(host); |
2603 | sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); |
|
- | 2604 | |
||
2079 | #endif /* end of --- */ |
2605 | /* Reset */ |
|
2080 | /* Configure to MMC/SD mode */ |
2606 | msdc_reset(); |
|
2081 | sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); |
2607 | msdc_clr_fifo(); |
|
2082 | |
2608 | |
|
2083 | /* Reset */ |
2609 | /* Disable card detection */ |
|
- | 2610 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
||
- | 2611 | |
||
- | 2612 | /* Disable and clear all interrupts */ |
||
- | 2613 | sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); |
||
- | 2614 | sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); |
||
2084 | msdc_reset_hw(host); |
2615 | |
|
2085 | msdc_clr_fifo(); |
2616 | #if 1 |
|
- | 2617 | /* reset tuning parameter */ |
||
- | 2618 | sdr_write32(MSDC_PAD_CTL0, 0x00090000); |
||
2086 | |
2619 | sdr_write32(MSDC_PAD_CTL1, 0x000A0000); |
|
Line 2087... | Line 2620... | |||
2087 | /* Disable card detection */ |
2620 | sdr_write32(MSDC_PAD_CTL2, 0x000A0000); |
|
2088 | sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); |
2621 | // sdr_write32(MSDC_PAD_TUNE, 0x00000000); |
|
2089 | |
2622 | sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward |
|
2090 | /* Disable and clear all interrupts */ |
2623 | // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); |
|
2091 | sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); |
2624 | sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward |
|
- | 2625 | sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); |
||
2092 | sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); |
2626 | sdr_write32(MSDC_IOCON, 0x00000000); |
|
2093 | |
2627 | #if 0 // use MT7620 default value: 0x403c004f |
|
2094 | #if 1 |
2628 | sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ |
|
2095 | /* reset tuning parameter */ |
2629 | #endif |
|
Line -... | Line 2630... | |||
- | 2630 | |
||
2096 | sdr_write32(MSDC_PAD_CTL0, 0x00090000); |
2631 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
|
2097 | sdr_write32(MSDC_PAD_CTL1, 0x000A0000); |
2632 | if (host->id == 1) { |
|
- | 2633 | sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1); |
||
- | 2634 | sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1); |
||
- | 2635 | |
||
2098 | sdr_write32(MSDC_PAD_CTL2, 0x000A0000); |
2636 | /* internal clock: latch read data */ |
|
- | 2637 | sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK); |
||
- | 2638 | } |
||
- | 2639 | } |
||
2099 | // sdr_write32(MSDC_PAD_TUNE, 0x00000000); |
2640 | #endif |
|
- | 2641 | |
||
2100 | sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward |
2642 | /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in |
|
2101 | // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); |
2643 | pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only |
|
2102 | sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward |
2644 | set when kernel driver wants to use SDIO bus interrupt */ |
|
2103 | sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); |
- | ||
2104 | sdr_write32(MSDC_IOCON, 0x00000000); |
- | ||
2105 | #if 0 // use MT7620 default value: 0x403c004f |
- | ||
2106 | sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ |
- | ||
2107 | #endif |
- | ||
2108 | |
- | ||
Line 2109... | Line -... | |||
2109 | if (sdr_read32(MSDC_ECO_VER) >= 4) { |
- | ||
2110 | if (host->id == 1) { |
2645 | /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ |
|
2111 | sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1); |
- | ||
2112 | sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1); |
- | ||
2113 | |
- | ||
2114 | /* internal clock: latch read data */ |
2646 | sdr_set_bits(SDC_CFG, SDC_CFG_SDIO); |
|
2115 | sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK); |
2647 | |
|
2116 | } |
2648 | /* disable detect SDIO device interupt function */ |
|
2117 | } |
2649 | sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE); |
|
2118 | #endif |
2650 | |
|
2119 | |
2651 | /* eneable SMT for glitch filter */ |
|
- | 2652 | sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); |
||
- | 2653 | sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); |
||
- | 2654 | sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); |
||
- | 2655 | |
||
- | 2656 | #if 1 |
||
- | 2657 | /* set clk, cmd, dat pad driving */ |
||
- | 2658 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, hw->clk_drv); |
||
- | 2659 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, hw->clk_drv); |
||
- | 2660 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, hw->cmd_drv); |
||
- | 2661 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, hw->cmd_drv); |
||
- | 2662 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, hw->dat_drv); |
||
- | 2663 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, hw->dat_drv); |
||
- | 2664 | #else |
||
- | 2665 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); |
||
- | 2666 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); |
||
- | 2667 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); |
||
- | 2668 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); |
||
- | 2669 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); |
||
- | 2670 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); |
||
- | 2671 | #endif |
||
- | 2672 | |
||
- | 2673 | /* set sampling edge */ |
||
- | 2674 | |
||
- | 2675 | /* write crc timeout detection */ |
||
- | 2676 | sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1); |
||
- | 2677 | |
||
- | 2678 | /* Configure to default data timeout */ |
||
- | 2679 | sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); |
||
- | 2680 | |
||
- | 2681 | msdc_set_buswidth(host, MMC_BUS_WIDTH_1); |
||
- | 2682 | |
||
- | 2683 | N_MSG(FUC, "init hardware done!"); |
||
- | 2684 | } |
||
- | 2685 | |
||
- | 2686 | /* called by msdc_drv_remove */ |
||
- | 2687 | static void msdc_deinit_hw(struct msdc_host *host) |
||
- | 2688 | { |
||
- | 2689 | u32 base = host->base; |
||
- | 2690 | |
||
- | 2691 | /* Disable and clear all interrupts */ |
||
- | 2692 | sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); |
||
- | 2693 | sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); |
||
- | 2694 | |
||
- | 2695 | /* Disable card detection */ |
||
- | 2696 | msdc_enable_cd_irq(host, 0); |
||
- | 2697 | // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ |
||
- | 2698 | } |
||
- | 2699 | |
||
- | 2700 | /* init gpd and bd list in msdc_drv_probe */ |
||
- | 2701 | static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) |
||
- | 2702 | { |
||
- | 2703 | gpd_t *gpd = dma->gpd; |
||
- | 2704 | bd_t *bd = dma->bd; |
||
- | 2705 | bd_t *ptr, *prev; |
||
- | 2706 | |
||
- | 2707 | /* we just support one gpd */ |
||
- | 2708 | int bdlen = MAX_BD_PER_GPD; |
||
- | 2709 | |
||
- | 2710 | /* init the 2 gpd */ |
||
- | 2711 | memset(gpd, 0, sizeof(gpd_t) * 2); |
||
- | 2712 | //gpd->next = (void *)virt_to_phys(gpd + 1); /* pointer to a null gpd, bug! kmalloc <-> virt_to_phys */ |
||
- | 2713 | //gpd->next = (dma->gpd_addr + 1); /* bug */ |
||
- | 2714 | gpd->next = (void *)((u32)dma->gpd_addr + sizeof(gpd_t)); |
||
- | 2715 | |
||
- | 2716 | //gpd->intr = 0; |
||
- | 2717 | gpd->bdp = 1; /* hwo, cs, bd pointer */ |
||
- | 2718 | //gpd->ptr = (void*)virt_to_phys(bd); |
||
- | 2719 | gpd->ptr = (void *)dma->bd_addr; /* physical address */ |
||
- | 2720 | |
||
- | 2721 | memset(bd, 0, sizeof(bd_t) * bdlen); |
||
- | 2722 | ptr = bd + bdlen - 1; |
||
- | 2723 | //ptr->eol = 1; /* 0 or 1 [Fix me]*/ |
||
- | 2724 | //ptr->next = 0; |
||
- | 2725 | |
||
- | 2726 | while (ptr != bd) { |
||
- | 2727 | prev = ptr - 1; |
||
- | 2728 | prev->next = (void *)(dma->bd_addr + sizeof(bd_t) *(ptr - bd)); |
||
- | 2729 | ptr = prev; |
||
- | 2730 | } |
||
- | 2731 | } |
||
- | 2732 | |
||
- | 2733 | static int msdc_drv_probe(struct platform_device *pdev) |
||
- | 2734 | { |
||
- | 2735 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
||
- | 2736 | __iomem void *base; |
||
- | 2737 | struct mmc_host *mmc; |
||
- | 2738 | struct resource *mem; |
||
- | 2739 | struct msdc_host *host; |
||
- | 2740 | struct msdc_hw *hw; |
||
- | 2741 | int ret, irq; |
||
- | 2742 | u32 reg; |
||
- | 2743 | |
||
- | 2744 | printk("MTK MSDC device init.\n"); |
||
- | 2745 | mtk_sd_device.dev.platform_data = &msdc0_hw; |
||
- | 2746 | if (ralink_soc == MT762X_SOC_MT7620A || ralink_soc == MT762X_SOC_MT7621AT) { |
||
- | 2747 | //#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) |
||
- | 2748 | reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<18); |
||
- | 2749 | //#if defined (CONFIG_RALINK_MT7620) |
||
- | 2750 | if (ralink_soc == MT762X_SOC_MT7620A) |
||
- | 2751 | reg |= 0x1<<18; |
||
Line 2120... | Line -... | |||
2120 | /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in |
- | ||
2121 | pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only |
- | ||
2122 | set when kernel driver wants to use SDIO bus interrupt */ |
- | ||
2123 | /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ |
- | ||
2124 | sdr_set_bits(SDC_CFG, SDC_CFG_SDIO); |
2752 | //#endif |
|
2125 | |
- | ||
2126 | /* disable detect SDIO device interupt function */ |
- | ||
2127 | sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE); |
- | ||
2128 | |
2753 | } else { |
|
2129 | /* eneable SMT for glitch filter */ |
- | ||
2130 | sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); |
2754 | //#elif defined (CONFIG_RALINK_MT7628) |
|
2131 | sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); |
2755 | /* TODO: maybe omitted when RAether already toggle AGPIO_CFG */ |
|
2132 | sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); |
2756 | reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c)); |
|
2133 | |
- | ||
2134 | #if 1 |
2757 | reg |= 0x1e << 16; |
|
2135 | /* set clk, cmd, dat pad driving */ |
- | ||
2136 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 4); |
2758 | sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c), reg); |
|
2137 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 4); |
- | ||
2138 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 4); |
2759 | |
|
2139 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 4); |
- | ||
2140 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 4); |
- | ||
2141 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 4); |
- | ||
2142 | #else |
2760 | reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<10); |
|
2143 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); |
- | ||
2144 | sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); |
- | ||
2145 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); |
- | ||
2146 | sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); |
- | ||
2147 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); |
- | ||
2148 | sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); |
2761 | #if defined (CONFIG_MTK_MMC_EMMC_8BIT) |
|
2149 | #endif |
- | ||
2150 | |
- | ||
2151 | /* set sampling edge */ |
- | ||
2152 | |
2762 | reg |= 0x3<<26 | 0x3<<28 | 0x3<<30; |
|
2153 | /* write crc timeout detection */ |
- | ||
2154 | sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1); |
2763 | msdc0_hw.data_pins = 8, |
|
2155 | |
- | ||
2156 | /* Configure to default data timeout */ |
2764 | #endif |
|
Line 2157... | Line -... | |||
2157 | sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); |
- | ||
2158 | |
2765 | //#endif |
|
2159 | msdc_set_buswidth(host, MMC_BUS_WIDTH_1); |
2766 | } |
|
2160 | |
- | ||
2161 | N_MSG(FUC, "init hardware done!"); |
- | ||
2162 | } |
- | ||
2163 | |
- | ||
2164 | /* called by msdc_drv_remove */ |
- | ||
2165 | static void msdc_deinit_hw(struct msdc_host *host) |
- | ||
2166 | { |
- | ||
2167 | void __iomem *base = host->base; |
- | ||
2168 | |
- | ||
2169 | /* Disable and clear all interrupts */ |
- | ||
Line -... | Line 2767... | |||
- | 2767 | sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60), reg); |
||
2170 | sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); |
2768 | //platform_device_register(&mtk_sd_device); |
|
2171 | sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); |
2769 | /* end of +++ */ |
|
- | 2770 | |
||
- | 2771 | pdev->dev.platform_data = &msdc0_hw; |
||
- | 2772 | |
||
- | 2773 | if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en")) |
||
- | 2774 | msdc0_hw.flags |= MSDC_WP_PIN_EN; |
||
- | 2775 | |
||
- | 2776 | /* Allocate MMC host for this device */ |
||
- | 2777 | mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); |
||
- | 2778 | if (!mmc) return -ENOMEM; |
||
- | 2779 | |
||
- | 2780 | hw = (struct msdc_hw*)pdev->dev.platform_data; |
||
- | 2781 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
||
- | 2782 | irq = platform_get_irq(pdev, 0); |
||
- | 2783 | |
||
- | 2784 | //BUG_ON((!hw) || (!mem) || (irq < 0)); /* --- by chhung */ |
||
- | 2785 | |
||
- | 2786 | base = devm_ioremap_resource(&pdev->dev, res); |
||
- | 2787 | if (IS_ERR(base)) |
||
Line 2172... | Line 2788... | |||
2172 | |
2788 | return PTR_ERR(base); |
|
Line 2173... | Line -... | |||
2173 | /* Disable card detection */ |
- | ||
2174 | msdc_enable_cd_irq(host, 0); |
- | ||
2175 | // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ |
2789 | |
|
2176 | } |
- | ||
2177 | |
- | ||
2178 | /* init gpd and bd list in msdc_drv_probe */ |
2790 | /* Set host parameters to mmc */ |
|
2179 | static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) |
- | ||
2180 | { |
- | ||
2181 | struct gpd *gpd = dma->gpd; |
2791 | mmc->ops = &mt_msdc_ops; |
|
2182 | struct bd *bd = dma->bd; |
2792 | mmc->f_min = HOST_MIN_MCLK; |
|
2183 | int i; |
- | ||
2184 | |
2793 | mmc->f_max = HOST_MAX_MCLK; |
|
Line 2185... | Line -... | |||
2185 | /* we just support one gpd, but gpd->next must be set for desc |
- | ||
2186 | * DMA. That's why we alloc 2 gpd structurs. |
- | ||
2187 | */ |
- | ||
2188 | |
- | ||
2189 | memset(gpd, 0, sizeof(struct gpd) * 2); |
- | ||
2190 | |
- | ||
2191 | gpd->bdp = 1; /* hwo, cs, bd pointer */ |
2794 | mmc->ocr_avail = MSDC_OCR_AVAIL; |
|
2192 | gpd->ptr = (void *)dma->bd_addr; /* physical address */ |
- | ||
2193 | gpd->next = (void *)((u32)dma->gpd_addr + sizeof(struct gpd)); |
- | ||
2194 | |
- | ||
2195 | memset(bd, 0, sizeof(struct bd) * MAX_BD_NUM); |
- | ||
2196 | for (i = 0; i < (MAX_BD_NUM - 1); i++) |
- | ||
2197 | bd[i].next = (void *)(dma->bd_addr + sizeof(*bd) * (i + 1)); |
- | ||
2198 | } |
- | ||
2199 | |
- | ||
2200 | static int msdc_drv_probe(struct platform_device *pdev) |
- | ||
2201 | { |
2795 | |
|
2202 | struct resource *res; |
- | ||
2203 | __iomem void *base; |
- | ||
2204 | struct mmc_host *mmc; |
- | ||
2205 | struct msdc_host *host; |
- | ||
2206 | struct msdc_hw *hw; |
- | ||
2207 | int ret; |
- | ||
2208 | u32 reg; |
- | ||
2209 | |
- | ||
2210 | //FIXME: this should be done by pinconf and not by the sd driver |
2796 | /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, |
|
2211 | if (ralink_soc == MT762X_SOC_MT7688 || |
2797 | For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */ |
|
2212 | ralink_soc == MT762X_SOC_MT7628AN) { |
2798 | if (hw->flags & MSDC_HIGHSPEED) { |
|
Line 2213... | Line 2799... | |||
2213 | /* set EPHY pads to digital mode */ |
2799 | mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
|
- | 2800 | } |
||
Line 2214... | Line -... | |||
2214 | reg = sdr_read32((void __iomem *)(RALINK_SYSCTL_BASE + 0x3c)); |
- | ||
2215 | reg |= 0x1e << 16; |
- | ||
2216 | sdr_write32((void __iomem *)(RALINK_SYSCTL_BASE + 0x3c), reg); |
- | ||
2217 | } |
- | ||
2218 | |
- | ||
2219 | hw = &msdc0_hw; |
- | ||
2220 | |
- | ||
2221 | if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en")) |
- | ||
2222 | msdc0_hw.flags |= MSDC_WP_PIN_EN; |
- | ||
2223 | |
- | ||
2224 | /* Allocate MMC host for this device */ |
- | ||
2225 | mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); |
- | ||
2226 | if (!mmc) |
- | ||
2227 | return -ENOMEM; |
2801 | if (hw->data_pins == 4) { /* current data_pins are all 4*/ |
|
Line 2228... | Line 2802... | |||
2228 | |
2802 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
|
2229 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2803 | } else if (hw->data_pins == 8) { |
|
Line 2230... | Line 2804... | |||
2230 | base = devm_ioremap_resource(&pdev->dev, res); |
2804 | mmc->caps |= MMC_CAP_8_BIT_DATA; |
|
2231 | if (IS_ERR(base)) { |
2805 | } |
|
2232 | ret = PTR_ERR(base); |
2806 | if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ)) |
|
2233 | goto host_free; |
2807 | mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */ |
|
2234 | } |
2808 | |
|
- | 2809 | cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high"); |
||
2235 | |
2810 | mtk_sw_poll = of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll"); |
|
2236 | /* Set host parameters to mmc */ |
2811 | |
|
2237 | mmc->ops = &mt_msdc_ops; |
2812 | if (mtk_sw_poll) |
|
2238 | mmc->f_min = HOST_MIN_MCLK; |
2813 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
|
2239 | mmc->f_max = HOST_MAX_MCLK; |
2814 | |
|
2240 | mmc->ocr_avail = MSDC_OCR_AVAIL; |
2815 | /* MMC core transfer sizes tunable parameters */ |
|
- | 2816 | #if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) |
||
- | 2817 | mmc->max_segs = MAX_HW_SGMTS; |
||
- | 2818 | #else |
||
- | 2819 | mmc->max_hw_segs = MAX_HW_SGMTS; |
||
- | 2820 | mmc->max_phys_segs = MAX_PHY_SGMTS; |
||
- | 2821 | #endif |
||
Line -... | Line 2822... | |||
- | 2822 | mmc->max_seg_size = MAX_SGMT_SZ; |
||
- | 2823 | mmc->max_blk_size = HOST_MAX_BLKSZ; |
||
- | 2824 | mmc->max_req_size = MAX_REQ_SZ; |
||
- | 2825 | mmc->max_blk_count = mmc->max_req_size; |
||
- | 2826 | |
||
2241 | |
2827 | host = mmc_priv(mmc); |
|
Line 2242... | Line 2828... | |||
2242 | mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
2828 | host->hw = hw; |
|
2243 | |
2829 | host->mmc = mmc; |
|
2244 | //TODO: read this as bus-width from dt (via mmc_of_parse) |
- | ||
Line 2245... | Line 2830... | |||
2245 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
2830 | host->id = 0; |
|
Line 2246... | Line -... | |||
2246 | |
- | ||
2247 | cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high"); |
2831 | host->error = 0; |
|
2248 | |
2832 | host->irq = irq; |
|
2249 | if (of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll")) |
- | ||
Line 2250... | Line 2833... | |||
2250 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
2833 | host->base = (unsigned long) base; |
|
Line 2251... | Line 2834... | |||
2251 | |
2834 | host->mclk = 0; /* mclk: the request clock of mmc sub-system */ |
|
2252 | /* MMC core transfer sizes tunable parameters */ |
2835 | host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ |
|
Line 2253... | Line 2836... | |||
2253 | mmc->max_segs = MAX_HW_SGMTS; |
2836 | host->sclk = 0; /* sclk: the really clock after divition */ |
|
2254 | |
2837 | host->pm_state = PMSG_RESUME; |
|
2255 | mmc->max_seg_size = MAX_SGMT_SZ; |
- | ||
2256 | mmc->max_blk_size = HOST_MAX_BLKSZ; |
- | ||
2257 | mmc->max_req_size = MAX_REQ_SZ; |
- | ||
2258 | mmc->max_blk_count = mmc->max_req_size; |
- | ||
2259 | |
- | ||
2260 | host = mmc_priv(mmc); |
- | ||
2261 | host->hw = hw; |
- | ||
2262 | host->mmc = mmc; |
- | ||
2263 | host->id = pdev->id; |
- | ||
2264 | if (host->id < 0 || host->id >= 4) |
- | ||
2265 | host->id = 0; |
2838 | host->suspend = 0; |
|
2266 | host->error = 0; |
2839 | host->core_clkon = 0; |
|
- | 2840 | host->card_clkon = 0; |
||
- | 2841 | host->core_power = 0; |
||
2267 | |
2842 | host->power_mode = MMC_POWER_OFF; |
|
- | 2843 | // host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; |
||
- | 2844 | host->timeout_ns = 0; |
||
2268 | host->irq = platform_get_irq(pdev, 0); |
2845 | host->timeout_clks = DEFAULT_DTOC * 65536; |
|
- | 2846 | |
||
- | 2847 | host->mrq = NULL; |
||
2269 | if (host->irq < 0) { |
2848 | //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ |
|
2270 | ret = -EINVAL; |
2849 | |
|
Line 2271... | Line 2850... | |||
2271 | goto host_free; |
2850 | host->dma.used_gpd = 0; |
|
2272 | } |
2851 | host->dma.used_bd = 0; |
|
- | 2852 | mmc_dev(mmc)->dma_mask = NULL; |
||
- | 2853 | |
||
- | 2854 | /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ |
||
2273 | |
2855 | host->dma.gpd = dma_alloc_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), &host->dma.gpd_addr, GFP_KERNEL); |
|
2274 | host->base = base; |
2856 | host->dma.bd = dma_alloc_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), &host->dma.bd_addr, GFP_KERNEL); |
|
2275 | host->mclk = 0; /* mclk: the request clock of mmc sub-system */ |
2857 | BUG_ON((!host->dma.gpd) || (!host->dma.bd)); |
|
- | 2858 | msdc_init_gpd_bd(host, &host->dma); |
||
2276 | host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ |
2859 | |
|
- | 2860 | #if 0 |
||
- | 2861 | tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host); |
||
- | 2862 | #else |
||
- | 2863 | INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card); |
||
2277 | host->sclk = 0; /* sclk: the really clock after divition */ |
2864 | #endif |
|
2278 | host->pm_state = PMSG_RESUME; |
2865 | spin_lock_init(&host->lock); |
|
2279 | host->suspend = 0; |
2866 | msdc_init_hw(host); |
|
Line 2280... | Line 2867... | |||
2280 | host->core_clkon = 0; |
2867 | |
|
2281 | host->card_clkon = 0; |
2868 | if (ralink_soc == MT762X_SOC_MT7621AT) |
|
2282 | host->core_power = 0; |
2869 | ret = request_irq((unsigned int)irq, msdc_irq, 0, dev_name(&pdev->dev), host); |
|
2283 | host->power_mode = MMC_POWER_OFF; |
2870 | else |
|
2284 | // host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; |
2871 | ret = request_irq((unsigned int)irq, msdc_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), host); |
|
Line 2285... | Line 2872... | |||
2285 | host->timeout_ns = 0; |
2872 | |
|
2286 | host->timeout_clks = DEFAULT_DTOC * 65536; |
2873 | if (ret) goto release; |
|
2287 | |
2874 | // mt65xx_irq_unmask(irq); /* --- by chhung */ |
|
2288 | host->mrq = NULL; |
2875 | |
|
2289 | //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ |
2876 | if (hw->flags & MSDC_CD_PIN_EN) { /* not set for sdio */ |
|
2290 | |
2877 | if (hw->request_cd_eirq) { /* not set for MT6575 */ |
|
2291 | mmc_dev(mmc)->dma_mask = NULL; |
2878 | hw->request_cd_eirq(msdc_eirq_cd, (void*)host); /* msdc_eirq_cd will not be used! */ |
|
2292 | |
2879 | } |
|
2293 | /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ |
2880 | } |
|
2294 | host->dma.gpd = dma_alloc_coherent(&pdev->dev, |
2881 | |
|
2295 | MAX_GPD_NUM * sizeof(struct gpd), |
2882 | if (hw->request_sdio_eirq) /* set to combo_sdio_request_eirq() for WIFI */ |
|
2296 | &host->dma.gpd_addr, GFP_KERNEL); |
2883 | hw->request_sdio_eirq(msdc_eirq_sdio, (void*)host); /* msdc_eirq_sdio() will be called when EIRQ */ |
|
Line 2297... | Line 2884... | |||
2297 | host->dma.bd = dma_alloc_coherent(&pdev->dev, |
2884 | |
|
2298 | MAX_BD_NUM * sizeof(struct bd), |
2885 | if (hw->register_pm) {/* yes for sdio */ |
|
2299 | &host->dma.bd_addr, GFP_KERNEL); |
2886 | #ifdef CONFIG_PM |
|
2300 | if (!host->dma.gpd || !host->dma.bd) { |
2887 | hw->register_pm(msdc_pm, (void*)host); /* combo_sdio_register_pm() */ |
|
2301 | ret = -ENOMEM; |
2888 | #endif |
|
2302 | goto release_mem; |
2889 | if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ |
|
Line 2303... | Line 2890... | |||
2303 | } |
2890 | ERR_MSG("MSDC_SYS_SUSPEND and register_pm both set"); |
|
2304 | msdc_init_gpd_bd(host, &host->dma); |
2891 | } |
|
2305 | |
2892 | //mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* pm not controlled by system but by client. */ /* --- by chhung */ |
|
2306 | INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card); |
2893 | } |
|
2307 | spin_lock_init(&host->lock); |
2894 | |
|
- | 2895 | platform_set_drvdata(pdev, mmc); |
||
Line 2308... | Line 2896... | |||
2308 | msdc_init_hw(host); |
2896 | |
|
2309 | |
2897 | ret = mmc_add_host(mmc); |
|
2310 | /* TODO check weather flags 0 is correct, the mtk-sd driver uses |
2898 | if (ret) goto free_irq; |
|
2311 | * IRQF_TRIGGER_LOW | IRQF_ONESHOT for flags |
2899 | |
|
2312 | * |
2900 | /* Config card detection pin and enable interrupts */ |
|
Line 2313... | Line 2901... | |||
2313 | * for flags 0 the trigger polarity is determined by the |
2901 | if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */ |
|
2314 | * device tree, but not the oneshot flag, but maybe it is also |
2902 | msdc_enable_cd_irq(host, 1); |
|
- | 2903 | } else { |
||
2315 | * not needed because the soc could be oneshot safe. |
2904 | msdc_enable_cd_irq(host, 0); |
|
2316 | */ |
2905 | } |
|
Line 2317... | Line 2906... | |||
2317 | ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq, 0, pdev->name, |
2906 | |
|
2318 | host); |
2907 | return 0; |
|
2319 | if (ret) |
2908 | |
|
2320 | goto release; |
- | ||
2321 | |
- |