From dc98691c9716fece8b005f0ae3734c68f85988b7 Mon Sep 17 00:00:00 2001 From: Michal Sieron Date: Mon, 23 May 2022 15:26:36 +0200 Subject: [PATCH] drivers: i2s: i2s_litex: Calculate offsets from DT To support both 8-bit and 32-bit Control/Status register variants, register offsets need to be calculated from device tree. Updated register data in device tree to the 32-bit CSR variant. Renamed defines to be similar to other LiteX drivers. Changed frequencies in clock-outputs nodes, so i2s/litex sample works. Signed-off-by: Michal Sieron --- drivers/i2s/i2s_litex.c | 40 +++++++++++++-------------- drivers/i2s/i2s_litex.h | 39 ++++++++++---------------- dts/riscv/riscv32-litex-vexriscv.dtsi | 36 ++++++++++++++++++++---- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/drivers/i2s/i2s_litex.c b/drivers/i2s/i2s_litex.c index fe75eecce00..15218175661 100644 --- a/drivers/i2s/i2s_litex.c +++ b/drivers/i2s/i2s_litex.c @@ -27,9 +27,9 @@ LOG_MODULE_REGISTER(i2s_litex); */ static void i2s_enable(uintptr_t reg) { - uint8_t reg_data = litex_read8(reg + I2S_CONTROL_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_CONTROL_OFFSET); - litex_write8(reg_data | I2S_ENABLE, reg + I2S_CONTROL_REG_OFFSET); + litex_write8(reg_data | I2S_ENABLE, reg + I2S_CONTROL_OFFSET); } /** @@ -39,9 +39,9 @@ static void i2s_enable(uintptr_t reg) */ static void i2s_disable(uintptr_t reg) { - uint8_t reg_data = litex_read8(reg + I2S_CONTROL_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_CONTROL_OFFSET); - litex_write8(reg_data & ~(I2S_ENABLE), reg + I2S_CONTROL_REG_OFFSET); + litex_write8(reg_data & ~(I2S_ENABLE), reg + I2S_CONTROL_OFFSET); } /** @@ -51,9 +51,9 @@ static void i2s_disable(uintptr_t reg) */ static void i2s_reset_fifo(uintptr_t reg) { - uint8_t reg_data = litex_read8(reg + I2S_CONTROL_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_CONTROL_OFFSET); - litex_write8(reg_data | I2S_FIFO_RESET, reg + I2S_CONTROL_REG_OFFSET); + litex_write8(reg_data | I2S_FIFO_RESET, reg + I2S_CONTROL_OFFSET); } /** @@ -66,7 +66,7 @@ static void i2s_reset_fifo(uintptr_t reg) */ static i2s_fmt_t i2s_get_foramt(uintptr_t reg) { - uint8_t reg_data = litex_read32(reg + I2S_CONFIG_REG_OFFSET); + uint8_t reg_data = litex_read32(reg + I2S_CONFIG_OFFSET); reg_data &= I2S_CONF_FORMAT_MASK; if (reg_data == LITEX_I2S_STANDARD) { @@ -86,7 +86,7 @@ static i2s_fmt_t i2s_get_foramt(uintptr_t reg) */ static uint32_t i2s_get_sample_width(uintptr_t reg) { - uint32_t reg_data = litex_read32(reg + I2S_CONFIG_REG_OFFSET); + uint32_t reg_data = litex_read32(reg + I2S_CONFIG_OFFSET); reg_data &= I2S_CONF_SAMPLE_WIDTH_MASK; return reg_data >> I2S_CONF_SAMPLE_WIDTH_OFFSET; @@ -101,7 +101,7 @@ static uint32_t i2s_get_sample_width(uintptr_t reg) */ static uint32_t i2s_get_audio_freq(uintptr_t reg) { - uint32_t reg_data = litex_read32(reg + I2S_CONFIG_REG_OFFSET); + uint32_t reg_data = litex_read32(reg + I2S_CONFIG_OFFSET); reg_data &= I2S_CONF_LRCK_MASK; return reg_data >> I2S_CONF_LRCK_FREQ_OFFSET; @@ -117,9 +117,9 @@ static void i2s_irq_enable(uintptr_t reg, int irq_type) { __ASSERT_NO_MSG(irq_type == I2S_EV_READY || irq_type == I2S_EV_ERROR); - uint8_t reg_data = litex_read8(reg + I2S_EV_ENABLE_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_EV_ENABLE_OFFSET); - litex_write8(reg_data | irq_type, reg + I2S_EV_ENABLE_REG_OFFSET); + litex_write8(reg_data | irq_type, reg + I2S_EV_ENABLE_OFFSET); } /** @@ -132,9 +132,9 @@ static void i2s_irq_disable(uintptr_t reg, int irq_type) { __ASSERT_NO_MSG(irq_type == I2S_EV_READY || irq_type == I2S_EV_ERROR); - uint8_t reg_data = litex_read8(reg + I2S_EV_ENABLE_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_EV_ENABLE_OFFSET); - litex_write8(reg_data & ~(irq_type), reg + I2S_EV_ENABLE_REG_OFFSET); + litex_write8(reg_data & ~(irq_type), reg + I2S_EV_ENABLE_OFFSET); } /** @@ -144,9 +144,9 @@ static void i2s_irq_disable(uintptr_t reg, int irq_type) */ static void i2s_clear_pending_irq(uintptr_t reg) { - uint8_t reg_data = litex_read8(reg + I2S_EV_PENDING_REG_OFFSET); + uint8_t reg_data = litex_read8(reg + I2S_EV_PENDING_OFFSET); - litex_write8(reg_data, reg + I2S_EV_PENDING_REG_OFFSET); + litex_write8(reg_data, reg + I2S_EV_PENDING_OFFSET); } /** @@ -323,18 +323,16 @@ static int i2s_litex_configure(const struct device *dev, enum i2s_dir dir, struct i2s_litex_data *const dev_data = dev->data; const struct i2s_litex_cfg *const cfg = dev->config; struct stream *stream; - int channels_concatenated; + int channels_concatenated = litex_read8(cfg->base + I2S_STATUS_OFFSET); int dev_audio_freq = i2s_get_audio_freq(cfg->base); int channel_div; if (dir == I2S_DIR_RX) { stream = &dev_data->rx; - channels_concatenated = litex_read8(I2S_RX_STATUS_REG) & - I2S_RX_STAT_CHANNEL_CONCATENATED_MASK; + channels_concatenated &= I2S_RX_STAT_CHANNEL_CONCATENATED_MASK; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; - channels_concatenated = litex_read8(I2S_TX_STATUS_REG) & - I2S_TX_STAT_CHANNEL_CONCATENATED_MASK; + channels_concatenated &= I2S_TX_STAT_CHANNEL_CONCATENATED_MASK; } else if (dir == I2S_DIR_BOTH) { return -ENOSYS; } else { @@ -612,7 +610,7 @@ static const struct i2s_driver_api i2s_litex_driver_api = { static void i2s_litex_irq_config_func_##dir(const struct device *dev); \ \ static struct i2s_litex_cfg i2s_litex_cfg_##dir = { \ - .base = DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_##dir), control), \ + .base = DT_REG_ADDR(DT_NODELABEL(i2s_##dir)), \ .fifo_base = \ DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_##dir), fifo), \ .fifo_depth = DT_PROP(DT_NODELABEL(i2s_##dir), fifo_depth), \ diff --git a/drivers/i2s/i2s_litex.h b/drivers/i2s/i2s_litex.h index f4dbc040b0a..f573f9fd14d 100644 --- a/drivers/i2s/i2s_litex.h +++ b/drivers/i2s/i2s_litex.h @@ -11,14 +11,6 @@ #include #include -/* i2s register offsets*/ -#define I2S_EV_STATUS_REG_OFFSET 0x0 -#define I2S_EV_PENDING_REG_OFFSET 0x4 -#define I2S_EV_ENABLE_REG_OFFSET 0x8 -#define I2S_CONTROL_REG_OFFSET 0xc -#define I2S_STATUS_REG_OFFSET 0x10 -#define I2S_CONFIG_REG_OFFSET 0x20 - /* i2s configuration mask*/ #define I2S_CONF_FORMAT_OFFSET 0 #define I2S_CONF_SAMPLE_WIDTH_OFFSET 2 @@ -36,14 +28,6 @@ #define I2S_EV_READY (1 << 0) #define I2S_EV_ERROR (1 << 1) /* i2s rx*/ -#define I2S_RX_BASE_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), control) -#define I2S_RX_EV_STATUS_REG (I2S_RX_BASE_ADDR + I2S_EV_STATUS_REG_OFFSET) -#define I2S_RX_EV_PENDING_REG (I2S_RX_BASE_ADDR + I2S_EV_PENDING_REG_OFFSET) -#define I2S_RX_EV_ENABLE_REG (I2S_RX_BASE_ADDR + I2S_EV_ENABLE_REG_OFFSET) -#define I2S_RX_CONTROL_REG (I2S_RX_BASE_ADDR + I2S_CONTROL_REG_OFFSET) -#define I2S_RX_STATUS_REG (I2S_RX_BASE_ADDR + I2S_STATUS_REG_OFFSET) -#define I2S_RX_CONFIG_REG (I2S_RX_BASE_ADDR + I2S_CONFIG_REG_OFFSET) - #define I2S_RX_STAT_CHANNEL_CONCATENATED_OFFSET 31 #define I2S_RX_STAT_CHANNEL_CONCATENATED_MASK \ (0x1 << I2S_RX_STAT_CHANNEL_CONCATENATED_OFFSET) @@ -52,14 +36,6 @@ #define I2S_RX_FIFO_DEPTH DT_PROP(DT_NODELABEL(i2s_rx), fifo_depth) /* i2s tx*/ -#define I2S_TX_BASE_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_tx), control) -#define I2S_TX_EV_STATUS_REG (I2S_RX_BASE_ADDR + I2S_EV_STATUS_REG_OFFSET) -#define I2S_TX_EV_PENDING_REG (I2S_TX_BASE_ADDR + I2S_EV_PENDING_REG_OFFSET) -#define I2S_TX_EV_ENABLE_REG (I2S_TX_BASE_ADDR + I2S_EV_ENABLE_REG_OFFSET) -#define I2S_TX_CONTROL_REG (I2S_TX_BASE_ADDR + I2S_CONTROL_REG_OFFSET) -#define I2S_TX_STATUS_REG (I2S_TX_BASE_ADDR + I2S_STATUS_REG_OFFSET) -#define I2S_TX_CONFIG_REG (I2S_TX_BASE_ADDR + I2S_CONFIG_REG_OFFSET) - #define I2S_TX_STAT_CHANNEL_CONCATENATED_OFFSET 24 #define I2S_TX_STAT_CHANNEL_CONCATENATED_MASK \ (0x1 << I2S_TX_STAT_CHANNEL_CONCATENATED_OFFSET) @@ -67,6 +43,21 @@ #define I2S_TX_FIFO_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_tx), fifo) #define I2S_TX_FIFO_DEPTH DT_PROP(DT_NODELABEL(i2s_tx), fifo_depth) +/* i2s register offsets (they are the same for all i2s nodes, both rx and tx) */ +#define I2S_BASE_ADDR DT_REG_ADDR(DT_NODELABEL(i2s_rx)) +#define I2S_EV_STATUS_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), ev_status) \ + - I2S_BASE_ADDR) +#define I2S_EV_PENDING_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), ev_pending) \ + - I2S_BASE_ADDR) +#define I2S_EV_ENABLE_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), ev_enable) \ + - I2S_BASE_ADDR) +#define I2S_CONTROL_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), rx_ctl) \ + - I2S_BASE_ADDR) +#define I2S_STATUS_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), rx_stat) \ + - I2S_BASE_ADDR) +#define I2S_CONFIG_OFFSET (DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_rx), rx_conf) \ + - I2S_BASE_ADDR) + enum litex_i2s_fmt { LITEX_I2S_STANDARD = 1, LITEX_I2S_LEFT_JUSTIFIED = 2, diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 504e9e2d2da..cc974e955d8 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -219,24 +219,48 @@ }; i2s_rx: i2s_rx@e000a800 { compatible = "litex,i2s"; - reg = <0xe000a800 0x20 0xb1000000 0x40000>; + reg = <0xe000a800 0x4 + 0xe000a804 0x4 + 0xe000a808 0x4 + 0xe000a80c 0x4 + 0xe000a810 0x4 + 0xe000a814 0x4 + 0xb1000000 0x40000>; interrupt-parent = <&intc0>; interrupts = <6 2>; #address-cells = <1>; #size-cells = <0>; - reg-names = "control", "fifo"; + reg-names = "ev_status", + "ev_pending", + "ev_enable", + "rx_ctl", + "rx_stat", + "rx_conf", + "fifo"; fifo_depth = <256>; label = "i2s_rx"; status = "disabled"; }; i2s_tx: i2s_tx@e000b000 { compatible = "litex,i2s"; - reg = <0xe000b000 0x20 0xb2000000 0x40000>; + reg = <0xe000b000 0x4 + 0xe000b004 0x4 + 0xe000b008 0x4 + 0xe000b00c 0x4 + 0xe000b010 0x4 + 0xe000b014 0x4 + 0xb2000000 0x40000>; interrupt-parent = <&intc0>; interrupts = <7 2>; #address-cells = <1>; #size-cells = <0>; - reg-names = "control", "fifo"; + reg-names = "ev_status", + "ev_pending", + "ev_enable", + "tx_ctl", + "tx_stat", + "tx_conf", + "fifo"; fifo_depth = <256>; label = "i2s_tx"; status = "disabled"; @@ -249,7 +273,7 @@ reg = <0>; compatible = "litex,clkout"; clock-output-names = "CLK_0"; - litex,clock-frequency = <100000000>; + litex,clock-frequency = <11289600>; litex,clock-phase = <0>; litex,clock-duty-num = <1>; litex,clock-duty-den = <2>; @@ -262,7 +286,7 @@ reg = <1>; compatible = "litex,clkout"; clock-output-names = "CLK_1"; - litex,clock-frequency = <100000000>; + litex,clock-frequency = <22579200>; litex,clock-phase = <0>; litex,clock-duty-num = <1>; litex,clock-duty-den = <2>;