|
7 | 7 |
|
8 | 8 | #if PBDRV_CONFIG_MMCSD_EV3 |
9 | 9 |
|
| 10 | +#include <pbdrv/gpio.h> |
| 11 | +#include <pbio/os.h> |
| 12 | + |
| 13 | +#include <tiam1808/hw/soc_AM1808.h> |
| 14 | +#include <tiam1808/hw/hw_mmcsd.h> |
| 15 | +#include <tiam1808/hw/hw_syscfg0_AM1808.h> |
| 16 | +#include <tiam1808/hw/hw_types.h> |
| 17 | + |
| 18 | +#include "../drv/gpio/gpio_ev3.h" |
| 19 | + |
10 | 20 | #include "../uart/uart_debug_first_port.h" |
11 | 21 |
|
| 22 | +// Init clock speed |
| 23 | +#define MMCSD_CLK_DIV_INIT ((SOC_SYSCLK_2_FREQ / 2 + 399999) / 400000 - 1) |
| 24 | +// Standard SD clock speed |
| 25 | +#define MMCSD_CLK_DIV_25M ((SOC_SYSCLK_2_FREQ / 2 + 24999999) / 25000000 - 1) |
| 26 | +// Not achievable, only 37.5 MHz can be reached |
| 27 | +#define MMCSD_CLK_DIV_50M ((SOC_SYSCLK_2_FREQ / 2 + 49999999) / 50000000 - 1) |
| 28 | + |
| 29 | +static const pbdrv_gpio_t pin_mmcsd_clk = PBDRV_GPIO_EV3_PIN(10, 3, 0, 4, 7); |
| 30 | +static const pbdrv_gpio_t pin_mmcsd_cmd = PBDRV_GPIO_EV3_PIN(10, 7, 4, 4, 6); |
| 31 | +static const pbdrv_gpio_t pin_mmcsd_dat0 = PBDRV_GPIO_EV3_PIN(10, 11, 8, 4, 5); |
| 32 | +static const pbdrv_gpio_t pin_mmcsd_dat1 = PBDRV_GPIO_EV3_PIN(10, 15, 12, 4, 4); |
| 33 | +static const pbdrv_gpio_t pin_mmcsd_dat2 = PBDRV_GPIO_EV3_PIN(10, 19, 16, 4, 3); |
| 34 | +static const pbdrv_gpio_t pin_mmcsd_dat3 = PBDRV_GPIO_EV3_PIN(10, 23, 20, 4, 2); |
| 35 | +// static const pbdrv_gpio_t pin_mmcsd_card_det = PBDRV_GPIO_EV3_PIN(11, 7, 4, 5, 14); |
| 36 | + |
| 37 | +static pbio_os_process_t ev3_mmcsd_process; |
| 38 | + |
| 39 | +pbio_error_t ev3_mmcsd_process_thread(pbio_os_state_t *state, void *context) { |
| 40 | + static pbio_os_timer_t timer; |
| 41 | + static uint32_t rca; |
| 42 | + |
| 43 | + PBIO_OS_ASYNC_BEGIN(state); |
| 44 | + |
| 45 | + // pbdrv_uart_debug_printf("mmcsd init defer\r\n"); |
| 46 | + |
| 47 | + // turn on clocks for 1 ms |
| 48 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCLK) = (MMCSD_CLK_DIV_INIT << MMCSD_MMCCLK_CLKRT_SHIFT) | MMCSD_MMCCLK_CLKEN; |
| 49 | + PBIO_OS_AWAIT_MS(state, &timer, 1); |
| 50 | + |
| 51 | + // cmd0 |
| 52 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0; |
| 53 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (0 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_NORSP << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 54 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 55 | + // pbdrv_uart_debug_printf("cmd0\r\n"); |
| 56 | + |
| 57 | + uint32_t resp[4]; |
| 58 | + uint32_t data[512 / 4]; |
| 59 | + |
| 60 | + // cmd8 |
| 61 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0x1aa; |
| 62 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (8 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R1 << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 63 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 64 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 65 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 66 | + pbdrv_uart_debug_printf("cmd8 %08x %08x\r\n", resp[0], resp[1]); |
| 67 | + |
| 68 | + while (1) { |
| 69 | + // acmd41 |
| 70 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0; |
| 71 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (55 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R1 << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 72 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 73 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 74 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 75 | + // pbdrv_uart_debug_printf("cmd55 %08x %08x\r\n", resp[0], resp[1]); |
| 76 | + |
| 77 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0x50300000; |
| 78 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (41 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R3 << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 79 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 80 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 81 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 82 | + // pbdrv_uart_debug_printf("acmd41 %08x %08x\r\n", resp[0], resp[1]); |
| 83 | + |
| 84 | + if (resp[1] & 0x80000000) { |
| 85 | + pbdrv_uart_debug_printf("acmd41 %08x %08x\r\n", resp[0], resp[1]); |
| 86 | + break; |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + // cmd2 |
| 91 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0; |
| 92 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (2 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R2 << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 93 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 94 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP01); |
| 95 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP23); |
| 96 | + resp[2] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 97 | + resp[3] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 98 | + pbdrv_uart_debug_printf("cmd2 %08x %08x %08x %08x\r\n", resp[0], resp[1], resp[2], resp[3]); |
| 99 | + |
| 100 | + // cmd3 |
| 101 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0; |
| 102 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (3 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R6 << MMCSD_MMCCMD_RSPFMT_SHIFT); |
| 103 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 104 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 105 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 106 | + pbdrv_uart_debug_printf("cmd3 %08x %08x\r\n", resp[0], resp[1]); |
| 107 | + |
| 108 | + rca = resp[1] & 0xffff0000; |
| 109 | + |
| 110 | + // Can use faster clocks now |
| 111 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCLK) = (MMCSD_CLK_DIV_25M << MMCSD_MMCCLK_CLKRT_SHIFT) | MMCSD_MMCCLK_CLKEN; |
| 112 | + |
| 113 | + // cmd9 |
| 114 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = rca; |
| 115 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (9 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R2 << MMCSD_MMCCMD_RSPFMT_SHIFT) | MMCSD_MMCCMD_PPLEN; |
| 116 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 117 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP01); |
| 118 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP23); |
| 119 | + resp[2] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 120 | + resp[3] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 121 | + pbdrv_uart_debug_printf("cmd9 %08x %08x %08x %08x\r\n", resp[0], resp[1], resp[2], resp[3]); |
| 122 | + |
| 123 | + // cmd7 |
| 124 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = rca; |
| 125 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (7 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R1 << MMCSD_MMCCMD_RSPFMT_SHIFT) | MMCSD_MMCCMD_PPLEN | MMCSD_MMCCMD_BSYEXP; |
| 126 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_BSYDNE); |
| 127 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 128 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 129 | + pbdrv_uart_debug_printf("cmd7 %08x %08x\r\n", resp[0], resp[1]); |
| 130 | + |
| 131 | + // acmd51 |
| 132 | + |
| 133 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCFIFOCTL) = MMCSD_MMCFIFOCTL_FIFORST; |
| 134 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCFIFOCTL) = MMCSD_MMCFIFOCTL_ACCWD_4BYTES | (0 << MMCSD_MMCFIFOCTL_FIFODIR_SHIFT); |
| 135 | + |
| 136 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = rca; |
| 137 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (55 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R1 << MMCSD_MMCCMD_RSPFMT_SHIFT) | MMCSD_MMCCMD_PPLEN; |
| 138 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_RSPDNE); |
| 139 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 140 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 141 | + // pbdrv_uart_debug_printf("cmd55 %08x %08x\r\n", resp[0], resp[1]); |
| 142 | + |
| 143 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCBLEN) = 8; |
| 144 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCNBLK) = 1; |
| 145 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCARGHL) = 0; |
| 146 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCMD) = (51 << MMCSD_MMCCMD_CMD_SHIFT) | (MMCSD_MMCCMD_RSPFMT_R1 << MMCSD_MMCCMD_RSPFMT_SHIFT) | MMCSD_MMCCMD_PPLEN | MMCSD_MMCCMD_WDATX; |
| 147 | + PBIO_OS_AWAIT_WHILE(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST1) & MMCSD_MMCST1_FIFOEMP); |
| 148 | + data[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCDRR); |
| 149 | + PBIO_OS_AWAIT_WHILE(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST1) & MMCSD_MMCST1_FIFOEMP); |
| 150 | + data[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCDRR); |
| 151 | + PBIO_OS_AWAIT_UNTIL(state, HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCST0) & MMCSD_MMCST0_DATDNE); |
| 152 | + resp[0] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP45); |
| 153 | + resp[1] = HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCRSP67); |
| 154 | + // pbdrv_uart_debug_printf("acmd51 %08x %08x\r\n", resp[0], resp[1]); |
| 155 | + pbdrv_uart_debug_printf("acmd51 %08x %08x\r\n", data[0], data[1]); |
| 156 | + |
| 157 | + pbdrv_uart_debug_printf("mmcsd init defer end\r\n"); |
| 158 | + |
| 159 | + PBIO_OS_ASYNC_END(PBIO_SUCCESS); |
| 160 | +} |
| 161 | + |
12 | 162 | void pbdrv_mmcsd_init(void) { |
13 | | - pbdrv_uart_debug_printf("mmcsd init\r\n"); |
| 163 | + // pbdrv_uart_debug_printf("mmcsd init\r\n"); |
| 164 | + |
| 165 | + // reset |
| 166 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCTL) = MMCSD_MMCCTL_CMDRST | MMCSD_MMCCTL_DATRST; |
| 167 | + HWREG(SOC_MMCSD_0_REGS + MMCSD_MMCCTL) = 0; |
| 168 | + |
| 169 | + // gpio |
| 170 | + pbdrv_gpio_alt(&pin_mmcsd_clk, SYSCFG_PINMUX10_PINMUX10_3_0_MMCSD0_CLK); |
| 171 | + pbdrv_gpio_alt(&pin_mmcsd_cmd, SYSCFG_PINMUX10_PINMUX10_7_4_MMCSD0_CMD); |
| 172 | + pbdrv_gpio_alt(&pin_mmcsd_dat0, SYSCFG_PINMUX10_PINMUX10_11_8_MMCSD0_DAT0); |
| 173 | + pbdrv_gpio_alt(&pin_mmcsd_dat1, SYSCFG_PINMUX10_PINMUX10_15_12_MMCSD0_DAT1); |
| 174 | + pbdrv_gpio_alt(&pin_mmcsd_dat2, SYSCFG_PINMUX10_PINMUX10_19_16_MMCSD0_DAT2); |
| 175 | + pbdrv_gpio_alt(&pin_mmcsd_dat3, SYSCFG_PINMUX10_PINMUX10_23_20_MMCSD0_DAT3); |
| 176 | + |
| 177 | + // defer |
| 178 | + pbio_os_process_start(&ev3_mmcsd_process, ev3_mmcsd_process_thread, NULL); |
14 | 179 | } |
15 | 180 |
|
16 | 181 | #endif // PBDRV_CONFIG_MMCSD_EV3 |
0 commit comments