#include <gpio.h>
#include <intc.h>
#include <avr32/io.h>
#include <compiler.h>
#include "platform_sdio.h"
#include "printf-stdarg.h"
Go to the source code of this file.
Defines | |
#define | ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) |
#define | mdelay(ms) |
Functions | |
static void | avr32_irq_handler (void) |
void | platform_sdio_cmd (U8 idx, U32 arg, U8 flags, U32 *rsp, const U8 *data, U16 len) |
void | platform_sdio_init (U8 *flags) |
void | platform_sdio_irq (U8 op) |
void | platform_sdio_reset (void) |
void | platform_sdio_rx (U8 *data, U16 len) |
void | platform_sdio_tx (const U8 *data, U16 len) |
#define ARRAY_SIZE | ( | a | ) | sizeof(a) / sizeof(a[0]) |
Definition at line 36 of file avr32_sdio.c.
Referenced by console_add_cmd(), console_schedule_cmd(), platform_init(), platform_sdio_init(), timer_init(), timer_poll(), and timer_sched_timeout().
#define mdelay | ( | ms | ) |
Value:
do { \ volatile int a = 0; \ int i; \ for (i = 0; i < ms * 5000; i++) \ a++; \ } while (0)
Definition at line 40 of file avr32_sdio.c.
Referenced by platform_sdio_reset().
static void avr32_irq_handler | ( | void | ) | [static] |
Definition at line 313 of file avr32_sdio.c.
References sdio_irq_handler(), and SDIO_IRQ_RX.
Referenced by platform_init(), and platform_sdio_init().
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 } 00323 }
void platform_sdio_cmd | ( | U8 | idx, | |
U32 | arg, | |||
U8 | flags, | |||
U32 * | rsp, | |||
const U8 * | data, | |||
U16 | len | |||
) |
Definition at line 141 of file avr32_sdio.c.
References CMD_FLAG_TO_HOST, and MAX_BLOCK_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; /* R6 */ 00159 break; 00160 00161 case 7: 00162 reg.CMDR.rsptyp = 3; /* R1b */ 00163 break; 00164 00165 case 52: 00166 reg.CMDR.rsptyp = 1; /* R5 */ 00167 break; 00168 00169 case 53: 00170 /* Set length */ 00171 Assert(len <= MAX_BLOCK_LEN); 00172 mci->BLKR.bcnt = len % MAX_BLOCK_LEN; 00173 00174 reg.CMDR.rsptyp = 1; /* R5 */ 00175 00176 /* Start data transfer */ 00177 reg.CMDR.trcmd = 1; 00178 00179 /* SDIO byte transfer */ 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 /* Command is transmitted when CMDR is written */ 00191 mci->argr = arg; 00192 mci->cmdr = reg.cmdr; 00193 00194 /* Wait until command is transmitted and a respone is recvd, 00195 * (only required if rsp is != NULL) 00196 */ 00197 while (!mci->SR.cmdrdy); 00198 if (rsp) 00199 *rsp = mci->rspr0; 00200 00201 /* Reading sr might reset some status bits, so make a shadow copy */ 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 }
void platform_sdio_init | ( | U8 * | flags | ) |
Definition at line 47 of file avr32_sdio.c.
References ARRAY_SIZE, avr32_irq_handler(), and SDIO_FLAG_POLL.
00048 { 00049 #ifdef _ASSERT_ENABLE_ /* To silence warning if Assert() macro is empty */ 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 /* Note: MCI_CLK enabled at reset in pm->pbbmask (see 8.6) */ 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 }
void platform_sdio_irq | ( | U8 | op | ) |
Definition at line 288 of file avr32_sdio.c.
References IRQ_OP_DISABLE, and IRQ_OP_ENABLE.
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
void platform_sdio_reset | ( | void | ) |
Definition at line 93 of file avr32_sdio.c.
References mdelay.
00094 { 00095 volatile avr32_mci_t *mci = &AVR32_MCI; 00096 00097 /* Reset MCI controller. It is not specified in the data sheet how long 00098 * to wait for reset to complete, so we'll just wait a few ms here. 00099 */ 00100 mci->CR.swrst = 1; 00101 mdelay(10); 00102 00103 /* Disable MCI controller during configuration */ 00104 mci->CR.mcidis = 1; 00105 00106 /* Use read proof, otherwise we might not be able to read all data and 00107 * will get overrun errors. 00108 */ 00109 mci->MR.rdproof = 1; 00110 00111 /* Write proof is needed to make 4-bit mode stable since we might not 00112 * be able to fill the fifo fast enough with the CPU. 00113 */ 00114 mci->MR.wrproof = 1; 00115 00116 /* Use maximum values for data timeout */ 00117 mci->DTOR.dtocyc = 0xf; 00118 mci->DTOR.dtomul = 0x7; 00119 00120 /* MCI_CLK = FMCK / (2 * (clkdiv + 1)), FMCK is 60 MHz */ 00121 mci->MR.clkdiv = 0; 00122 00123 /* 4 bit or 1 bit */ 00124 #ifdef USE_1BIT_MODE 00125 mci->SDCR.sdcbus = 0; 00126 #else 00127 mci->SDCR.sdcbus = 2; 00128 #endif 00129 00130 /* Use MCI slot A/B */ 00131 #ifdef SDIO_SLOT_A 00132 mci->SDCR.sdcsel = 0; 00133 #else 00134 mci->SDCR.sdcsel = 1; 00135 #endif 00136 00137 /* Enable MCI controller */ 00138 mci->CR.mcien = 1; 00139 }
void platform_sdio_rx | ( | U8 * | data, | |
U16 | len | |||
) |
Definition at line 253 of file avr32_sdio.c.
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 /* XXX when len is not size aligned to 4 bytes, we might 00267 * write outside the buffer. For now we'll just hope that 00268 * nothing else live there. 00269 */ 00270 00271 /* access data using byte pointers, see platform_sdio_tx() */ 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 /* 4 bytes recv'd */ 00279 (void) *ptr.u32ptr++; 00280 if (len >= 4) 00281 len -= 4; 00282 else 00283 len = 0; 00284 } 00285 } 00286
void platform_sdio_tx | ( | const U8 * | data, | |
U16 | len | |||
) |
Definition at line 216 of file avr32_sdio.c.
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 /* XXX when len is not size aligned to 4 bytes, we might 00229 * read outside the buffer. Should probably be ok since 00230 * word size is 4 bytes. 00231 */ 00232 00233 /* access data using byte pointers since we might get unaligned 00234 * data from lwip. The cpu will issue a data abort if we try 00235 * to access data which is not aligned to 4 bytes using a 00236 * word pointer. 00237 */ 00238 mci->tdr = (ptr.u8ptr[0] << 24) | (ptr.u8ptr[1] << 16) | 00239 (ptr.u8ptr[2] << 8) | ptr.u8ptr[3]; 00240 00241 /* ok, 4 bytes transmitted */ 00242 ptr.u32ptr++; 00243 if (len >= 4) 00244 len -= 4; 00245 else 00246 len = 0; 00247 } 00248 00249 /* Wait for the bus to become idle */ 00250 while (!mci->SR.xfrdone); 00251 }