1.1 --- a/pkg/devices/lib/msc/include/msc-common.h Sun Feb 18 22:43:39 2024 +0100
1.2 +++ b/pkg/devices/lib/msc/include/msc-common.h Sun Feb 18 22:45:07 2024 +0100
1.3 @@ -69,6 +69,11 @@
1.4 void start_clock();
1.5 void stop_clock();
1.6
1.7 + // Hardware properties.
1.8 +
1.9 + virtual bool have_dma_enable_in_command();
1.10 + virtual bool have_dma_selection();
1.11 +
1.12 // Command properties.
1.13
1.14 bool command_will_write(uint8_t index);
2.1 --- a/pkg/devices/lib/msc/include/msc-defs.h Sun Feb 18 22:43:39 2024 +0100
2.2 +++ b/pkg/devices/lib/msc/include/msc-defs.h Sun Feb 18 22:45:07 2024 +0100
2.3 @@ -198,14 +198,16 @@
2.4 Cdc_io_abort = 0x0800, // IO_ABORT
2.5
2.6 Cdc_bus_width_field_mask = 0x3, // BUS_WIDTH
2.7 - Cdc_bus_width_field_1bit = 0, // = 0
2.8 - Cdc_bus_width_field_4bit = 2, // = 2
2.9 + Cdc_bus_width_1bit = 0,
2.10 + Cdc_bus_width_4bit = 2,
2.11 Cdc_bus_width_field_shift = 9,
2.12
2.13 // JZ4740 only.
2.14
2.15 - Cdc_dma_enable = 0x0100, // DMA_EN
2.16 - Cdc_dma_disable = 0x0000,
2.17 + Cdc_dma_field_mask = 0x1, // DMA_EN
2.18 + Cdc_dma_disable = 0,
2.19 + Cdc_dma_enable = 1,
2.20 + Cdc_dma_field_shift = 8,
2.21
2.22 // Common.
2.23
3.1 --- a/pkg/devices/lib/msc/src/common.cc Sun Feb 18 22:43:39 2024 +0100
3.2 +++ b/pkg/devices/lib/msc/src/common.cc Sun Feb 18 22:45:07 2024 +0100
3.3 @@ -66,9 +66,9 @@
3.4 {
3.5 switch (width)
3.6 {
3.7 - case 4: return Cdc_bus_width_field_4bit;
3.8 - case 1: return Cdc_bus_width_field_1bit;
3.9 - default: return Cdc_bus_width_field_1bit;
3.10 + case 4: return Cdc_bus_width_4bit;
3.11 + case 1: return Cdc_bus_width_1bit;
3.12 + default: return Cdc_bus_width_1bit;
3.13 }
3.14 }
3.15
3.16 @@ -161,6 +161,18 @@
3.17 }
3.18
3.19 bool
3.20 +Msc_channel::have_dma_enable_in_command()
3.21 +{
3.22 + return false;
3.23 +}
3.24 +
3.25 +bool
3.26 +Msc_channel::have_dma_selection()
3.27 +{
3.28 + return true;
3.29 +}
3.30 +
3.31 +bool
3.32 Msc_channel::command_will_write(uint8_t index)
3.33 {
3.34 // NOTE: Probably incomplete coverage.
3.35 @@ -355,10 +367,11 @@
3.36 {
3.37 stop_clock();
3.38
3.39 - // Enable DMA for data transfers.
3.40 - // NOTE: Needed for JZ4780 and later SoCs.
3.41 + // Enable DMA for data transfers for JZ4780, X1600 and others that have a
3.42 + // channel-level control selecting special or conventional DMA.
3.43
3.44 - _regs[Msc_dma_control] = (data ? Dma_select_common_dma | Dma_enable : Dma_disable);
3.45 + if (have_dma_selection())
3.46 + _regs[Msc_dma_control] = (data ? Dma_select_common_dma | Dma_enable : Dma_disable);
3.47
3.48 // Set the command index and argument.
3.49
3.50 @@ -373,7 +386,8 @@
3.51 // NOTE: May need to set the SD bus width.
3.52
3.53 set_field(Msc_command_data_control, Cdc_bus_width_field_mask,
3.54 - Cdc_bus_width_field_shift, encode_bus_width(_cards[_card].bus_width));
3.55 + Cdc_bus_width_field_shift,
3.56 + encode_bus_width(_cards[_card].bus_width));
3.57
3.58 set_field(Msc_command_data_control, Cdc_recv_fifo_level_field_mask,
3.59 Cdc_recv_fifo_level_field_shift, Cdc_fifo_level_16);
3.60 @@ -382,22 +396,24 @@
3.61 Cdc_trans_fifo_level_field_shift, Cdc_fifo_level_16);
3.62
3.63 // Set and clear control bits appropriate to the command.
3.64 - // NOTE: Pre-JZ4780 SoCs enable DMA in this register.
3.65
3.66 _regs[Msc_command_data_control] = _regs[Msc_command_data_control] |
3.67 - // (data ? Cdc_dma_enable : Cdc_dma_disable) |
3.68 (busy ? Cdc_expect_busy : Cdc_do_not_expect_busy) |
3.69 (data ? Cdc_data_with_command : Cdc_no_data_with_command) |
3.70 (write ? Cdc_write_operation : Cdc_read_operation);
3.71
3.72 _regs[Msc_command_data_control] = _regs[Msc_command_data_control] &
3.73 - ~(
3.74 - // (data ? Cdc_dma_disable : Cdc_dma_enable) |
3.75 - (busy ? Cdc_do_not_expect_busy : Cdc_expect_busy) |
3.76 + ~((busy ? Cdc_do_not_expect_busy : Cdc_expect_busy) |
3.77 (data ? Cdc_no_data_with_command : Cdc_data_with_command) |
3.78 (write ? Cdc_read_operation : Cdc_write_operation) |
3.79 Cdc_stream_block | Cdc_init_sequence);
3.80
3.81 + // Pre-JZ4780 SoCs enable DMA in the command/data register.
3.82 +
3.83 + if (have_dma_enable_in_command())
3.84 + set_field(Msc_command_data_control, Cdc_dma_field_mask, Cdc_dma_field_shift,
3.85 + data ? Cdc_dma_enable : Cdc_dma_disable);
3.86 +
3.87 // Unmask interrupts, start the clock, then initiate the command.
3.88
3.89 uint32_t flags = Int_end_command_response | Int_response_timeout;