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