[154] | 1 | /*------------------------------------------------------------------------*/
|
---|
| 2 | /* FRK-RX62N: MMCv3/SDv1/SDv2 (SPI mode) Control Module */
|
---|
| 3 | /*------------------------------------------------------------------------*/
|
---|
| 4 | /*
|
---|
| 5 | / Copyright (C) 2014, ChaN, all right reserved.
|
---|
| 6 | /
|
---|
| 7 | / * This software is a free software and there is NO WARRANTY.
|
---|
| 8 | / * No restriction on use. You can use, modify and redistribute it for
|
---|
| 9 | / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
---|
| 10 | / * Redistributions of source code must retain the above copyright notice.
|
---|
| 11 | /
|
---|
| 12 | /-------------------------------------------------------------------------*/
|
---|
| 13 |
|
---|
| 14 | #include <kernel.h> /* Platform dependent include file */
|
---|
| 15 | #include <t_syslog.h>
|
---|
| 16 | #include <kernel/kernel_rename.h>
|
---|
| 17 | #include <sil.h>
|
---|
| 18 | #include <string.h>
|
---|
| 19 | #include "pffconf.h"
|
---|
| 20 | #include "target_config.h"
|
---|
| 21 | #include "kernel_cfg.h"
|
---|
| 22 | #include "mmc_rspi.h"
|
---|
| 23 |
|
---|
| 24 | static void CS_LOW()
|
---|
| 25 | {
|
---|
| 26 | sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) & ~PORT_PODR_B0_BIT); /* Set CS# low */
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | static void CS_HIGH()
|
---|
| 30 | {
|
---|
| 31 | sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT); /* Set CS# high */
|
---|
| 32 | }
|
---|
| 33 |
|
---|
| 34 | static bool_t WP()
|
---|
| 35 | {
|
---|
| 36 | return false;
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | static bool_t INS()
|
---|
| 40 | {
|
---|
| 41 | return (sil_reb_mem(PORT1_PIDR_ADDR) & PORT_PIDR_B5_BIT) == 0;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | static void CTRL_INIT()
|
---|
| 45 | {
|
---|
| 46 | /* CS=OUT */
|
---|
| 47 | sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B0_BIT);
|
---|
| 48 | /* INS=IN */
|
---|
| 49 | sil_wrb_mem(PORT1_PDR_ADDR, sil_reb_mem(PORT1_PDR_ADDR) & ~PORT_PDR_B5_BIT);
|
---|
| 50 | /* SPICLK,SPIMOSI=OUT */
|
---|
| 51 | sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
|
---|
| 52 | /* CS,SPICLK,SPIMOSI=HI */
|
---|
| 53 | sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
|
---|
| 54 | /* SPIMISO=IN */
|
---|
| 55 | sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) & ~PORT_PDR_B7_BIT);
|
---|
| 56 | /* SPIMISO=PULLUP */
|
---|
| 57 | sil_wrb_mem(PORTC_PCR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B7_BIT);
|
---|
| 58 | /* CMOSðIð */
|
---|
| 59 | sil_wrb_mem(PORTC_ODR0_ADDR, 0x00);
|
---|
| 60 | /* CMOSðIð */
|
---|
| 61 | sil_wrb_mem(PORTC_ODR1_ADDR, 0x00);
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | #define F_PCLK 48000000UL /* PCLK frequency (configured by SCKCR.PCK) */
|
---|
| 65 | #define SCLK_FAST 24000000UL /* SCLK frequency (R/W) */
|
---|
| 66 | #define SCLK_SLOW 375000UL /* SCLK frequency (Init) */
|
---|
| 67 |
|
---|
| 68 | static void RSPI_ATTACH()
|
---|
| 69 | {
|
---|
| 70 | /*
|
---|
| 71 | * W
|
---|
| 72 | [Xgbv@\ÌÝè(RSPI0)
|
---|
| 73 | */
|
---|
| 74 | sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* ÝÂ */
|
---|
| 75 | sil_wrw_mem(SYSTEM_MSTPCRB_ADDR,
|
---|
| 76 | sil_rew_mem(SYSTEM_MSTPCRB_ADDR) & ~SYSTEM_MSTPCRB_MSTPB17_BIT);
|
---|
| 77 | sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* ÝÖ~ */
|
---|
| 78 |
|
---|
| 79 | /* P15ðGPIOƵÄgp */
|
---|
| 80 | sil_wrb_mem(PORT1_PMR_ADDR,
|
---|
| 81 | sil_reb_mem(PORT1_PMR_ADDR) & ~PORT_PMR_B5_BIT);
|
---|
| 82 | /* PC0ðGPIOƵÄgp */
|
---|
| 83 | sil_wrb_mem(PORTC_PMR_ADDR,
|
---|
| 84 | sil_reb_mem(PORTC_PMR_ADDR) & ~PORT_PMR_B0_BIT);
|
---|
| 85 | /* PC5, PC6, PC7ðüÓ@\ƵÄgp */
|
---|
| 86 | sil_wrb_mem(PORTC_PMR_ADDR,
|
---|
| 87 | sil_reb_mem(PORTC_PMR_ADDR) | PORT_PMR_B5_BIT | PORT_PMR_B6_BIT | PORT_PMR_B7_BIT);
|
---|
| 88 |
|
---|
| 89 | /* «ÝveNgWX^ÌÝè PFSWErbgÖÌ«Ýð */
|
---|
| 90 | sil_wrb_mem(MPC_PWPR_ADDR, 0x00);
|
---|
| 91 | /* «ÝveNgWX^ÌÝè PxxFSWX^ÖÌ«Ýð */
|
---|
| 92 | sil_wrb_mem(MPC_PWPR_ADDR, 0x40);
|
---|
| 93 |
|
---|
| 94 | /* RSPCKAðIð */
|
---|
| 95 | sil_wrb_mem(MPC_PC5PFS_ADDR, 0x0d);
|
---|
| 96 | /* MOSIAðIð */
|
---|
| 97 | sil_wrb_mem(MPC_PC6PFS_ADDR, 0x0d);
|
---|
| 98 | /* MISOAðIð */
|
---|
| 99 | sil_wrb_mem(MPC_PC7PFS_ADDR, 0x0d);
|
---|
| 100 |
|
---|
| 101 | /* «ÝveNgWX^ÌÝè «ÝðÖ~ */
|
---|
| 102 | sil_wrb_mem(MPC_PWPR_ADDR, 0x80);
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | static void FCLK_FAST()
|
---|
| 106 | {
|
---|
| 107 | /* RSPI@\ð³ø» */
|
---|
| 108 | sil_wrb_mem(RSPI0_SPCR_ADDR,
|
---|
| 109 | sil_reb_mem(RSPI0_SPCR_ADDR) & ~RSPI_SPCR_SPE_BIT);
|
---|
| 110 | /* rbg[gÝè */
|
---|
| 111 | sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_FAST - 1);
|
---|
| 112 | /* RSPI@\ðLø» */
|
---|
| 113 | sil_wrb_mem(RSPI0_SPCR_ADDR,
|
---|
| 114 | sil_reb_mem(RSPI0_SPCR_ADDR) | RSPI_SPCR_SPE_BIT);
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | #ifdef SIL_ENDIAN_LITTLE
|
---|
| 118 | #define LDDW(x) rev_endian_uint32(x) /* Little endian: swap bytes */
|
---|
| 119 | #else
|
---|
| 120 | #define LDDW(x) x /* Big endian: no swap */
|
---|
| 121 | #endif
|
---|
| 122 |
|
---|
| 123 |
|
---|
| 124 |
|
---|
| 125 | /*--------------------------------------------------------------------------
|
---|
| 126 |
|
---|
| 127 | Module Private Functions
|
---|
| 128 |
|
---|
| 129 | ---------------------------------------------------------------------------*/
|
---|
| 130 |
|
---|
| 131 | /* MMC/SD command */
|
---|
| 132 | #define CMD0 (0) /* GO_IDLE_STATE */
|
---|
| 133 | #define CMD1 (1) /* SEND_OP_COND (MMC) */
|
---|
| 134 | #define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
|
---|
| 135 | #define CMD8 (8) /* SEND_IF_COND */
|
---|
| 136 | #define CMD9 (9) /* SEND_CSD */
|
---|
| 137 | #define CMD10 (10) /* SEND_CID */
|
---|
| 138 | #define CMD12 (12) /* STOP_TRANSMISSION */
|
---|
| 139 | #define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
|
---|
| 140 | #define CMD16 (16) /* SET_BLOCKLEN */
|
---|
| 141 | #define CMD17 (17) /* READ_SINGLE_BLOCK */
|
---|
| 142 | #define CMD18 (18) /* READ_MULTIPLE_BLOCK */
|
---|
| 143 | #define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
|
---|
| 144 | #define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
|
---|
| 145 | #define CMD24 (24) /* WRITE_BLOCK */
|
---|
| 146 | #define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
|
---|
| 147 | #define CMD32 (32) /* ERASE_ER_BLK_START */
|
---|
| 148 | #define CMD33 (33) /* ERASE_ER_BLK_END */
|
---|
| 149 | #define CMD38 (38) /* ERASE */
|
---|
| 150 | #define CMD55 (55) /* APP_CMD */
|
---|
| 151 | #define CMD58 (58) /* READ_OCR */
|
---|
| 152 |
|
---|
| 153 |
|
---|
| 154 |
|
---|
| 155 | static volatile
|
---|
| 156 | DSTATUS Stat = STA_NOINIT; /* Physical drive status */
|
---|
| 157 |
|
---|
| 158 | static volatile
|
---|
| 159 | WORD Timer1, Timer2; /* 1000Hz decrement timer stopped at zero (driven by mmc_rspi_timerproc()) */
|
---|
| 160 |
|
---|
| 161 | static
|
---|
| 162 | BYTE CardType; /* Card type flags */
|
---|
| 163 |
|
---|
| 164 | static
|
---|
| 165 | BYTE CSD[16], CID[16];
|
---|
| 166 |
|
---|
| 167 | static
|
---|
| 168 | uint64_t CardCapacity;
|
---|
| 169 |
|
---|
| 170 | static
|
---|
| 171 | uint32_t CardBlockSize;
|
---|
| 172 |
|
---|
| 173 | /*-----------------------------------------------------------------------*/
|
---|
| 174 | /* Control SPI module */
|
---|
| 175 | /*-----------------------------------------------------------------------*/
|
---|
| 176 | /* Only these five functions are platform dependent. Any other functions */
|
---|
| 177 | /* are portable to different system. */
|
---|
| 178 |
|
---|
| 179 | /*---------------------------------*/
|
---|
| 180 | /* Enable SPI and MMC/SDC controls */
|
---|
| 181 | /*---------------------------------*/
|
---|
| 182 | static
|
---|
| 183 | void power_on(void)
|
---|
| 184 | {
|
---|
| 185 | /* Initialize CS/INS/WP port */
|
---|
| 186 | CTRL_INIT();
|
---|
| 187 |
|
---|
| 188 | /* Attach RSPI0 module to I/O pads, disable module stop */
|
---|
| 189 | RSPI_ATTACH();
|
---|
| 190 |
|
---|
| 191 | /* Initialize RSPI module */
|
---|
| 192 | sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
|
---|
| 193 | sil_wrb_mem(RSPI0_SPPCR_ADDR, 0); /* Fixed idle value, disable loop-back mode */
|
---|
| 194 | sil_wrb_mem(RSPI0_SPSCR_ADDR, 0); /* Disable sequence control */
|
---|
| 195 | sil_wrb_mem(RSPI0_SPDCR_ADDR, 0x20); /* SPLW=1 */
|
---|
| 196 | sil_wrh_mem(RSPI0_SPCMD0_ADDR, 0x0700); /* LSBF=0, SPB=7, BRDV=0, CPOL=0, CPHA=0 */
|
---|
| 197 | sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_SLOW - 1); /* Bit rate */
|
---|
| 198 | sil_wrb_mem(RSPI0_SPCR_ADDR, 0xC9); /* Start RSPI in master mode */
|
---|
| 199 |
|
---|
| 200 | //ena_int(INTNO_MMC_RSPI_SPRI);
|
---|
| 201 | //ena_int(INTNO_MMC_RSPI_SPTI);
|
---|
| 202 | //ena_int(INTNO_MMC_RSPI_SPII);
|
---|
| 203 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 204 |
|
---|
| 205 | sta_cyc(MMC_RSPI_CYC);
|
---|
| 206 | }
|
---|
| 207 |
|
---|
| 208 |
|
---|
| 209 | /*---------------------*/
|
---|
| 210 | /* Disable SPI */
|
---|
| 211 | /*---------------------*/
|
---|
| 212 | static
|
---|
| 213 | void power_off(void) /* Disable MMC/SDC interface */
|
---|
| 214 | {
|
---|
| 215 | stp_cyc(MMC_RSPI_CYC);
|
---|
| 216 |
|
---|
| 217 | //dis_int(INTNO_MMC_RSPI_SPRI);
|
---|
| 218 | //dis_int(INTNO_MMC_RSPI_SPTI);
|
---|
| 219 | //dis_int(INTNO_MMC_RSPI_SPII);
|
---|
| 220 |
|
---|
| 221 | sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 |
|
---|
| 225 | /*---------------------*/
|
---|
| 226 | /* Send/Receive a byte */
|
---|
| 227 | /*---------------------*/
|
---|
| 228 | static
|
---|
| 229 | BYTE xchg_spi(
|
---|
| 230 | BYTE dat /* Data to send */
|
---|
| 231 | )
|
---|
| 232 | {
|
---|
| 233 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 234 | sil_wrw_mem(RSPI0_SPDR_ADDR, dat); /* Start transmission (lower 8bits) */
|
---|
| 235 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 236 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 237 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 238 | return sil_rew_mem(RSPI0_SPDR_ADDR); /* Returen received byte (lower 8bits) */
|
---|
| 239 | }
|
---|
| 240 |
|
---|
| 241 |
|
---|
| 242 | /*---------------------*/
|
---|
| 243 | /* Send multiple bytes */
|
---|
| 244 | /*---------------------*/
|
---|
| 245 | static
|
---|
| 246 | void xmit_spi_multi(
|
---|
| 247 | const BYTE *buff, /* Pointer to the data */
|
---|
| 248 | UINT btx /* Number of bytes to send (multiple of 4) */
|
---|
| 249 | )
|
---|
| 250 | {
|
---|
| 251 | const DWORD *lp = (const DWORD*)buff;
|
---|
| 252 |
|
---|
| 253 | sil_wrh_mem(RSPI0_SPCMD0_ADDR,
|
---|
| 254 | (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
|
---|
| 255 |
|
---|
| 256 | do {
|
---|
| 257 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 258 | sil_wrw_mem(RSPI0_SPDR_ADDR, LDDW(*lp++)); /* Send four data bytes */
|
---|
| 259 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 260 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 261 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 262 | sil_rew_mem(RSPI0_SPDR_ADDR); /* Discard four received bytes */
|
---|
| 263 | } while (btx -= 4); /* Repeat until all data sent */
|
---|
| 264 |
|
---|
| 265 | sil_wrh_mem(RSPI0_SPCMD0_ADDR,
|
---|
| 266 | (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 |
|
---|
| 270 | /*------------------------*/
|
---|
| 271 | /* Receive multiple bytes */
|
---|
| 272 | /*------------------------*/
|
---|
| 273 | static
|
---|
| 274 | void rcvr_spi_multi(
|
---|
| 275 | BYTE *buff, /* Pointer to data buffer */
|
---|
| 276 | UINT size, /* Buffer size */
|
---|
| 277 | UINT skip,
|
---|
| 278 | UINT btr /* Number of bytes to receive (multiple of 4) */
|
---|
| 279 | )
|
---|
| 280 | {
|
---|
| 281 | DWORD *lp, data;
|
---|
| 282 | UINT pos, start = skip & ~3, end = (skip + size) & ~3, temp, dpos;
|
---|
| 283 |
|
---|
| 284 | sil_wrh_mem(RSPI0_SPCMD0_ADDR,
|
---|
| 285 | (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
|
---|
| 286 |
|
---|
| 287 | for (pos = 0; pos < start; pos += 4) {
|
---|
| 288 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 289 | sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
|
---|
| 290 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 291 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 292 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 293 | sil_rew_mem(RSPI0_SPDR_ADDR); /* skip four received bytes */
|
---|
| 294 | }
|
---|
| 295 |
|
---|
| 296 | if ((temp = skip & 3) != 0) {
|
---|
| 297 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 298 | sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
|
---|
| 299 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 300 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 301 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 302 | data = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
|
---|
| 303 | pos += 4;
|
---|
| 304 | dpos = 0;
|
---|
| 305 | switch (temp) {
|
---|
| 306 | case 1:
|
---|
| 307 | buff[dpos++] = (BYTE)(data >> 8);
|
---|
| 308 | case 2:
|
---|
| 309 | buff[dpos++] = (BYTE)(data >> 16);
|
---|
| 310 | case 3:
|
---|
| 311 | buff[dpos++] = (BYTE)(data >> 24);
|
---|
| 312 | }
|
---|
| 313 | lp = (DWORD*)&buff[dpos];
|
---|
| 314 | }
|
---|
| 315 | else
|
---|
| 316 | lp = (DWORD*)buff;
|
---|
| 317 |
|
---|
| 318 | for (; pos < end; pos += 4) {
|
---|
| 319 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 320 | sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
|
---|
| 321 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 322 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 323 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 324 | *lp++ = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
|
---|
| 325 | } /* Repeat until all data received */
|
---|
| 326 |
|
---|
| 327 | if ((temp = (skip + size) & 3) != 0) {
|
---|
| 328 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 329 | sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
|
---|
| 330 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 331 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 332 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 333 | data = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
|
---|
| 334 | pos += 4;
|
---|
| 335 | buff = (BYTE *)lp;
|
---|
| 336 | switch (temp) {
|
---|
| 337 | case 3:
|
---|
| 338 | buff[2] = (BYTE)(data >> 16);
|
---|
| 339 | case 2:
|
---|
| 340 | buff[1] = (BYTE)(data >> 8);
|
---|
| 341 | case 1:
|
---|
| 342 | buff[0] = (BYTE)data;
|
---|
| 343 | }
|
---|
| 344 | }
|
---|
| 345 |
|
---|
| 346 | for (pos = 0; pos < btr; pos += 4) {
|
---|
| 347 | sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
|
---|
| 348 | sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
|
---|
| 349 | /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
|
---|
| 350 | while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
|
---|
| 351 | sil_wrb_mem(ICU_IR039_ADDR, 0x00);
|
---|
| 352 | sil_rew_mem(RSPI0_SPDR_ADDR); /* skip four received bytes */
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | sil_wrh_mem(RSPI0_SPCMD0_ADDR,
|
---|
| 356 | (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 |
|
---|
| 360 |
|
---|
| 361 |
|
---|
| 362 | /*-----------------------------------------------------------------------*/
|
---|
| 363 | /* Wait for card ready */
|
---|
| 364 | /*-----------------------------------------------------------------------*/
|
---|
| 365 |
|
---|
| 366 | static
|
---|
| 367 | int wait_ready( /* 1:Ready, 0:Timeout */
|
---|
| 368 | UINT wt /* Timeout [ms] */
|
---|
| 369 | )
|
---|
| 370 | {
|
---|
| 371 | Timer2 = (WORD)wt;
|
---|
| 372 |
|
---|
| 373 | do {
|
---|
| 374 | if (xchg_spi(0xFF) == 0xFF) return 1; /* Card goes ready */
|
---|
| 375 | /* This loop takes a time. Insert rot_rdq() here for multitask envilonment. */
|
---|
| 376 | } while (Timer2); /* Wait until card goes ready or timeout */
|
---|
| 377 |
|
---|
| 378 | return 0; /* Timeout occured */
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 |
|
---|
| 382 |
|
---|
| 383 | /*-----------------------------------------------------------------------*/
|
---|
| 384 | /* Deselect card and release SPI */
|
---|
| 385 | /*-----------------------------------------------------------------------*/
|
---|
| 386 |
|
---|
| 387 | static
|
---|
| 388 | void deselect(void)
|
---|
| 389 | {
|
---|
| 390 | CS_HIGH(); /* Set CS# high */
|
---|
| 391 | xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
|
---|
| 392 | }
|
---|
| 393 |
|
---|
| 394 |
|
---|
| 395 |
|
---|
| 396 | /*-----------------------------------------------------------------------*/
|
---|
| 397 | /* Select card and wait for ready */
|
---|
| 398 | /*-----------------------------------------------------------------------*/
|
---|
| 399 |
|
---|
| 400 | static
|
---|
| 401 | int select(void) /* 1:OK, 0:Timeout */
|
---|
| 402 | {
|
---|
| 403 | CS_LOW(); /* Set CS# low */
|
---|
| 404 | xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
|
---|
| 405 |
|
---|
| 406 | if (wait_ready(500)) return 1; /* Wait for card ready */
|
---|
| 407 |
|
---|
| 408 | deselect();
|
---|
| 409 | return 0; /* Failed to select the card due to timeout */
|
---|
| 410 | }
|
---|
| 411 |
|
---|
| 412 |
|
---|
| 413 |
|
---|
| 414 | /*-----------------------------------------------------------------------*/
|
---|
| 415 | /* Receive a data packet from the MMC */
|
---|
| 416 | /*-----------------------------------------------------------------------*/
|
---|
| 417 |
|
---|
| 418 | static
|
---|
| 419 | int rcvr_datablock( /* 1:OK, 0:Error */
|
---|
| 420 | BYTE *buff, /* Data buffer */
|
---|
| 421 | UINT size, /* Buffer size */
|
---|
| 422 | UINT skip,
|
---|
| 423 | UINT btr /* Data block length (byte) */
|
---|
| 424 | )
|
---|
| 425 | {
|
---|
| 426 | BYTE token;
|
---|
| 427 |
|
---|
| 428 |
|
---|
| 429 | Timer1 = 200;
|
---|
| 430 | do { /* Wait for DataStart token in timeout of 200ms */
|
---|
| 431 | token = xchg_spi(0xFF);
|
---|
| 432 | /* This loop will take a time. Insert rot_rdq() here for multitask envilonment. */
|
---|
| 433 | } while ((token == 0xFF) && Timer1);
|
---|
| 434 | if (token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */
|
---|
| 435 |
|
---|
| 436 | rcvr_spi_multi(buff, size, skip, btr); /* Store trailing data to the buffer */
|
---|
| 437 | xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
|
---|
| 438 |
|
---|
| 439 | return 1; /* Function succeeded */
|
---|
| 440 | }
|
---|
| 441 |
|
---|
| 442 |
|
---|
| 443 |
|
---|
| 444 | /*-----------------------------------------------------------------------*/
|
---|
| 445 | /* Send a data packet to the MMC */
|
---|
| 446 | /*-----------------------------------------------------------------------*/
|
---|
| 447 |
|
---|
| 448 | #if _USE_WRITE
|
---|
| 449 | static
|
---|
| 450 | int xmit_datablock( /* 1:OK, 0:Failed */
|
---|
| 451 | const BYTE *buff, /* Ponter to 512 byte data to be sent */
|
---|
| 452 | BYTE token /* Token */
|
---|
| 453 | )
|
---|
| 454 | {
|
---|
| 455 | BYTE resp;
|
---|
| 456 |
|
---|
| 457 |
|
---|
| 458 | if (!wait_ready(500)) return 0; /* Wait for card ready */
|
---|
| 459 |
|
---|
| 460 | xchg_spi(token); /* Send token */
|
---|
| 461 | if (token != 0xFD) { /* Send data if token is other than StopTran */
|
---|
| 462 | xmit_spi_multi(buff, 512); /* Data */
|
---|
| 463 | xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */
|
---|
| 464 |
|
---|
| 465 | resp = xchg_spi(0xFF); /* Receive data resp */
|
---|
| 466 | if ((resp & 0x1F) != 0x05) /* Function fails if the data packet was not accepted */
|
---|
| 467 | return 0;
|
---|
| 468 | }
|
---|
| 469 | return 1;
|
---|
| 470 | }
|
---|
| 471 | #endif /* _USE_WRITE */
|
---|
| 472 |
|
---|
| 473 |
|
---|
| 474 |
|
---|
| 475 | /*-----------------------------------------------------------------------*/
|
---|
| 476 | /* Send a command packet to the MMC */
|
---|
| 477 | /*-----------------------------------------------------------------------*/
|
---|
| 478 |
|
---|
| 479 | static
|
---|
| 480 | BYTE send_cmd( /* Return value: R1 resp (bit7==1:Failed to send) */
|
---|
| 481 | BYTE cmd, /* Command index */
|
---|
| 482 | DWORD arg /* Argument */
|
---|
| 483 | )
|
---|
| 484 | {
|
---|
| 485 | BYTE n, res;
|
---|
| 486 |
|
---|
| 487 |
|
---|
| 488 | if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */
|
---|
| 489 | cmd &= 0x7F;
|
---|
| 490 | res = send_cmd(CMD55, 0);
|
---|
| 491 | if (res > 1) return res;
|
---|
| 492 | }
|
---|
| 493 |
|
---|
| 494 | /* Select the card and wait for ready except to stop multiple block read */
|
---|
| 495 | if (cmd != CMD12) {
|
---|
| 496 | deselect();
|
---|
| 497 | if (!select()) return 0xFF;
|
---|
| 498 | }
|
---|
| 499 |
|
---|
| 500 | /* Send command packet */
|
---|
| 501 | xchg_spi(0x40 | cmd); /* Start + command index */
|
---|
| 502 | xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
|
---|
| 503 | xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
|
---|
| 504 | xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
|
---|
| 505 | xchg_spi((BYTE)arg); /* Argument[7..0] */
|
---|
| 506 | n = 0x01; /* Dummy CRC + Stop */
|
---|
| 507 | if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
|
---|
| 508 | if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
---|
| 509 | xchg_spi(n);
|
---|
| 510 |
|
---|
| 511 | /* Receive command resp */
|
---|
| 512 | if (cmd == CMD12) xchg_spi(0xFF); /* Diacard stuff byte on CMD12 */
|
---|
| 513 | n = 10; /* Wait for response (10 bytes max) */
|
---|
| 514 | do
|
---|
| 515 | res = xchg_spi(0xFF);
|
---|
| 516 | while ((res & 0x80) && --n);
|
---|
| 517 |
|
---|
| 518 | return res; /* Return received response */
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 |
|
---|
| 522 |
|
---|
| 523 | /*--------------------------------------------------------------------------
|
---|
| 524 |
|
---|
| 525 | Public Functions
|
---|
| 526 |
|
---|
| 527 | ---------------------------------------------------------------------------*/
|
---|
| 528 |
|
---|
| 529 |
|
---|
| 530 | /*-----------------------------------------------------------------------*/
|
---|
| 531 | /* Initialize disk drive */
|
---|
| 532 | /*-----------------------------------------------------------------------*/
|
---|
| 533 |
|
---|
| 534 | DSTATUS mmc_rspi_initialize(void)
|
---|
| 535 | {
|
---|
| 536 | BYTE n, cmd, ty, ocr[4];
|
---|
| 537 |
|
---|
| 538 |
|
---|
| 539 | power_on(); /* Initialize RSPI */
|
---|
| 540 | for (n = 10; n; n--) xchg_spi(0xFF);/* Send 80 dummy clocks */
|
---|
| 541 |
|
---|
| 542 | ty = 0;
|
---|
| 543 | if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI/Idle state */
|
---|
| 544 | Timer1 = 1000; /* Initialization timeout = 1 sec */
|
---|
| 545 | if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
|
---|
| 546 | for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */
|
---|
| 547 | if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Is the card supports vcc of 2.7-3.6V? */
|
---|
| 548 | while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for end of initialization with ACMD41(HCS) */
|
---|
| 549 | if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
|
---|
| 550 | for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
|
---|
| 551 | ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Card id SDv2 */
|
---|
| 552 | }
|
---|
| 553 | }
|
---|
| 554 | }
|
---|
| 555 | else { /* Not SDv2 card */
|
---|
| 556 | if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMC? */
|
---|
| 557 | ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */
|
---|
| 558 | }
|
---|
| 559 | else {
|
---|
| 560 | ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
|
---|
| 561 | }
|
---|
| 562 | while (Timer1 && send_cmd(cmd, 0)); /* Wait for end of initialization */
|
---|
| 563 | //if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
|
---|
| 564 | // ty = 0;
|
---|
| 565 | }
|
---|
| 566 | if (ty) {
|
---|
| 567 | if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
|
---|
| 568 | && rcvr_datablock(CSD, 16, 0, 16)){
|
---|
| 569 | /* CSD Ver.1.0 */
|
---|
| 570 | if ((CSD[0] & 0xC0) == 0) {
|
---|
| 571 | CardBlockSize = 1 << (CSD[5] & 0x0F);
|
---|
| 572 | CardCapacity = (((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1;
|
---|
| 573 | CardCapacity *= (((uint64_t)1) << ((((CSD[9] & 0x03) << 1) | (CSD[10] & 0x80) >> 7) + 2));
|
---|
| 574 | CardCapacity *= (uint64_t)CardBlockSize;
|
---|
| 575 | }
|
---|
| 576 | else {
|
---|
| 577 | CardBlockSize = 512;
|
---|
| 578 | CardCapacity = ((uint64_t)((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1)) * 512 * 1024;
|
---|
| 579 | }
|
---|
| 580 | if (send_cmd(CMD10, 0) != 0 /* READ_CID */
|
---|
| 581 | || !rcvr_datablock(CID, 16, 0, 16)) {
|
---|
| 582 | ty = 0;
|
---|
| 583 | }
|
---|
| 584 | }
|
---|
| 585 | else {
|
---|
| 586 | ty = 0;
|
---|
| 587 | }
|
---|
| 588 | }
|
---|
| 589 | }
|
---|
| 590 | CardType = ty; /* Card type */
|
---|
| 591 | deselect();
|
---|
| 592 |
|
---|
| 593 | if (ty) { /* OK */
|
---|
| 594 | FCLK_FAST(); /* Set fast clock */
|
---|
| 595 | Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
|
---|
| 596 | }
|
---|
| 597 | else { /* Failed */
|
---|
| 598 | power_off();
|
---|
| 599 | Stat = STA_NOINIT;
|
---|
| 600 | }
|
---|
| 601 |
|
---|
| 602 | return Stat;
|
---|
| 603 | }
|
---|
| 604 |
|
---|
| 605 |
|
---|
| 606 |
|
---|
| 607 | /*-----------------------------------------------------------------------*/
|
---|
| 608 | /* Get disk status */
|
---|
| 609 | /*-----------------------------------------------------------------------*/
|
---|
| 610 |
|
---|
| 611 | DSTATUS mmc_rspi_get_status(void)
|
---|
| 612 | {
|
---|
| 613 | return Stat; /* Return disk status */
|
---|
| 614 | }
|
---|
| 615 |
|
---|
| 616 |
|
---|
| 617 |
|
---|
| 618 | /*-----------------------------------------------------------------------*/
|
---|
| 619 | /* Read sector(s) */
|
---|
| 620 | /*-----------------------------------------------------------------------*/
|
---|
| 621 |
|
---|
| 622 | DRESULT mmc_rspi_readp(
|
---|
| 623 | BYTE *buff, /* Pointer to the data buffer to store read data */
|
---|
| 624 | DWORD sector, /* Start sector number (LBA) */
|
---|
| 625 | UINT offset, /* Offset in the sector */
|
---|
| 626 | UINT count /* Byte count */
|
---|
| 627 | )
|
---|
| 628 | {
|
---|
| 629 | if (!count) return RES_PARERR; /* Check parameter */
|
---|
| 630 | if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
|
---|
| 631 |
|
---|
| 632 | if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */
|
---|
| 633 |
|
---|
| 634 | if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
|
---|
| 635 | && rcvr_datablock(buff, count, offset, 512))
|
---|
| 636 | count = 0;
|
---|
| 637 | deselect();
|
---|
| 638 |
|
---|
| 639 | return count ? RES_ERROR : RES_OK; /* Return result */
|
---|
| 640 | }
|
---|
| 641 |
|
---|
| 642 |
|
---|
| 643 |
|
---|
| 644 | /*-----------------------------------------------------------------------*/
|
---|
| 645 | /* Write sector(s) */
|
---|
| 646 | /*-----------------------------------------------------------------------*/
|
---|
| 647 |
|
---|
| 648 | #if _USE_WRITE
|
---|
| 649 | DRESULT mmc_rspi_writep(
|
---|
| 650 | const BYTE *buff, /* Ponter to the data to write */
|
---|
| 651 | DWORD sector /* Start sector number (LBA) */
|
---|
| 652 | )
|
---|
| 653 | {
|
---|
| 654 | DRESULT res = RES_ERROR;
|
---|
| 655 | if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
|
---|
| 656 | if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
|
---|
| 657 |
|
---|
| 658 | if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */
|
---|
| 659 |
|
---|
| 660 | if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
|
---|
| 661 | && xmit_datablock(buff, 0xFE))
|
---|
| 662 | res = RES_OK;
|
---|
| 663 | deselect();
|
---|
| 664 |
|
---|
| 665 | return res; /* Return result */
|
---|
| 666 | }
|
---|
| 667 | #endif /* _USE_WRITE */
|
---|
| 668 |
|
---|
| 669 |
|
---|
| 670 |
|
---|
| 671 | /*-----------------------------------------------------------------------*/
|
---|
| 672 | /* Miscellaneous drive controls other than data read/write */
|
---|
| 673 | /*-----------------------------------------------------------------------*/
|
---|
| 674 |
|
---|
| 675 | #if _USE_IOCTL
|
---|
| 676 | DRESULT mmc_rspi_ioctl(
|
---|
| 677 | BYTE ctrl, /* Control command code */
|
---|
| 678 | void *buff /* Pointer to the conrtol data */
|
---|
| 679 | )
|
---|
| 680 | {
|
---|
| 681 | DRESULT res;
|
---|
| 682 | BYTE n, csd[16], *ptr = buff;
|
---|
| 683 | DWORD *dp, st, ed;
|
---|
| 684 |
|
---|
| 685 |
|
---|
| 686 | if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
|
---|
| 687 |
|
---|
| 688 | res = RES_ERROR;
|
---|
| 689 |
|
---|
| 690 | switch (ctrl) {
|
---|
| 691 | case CTRL_SYNC: /* Wait for end of internal write process of the drive */
|
---|
| 692 | if (select()) res = RES_OK;
|
---|
| 693 | break;
|
---|
| 694 |
|
---|
| 695 | case GET_SECTOR_SIZE:
|
---|
| 696 | *(WORD*)buff = 512;
|
---|
| 697 | res = RES_OK;
|
---|
| 698 | break;
|
---|
| 699 |
|
---|
| 700 | case GET_SECTOR_COUNT:
|
---|
| 701 | *(DWORD*)buff = CardCapacity / 512;
|
---|
| 702 | res = RES_OK;
|
---|
| 703 | break;
|
---|
| 704 |
|
---|
| 705 | case GET_BLOCK_SIZE:
|
---|
| 706 | *(DWORD*)buff = CardBlockSize;
|
---|
| 707 | res = RES_OK;
|
---|
| 708 | break;
|
---|
| 709 |
|
---|
| 710 | case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM == 1) */
|
---|
| 711 | if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */
|
---|
| 712 | if (mmc_rspi_ioctl(MMC_GET_CSD, csd)) break; /* Get CSD */
|
---|
| 713 | if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
|
---|
| 714 | dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */
|
---|
| 715 | if (!(CardType & CT_BLOCK)) {
|
---|
| 716 | st *= 512; ed *= 512;
|
---|
| 717 | }
|
---|
| 718 | if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) /* Erase sector block */
|
---|
| 719 | res = RES_OK;
|
---|
| 720 | break;
|
---|
| 721 |
|
---|
| 722 | /* Following command are not used by FatFs module */
|
---|
| 723 |
|
---|
| 724 | case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */
|
---|
| 725 | *ptr = CardType;
|
---|
| 726 | res = RES_OK;
|
---|
| 727 | break;
|
---|
| 728 |
|
---|
| 729 | case MMC_GET_CSD: /* Read CSD (16 bytes) */
|
---|
| 730 | memcpy(ptr, CSD, sizeof(CSD));
|
---|
| 731 | res = RES_OK;
|
---|
| 732 | break;
|
---|
| 733 |
|
---|
| 734 | case MMC_GET_CID: /* Read CID (16 bytes) */
|
---|
| 735 | memcpy(ptr, CID, sizeof(CID));
|
---|
| 736 | res = RES_OK;
|
---|
| 737 | break;
|
---|
| 738 |
|
---|
| 739 | case MMC_GET_OCR: /* Read OCR (4 bytes) */
|
---|
| 740 | if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
|
---|
| 741 | for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
|
---|
| 742 | res = RES_OK;
|
---|
| 743 | }
|
---|
| 744 | break;
|
---|
| 745 |
|
---|
| 746 | case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */
|
---|
| 747 | if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
|
---|
| 748 | xchg_spi(0xFF);
|
---|
| 749 | if (rcvr_datablock(ptr, 64, 0, 64))
|
---|
| 750 | res = RES_OK;
|
---|
| 751 | }
|
---|
| 752 | break;
|
---|
| 753 |
|
---|
| 754 | default:
|
---|
| 755 | res = RES_PARERR;
|
---|
| 756 | }
|
---|
| 757 |
|
---|
| 758 | deselect();
|
---|
| 759 |
|
---|
| 760 | return res;
|
---|
| 761 | }
|
---|
| 762 | #endif /* _USE_IOCTL */
|
---|
| 763 |
|
---|
| 764 |
|
---|
| 765 | /*-----------------------------------------------------------------------*/
|
---|
| 766 | /* Device timer function */
|
---|
| 767 | /*-----------------------------------------------------------------------*/
|
---|
| 768 | /* This function must be called from system timer process
|
---|
| 769 | / in period of 1 ms to generate card control timing.
|
---|
| 770 | */
|
---|
| 771 |
|
---|
| 772 | void mmc_rspi_timerproc(void)
|
---|
| 773 | {
|
---|
| 774 | WORD n;
|
---|
| 775 | BYTE s;
|
---|
| 776 |
|
---|
| 777 |
|
---|
| 778 | n = Timer1; /* 1kHz decrement timer stopped at 0 */
|
---|
| 779 | if (n) Timer1 = --n;
|
---|
| 780 | n = Timer2;
|
---|
| 781 | if (n) Timer2 = --n;
|
---|
| 782 |
|
---|
| 783 | s = Stat;
|
---|
| 784 | if (WP()) /* Write protected */
|
---|
| 785 | s |= STA_PROTECT;
|
---|
| 786 | else /* Write enabled */
|
---|
| 787 | s &= ~STA_PROTECT;
|
---|
| 788 | if (INS()) /* Card is in socket */
|
---|
| 789 | s &= ~STA_NODISK;
|
---|
| 790 | else /* Socket empty */
|
---|
| 791 | s |= (STA_NODISK | STA_NOINIT);
|
---|
| 792 | Stat = s;
|
---|
| 793 | }
|
---|
| 794 |
|
---|
| 795 | void mmc_rspi_spri_handler(void)
|
---|
| 796 | {
|
---|
| 797 | i_begin_int(INTNO_MMC_RSPI_SPRI);
|
---|
| 798 |
|
---|
| 799 | i_end_int(INTNO_MMC_RSPI_SPRI);
|
---|
| 800 | }
|
---|
| 801 |
|
---|
| 802 | void mmc_rspi_spti_handler(void)
|
---|
| 803 | {
|
---|
| 804 | i_begin_int(INTNO_MMC_RSPI_SPTI);
|
---|
| 805 |
|
---|
| 806 | i_end_int(INTNO_MMC_RSPI_SPTI);
|
---|
| 807 | }
|
---|
| 808 |
|
---|
| 809 | void mmc_rspi_spii_handler(void)
|
---|
| 810 | {
|
---|
| 811 | i_begin_int(INTNO_MMC_RSPI_SPII);
|
---|
| 812 |
|
---|
| 813 | i_end_int(INTNO_MMC_RSPI_SPII);
|
---|
| 814 | }
|
---|
| 815 |
|
---|
| 816 | void mmc_rspi_cychdr(intptr_t exinf)
|
---|
| 817 | {
|
---|
| 818 | mmc_rspi_timerproc();
|
---|
| 819 | }
|
---|