1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT snps_designware_dma
8
9 #include <errno.h>
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <zephyr/init.h>
16 #include <zephyr/drivers/dma.h>
17 #include <soc.h>
18 #include "dma_dw_common.h"
19
20 #include <zephyr/logging/log.h>
21 #include <zephyr/irq.h>
22 LOG_MODULE_REGISTER(dma_dw, CONFIG_DMA_LOG_LEVEL);
23
24 /* Device constant configuration parameters */
25 struct dw_dma_cfg {
26 struct dw_dma_dev_cfg dw_cfg;
27 void (*irq_config)(void);
28 };
29
dw_dma_init(const struct device * dev)30 static int dw_dma_init(const struct device *dev)
31 {
32 const struct dw_dma_cfg *const dev_cfg = dev->config;
33
34 /* Disable all channels and Channel interrupts */
35 int ret = dw_dma_setup(dev);
36
37 if (ret != 0) {
38 LOG_ERR("failed to initialize DW DMA %s", dev->name);
39 goto out;
40 }
41
42 /* Configure interrupts */
43 dev_cfg->irq_config();
44
45 LOG_INF("Device %s initialized", dev->name);
46
47 out:
48 return ret;
49 }
50
51 static DEVICE_API(dma, dw_dma_driver_api) = {
52 .config = dw_dma_config,
53 .start = dw_dma_start,
54 .stop = dw_dma_stop,
55 };
56
57 #define DW_DMAC_INIT(inst) \
58 \
59 static struct dw_drv_plat_data dmac##inst = { \
60 .chan[0] = { \
61 .class = 6, \
62 .weight = 0, \
63 }, \
64 .chan[1] = { \
65 .class = 6, \
66 .weight = 0, \
67 }, \
68 .chan[2] = { \
69 .class = 6, \
70 .weight = 0, \
71 }, \
72 .chan[3] = { \
73 .class = 6, \
74 .weight = 0, \
75 }, \
76 .chan[4] = { \
77 .class = 6, \
78 .weight = 0, \
79 }, \
80 .chan[5] = { \
81 .class = 6, \
82 .weight = 0, \
83 }, \
84 .chan[6] = { \
85 .class = 6, \
86 .weight = 0, \
87 }, \
88 .chan[7] = { \
89 .class = 6, \
90 .weight = 0, \
91 }, \
92 }; \
93 \
94 static void dw_dma##inst##_irq_config(void); \
95 \
96 static const struct dw_dma_cfg dw_dma##inst##_config = { \
97 .dw_cfg = { \
98 .base = DT_INST_REG_ADDR(inst), \
99 }, \
100 .irq_config = dw_dma##inst##_irq_config \
101 }; \
102 \
103 static struct dw_dma_dev_data dw_dma##inst##_data = { \
104 .channel_data = &dmac##inst, \
105 }; \
106 \
107 DEVICE_DT_INST_DEFINE(inst, \
108 &dw_dma_init, \
109 NULL, \
110 &dw_dma##inst##_data, \
111 &dw_dma##inst##_config, POST_KERNEL, \
112 CONFIG_DMA_INIT_PRIORITY, \
113 &dw_dma_driver_api); \
114 \
115 static void dw_dma##inst##_irq_config(void) \
116 { \
117 IRQ_CONNECT(DT_INST_IRQN(inst), \
118 DT_INST_IRQ(inst, priority), dw_dma_isr, \
119 DEVICE_DT_INST_GET(inst), \
120 DT_INST_IRQ(inst, sense)); \
121 irq_enable(DT_INST_IRQN(inst)); \
122 }
123
124 DT_INST_FOREACH_STATUS_OKAY(DW_DMAC_INIT)
125