blob: 3a38ac501e8594d1f473a401b15822ba9ab89a45 [file] [log] [blame]
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +05301/*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
Kumar Galab60b4be2021-03-01 15:56:27 -06007#define DT_DRV_COMPAT altr_msgdma
8
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +02009#include <zephyr/device.h>
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053010#include <errno.h>
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020011#include <zephyr/init.h>
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053012#include <string.h>
13#include <soc.h>
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020014#include <zephyr/drivers/dma.h>
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053015#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-Paretasfb60aab2022-05-06 10:25:46 +020020#include <zephyr/logging/log.h>
Tom Burdickad2799e2022-03-08 10:26:51 -060021LOG_MODULE_REGISTER(dma_nios2, CONFIG_DMA_LOG_LEVEL);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053022
23/* Device configuration parameters */
Tom Burdickad2799e2022-03-08 10:26:51 -060024struct nios2_msgdma_dev_data {
Tomasz Bursztykad1aee6b2020-07-08 10:23:21 +020025 const struct device *dev;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053026 alt_msgdma_dev *msgdma_dev;
27 alt_msgdma_standard_descriptor desc;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050028 uint32_t direction;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053029 struct k_sem sem_lock;
Tomasz Bursztyka15807682020-07-29 09:02:03 +020030 void *user_data;
Tomasz Bursztyka3a3f10c2020-07-29 08:55:43 +020031 dma_callback_t dma_callback;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053032};
33
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053034static void nios2_msgdma_isr(void *arg)
35{
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020036 const struct device *dev = (const struct device *)arg;
Tom Burdickad2799e2022-03-08 10:26:51 -060037 struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053038
39 /* Call Altera HAL driver ISR */
Tom Burdickad2799e2022-03-08 10:26:51 -060040 alt_handle_irq(dev_data->msgdma_dev, DT_INST_IRQN(0));
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053041}
42
43static void nios2_msgdma_callback(void *context)
44{
Tom Burdickad2799e2022-03-08 10:26:51 -060045 struct nios2_msgdma_dev_data *dev_data =
46 (struct nios2_msgdma_dev_data *)context;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053047 int err_code;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050048 uint32_t status;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053049
Tom Burdickad2799e2022-03-08 10:26:51 -060050 status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev_data->msgdma_dev->csr_base);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053051
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 Nashif07ff2d52018-09-17 14:47:17 -050060 LOG_DBG("msgdma csr status Reg: 0x%x", status);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053061
Tom Burdickad2799e2022-03-08 10:26:51 -060062 dev_data->dma_callback(dev_data->dev, dev_data->user_data, 0, err_code);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053063}
64
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020065static int nios2_msgdma_config(const struct device *dev, uint32_t channel,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053066 struct dma_config *cfg)
67{
Tom Burdickad2799e2022-03-08 10:26:51 -060068 struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053069 struct dma_block_config *dma_block;
70 int status;
Kumar Galaa1b77fd2020-05-27 11:26:57 -050071 uint32_t control;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053072
73 /* Nios-II MSGDMA supports only one channel per DMA core */
Patrik Flykt24d71432019-03-26 19:57:45 -060074 if (channel != 0U) {
Anas Nashif07ff2d52018-09-17 14:47:17 -050075 LOG_ERR("invalid channel number");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053076 return -EINVAL;
77 }
78
79#if MSGDMA_0_CSR_PREFETCHER_ENABLE
80 if (cfg->block_count > 1) {
Anas Nashif07ff2d52018-09-17 14:47:17 -050081 LOG_ERR("driver yet add support multiple descriptors");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053082 return -EINVAL;
83 }
84#else
Patrik Flykt24d71432019-03-26 19:57:45 -060085 if (cfg->block_count != 1U) {
Anas Nashif07ff2d52018-09-17 14:47:17 -050086 LOG_ERR("invalid block count!!");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053087 return -EINVAL;
88 }
89#endif
90
91 if (cfg->head_block == NULL) {
Anas Nashif07ff2d52018-09-17 14:47:17 -050092 LOG_ERR("head_block ptr NULL!!");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053093 return -EINVAL;
94 }
95
96 if (cfg->head_block->block_size > MSGDMA_0_DESCRIPTOR_SLAVE_MAX_BYTE) {
Anas Nashif07ff2d52018-09-17 14:47:17 -050097 LOG_ERR("DMA error: Data size too big: %d",
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +053098 cfg->head_block->block_size);
99 return -EINVAL;
100 }
101
Tom Burdickad2799e2022-03-08 10:26:51 -0600102 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 Pallala15447fa2018-05-03 19:24:21 +0530106 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 Burdickad2799e2022-03-08 10:26:51 -0600110 if (dev_data->direction == MEMORY_TO_MEMORY) {
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530111 status = alt_msgdma_construct_standard_mm_to_mm_descriptor(
Tom Burdickad2799e2022-03-08 10:26:51 -0600112 dev_data->msgdma_dev, &dev_data->desc,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530113 (alt_u32 *)dma_block->source_address,
114 (alt_u32 *)dma_block->dest_address,
115 dma_block->block_size,
116 control);
Tom Burdickad2799e2022-03-08 10:26:51 -0600117 } else if (dev_data->direction == MEMORY_TO_PERIPHERAL) {
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530118 status = alt_msgdma_construct_standard_mm_to_st_descriptor(
Tom Burdickad2799e2022-03-08 10:26:51 -0600119 dev_data->msgdma_dev, &dev_data->desc,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530120 (alt_u32 *)dma_block->source_address,
121 dma_block->block_size,
122 control);
Tom Burdickad2799e2022-03-08 10:26:51 -0600123 } else if (dev_data->direction == PERIPHERAL_TO_MEMORY) {
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530124 status = alt_msgdma_construct_standard_st_to_mm_descriptor(
Tom Burdickad2799e2022-03-08 10:26:51 -0600125 dev_data->msgdma_dev, &dev_data->desc,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530126 (alt_u32 *)dma_block->dest_address,
127 dma_block->block_size,
128 control);
129 } else {
Anas Nashif07ff2d52018-09-17 14:47:17 -0500130 LOG_ERR("invalid channel direction");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530131 status = -EINVAL;
132 }
133
134 /* Register msgdma callback */
Tom Burdickad2799e2022-03-08 10:26:51 -0600135 alt_msgdma_register_callback(dev_data->msgdma_dev,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530136 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 Burdickad2799e2022-03-08 10:26:51 -0600140 dev_data);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530141
142 /* Clear the IRQ status */
Tom Burdickad2799e2022-03-08 10:26:51 -0600143 IOWR_ALTERA_MSGDMA_CSR_STATUS(dev_data->msgdma_dev->csr_base,
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530144 ALTERA_MSGDMA_CSR_IRQ_SET_MASK);
Tom Burdickad2799e2022-03-08 10:26:51 -0600145 k_sem_give(&dev_data->sem_lock);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530146
147 return status;
148}
149
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200150static int nios2_msgdma_transfer_start(const struct device *dev,
151 uint32_t channel)
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530152{
Tom Burdickad2799e2022-03-08 10:26:51 -0600153 struct nios2_msgdma_dev_data *cfg = (struct nios2_msgdma_dev_data *)dev->data;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530154 int status;
155
Nazar Kazakovf483b1b2022-03-16 21:07:43 +0000156 /* Nios-II MSGDMA supports only one channel per DMA core */
Patrik Flykt24d71432019-03-26 19:57:45 -0600157 if (channel != 0U) {
Anas Nashif07ff2d52018-09-17 14:47:17 -0500158 LOG_ERR("Invalid channel number");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530159 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 Nashif07ff2d52018-09-17 14:47:17 -0500168 LOG_ERR("DMA transfer error (%d)", status);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530169 }
170
171 return status;
172}
173
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200174static int nios2_msgdma_transfer_stop(const struct device *dev,
175 uint32_t channel)
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530176{
Tom Burdickad2799e2022-03-08 10:26:51 -0600177 struct nios2_msgdma_dev_data *cfg = (struct nios2_msgdma_dev_data *)dev->data;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530178 int ret = -EIO;
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500179 uint32_t status;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530180
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 Nashif07ff2d52018-09-17 14:47:17 -0500190 LOG_DBG("DMA Dispatcher stopped");
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530191 ret = 0;
192 }
193
Anas Nashif07ff2d52018-09-17 14:47:17 -0500194 LOG_DBG("msgdma csr status Reg: 0x%x", status);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530195
196 return status;
197}
198
199static 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 Bursztykae18fcbb2020-04-30 20:33:38 +0200205static int nios2_msgdma0_initialize(const struct device *dev)
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530206{
Tom Burdickad2799e2022-03-08 10:26:51 -0600207 struct nios2_msgdma_dev_data *dev_data = (struct nios2_msgdma_dev_data *)dev->data;
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530208
Tom Burdickad2799e2022-03-08 10:26:51 -0600209 dev_data->dev = dev;
Tomasz Bursztykad1aee6b2020-07-08 10:23:21 +0200210
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530211 /* Initialize semaphore */
Tom Burdickad2799e2022-03-08 10:26:51 -0600212 k_sem_init(&dev_data->sem_lock, 1, 1);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530213
Tom Burdickad2799e2022-03-08 10:26:51 -0600214 alt_msgdma_init(dev_data->msgdma_dev, 0, DT_INST_IRQN(0));
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530215
Kumar Galac308c4b12021-03-02 19:59:51 -0600216 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
Kumar Galab60b4be2021-03-01 15:56:27 -0600217 nios2_msgdma_isr, DEVICE_DT_INST_GET(0), 0);
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530218
Kumar Galab60b4be2021-03-01 15:56:27 -0600219 irq_enable(DT_INST_IRQN(0));
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530220
221 return 0;
222}
223
224ALTERA_MSGDMA_CSR_DESCRIPTOR_SLAVE_INSTANCE(MSGDMA_0, MSGDMA_0_CSR,
225 MSGDMA_0_DESCRIPTOR_SLAVE, msgdma_dev0)
226
Tom Burdickad2799e2022-03-08 10:26:51 -0600227static struct nios2_msgdma_dev_data dma0_nios2_data = {
Ramakrishna Pallala15447fa2018-05-03 19:24:21 +0530228 .msgdma_dev = &msgdma_dev0,
229};
230
Kumar Galab60b4be2021-03-01 15:56:27 -0600231DEVICE_DT_INST_DEFINE(0, &nios2_msgdma0_initialize,
Tom Burdickad2799e2022-03-08 10:26:51 -0600232 NULL, &dma0_nios2_data, NULL, POST_KERNEL,
Maureen Helmb5396992021-10-28 13:49:26 -0500233 CONFIG_DMA_INIT_PRIORITY, &nios2_msgdma_driver_api);