paul@264 | 1 | /* |
paul@264 | 2 | * MSC (MMC/SD controller) peripheral support. |
paul@264 | 3 | * |
paul@264 | 4 | * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> |
paul@264 | 5 | * |
paul@264 | 6 | * This program is free software; you can redistribute it and/or |
paul@264 | 7 | * modify it under the terms of the GNU General Public License as |
paul@264 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@264 | 9 | * the License, or (at your option) any later version. |
paul@264 | 10 | * |
paul@264 | 11 | * This program is distributed in the hope that it will be useful, |
paul@264 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@264 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@264 | 14 | * GNU General Public License for more details. |
paul@264 | 15 | * |
paul@264 | 16 | * You should have received a copy of the GNU General Public License |
paul@264 | 17 | * along with this program; if not, write to the Free Software |
paul@264 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@264 | 19 | * Boston, MA 02110-1301, USA |
paul@264 | 20 | */ |
paul@264 | 21 | |
paul@264 | 22 | #pragma once |
paul@264 | 23 | |
paul@264 | 24 | #include <l4/devices/msc-common.h> |
paul@264 | 25 | |
paul@264 | 26 | |
paul@264 | 27 | |
paul@264 | 28 | // Register locations for each channel. |
paul@264 | 29 | |
paul@264 | 30 | enum Regs : unsigned |
paul@264 | 31 | { |
paul@264 | 32 | Msc_control = 0x000, // MSC_CTRL |
paul@264 | 33 | Msc_status = 0x004, // MSC_STAT |
paul@264 | 34 | Msc_clock_rate = 0x008, // MSC_CLKRT |
paul@264 | 35 | Msc_command_data_control = 0x00c, // MSC_CMDAT |
paul@264 | 36 | Msc_response_timeout = 0x010, // MSC_RESTO |
paul@264 | 37 | Msc_read_timeout = 0x014, // MSC_RDTO |
paul@264 | 38 | Msc_block_length = 0x018, // MSC_BLKLEN |
paul@264 | 39 | Msc_block_count = 0x01c, // MSC_NOB |
paul@264 | 40 | Msc_block_success_count = 0x020, // MSC_SNOB |
paul@264 | 41 | Msc_interrupt_mask = 0x024, // MSC_IMASK |
paul@264 | 42 | Msc_interrupt_flag = 0x028, // MSC_IFLG/MSC_IREG |
paul@264 | 43 | Msc_command_index = 0x02c, // MSC_CMD |
paul@264 | 44 | Msc_command_argument = 0x030, // MSC_ARG |
paul@264 | 45 | Msc_response_fifo = 0x034, // MSC_RES |
paul@264 | 46 | Msc_recv_data_fifo = 0x038, // MSC_RXFIFO |
paul@264 | 47 | Msc_trans_data_fifo = 0x03c, // MSC_TXFIFO |
paul@264 | 48 | |
paul@264 | 49 | // JZ4780/X1600 only. |
paul@264 | 50 | |
paul@264 | 51 | Msc_low_power_mode = 0x040, // MSC_LPM |
paul@264 | 52 | Msc_dma_control = 0x044, // MSC_DMAC |
paul@264 | 53 | Msc_dma_descriptor_address = 0x048, // MSC_DMANDA |
paul@264 | 54 | Msc_dma_data_address = 0x04c, // MSC_DMADA |
paul@264 | 55 | Msc_dma_data_length = 0x050, // MSC_DMALEN |
paul@264 | 56 | Msc_dma_command = 0x054, // MSC_DMACMD |
paul@264 | 57 | Msc_control2 = 0x058, // MSC_CTRL2 |
paul@264 | 58 | Msc_rtfifo_data_counter = 0x05c, // MSC_RTCNT |
paul@264 | 59 | |
paul@264 | 60 | // Channel block size/offset. |
paul@264 | 61 | |
paul@264 | 62 | Msc_channel_offset = 0x10000, |
paul@264 | 63 | }; |
paul@264 | 64 | |
paul@264 | 65 | // Field definitions. |
paul@264 | 66 | |
paul@264 | 67 | enum Control_bits : unsigned |
paul@264 | 68 | { |
paul@264 | 69 | // JZ4780/X1600 only. |
paul@264 | 70 | |
paul@264 | 71 | Control_send_ccsd = 0x8000, // SEND_CCSD |
paul@264 | 72 | Control_send_ccsd_automatically = 0x4000, // SEND_CCSD |
paul@264 | 73 | |
paul@264 | 74 | // Common. |
paul@264 | 75 | |
paul@264 | 76 | Control_exit_multiple = 0x0080, // EXIT_MULTIPLE |
paul@264 | 77 | Control_exit_transfer = 0x0040, // EXIT_TRANSFER |
paul@264 | 78 | Control_start_read_wait = 0x0020, // START_READ_WAIT |
paul@264 | 79 | Control_stop_read_wait = 0x0010, // STOP_READ_WAIT |
paul@264 | 80 | Control_reset = 0x0008, // RESET |
paul@264 | 81 | Control_start_operation = 0x0004, // START_OP |
paul@264 | 82 | |
paul@264 | 83 | Control_clock_control_field_mask = 0x3, // CLOCK_CTRL |
paul@264 | 84 | Control_clock_control_start = 2, |
paul@264 | 85 | Control_clock_control_stop = 1, |
paul@264 | 86 | Control_clock_control_field_shift = 0, |
paul@264 | 87 | }; |
paul@264 | 88 | |
paul@264 | 89 | enum Control2_bits : unsigned |
paul@264 | 90 | { |
paul@264 | 91 | // JZ4780/X1600 only. |
paul@264 | 92 | |
paul@264 | 93 | Control2_pin_level_polarity_field_mask = 0x1f, // PIP |
paul@264 | 94 | Control2_pin_level_polarity_field_shift = 24, |
paul@264 | 95 | |
paul@264 | 96 | // JZ4780 only. |
paul@264 | 97 | |
paul@264 | 98 | Control2_reset_enable = 0x00800000, // RST_EN |
paul@264 | 99 | |
paul@264 | 100 | // JZ4780/X1600 only. |
paul@264 | 101 | |
paul@264 | 102 | Control2_stop_read_operation_mode = 0x00000010, // STPRM |
paul@264 | 103 | |
paul@264 | 104 | // JZ4780 only. |
paul@264 | 105 | |
paul@264 | 106 | Control2_signal_voltage_change = 0x00000008, // SVC |
paul@264 | 107 | |
paul@264 | 108 | // JZ4780/X1600 only. |
paul@264 | 109 | |
paul@264 | 110 | Control2_speed_mode_field_mask = 0x7, // SMS |
paul@264 | 111 | Control2_speed_mode_default = 0, // = 0 |
paul@264 | 112 | Control2_speed_mode_high = 1, // = 1 |
paul@264 | 113 | Control2_speed_mode_sdr12 = 2, // = 2 |
paul@264 | 114 | Control2_speed_mode_sdr25 = 3, // = 3 |
paul@264 | 115 | Control2_speed_mode_sdr50 = 4, // = 4 |
paul@264 | 116 | Control2_speed_mode_field_shift = 0, |
paul@264 | 117 | }; |
paul@264 | 118 | |
paul@264 | 119 | enum Status_bits : unsigned |
paul@264 | 120 | { |
paul@264 | 121 | // JZ4780/X1600 only. |
paul@264 | 122 | |
paul@264 | 123 | Status_auto_cmd12_done = 0x80000000, // AUTO_CMD12_DONE |
paul@264 | 124 | |
paul@264 | 125 | // JZ4780 only. |
paul@264 | 126 | |
paul@264 | 127 | Status_auto_cmd23_done = 0x40000000, // AUTO_CMD23_DONE |
paul@264 | 128 | Status_signal_voltage_change = 0x20000000, // SVS |
paul@264 | 129 | |
paul@264 | 130 | // JZ4780/X1600 only. |
paul@264 | 131 | |
paul@264 | 132 | Status_pin_level_field_mask = 0x1f, // PIN_LEVEL |
paul@264 | 133 | Status_pin_level_field_shift = 24, |
paul@264 | 134 | |
paul@264 | 135 | Status_boot_crc_error = 0x00100000, // BCE |
paul@264 | 136 | Status_boot_data_end = 0x00080000, // BDE |
paul@264 | 137 | Status_boot_ack_error = 0x00040000, // BAE |
paul@264 | 138 | Status_boot_ack_received = 0x00020000, // BAR |
paul@264 | 139 | Status_dma_end = 0x00010000, // DMAEND |
paul@264 | 140 | |
paul@264 | 141 | // Common. |
paul@264 | 142 | |
paul@264 | 143 | Status_resetting = 0x8000, // IS_RESETTING |
paul@264 | 144 | Status_sdio_interrupt_active = 0x4000, // SDIO_INT_ACTIVE |
paul@264 | 145 | Status_programming_done = 0x2000, // PRG_DONE |
paul@264 | 146 | Status_data_transfer_done = 0x1000, // DATA_TRAN_DONE |
paul@264 | 147 | Status_end_command_response = 0x0800, // END_CMD_RES |
paul@264 | 148 | Status_data_fifo_almost_full = 0x0400, // DATA_FIFO_AFULL |
paul@264 | 149 | Status_read_wait = 0x0200, // IS_READWAIT |
paul@264 | 150 | Status_clock_enabled = 0x0100, // CLK_EN |
paul@264 | 151 | Status_data_fifo_full = 0x0080, // DATA_FIFO_FULL |
paul@264 | 152 | Status_data_fifo_empty = 0x0040, // DATA_FIFO_EMPTY |
paul@264 | 153 | Status_response_crc_error = 0x0020, // CRC_RES_ERR |
paul@264 | 154 | Status_read_crc_error = 0x0010, // CRC_READ_ERROR |
paul@264 | 155 | Status_write_crc_error_no_status = 0x0008, // CRC_WRITE_ERROR (2) |
paul@264 | 156 | Status_write_crc_error_data = 0x0004, // CRC_WRITE_ERROR (1) |
paul@264 | 157 | Status_timeout_response = 0x0002, // TIME_OUT_RES |
paul@264 | 158 | Status_timeout_read = 0x0001, // TIME_OUT_READ |
paul@264 | 159 | }; |
paul@264 | 160 | |
paul@264 | 161 | enum Clock_rate_bits : unsigned |
paul@264 | 162 | { |
paul@264 | 163 | Clock_rate_field_mask = 0x7, // CLK_RATE |
paul@264 | 164 | Clock_rate_field_shift = 0, |
paul@264 | 165 | }; |
paul@264 | 166 | |
paul@264 | 167 | enum Command_data_control_bits : unsigned |
paul@264 | 168 | { |
paul@264 | 169 | // JZ4780/X1600 only. |
paul@264 | 170 | |
paul@264 | 171 | Cdc_ccs_expected = 0x80000000, // CCS_EXPECTED |
paul@264 | 172 | Cdc_read_ce_ata = 0x40000000, // READ_CEATA |
paul@264 | 173 | Cdc_disable_boot = 0x08000000, // DIS_BOOT |
paul@264 | 174 | Cdc_expect_boot_ack = 0x02000000, // EXP_BOOT_ACK |
paul@264 | 175 | Cdc_alternative_boot_mode = 0x01000000, // BOOT_MODE |
paul@264 | 176 | |
paul@264 | 177 | // JZ4780 only. |
paul@264 | 178 | |
paul@264 | 179 | Cdc_auto_cmd23 = 0x00040000, // AUTO_CMD23 |
paul@264 | 180 | |
paul@264 | 181 | // JZ4780/X1600 only. |
paul@264 | 182 | |
paul@264 | 183 | Cdc_sdio_interrupt_2cycle = 0x00020000, // SDIO_PRDT |
paul@264 | 184 | Cdc_auto_cmd12 = 0x00010000, // AUTO_CMD12 |
paul@264 | 185 | |
paul@264 | 186 | Cdc_recv_fifo_level_field_mask = 0x3, // RTRG |
paul@264 | 187 | Cdc_fifo_level_16 = 0, |
paul@264 | 188 | Cdc_fifo_level_32 = 1, |
paul@264 | 189 | Cdc_fifo_level_64 = 2, |
paul@264 | 190 | Cdc_fifo_level_96 = 3, |
paul@264 | 191 | Cdc_recv_fifo_level_field_shift = 14, |
paul@264 | 192 | |
paul@264 | 193 | Cdc_trans_fifo_level_field_mask = 0x3, // TTRG |
paul@264 | 194 | Cdc_trans_fifo_level_field_shift = 12, |
paul@264 | 195 | |
paul@264 | 196 | // Common. |
paul@264 | 197 | |
paul@264 | 198 | Cdc_io_abort = 0x0800, // IO_ABORT |
paul@264 | 199 | |
paul@264 | 200 | Cdc_bus_width_field_mask = 0x3, // BUS_WIDTH |
paul@266 | 201 | Cdc_bus_width_1bit = 0, |
paul@266 | 202 | Cdc_bus_width_4bit = 2, |
paul@264 | 203 | Cdc_bus_width_field_shift = 9, |
paul@264 | 204 | |
paul@264 | 205 | // JZ4740 only. |
paul@264 | 206 | |
paul@266 | 207 | Cdc_dma_field_mask = 0x1, // DMA_EN |
paul@266 | 208 | Cdc_dma_disable = 0, |
paul@266 | 209 | Cdc_dma_enable = 1, |
paul@266 | 210 | Cdc_dma_field_shift = 8, |
paul@264 | 211 | |
paul@264 | 212 | // Common. |
paul@264 | 213 | |
paul@264 | 214 | Cdc_init_sequence = 0x0080, // INIT |
paul@264 | 215 | |
paul@264 | 216 | Cdc_expect_busy = 0x0040, // BUSY |
paul@264 | 217 | Cdc_do_not_expect_busy = 0x0000, |
paul@264 | 218 | |
paul@264 | 219 | Cdc_stream_block = 0x0020, // STREAM_BLOCK |
paul@264 | 220 | Cdc_not_stream_block = 0x0000, |
paul@264 | 221 | |
paul@264 | 222 | Cdc_write_operation = 0x0010, // WRITE_READ |
paul@264 | 223 | Cdc_read_operation = 0x0000, |
paul@264 | 224 | |
paul@264 | 225 | Cdc_data_with_command = 0x0008, // DATA_EN |
paul@264 | 226 | Cdc_no_data_with_command = 0x0000, |
paul@264 | 227 | |
paul@264 | 228 | Cdc_response_format_field_mask = 0x7, // RESPONSE_FORMAT |
paul@264 | 229 | Cdc_response_format_field_shift = 0, |
paul@264 | 230 | }; |
paul@264 | 231 | |
paul@264 | 232 | enum Response_timeout_bits : unsigned |
paul@264 | 233 | { |
paul@264 | 234 | // NOTE: 16-bit value in the JZ4780. |
paul@264 | 235 | // NOTE: 32-bit value in the X1600. |
paul@264 | 236 | |
paul@264 | 237 | Response_timeout_mask = 0x000000ff, // RES_TO |
paul@264 | 238 | }; |
paul@264 | 239 | |
paul@264 | 240 | enum Read_timeout_bits : unsigned |
paul@264 | 241 | { |
paul@264 | 242 | // NOTE: 16-bit value prior to the JZ4780/X1600. |
paul@264 | 243 | |
paul@264 | 244 | Read_timeout_mask = 0xffffffff, // READ_TO |
paul@264 | 245 | }; |
paul@264 | 246 | |
paul@264 | 247 | enum Block_length_bits : unsigned |
paul@264 | 248 | { |
paul@264 | 249 | // NOTE: 16-bit value in the JZ4780/X1600. |
paul@264 | 250 | |
paul@264 | 251 | Block_length_mask = 0x00000fff, // BLK_LEN |
paul@264 | 252 | }; |
paul@264 | 253 | |
paul@264 | 254 | enum Block_count_bits : unsigned |
paul@264 | 255 | { |
paul@264 | 256 | Block_count_mask = 0x0000ffff, // NOB/SNOB |
paul@264 | 257 | }; |
paul@264 | 258 | |
paul@264 | 259 | // Interrupt mask/flag bits. |
paul@264 | 260 | |
paul@264 | 261 | enum Interrupt_bits : unsigned |
paul@264 | 262 | { |
paul@264 | 263 | // X1600 only. |
paul@264 | 264 | |
paul@264 | 265 | Int_dma_data_done = 0x80000000, // DMA_DATA_DONE |
paul@264 | 266 | |
paul@264 | 267 | // JZ4780 only. |
paul@264 | 268 | |
paul@264 | 269 | Int_auto_cmd23_done = 0x40000000, // AUTO_CMD23_DONE |
paul@264 | 270 | Int_signal_voltage_change = 0x20000000, // SVS |
paul@264 | 271 | |
paul@264 | 272 | // JZ4780/X1600 only. |
paul@264 | 273 | |
paul@264 | 274 | Int_pin_level_field_mask = 0x1f, // PIN_LEVEL |
paul@264 | 275 | Int_pin_level_field_shift = 24, |
paul@264 | 276 | |
paul@264 | 277 | // X1600 only. |
paul@264 | 278 | |
paul@264 | 279 | Int_write_request_all_done = 0x00800000, // WR_ALL_DONE |
paul@264 | 280 | |
paul@264 | 281 | // JZ4780/X1600 only. |
paul@264 | 282 | |
paul@264 | 283 | Int_boot_crc_error = 0x00100000, // BCE |
paul@264 | 284 | Int_boot_data_end = 0x00080000, // BDE |
paul@264 | 285 | Int_boot_ack_error = 0x00040000, // BAE |
paul@264 | 286 | Int_boot_ack_received = 0x00020000, // BAR |
paul@264 | 287 | Int_dma_end = 0x00010000, // DMAEND |
paul@264 | 288 | Int_auto_cmd12_done = 0x00008000, // AUTO_CMD12_DONE |
paul@264 | 289 | Int_data_fifo_full = 0x00004000, // DATA_FIFO_FULL |
paul@264 | 290 | Int_data_fifo_empty = 0x00002000, // DATA_FIFO_EMP |
paul@264 | 291 | Int_crc_response_error = 0x00001000, // CRC_RES_ERR |
paul@264 | 292 | Int_crc_read_error = 0x00000800, // CRC_READ_ERR |
paul@264 | 293 | Int_crc_write_error = 0x00000400, // CRC_WRITE_ERR |
paul@264 | 294 | Int_response_timeout = 0x00000200, // TIME_OUT_RES |
paul@264 | 295 | Int_read_timeout = 0x00000100, // TIME_OUT_READ |
paul@264 | 296 | |
paul@264 | 297 | // Common. |
paul@264 | 298 | |
paul@264 | 299 | Int_sdio = 0x80, // SDIO |
paul@264 | 300 | Int_trans_fifo_write_request = 0x40, // TXFIFO_WR_REQ |
paul@264 | 301 | Int_recv_fifo_read_request = 0x20, // RXFIFO_RD_REQ |
paul@264 | 302 | Int_end_command_response = 0x04, // END_CMD_RES |
paul@264 | 303 | Int_programming_done = 0x02, // PRG_DONE |
paul@264 | 304 | Int_data_transfer_done = 0x01, // DATA_TRAN_DONE |
paul@264 | 305 | }; |
paul@264 | 306 | |
paul@264 | 307 | enum Command_index_bits : unsigned |
paul@264 | 308 | { |
paul@264 | 309 | Command_index_mask = 0x0000003f, // CMD_INDEX |
paul@264 | 310 | }; |
paul@264 | 311 | |
paul@264 | 312 | enum Command_argument_bits : unsigned |
paul@264 | 313 | { |
paul@264 | 314 | Command_argument_mask = 0xffffffff, // ARG |
paul@264 | 315 | }; |
paul@264 | 316 | |
paul@264 | 317 | enum Response_fifo_bits : unsigned |
paul@264 | 318 | { |
paul@264 | 319 | Response_fifo_mask = 0x0000ffff, // DATA |
paul@264 | 320 | }; |
paul@264 | 321 | |
paul@264 | 322 | enum Recv_data_fifo_bits : unsigned |
paul@264 | 323 | { |
paul@264 | 324 | Recv_data_fifo_mask = 0xffffffff, // DATA |
paul@264 | 325 | }; |
paul@264 | 326 | |
paul@264 | 327 | enum Trans_data_fifo_bits : unsigned |
paul@264 | 328 | { |
paul@264 | 329 | Trans_data_fifo_mask = 0xffffffff, // DATA |
paul@264 | 330 | }; |
paul@264 | 331 | |
paul@264 | 332 | enum Low_power_mode_bits : unsigned |
paul@264 | 333 | { |
paul@264 | 334 | Low_power_mode_enable = 0x00000001, // LPM |
paul@264 | 335 | }; |
paul@264 | 336 | |
paul@264 | 337 | enum Dma_control_bits : unsigned |
paul@264 | 338 | { |
paul@264 | 339 | Dma_mode_specify_transfer_length = 0x80, // MODE_SEL |
paul@264 | 340 | |
paul@264 | 341 | Dma_address_offset_field_mask = 0x3, // AOFST |
paul@264 | 342 | Dma_address_offset_field_shift = 5, |
paul@264 | 343 | |
paul@264 | 344 | Dma_align_enable = 0x10, // ALIGNEN |
paul@264 | 345 | |
paul@264 | 346 | Dma_burst_type_field_mask = 0x3, // INCR |
paul@264 | 347 | Dma_burst_type_incr16 = 0, |
paul@264 | 348 | Dma_burst_type_incr32 = 1, |
paul@264 | 349 | Dma_burst_type_incr64 = 2, |
paul@264 | 350 | Dma_burst_type_field_shift = 2, |
paul@264 | 351 | |
paul@264 | 352 | Dma_select_common_dma = 0x02, // DMASEL |
paul@264 | 353 | Dma_select_special_dma = 0x00, |
paul@264 | 354 | |
paul@264 | 355 | Dma_enable = 0x01, // DMAEN |
paul@264 | 356 | Dma_disable = 0x00, |
paul@264 | 357 | }; |
paul@264 | 358 | |
paul@264 | 359 | |
paul@264 | 360 | |
paul@264 | 361 | // Command indexes. |
paul@264 | 362 | |
paul@264 | 363 | enum Command_index : unsigned |
paul@264 | 364 | { |
paul@264 | 365 | Command_go_idle_state = 0, |
paul@264 | 366 | Command_send_op_cond = 1, |
paul@264 | 367 | Command_all_send_cid = 2, |
paul@264 | 368 | Command_send_relative_addr = 3, // SD |
paul@264 | 369 | Command_set_relative_addr = 3, // MMC |
paul@264 | 370 | Command_set_dsr = 4, |
paul@264 | 371 | Command_io_send_op_cond = 5, // SDIO |
paul@264 | 372 | Command_select_deselect_card = 7, |
paul@264 | 373 | Command_send_if_cond = 8, |
paul@264 | 374 | Command_send_csd = 9, |
paul@264 | 375 | Command_send_cid = 10, |
paul@264 | 376 | Command_read_dat_until_stop = 11, |
paul@264 | 377 | Command_stop_transmission = 12, |
paul@264 | 378 | Command_send_status = 13, |
paul@264 | 379 | Command_go_inactive_state = 15, |
paul@264 | 380 | Command_set_blocklen = 16, |
paul@264 | 381 | Command_read_single_block = 17, |
paul@264 | 382 | Command_read_multiple_block = 18, |
paul@264 | 383 | Command_write_dat_until_stop = 20, |
paul@264 | 384 | Command_set_block_count = 23, |
paul@264 | 385 | Command_write_block = 24, |
paul@264 | 386 | Command_write_multiple_block = 25, |
paul@264 | 387 | Command_program_cid = 26, |
paul@264 | 388 | Command_program_csd = 27, |
paul@264 | 389 | Command_set_write_prot = 28, |
paul@264 | 390 | Command_clr_write_prot = 29, |
paul@264 | 391 | Command_send_write_prot = 30, |
paul@264 | 392 | Command_tag_sector_start = 32, |
paul@264 | 393 | Command_tag_sector_end = 33, |
paul@264 | 394 | Command_untag_sector = 34, |
paul@264 | 395 | Command_tag_erase_group_start = 35, |
paul@264 | 396 | Command_tag_erase_group_end = 36, |
paul@264 | 397 | Command_untag_erase_group = 37, |
paul@264 | 398 | Command_erase = 38, |
paul@264 | 399 | Command_fast_io = 39, |
paul@264 | 400 | Command_go_irq_state = 40, |
paul@264 | 401 | Command_lock_unlock = 42, |
paul@264 | 402 | Command_io_rw_direct = 52, // SDIO |
paul@264 | 403 | Command_app_cmd = 55, |
paul@264 | 404 | Command_gen_cmd = 56, |
paul@264 | 405 | }; |
paul@264 | 406 | |
paul@264 | 407 | // Application-specific command indexes, used by first issuing Command_app_cmd. |
paul@264 | 408 | |
paul@264 | 409 | enum App_command_index : unsigned |
paul@264 | 410 | { |
paul@264 | 411 | App_command_set_bus_width = 6, |
paul@264 | 412 | App_command_sd_status = 13, |
paul@264 | 413 | App_command_send_num_wr_blocks = 22, |
paul@264 | 414 | App_command_set_wr_block_erase_count = 23, |
paul@264 | 415 | App_command_sd_send_op_cond = 41, |
paul@264 | 416 | App_command_set_clr_card_detect = 42, |
paul@264 | 417 | App_command_send_scr = 51, |
paul@264 | 418 | App_command_read_ocr = 58, |
paul@264 | 419 | }; |
paul@264 | 420 | |
paul@264 | 421 | enum Bus_width_bits : unsigned |
paul@264 | 422 | { |
paul@264 | 423 | Bus_width_1bit = 0, |
paul@264 | 424 | Bus_width_4bit = 2, |
paul@264 | 425 | }; |
paul@264 | 426 | |
paul@264 | 427 | // Command response sizes in 16-bit units. |
paul@264 | 428 | |
paul@264 | 429 | enum Response_sizes : unsigned |
paul@264 | 430 | { |
paul@264 | 431 | Response_size_R1 = 3, |
paul@264 | 432 | Response_size_R2 = 8, // omits the CRC and end bit |
paul@264 | 433 | Response_size_R3 = 3, |
paul@264 | 434 | Response_size_R4 = 3, |
paul@264 | 435 | Response_size_R5 = 3, |
paul@264 | 436 | Response_size_R6 = 3, |
paul@264 | 437 | Response_size_R7 = 3, |
paul@264 | 438 | }; |
paul@264 | 439 | |
paul@264 | 440 | // SD_SEND_OP_COND argument flags. |
paul@264 | 441 | |
paul@264 | 442 | enum Ocr_argument_flags : unsigned |
paul@264 | 443 | { |
paul@264 | 444 | Ocr_high_capacity_storage = 0x40000000, |
paul@264 | 445 | }; |
paul@264 | 446 | |
paul@264 | 447 | // SD_SEND_OP_COND response flags (R3). |
paul@264 | 448 | |
paul@264 | 449 | enum Ocr_response_flags : unsigned |
paul@264 | 450 | { |
paul@264 | 451 | Ocr_card_powered_up = 0x80000000, |
paul@264 | 452 | }; |
paul@264 | 453 | |
paul@264 | 454 | // R1 status flags. |
paul@264 | 455 | |
paul@264 | 456 | enum R1_status_flags : unsigned |
paul@264 | 457 | { |
paul@264 | 458 | R1_status_error_mask = 0xffff0000, |
paul@264 | 459 | }; |
paul@264 | 460 | |
paul@264 | 461 | |
paul@264 | 462 | |
paul@264 | 463 | // MMC response structures. |
paul@264 | 464 | // These are 16-bit aligned to permit conversion to 16-bit arrays. |
paul@264 | 465 | |
paul@264 | 466 | struct R1 |
paul@264 | 467 | { |
paul@264 | 468 | uint8_t end_crc; |
paul@264 | 469 | uint32_t status; |
paul@264 | 470 | uint8_t index:6, trans_start:2; |
paul@264 | 471 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 472 | |
paul@264 | 473 | struct R2 |
paul@264 | 474 | { |
paul@264 | 475 | // uint8_t end_crc; (not retrieved) |
paul@264 | 476 | |
paul@264 | 477 | union |
paul@264 | 478 | { |
paul@264 | 479 | uint8_t raw[15]; |
paul@264 | 480 | struct CID cid; |
paul@264 | 481 | struct CSD csd; |
paul@264 | 482 | } payload; |
paul@264 | 483 | |
paul@264 | 484 | uint8_t reserved_trans_start; |
paul@264 | 485 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 486 | |
paul@264 | 487 | struct R3 |
paul@264 | 488 | { |
paul@264 | 489 | uint8_t end_reserved; |
paul@264 | 490 | uint32_t ocr; |
paul@264 | 491 | uint8_t reserved_trans_start; |
paul@264 | 492 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 493 | |
paul@264 | 494 | // SDIO response structures. |
paul@264 | 495 | |
paul@264 | 496 | struct R4 |
paul@264 | 497 | { |
paul@264 | 498 | uint8_t end_reserved; |
paul@264 | 499 | uint32_t ocr:24, stuff:3, memory_present:1, number_io_functions:3, ready:1; |
paul@264 | 500 | uint8_t reserved_trans_start; |
paul@264 | 501 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 502 | |
paul@264 | 503 | struct R5 |
paul@264 | 504 | { |
paul@264 | 505 | uint8_t end_crc; |
paul@264 | 506 | uint8_t data; |
paul@264 | 507 | uint8_t out_of_range:1, invalid_function_number:1, reserved:1, error:1, |
paul@264 | 508 | io_current_state:2, illegal_command:1, crc_error:1; |
paul@264 | 509 | uint16_t stuff; |
paul@264 | 510 | uint8_t index:6, trans_start:2; |
paul@264 | 511 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 512 | |
paul@264 | 513 | struct R6 |
paul@264 | 514 | { |
paul@264 | 515 | uint8_t end_crc; |
paul@264 | 516 | uint16_t status; |
paul@264 | 517 | uint16_t rca; |
paul@264 | 518 | uint8_t index:6, trans_start:2; |
paul@264 | 519 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |
paul@264 | 520 | |
paul@264 | 521 | struct R7 |
paul@264 | 522 | { |
paul@264 | 523 | uint8_t end_crc; |
paul@264 | 524 | |
paul@264 | 525 | union |
paul@264 | 526 | { |
paul@264 | 527 | uint32_t check:8, voltage:4, reserved:20; |
paul@264 | 528 | uint32_t raw; |
paul@264 | 529 | } check_voltage; |
paul@264 | 530 | |
paul@264 | 531 | uint8_t index:6, trans_start:2; |
paul@264 | 532 | } __attribute__((packed,aligned(__alignof__(uint16_t)))); |