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_1bit = 0, 202 Cdc_bus_width_4bit = 2, 203 Cdc_bus_width_field_shift = 9, 204 205 // JZ4740 only. 206 207 Cdc_dma_field_mask = 0x1, // DMA_EN 208 Cdc_dma_disable = 0, 209 Cdc_dma_enable = 1, 210 Cdc_dma_field_shift = 8, 211 212 // Common. 213 214 Cdc_init_sequence = 0x0080, // INIT 215 216 Cdc_expect_busy = 0x0040, // BUSY 217 Cdc_do_not_expect_busy = 0x0000, 218 219 Cdc_stream_block = 0x0020, // STREAM_BLOCK 220 Cdc_not_stream_block = 0x0000, 221 222 Cdc_write_operation = 0x0010, // WRITE_READ 223 Cdc_read_operation = 0x0000, 224 225 Cdc_data_with_command = 0x0008, // DATA_EN 226 Cdc_no_data_with_command = 0x0000, 227 228 Cdc_response_format_field_mask = 0x7, // RESPONSE_FORMAT 229 Cdc_response_format_field_shift = 0, 230 }; 231 232 enum Response_timeout_bits : unsigned 233 { 234 // NOTE: 16-bit value in the JZ4780. 235 // NOTE: 32-bit value in the X1600. 236 237 Response_timeout_mask = 0x000000ff, // RES_TO 238 }; 239 240 enum Read_timeout_bits : unsigned 241 { 242 // NOTE: 16-bit value prior to the JZ4780/X1600. 243 244 Read_timeout_mask = 0xffffffff, // READ_TO 245 }; 246 247 enum Block_length_bits : unsigned 248 { 249 // NOTE: 16-bit value in the JZ4780/X1600. 250 251 Block_length_mask = 0x00000fff, // BLK_LEN 252 }; 253 254 enum Block_count_bits : unsigned 255 { 256 Block_count_mask = 0x0000ffff, // NOB/SNOB 257 }; 258 259 // Interrupt mask/flag bits. 260 261 enum Interrupt_bits : unsigned 262 { 263 // X1600 only. 264 265 Int_dma_data_done = 0x80000000, // DMA_DATA_DONE 266 267 // JZ4780 only. 268 269 Int_auto_cmd23_done = 0x40000000, // AUTO_CMD23_DONE 270 Int_signal_voltage_change = 0x20000000, // SVS 271 272 // JZ4780/X1600 only. 273 274 Int_pin_level_field_mask = 0x1f, // PIN_LEVEL 275 Int_pin_level_field_shift = 24, 276 277 // X1600 only. 278 279 Int_write_request_all_done = 0x00800000, // WR_ALL_DONE 280 281 // JZ4780/X1600 only. 282 283 Int_boot_crc_error = 0x00100000, // BCE 284 Int_boot_data_end = 0x00080000, // BDE 285 Int_boot_ack_error = 0x00040000, // BAE 286 Int_boot_ack_received = 0x00020000, // BAR 287 Int_dma_end = 0x00010000, // DMAEND 288 Int_auto_cmd12_done = 0x00008000, // AUTO_CMD12_DONE 289 Int_data_fifo_full = 0x00004000, // DATA_FIFO_FULL 290 Int_data_fifo_empty = 0x00002000, // DATA_FIFO_EMP 291 Int_crc_response_error = 0x00001000, // CRC_RES_ERR 292 Int_crc_read_error = 0x00000800, // CRC_READ_ERR 293 Int_crc_write_error = 0x00000400, // CRC_WRITE_ERR 294 Int_response_timeout = 0x00000200, // TIME_OUT_RES 295 Int_read_timeout = 0x00000100, // TIME_OUT_READ 296 297 // Common. 298 299 Int_sdio = 0x80, // SDIO 300 Int_trans_fifo_write_request = 0x40, // TXFIFO_WR_REQ 301 Int_recv_fifo_read_request = 0x20, // RXFIFO_RD_REQ 302 Int_end_command_response = 0x04, // END_CMD_RES 303 Int_programming_done = 0x02, // PRG_DONE 304 Int_data_transfer_done = 0x01, // DATA_TRAN_DONE 305 }; 306 307 enum Command_index_bits : unsigned 308 { 309 Command_index_mask = 0x0000003f, // CMD_INDEX 310 }; 311 312 enum Command_argument_bits : unsigned 313 { 314 Command_argument_mask = 0xffffffff, // ARG 315 }; 316 317 enum Response_fifo_bits : unsigned 318 { 319 Response_fifo_mask = 0x0000ffff, // DATA 320 }; 321 322 enum Recv_data_fifo_bits : unsigned 323 { 324 Recv_data_fifo_mask = 0xffffffff, // DATA 325 }; 326 327 enum Trans_data_fifo_bits : unsigned 328 { 329 Trans_data_fifo_mask = 0xffffffff, // DATA 330 }; 331 332 enum Low_power_mode_bits : unsigned 333 { 334 Low_power_mode_enable = 0x00000001, // LPM 335 }; 336 337 enum Dma_control_bits : unsigned 338 { 339 Dma_mode_specify_transfer_length = 0x80, // MODE_SEL 340 341 Dma_address_offset_field_mask = 0x3, // AOFST 342 Dma_address_offset_field_shift = 5, 343 344 Dma_align_enable = 0x10, // ALIGNEN 345 346 Dma_burst_type_field_mask = 0x3, // INCR 347 Dma_burst_type_incr16 = 0, 348 Dma_burst_type_incr32 = 1, 349 Dma_burst_type_incr64 = 2, 350 Dma_burst_type_field_shift = 2, 351 352 Dma_select_common_dma = 0x02, // DMASEL 353 Dma_select_special_dma = 0x00, 354 355 Dma_enable = 0x01, // DMAEN 356 Dma_disable = 0x00, 357 }; 358 359 360 361 // Command indexes. 362 363 enum Command_index : unsigned 364 { 365 Command_go_idle_state = 0, 366 Command_send_op_cond = 1, 367 Command_all_send_cid = 2, 368 Command_send_relative_addr = 3, // SD 369 Command_set_relative_addr = 3, // MMC 370 Command_set_dsr = 4, 371 Command_io_send_op_cond = 5, // SDIO 372 Command_select_deselect_card = 7, 373 Command_send_if_cond = 8, 374 Command_send_csd = 9, 375 Command_send_cid = 10, 376 Command_read_dat_until_stop = 11, 377 Command_stop_transmission = 12, 378 Command_send_status = 13, 379 Command_go_inactive_state = 15, 380 Command_set_blocklen = 16, 381 Command_read_single_block = 17, 382 Command_read_multiple_block = 18, 383 Command_write_dat_until_stop = 20, 384 Command_set_block_count = 23, 385 Command_write_block = 24, 386 Command_write_multiple_block = 25, 387 Command_program_cid = 26, 388 Command_program_csd = 27, 389 Command_set_write_prot = 28, 390 Command_clr_write_prot = 29, 391 Command_send_write_prot = 30, 392 Command_tag_sector_start = 32, 393 Command_tag_sector_end = 33, 394 Command_untag_sector = 34, 395 Command_tag_erase_group_start = 35, 396 Command_tag_erase_group_end = 36, 397 Command_untag_erase_group = 37, 398 Command_erase = 38, 399 Command_fast_io = 39, 400 Command_go_irq_state = 40, 401 Command_lock_unlock = 42, 402 Command_io_rw_direct = 52, // SDIO 403 Command_app_cmd = 55, 404 Command_gen_cmd = 56, 405 }; 406 407 // Application-specific command indexes, used by first issuing Command_app_cmd. 408 409 enum App_command_index : unsigned 410 { 411 App_command_set_bus_width = 6, 412 App_command_sd_status = 13, 413 App_command_send_num_wr_blocks = 22, 414 App_command_set_wr_block_erase_count = 23, 415 App_command_sd_send_op_cond = 41, 416 App_command_set_clr_card_detect = 42, 417 App_command_send_scr = 51, 418 App_command_read_ocr = 58, 419 }; 420 421 enum Bus_width_bits : unsigned 422 { 423 Bus_width_1bit = 0, 424 Bus_width_4bit = 2, 425 }; 426 427 // Command response sizes in 16-bit units. 428 429 enum Response_sizes : unsigned 430 { 431 Response_size_R1 = 3, 432 Response_size_R2 = 8, // omits the CRC and end bit 433 Response_size_R3 = 3, 434 Response_size_R4 = 3, 435 Response_size_R5 = 3, 436 Response_size_R6 = 3, 437 Response_size_R7 = 3, 438 }; 439 440 // SD_SEND_OP_COND argument flags. 441 442 enum Ocr_argument_flags : unsigned 443 { 444 Ocr_high_capacity_storage = 0x40000000, 445 }; 446 447 // SD_SEND_OP_COND response flags (R3). 448 449 enum Ocr_response_flags : unsigned 450 { 451 Ocr_card_powered_up = 0x80000000, 452 }; 453 454 // R1 status flags. 455 456 enum R1_status_flags : unsigned 457 { 458 R1_status_error_mask = 0xffff0000, 459 }; 460 461 462 463 // MMC response structures. 464 // These are 16-bit aligned to permit conversion to 16-bit arrays. 465 466 struct R1 467 { 468 uint8_t end_crc; 469 uint32_t status; 470 uint8_t index:6, trans_start:2; 471 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 472 473 struct R2 474 { 475 // uint8_t end_crc; (not retrieved) 476 477 union 478 { 479 uint8_t raw[15]; 480 struct CID cid; 481 struct CSD csd; 482 } payload; 483 484 uint8_t reserved_trans_start; 485 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 486 487 struct R3 488 { 489 uint8_t end_reserved; 490 uint32_t ocr; 491 uint8_t reserved_trans_start; 492 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 493 494 // SDIO response structures. 495 496 struct R4 497 { 498 uint8_t end_reserved; 499 uint32_t ocr:24, stuff:3, memory_present:1, number_io_functions:3, ready:1; 500 uint8_t reserved_trans_start; 501 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 502 503 struct R5 504 { 505 uint8_t end_crc; 506 uint8_t data; 507 uint8_t out_of_range:1, invalid_function_number:1, reserved:1, error:1, 508 io_current_state:2, illegal_command:1, crc_error:1; 509 uint16_t stuff; 510 uint8_t index:6, trans_start:2; 511 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 512 513 struct R6 514 { 515 uint8_t end_crc; 516 uint16_t status; 517 uint16_t rca; 518 uint8_t index:6, trans_start:2; 519 } __attribute__((packed,aligned(__alignof__(uint16_t)))); 520 521 struct R7 522 { 523 uint8_t end_crc; 524 525 union 526 { 527 uint32_t check:8, voltage:4, reserved:20; 528 uint32_t raw; 529 } check_voltage; 530 531 uint8_t index:6, trans_start:2; 532 } __attribute__((packed,aligned(__alignof__(uint16_t))));