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