# HG changeset patch # User Paul Boddie # Date 1708292707 -3600 # Node ID b60c8cf438402842e13ef38bc4bb94aaa1c2dc0e # Parent 6bf4d6f69bcf0dd687bcc24622664b27c745140c Support different DMA configuration methods. diff -r 6bf4d6f69bcf -r b60c8cf43840 pkg/devices/lib/msc/include/msc-common.h --- a/pkg/devices/lib/msc/include/msc-common.h Sun Feb 18 22:43:39 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-common.h Sun Feb 18 22:45:07 2024 +0100 @@ -69,6 +69,11 @@ void start_clock(); void stop_clock(); + // Hardware properties. + + virtual bool have_dma_enable_in_command(); + virtual bool have_dma_selection(); + // Command properties. bool command_will_write(uint8_t index); diff -r 6bf4d6f69bcf -r b60c8cf43840 pkg/devices/lib/msc/include/msc-defs.h --- a/pkg/devices/lib/msc/include/msc-defs.h Sun Feb 18 22:43:39 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-defs.h Sun Feb 18 22:45:07 2024 +0100 @@ -198,14 +198,16 @@ Cdc_io_abort = 0x0800, // IO_ABORT Cdc_bus_width_field_mask = 0x3, // BUS_WIDTH - Cdc_bus_width_field_1bit = 0, // = 0 - Cdc_bus_width_field_4bit = 2, // = 2 + Cdc_bus_width_1bit = 0, + Cdc_bus_width_4bit = 2, Cdc_bus_width_field_shift = 9, // JZ4740 only. - Cdc_dma_enable = 0x0100, // DMA_EN - Cdc_dma_disable = 0x0000, + Cdc_dma_field_mask = 0x1, // DMA_EN + Cdc_dma_disable = 0, + Cdc_dma_enable = 1, + Cdc_dma_field_shift = 8, // Common. diff -r 6bf4d6f69bcf -r b60c8cf43840 pkg/devices/lib/msc/src/common.cc --- a/pkg/devices/lib/msc/src/common.cc Sun Feb 18 22:43:39 2024 +0100 +++ b/pkg/devices/lib/msc/src/common.cc Sun Feb 18 22:45:07 2024 +0100 @@ -66,9 +66,9 @@ { switch (width) { - case 4: return Cdc_bus_width_field_4bit; - case 1: return Cdc_bus_width_field_1bit; - default: return Cdc_bus_width_field_1bit; + case 4: return Cdc_bus_width_4bit; + case 1: return Cdc_bus_width_1bit; + default: return Cdc_bus_width_1bit; } } @@ -161,6 +161,18 @@ } bool +Msc_channel::have_dma_enable_in_command() +{ + return false; +} + +bool +Msc_channel::have_dma_selection() +{ + return true; +} + +bool Msc_channel::command_will_write(uint8_t index) { // NOTE: Probably incomplete coverage. @@ -355,10 +367,11 @@ { stop_clock(); - // Enable DMA for data transfers. - // NOTE: Needed for JZ4780 and later SoCs. + // Enable DMA for data transfers for JZ4780, X1600 and others that have a + // channel-level control selecting special or conventional DMA. - _regs[Msc_dma_control] = (data ? Dma_select_common_dma | Dma_enable : Dma_disable); + if (have_dma_selection()) + _regs[Msc_dma_control] = (data ? Dma_select_common_dma | Dma_enable : Dma_disable); // Set the command index and argument. @@ -373,7 +386,8 @@ // NOTE: May need to set the SD bus width. set_field(Msc_command_data_control, Cdc_bus_width_field_mask, - Cdc_bus_width_field_shift, encode_bus_width(_cards[_card].bus_width)); + Cdc_bus_width_field_shift, + encode_bus_width(_cards[_card].bus_width)); set_field(Msc_command_data_control, Cdc_recv_fifo_level_field_mask, Cdc_recv_fifo_level_field_shift, Cdc_fifo_level_16); @@ -382,22 +396,24 @@ Cdc_trans_fifo_level_field_shift, Cdc_fifo_level_16); // Set and clear control bits appropriate to the command. - // NOTE: Pre-JZ4780 SoCs enable DMA in this register. _regs[Msc_command_data_control] = _regs[Msc_command_data_control] | - // (data ? Cdc_dma_enable : Cdc_dma_disable) | (busy ? Cdc_expect_busy : Cdc_do_not_expect_busy) | (data ? Cdc_data_with_command : Cdc_no_data_with_command) | (write ? Cdc_write_operation : Cdc_read_operation); _regs[Msc_command_data_control] = _regs[Msc_command_data_control] & - ~( - // (data ? Cdc_dma_disable : Cdc_dma_enable) | - (busy ? Cdc_do_not_expect_busy : Cdc_expect_busy) | + ~((busy ? Cdc_do_not_expect_busy : Cdc_expect_busy) | (data ? Cdc_no_data_with_command : Cdc_data_with_command) | (write ? Cdc_read_operation : Cdc_write_operation) | Cdc_stream_block | Cdc_init_sequence); + // Pre-JZ4780 SoCs enable DMA in the command/data register. + + if (have_dma_enable_in_command()) + set_field(Msc_command_data_control, Cdc_dma_field_mask, Cdc_dma_field_shift, + data ? Cdc_dma_enable : Cdc_dma_disable); + // Unmask interrupts, start the clock, then initiate the command. uint32_t flags = Int_end_command_response | Int_response_timeout;