1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT nordic_nrf_can
7 
8 #include <stdint.h>
9 
10 #include <zephyr/arch/cpu.h>
11 #include <zephyr/device.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/drivers/can.h>
14 #include <zephyr/drivers/can/can_mcan.h>
15 #include <zephyr/drivers/clock_control.h>
16 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
17 #include <zephyr/drivers/pinctrl.h>
18 #include <zephyr/irq.h>
19 
20 #ifdef CONFIG_SOC_NRF54H20_GPD
21 #include <nrf/gpd.h>
22 #endif
23 
24 /* nRF CAN wrapper offsets */
25 #define CAN_TASKS_START	  offsetof(NRF_CAN_Type, TASKS_START)
26 #define CAN_EVENTS_CORE_0 offsetof(NRF_CAN_Type, EVENTS_CORE[0])
27 #define CAN_EVENTS_CORE_1 offsetof(NRF_CAN_Type, EVENTS_CORE[1])
28 #define CAN_INTEN	  offsetof(NRF_CAN_Type, INTEN)
29 
30 struct can_nrf_config {
31 	uint32_t wrapper;
32 	uint32_t mcan;
33 	uint32_t mrba;
34 	uint32_t mram;
35 	const struct device *auxpll;
36 	const struct device *hsfll;
37 	const struct pinctrl_dev_config *pcfg;
38 	void (*irq_configure)(void);
39 	uint16_t irq;
40 };
41 
can_nrf_irq_handler(const struct device * dev)42 static void can_nrf_irq_handler(const struct device *dev)
43 {
44 	const struct can_mcan_config *mcan_config = dev->config;
45 	const struct can_nrf_config *config = mcan_config->custom;
46 
47 	if (sys_read32(config->wrapper + CAN_EVENTS_CORE_0) == 1U) {
48 		sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_0);
49 		can_mcan_line_0_isr(dev);
50 	}
51 
52 	if (sys_read32(config->wrapper + CAN_EVENTS_CORE_1) == 1U) {
53 		sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_1);
54 		can_mcan_line_1_isr(dev);
55 	}
56 }
57 
can_nrf_get_core_clock(const struct device * dev,uint32_t * rate)58 static int can_nrf_get_core_clock(const struct device *dev, uint32_t *rate)
59 {
60 	const struct can_mcan_config *mcan_config = dev->config;
61 	const struct can_nrf_config *config = mcan_config->custom;
62 
63 	return clock_control_get_rate(config->auxpll, NULL, rate);
64 }
65 
66 static DEVICE_API(can, can_nrf_api) = {
67 	.get_capabilities = can_mcan_get_capabilities,
68 	.start = can_mcan_start,
69 	.stop = can_mcan_stop,
70 	.set_mode = can_mcan_set_mode,
71 	.set_timing = can_mcan_set_timing,
72 	.send = can_mcan_send,
73 	.add_rx_filter = can_mcan_add_rx_filter,
74 	.remove_rx_filter = can_mcan_remove_rx_filter,
75 	.get_state = can_mcan_get_state,
76 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
77 	.recover = can_mcan_recover,
78 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
79 	.get_core_clock = can_nrf_get_core_clock,
80 	.get_max_filters = can_mcan_get_max_filters,
81 	.set_state_change_callback = can_mcan_set_state_change_callback,
82 	.timing_min = CAN_MCAN_TIMING_MIN_INITIALIZER,
83 	.timing_max = CAN_MCAN_TIMING_MAX_INITIALIZER,
84 #ifdef CONFIG_CAN_FD_MODE
85 	.set_timing_data = can_mcan_set_timing_data,
86 	.timing_data_min = CAN_MCAN_TIMING_DATA_MIN_INITIALIZER,
87 	.timing_data_max = CAN_MCAN_TIMING_DATA_MAX_INITIALIZER,
88 #endif /* CONFIG_CAN_FD_MODE */
89 };
90 
can_nrf_read_reg(const struct device * dev,uint16_t reg,uint32_t * val)91 static int can_nrf_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
92 {
93 	const struct can_mcan_config *mcan_config = dev->config;
94 	const struct can_nrf_config *config = mcan_config->custom;
95 
96 	return can_mcan_sys_read_reg(config->mcan, reg, val);
97 }
98 
can_nrf_write_reg(const struct device * dev,uint16_t reg,uint32_t val)99 static int can_nrf_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
100 {
101 	const struct can_mcan_config *mcan_config = dev->config;
102 	const struct can_nrf_config *config = mcan_config->custom;
103 
104 	return can_mcan_sys_write_reg(config->mcan, reg, val);
105 }
106 
can_nrf_read_mram(const struct device * dev,uint16_t offset,void * dst,size_t len)107 static int can_nrf_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
108 {
109 	const struct can_mcan_config *mcan_config = dev->config;
110 	const struct can_nrf_config *config = mcan_config->custom;
111 
112 	return can_mcan_sys_read_mram(config->mram, offset, dst, len);
113 }
114 
can_nrf_write_mram(const struct device * dev,uint16_t offset,const void * src,size_t len)115 static int can_nrf_write_mram(const struct device *dev, uint16_t offset, const void *src,
116 			      size_t len)
117 {
118 	const struct can_mcan_config *mcan_config = dev->config;
119 	const struct can_nrf_config *config = mcan_config->custom;
120 
121 	return can_mcan_sys_write_mram(config->mram, offset, src, len);
122 }
123 
can_nrf_clear_mram(const struct device * dev,uint16_t offset,size_t len)124 static int can_nrf_clear_mram(const struct device *dev, uint16_t offset, size_t len)
125 {
126 	const struct can_mcan_config *mcan_config = dev->config;
127 	const struct can_nrf_config *config = mcan_config->custom;
128 
129 	return can_mcan_sys_clear_mram(config->mram, offset, len);
130 }
131 
132 static const struct can_mcan_ops can_mcan_nrf_ops = {
133 	.read_reg = can_nrf_read_reg,
134 	.write_reg = can_nrf_write_reg,
135 	.read_mram = can_nrf_read_mram,
136 	.write_mram = can_nrf_write_mram,
137 	.clear_mram = can_nrf_clear_mram,
138 };
139 
configure_hsfll(const struct device * dev,bool on)140 static int configure_hsfll(const struct device *dev, bool on)
141 {
142 	const struct can_mcan_config *mcan_config = dev->config;
143 	const struct can_nrf_config *config = mcan_config->custom;
144 	struct nrf_clock_spec spec = { 0 };
145 
146 	/* If CAN is on, HSFLL frequency >= AUXPLL frequency */
147 	if (on) {
148 		int ret;
149 
150 		ret = clock_control_get_rate(dev, NULL, &spec.frequency);
151 		if (ret < 0) {
152 			return ret;
153 		}
154 	}
155 
156 	return nrf_clock_control_request_sync(config->hsfll, &spec, K_FOREVER);
157 }
158 
can_nrf_init(const struct device * dev)159 static int can_nrf_init(const struct device *dev)
160 {
161 	const struct can_mcan_config *mcan_config = dev->config;
162 	const struct can_nrf_config *config = mcan_config->custom;
163 	int ret;
164 
165 	if (!device_is_ready(config->auxpll) || !device_is_ready(config->hsfll)) {
166 		return -ENODEV;
167 	}
168 
169 	ret = configure_hsfll(dev, true);
170 	if (ret < 0) {
171 		return ret;
172 	}
173 
174 	ret = clock_control_on(config->auxpll, NULL);
175 	if (ret < 0) {
176 		return ret;
177 	}
178 
179 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
180 	if (ret < 0) {
181 		return ret;
182 	}
183 
184 
185 	sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_0);
186 	sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_1);
187 	sys_write32(CAN_INTEN_CORE0_Msk | CAN_INTEN_CORE1_Msk, config->wrapper + CAN_INTEN);
188 	sys_write32(1U, config->wrapper + CAN_TASKS_START);
189 
190 #ifdef CONFIG_SOC_NRF54H20_GPD
191 	ret = nrf_gpd_retain_pins_set(config->pcfg, false);
192 	if (ret < 0) {
193 		return ret;
194 	}
195 #endif
196 
197 	config->irq_configure();
198 
199 	ret = can_mcan_configure_mram(dev, config->mrba, config->mram);
200 	if (ret < 0) {
201 		return ret;
202 	}
203 
204 	ret = can_mcan_init(dev);
205 	if (ret < 0) {
206 		return ret;
207 	}
208 
209 	return 0;
210 }
211 
212 #define CAN_NRF_DEFINE(n)                                                                          \
213 	PINCTRL_DT_INST_DEFINE(n);                                                                 \
214                                                                                                    \
215 	static inline void can_nrf_irq_configure##n(void)                                          \
216 	{                                                                                          \
217 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), can_nrf_irq_handler,        \
218 			    DEVICE_DT_INST_GET(n), 0);                                             \
219 		irq_enable(DT_INST_IRQN(n));                                                       \
220 	}                                                                                          \
221                                                                                                    \
222 	static const struct can_nrf_config can_nrf_config##n = {                                   \
223 		.wrapper = DT_INST_REG_ADDR_BY_NAME(n, wrapper),                                   \
224 		.mcan = CAN_MCAN_DT_INST_MCAN_ADDR(n),                                             \
225 		.mrba = CAN_MCAN_DT_INST_MRBA(n),                                                  \
226 		.mram = CAN_MCAN_DT_INST_MRAM_ADDR(n),                                             \
227 		.auxpll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, auxpll)),                   \
228 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),                                         \
229 		.hsfll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, hsfll)),                     \
230 		.irq = DT_INST_IRQN(n),                                                            \
231 		.irq_configure = can_nrf_irq_configure##n,                                         \
232 	};                                                                                         \
233                                                                                                    \
234 	CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, can_mcan_nrf_cbs##n);                                 \
235                                                                                                    \
236 	static const struct can_mcan_config can_mcan_nrf_config##n = CAN_MCAN_DT_CONFIG_INST_GET(  \
237 		n, &can_nrf_config##n, &can_mcan_nrf_ops, &can_mcan_nrf_cbs##n);                   \
238                                                                                                    \
239 	static struct can_mcan_data can_mcan_nrf_data##n = CAN_MCAN_DATA_INITIALIZER(NULL);        \
240                                                                                                    \
241 	DEVICE_DT_INST_DEFINE(n, can_nrf_init, NULL, &can_mcan_nrf_data##n,                        \
242 			      &can_mcan_nrf_config##n, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,      \
243 			      &can_nrf_api);
244 
245 DT_INST_FOREACH_STATUS_OKAY(CAN_NRF_DEFINE)
246