00001
00028 #include <gpio.h>
00029 #include <intc.h>
00030 #include <avr32/io.h>
00031 #include <compiler.h>
00032
00033 #include "platform_sdio.h"
00034 #include "printf-stdarg.h"
00035
00036 #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
00037
00038 __attribute__((__interrupt__)) static void avr32_irq_handler(void);
00039
00040 #define mdelay(ms) do { \
00041 volatile int a = 0; \
00042 int i; \
00043 for (i = 0; i < ms * 5000; i++) \
00044 a++; \
00045 } while (0)
00046
00047 void platform_sdio_init(U8 *flags)
00048 {
00049 #ifdef _ASSERT_ENABLE_
00050 volatile avr32_pm_t *pm = &AVR32_PM;
00051 #endif
00052 const gpio_map_t GPIO_MAP = {
00053 #ifdef SDIO_SLOT_A
00054 { AVR32_MCI_CLK_0_PIN, AVR32_MCI_CLK_0_FUNCTION },
00055 { AVR32_MCI_CMD_0_PIN, AVR32_MCI_CMD_0_FUNCTION },
00056 { AVR32_MCI_DATA_0_PIN, AVR32_MCI_DATA_0_FUNCTION },
00057 { AVR32_MCI_DATA_1_PIN, AVR32_MCI_DATA_1_FUNCTION },
00058 { AVR32_MCI_DATA_2_PIN, AVR32_MCI_DATA_2_FUNCTION },
00059 { AVR32_MCI_DATA_3_PIN, AVR32_MCI_DATA_3_FUNCTION }
00060 #else
00061 { AVR32_MCI_CLK_0_PIN, AVR32_MCI_CLK_0_FUNCTION },
00062 { AVR32_MCI_CMD_1_0_PIN, AVR32_MCI_CMD_1_0_FUNCTION },
00063 { AVR32_MCI_DATA_8_0_PIN, AVR32_MCI_DATA_8_0_FUNCTION },
00064 { AVR32_MCI_DATA_9_0_PIN, AVR32_MCI_DATA_9_0_FUNCTION },
00065 { AVR32_MCI_DATA_10_0_PIN, AVR32_MCI_DATA_10_0_FUNCTION },
00066 { AVR32_MCI_DATA_11_0_PIN, AVR32_MCI_DATA_11_0_FUNCTION }
00067 #endif
00068 };
00069 U32 i;
00070
00071 gpio_enable_module(GPIO_MAP, ARRAY_SIZE(GPIO_MAP));
00072 for (i = 0; i < ARRAY_SIZE(GPIO_MAP); i++)
00073 gpio_enable_pin_pull_up((GPIO_MAP)[i].pin);
00074
00075
00076 Assert(pm->pbbmask & (1 << 8));
00077
00078 *flags = 0;
00079
00080 #ifdef USE_1BIT_MODE
00081 *flags |= SDIO_1BIT_MODE;
00082 #endif
00083
00084 #ifdef USE_POLL
00085 *flags |= SDIO_FLAG_POLL;
00086 return;
00087 #else
00088 INTC_register_interrupt(&avr32_irq_handler, AVR32_MCI_IRQ,
00089 AVR32_INTC_INT0);
00090 #endif
00091 }
00092
00093 void platform_sdio_reset(void)
00094 {
00095 volatile avr32_mci_t *mci = &AVR32_MCI;
00096
00097
00098
00099
00100 mci->CR.swrst = 1;
00101 mdelay(10);
00102
00103
00104 mci->CR.mcidis = 1;
00105
00106
00107
00108
00109 mci->MR.rdproof = 1;
00110
00111
00112
00113
00114 mci->MR.wrproof = 1;
00115
00116
00117 mci->DTOR.dtocyc = 0xf;
00118 mci->DTOR.dtomul = 0x7;
00119
00120
00121 mci->MR.clkdiv = 0;
00122
00123
00124 #ifdef USE_1BIT_MODE
00125 mci->SDCR.sdcbus = 0;
00126 #else
00127 mci->SDCR.sdcbus = 2;
00128 #endif
00129
00130
00131 #ifdef SDIO_SLOT_A
00132 mci->SDCR.sdcsel = 0;
00133 #else
00134 mci->SDCR.sdcsel = 1;
00135 #endif
00136
00137
00138 mci->CR.mcien = 1;
00139 }
00140
00141 void platform_sdio_cmd(U8 idx, U32 arg, U8 flags, U32 *rsp,
00142 const U8 *data, U16 len)
00143 {
00144 volatile avr32_mci_t *mci = &AVR32_MCI;
00145 U32 sr;
00146 union {
00147 avr32_mci_cmdr_t CMDR;
00148 U32 cmdr;
00149 } reg = { { 0 } };
00150
00151 Assert(idx < (1 << 6));
00152 Assert(mci->SR.cmdrdy);
00153
00154 reg.CMDR.cmdnb = idx;
00155
00156 switch (idx) {
00157 case 3:
00158 reg.CMDR.rsptyp = 1;
00159 break;
00160
00161 case 7:
00162 reg.CMDR.rsptyp = 3;
00163 break;
00164
00165 case 52:
00166 reg.CMDR.rsptyp = 1;
00167 break;
00168
00169 case 53:
00170
00171 Assert(len <= MAX_BLOCK_LEN);
00172 mci->BLKR.bcnt = len % MAX_BLOCK_LEN;
00173
00174 reg.CMDR.rsptyp = 1;
00175
00176
00177 reg.CMDR.trcmd = 1;
00178
00179
00180 reg.CMDR.trtyp = 4;
00181
00182 if (flags & CMD_FLAG_TO_HOST)
00183 reg.CMDR.trdir = 1;
00184 break;
00185
00186 default:
00187 Assert(0);
00188 }
00189
00190
00191 mci->argr = arg;
00192 mci->cmdr = reg.cmdr;
00193
00194
00195
00196
00197 while (!mci->SR.cmdrdy);
00198 if (rsp)
00199 *rsp = mci->rspr0;
00200
00201
00202 sr = mci->sr;
00203 #if 0
00204 Assert(!(sr & AVR32_MCI_SR_DTOE_MASK));
00205 Assert(!(sr & AVR32_MCI_SR_OVRE_MASK));
00206 Assert(!(sr & AVR32_MCI_SR_CSTOE_MASK));
00207 Assert(!(sr & AVR32_MCI_SR_RCRCE_MASK));
00208 Assert(!(sr & AVR32_MCI_SR_RDIRE_MASK));
00209 Assert(!(sr & AVR32_MCI_SR_RENDE_MASK));
00210 Assert(!(sr & AVR32_MCI_SR_RINDE_MASK));
00211 Assert(!(sr & AVR32_MCI_SR_RTOE_MASK));
00212 #endif
00213 }
00214
00215
00216 void platform_sdio_tx(const U8 *data, U16 len)
00217 {
00218 volatile avr32_mci_t *mci = &AVR32_MCI;
00219 UnionCPtr ptr;
00220
00221 Assert(data);
00222 Assert(len);
00223
00224 ptr.u8ptr = data;
00225 while (len) {
00226 while (!mci->SR.txrdy);
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 mci->tdr = (ptr.u8ptr[0] << 24) | (ptr.u8ptr[1] << 16) |
00239 (ptr.u8ptr[2] << 8) | ptr.u8ptr[3];
00240
00241
00242 ptr.u32ptr++;
00243 if (len >= 4)
00244 len -= 4;
00245 else
00246 len = 0;
00247 }
00248
00249
00250 while (!mci->SR.xfrdone);
00251 }
00252
00253 void platform_sdio_rx(U8 *data, U16 len)
00254 {
00255 volatile avr32_mci_t *mci = &AVR32_MCI;
00256 UnionPtr ptr;
00257
00258 Assert(data);
00259 Assert(len);
00260
00261 ptr.u8ptr = data;
00262 while (len) {
00263 U32 rdr;
00264 while (!mci->SR.rxrdy);
00265
00266
00267
00268
00269
00270
00271
00272 rdr = mci->rdr;
00273 ptr.u8ptr[0] = (rdr >> 24) & 0xff;
00274 ptr.u8ptr[1] = (rdr >> 16) & 0xff;
00275 ptr.u8ptr[2] = (rdr >> 8) & 0xff;
00276 ptr.u8ptr[3] = rdr & 0xff;
00277
00278
00279 (void) *ptr.u32ptr++;
00280 if (len >= 4)
00281 len -= 4;
00282 else
00283 len = 0;
00284 }
00285 }
00286
00287 void platform_sdio_irq(U8 op)
00288 {
00289 volatile avr32_mci_t *mci = &AVR32_MCI;
00290
00291 #ifdef USE_POLL
00292 return;
00293 #endif
00294
00295 #ifdef SDIO_SLOT_A
00296 if (op == IRQ_OP_ENABLE)
00297 mci->IER.sdioirqa = 1;
00298 else if (op == IRQ_OP_DISABLE)
00299 mci->IDR.sdioirqa = 1;
00300 else
00301 Assert(0);
00302 #else
00303 if (op == IRQ_OP_ENABLE)
00304 mci->IER.sdioirqb = 1;
00305 else if (op == IRQ_OP_DISABLE)
00306 mci->IDR.sdioirqb = 1;
00307 else
00308 Assert(0);
00309 #endif
00310 }
00311
00312 __attribute__((__interrupt__)) static void avr32_irq_handler(void)
00313 {
00314 volatile avr32_mci_t *mci = &AVR32_MCI;
00315
00316 uint8_t status = 0;
00317
00318 if (mci->SR.sdioirqa || mci->SR.sdioirqb)
00319 status |= SDIO_IRQ_RX;
00320
00321 sdio_irq_handler(status);
00322 }