Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 Intel Corporation |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
Kumar Gala | b60b4be | 2021-03-01 15:56:27 -0600 | [diff] [blame] | 7 | #define DT_DRV_COMPAT altr_msgdma |
| 8 | |
Gerard Marull-Paretas | fb60aab | 2022-05-06 10:25:46 +0200 | [diff] [blame^] | 9 | #include <zephyr/device.h> |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 10 | #include <errno.h> |
Gerard Marull-Paretas | fb60aab | 2022-05-06 10:25:46 +0200 | [diff] [blame^] | 11 | #include <zephyr/init.h> |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 12 | #include <string.h> |
| 13 | #include <soc.h> |
Gerard Marull-Paretas | fb60aab | 2022-05-06 10:25:46 +0200 | [diff] [blame^] | 14 | #include <zephyr/drivers/dma.h> |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 15 | #include <altera_common.h> |
| 16 | #include "altera_msgdma_csr_regs.h" |
| 17 | #include "altera_msgdma_descriptor_regs.h" |
| 18 | #include "altera_msgdma.h" |
| 19 | |
Gerard Marull-Paretas | fb60aab | 2022-05-06 10:25:46 +0200 | [diff] [blame^] | 20 | #include <zephyr/logging/log.h> |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 21 | LOG_MODULE_REGISTER(dma_nios2, CONFIG_DMA_LOG_LEVEL); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 22 | |
| 23 | /* Device configuration parameters */ |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 24 | struct nios2_msgdma_dev_data { |
Tomasz Bursztyka | d1aee6b | 2020-07-08 10:23:21 +0200 | [diff] [blame] | 25 | const struct device *dev; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 26 | alt_msgdma_dev *msgdma_dev; |
| 27 | alt_msgdma_standard_descriptor desc; |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 28 | uint32_t direction; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 29 | struct k_sem sem_lock; |
Tomasz Bursztyka | 1580768 | 2020-07-29 09:02:03 +0200 | [diff] [blame] | 30 | void *user_data; |
Tomasz Bursztyka | 3a3f10c | 2020-07-29 08:55:43 +0200 | [diff] [blame] | 31 | dma_callback_t dma_callback; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 32 | }; |
| 33 | |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 34 | static void nios2_msgdma_isr(void *arg) |
| 35 | { |
Tomasz Bursztyka | e18fcbb | 2020-04-30 20:33:38 +0200 | [diff] [blame] | 36 | const struct device *dev = (const struct device *)arg; |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 37 | struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 38 | |
| 39 | /* Call Altera HAL driver ISR */ |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 40 | alt_handle_irq(dev_data->msgdma_dev, DT_INST_IRQN(0)); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | static void nios2_msgdma_callback(void *context) |
| 44 | { |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 45 | struct nios2_msgdma_dev_data *dev_data = |
| 46 | (struct nios2_msgdma_dev_data *)context; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 47 | int err_code; |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 48 | uint32_t status; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 49 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 50 | status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev_data->msgdma_dev->csr_base); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 51 | |
| 52 | if (status & ALTERA_MSGDMA_CSR_STOPPED_ON_ERROR_MASK) { |
| 53 | err_code = -EIO; |
| 54 | } else if (status & ALTERA_MSGDMA_CSR_BUSY_MASK) { |
| 55 | err_code = -EBUSY; |
| 56 | } else { |
| 57 | err_code = 0; |
| 58 | } |
| 59 | |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 60 | LOG_DBG("msgdma csr status Reg: 0x%x", status); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 61 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 62 | dev_data->dma_callback(dev_data->dev, dev_data->user_data, 0, err_code); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 63 | } |
| 64 | |
Tomasz Bursztyka | e18fcbb | 2020-04-30 20:33:38 +0200 | [diff] [blame] | 65 | static int nios2_msgdma_config(const struct device *dev, uint32_t channel, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 66 | struct dma_config *cfg) |
| 67 | { |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 68 | struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 69 | struct dma_block_config *dma_block; |
| 70 | int status; |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 71 | uint32_t control; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 72 | |
| 73 | /* Nios-II MSGDMA supports only one channel per DMA core */ |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 74 | if (channel != 0U) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 75 | LOG_ERR("invalid channel number"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 76 | return -EINVAL; |
| 77 | } |
| 78 | |
| 79 | #if MSGDMA_0_CSR_PREFETCHER_ENABLE |
| 80 | if (cfg->block_count > 1) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 81 | LOG_ERR("driver yet add support multiple descriptors"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 82 | return -EINVAL; |
| 83 | } |
| 84 | #else |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 85 | if (cfg->block_count != 1U) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 86 | LOG_ERR("invalid block count!!"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 87 | return -EINVAL; |
| 88 | } |
| 89 | #endif |
| 90 | |
| 91 | if (cfg->head_block == NULL) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 92 | LOG_ERR("head_block ptr NULL!!"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 93 | return -EINVAL; |
| 94 | } |
| 95 | |
| 96 | if (cfg->head_block->block_size > MSGDMA_0_DESCRIPTOR_SLAVE_MAX_BYTE) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 97 | LOG_ERR("DMA error: Data size too big: %d", |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 98 | cfg->head_block->block_size); |
| 99 | return -EINVAL; |
| 100 | } |
| 101 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 102 | k_sem_take(&dev_data->sem_lock, K_FOREVER); |
| 103 | dev_data->dma_callback = cfg->dma_callback; |
| 104 | dev_data->user_data = cfg->user_data; |
| 105 | dev_data->direction = cfg->channel_direction; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 106 | dma_block = cfg->head_block; |
| 107 | control = ALTERA_MSGDMA_DESCRIPTOR_CONTROL_TRANSFER_COMPLETE_IRQ_MASK | |
| 108 | ALTERA_MSGDMA_DESCRIPTOR_CONTROL_EARLY_TERMINATION_IRQ_MASK; |
| 109 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 110 | if (dev_data->direction == MEMORY_TO_MEMORY) { |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 111 | status = alt_msgdma_construct_standard_mm_to_mm_descriptor( |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 112 | dev_data->msgdma_dev, &dev_data->desc, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 113 | (alt_u32 *)dma_block->source_address, |
| 114 | (alt_u32 *)dma_block->dest_address, |
| 115 | dma_block->block_size, |
| 116 | control); |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 117 | } else if (dev_data->direction == MEMORY_TO_PERIPHERAL) { |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 118 | status = alt_msgdma_construct_standard_mm_to_st_descriptor( |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 119 | dev_data->msgdma_dev, &dev_data->desc, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 120 | (alt_u32 *)dma_block->source_address, |
| 121 | dma_block->block_size, |
| 122 | control); |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 123 | } else if (dev_data->direction == PERIPHERAL_TO_MEMORY) { |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 124 | status = alt_msgdma_construct_standard_st_to_mm_descriptor( |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 125 | dev_data->msgdma_dev, &dev_data->desc, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 126 | (alt_u32 *)dma_block->dest_address, |
| 127 | dma_block->block_size, |
| 128 | control); |
| 129 | } else { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 130 | LOG_ERR("invalid channel direction"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 131 | status = -EINVAL; |
| 132 | } |
| 133 | |
| 134 | /* Register msgdma callback */ |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 135 | alt_msgdma_register_callback(dev_data->msgdma_dev, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 136 | nios2_msgdma_callback, |
| 137 | ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK | |
| 138 | ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK | |
| 139 | ALTERA_MSGDMA_CSR_STOP_ON_EARLY_TERMINATION_MASK, |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 140 | dev_data); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 141 | |
| 142 | /* Clear the IRQ status */ |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 143 | IOWR_ALTERA_MSGDMA_CSR_STATUS(dev_data->msgdma_dev->csr_base, |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 144 | ALTERA_MSGDMA_CSR_IRQ_SET_MASK); |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 145 | k_sem_give(&dev_data->sem_lock); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 146 | |
| 147 | return status; |
| 148 | } |
| 149 | |
Tomasz Bursztyka | e18fcbb | 2020-04-30 20:33:38 +0200 | [diff] [blame] | 150 | static int nios2_msgdma_transfer_start(const struct device *dev, |
| 151 | uint32_t channel) |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 152 | { |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 153 | struct nios2_msgdma_dev_data *cfg = (struct nios2_msgdma_dev_data *)dev->data; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 154 | int status; |
| 155 | |
Nazar Kazakov | f483b1b | 2022-03-16 21:07:43 +0000 | [diff] [blame] | 156 | /* Nios-II MSGDMA supports only one channel per DMA core */ |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 157 | if (channel != 0U) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 158 | LOG_ERR("Invalid channel number"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 159 | return -EINVAL; |
| 160 | } |
| 161 | |
| 162 | k_sem_take(&cfg->sem_lock, K_FOREVER); |
| 163 | status = alt_msgdma_standard_descriptor_async_transfer(cfg->msgdma_dev, |
| 164 | &cfg->desc); |
| 165 | k_sem_give(&cfg->sem_lock); |
| 166 | |
| 167 | if (status < 0) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 168 | LOG_ERR("DMA transfer error (%d)", status); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | return status; |
| 172 | } |
| 173 | |
Tomasz Bursztyka | e18fcbb | 2020-04-30 20:33:38 +0200 | [diff] [blame] | 174 | static int nios2_msgdma_transfer_stop(const struct device *dev, |
| 175 | uint32_t channel) |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 176 | { |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 177 | struct nios2_msgdma_dev_data *cfg = (struct nios2_msgdma_dev_data *)dev->data; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 178 | int ret = -EIO; |
Kumar Gala | a1b77fd | 2020-05-27 11:26:57 -0500 | [diff] [blame] | 179 | uint32_t status; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 180 | |
| 181 | k_sem_take(&cfg->sem_lock, K_FOREVER); |
| 182 | /* Stop the DMA Dispatcher */ |
| 183 | IOWR_ALTERA_MSGDMA_CSR_CONTROL(cfg->msgdma_dev->csr_base, |
| 184 | ALTERA_MSGDMA_CSR_STOP_MASK); |
| 185 | |
| 186 | status = IORD_ALTERA_MSGDMA_CSR_STATUS(cfg->msgdma_dev->csr_base); |
| 187 | k_sem_give(&cfg->sem_lock); |
| 188 | |
| 189 | if (status & ALTERA_MSGDMA_CSR_STOP_STATE_MASK) { |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 190 | LOG_DBG("DMA Dispatcher stopped"); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 191 | ret = 0; |
| 192 | } |
| 193 | |
Anas Nashif | 07ff2d5 | 2018-09-17 14:47:17 -0500 | [diff] [blame] | 194 | LOG_DBG("msgdma csr status Reg: 0x%x", status); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 195 | |
| 196 | return status; |
| 197 | } |
| 198 | |
| 199 | static const struct dma_driver_api nios2_msgdma_driver_api = { |
| 200 | .config = nios2_msgdma_config, |
| 201 | .start = nios2_msgdma_transfer_start, |
| 202 | .stop = nios2_msgdma_transfer_stop, |
| 203 | }; |
| 204 | |
Tomasz Bursztyka | e18fcbb | 2020-04-30 20:33:38 +0200 | [diff] [blame] | 205 | static int nios2_msgdma0_initialize(const struct device *dev) |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 206 | { |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 207 | struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data; |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 208 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 209 | dev_data->dev = dev; |
Tomasz Bursztyka | d1aee6b | 2020-07-08 10:23:21 +0200 | [diff] [blame] | 210 | |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 211 | /* Initialize semaphore */ |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 212 | k_sem_init(&dev_data->sem_lock, 1, 1); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 213 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 214 | alt_msgdma_init(dev_data->msgdma_dev, 0, DT_INST_IRQN(0)); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 215 | |
Kumar Gala | c308c4b1 | 2021-03-02 19:59:51 -0600 | [diff] [blame] | 216 | IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), |
Kumar Gala | b60b4be | 2021-03-01 15:56:27 -0600 | [diff] [blame] | 217 | nios2_msgdma_isr, DEVICE_DT_INST_GET(0), 0); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 218 | |
Kumar Gala | b60b4be | 2021-03-01 15:56:27 -0600 | [diff] [blame] | 219 | irq_enable(DT_INST_IRQN(0)); |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 220 | |
| 221 | return 0; |
| 222 | } |
| 223 | |
| 224 | ALTERA_MSGDMA_CSR_DESCRIPTOR_SLAVE_INSTANCE(MSGDMA_0, MSGDMA_0_CSR, |
| 225 | MSGDMA_0_DESCRIPTOR_SLAVE, msgdma_dev0) |
| 226 | |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 227 | static struct nios2_msgdma_dev_data dma0_nios2_data = { |
Ramakrishna Pallala | 15447fa | 2018-05-03 19:24:21 +0530 | [diff] [blame] | 228 | .msgdma_dev = &msgdma_dev0, |
| 229 | }; |
| 230 | |
Kumar Gala | b60b4be | 2021-03-01 15:56:27 -0600 | [diff] [blame] | 231 | DEVICE_DT_INST_DEFINE(0, &nios2_msgdma0_initialize, |
Tom Burdick | ad2799e | 2022-03-08 10:26:51 -0600 | [diff] [blame] | 232 | NULL, &dma0_nios2_data, NULL, POST_KERNEL, |
Maureen Helm | b539699 | 2021-10-28 13:49:26 -0500 | [diff] [blame] | 233 | CONFIG_DMA_INIT_PRIORITY, &nios2_msgdma_driver_api); |