1 /*
2  * Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <zephyr/drivers/can.h>
9 #include <zephyr/drivers/can/can_mcan.h>
10 #include <zephyr/drivers/clock_control.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/irq.h>
14 #include <zephyr/drivers/reset.h>
15 
16 LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL);
17 
18 #define DT_DRV_COMPAT nxp_lpc_mcan
19 
20 /* Message RAM Base Address register */
21 #define MCUX_MCAN_MRBA	 0x200
22 #define MCUX_MCAN_MRBA_BA GENMASK(31, 16)
23 
24 struct mcux_mcan_config {
25 	mm_reg_t base;
26 	mem_addr_t mram;
27 	const struct device *clock_dev;
28 	clock_control_subsys_t clock_subsys;
29 	void (*irq_config_func)(const struct device *dev);
30 	const struct pinctrl_dev_config *pincfg;
31 	const struct reset_dt_spec reset;
32 };
33 
mcux_mcan_read_reg(const struct device * dev,uint16_t reg,uint32_t * val)34 static int mcux_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
35 {
36 	const struct can_mcan_config *mcan_config = dev->config;
37 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
38 
39 	return can_mcan_sys_read_reg(mcux_config->base, reg, val);
40 }
41 
mcux_mcan_write_reg(const struct device * dev,uint16_t reg,uint32_t val)42 static int mcux_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
43 {
44 	const struct can_mcan_config *mcan_config = dev->config;
45 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
46 
47 	return can_mcan_sys_write_reg(mcux_config->base, reg, val);
48 }
49 
mcux_mcan_read_mram(const struct device * dev,uint16_t offset,void * dst,size_t len)50 static int mcux_mcan_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
51 {
52 	const struct can_mcan_config *mcan_config = dev->config;
53 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
54 
55 	return can_mcan_sys_read_mram(mcux_config->mram, offset, dst, len);
56 }
57 
mcux_mcan_write_mram(const struct device * dev,uint16_t offset,const void * src,size_t len)58 static int mcux_mcan_write_mram(const struct device *dev, uint16_t offset, const void *src,
59 				size_t len)
60 {
61 	const struct can_mcan_config *mcan_config = dev->config;
62 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
63 
64 	return can_mcan_sys_write_mram(mcux_config->mram, offset, src, len);
65 }
66 
mcux_mcan_clear_mram(const struct device * dev,uint16_t offset,size_t len)67 static int mcux_mcan_clear_mram(const struct device *dev, uint16_t offset, size_t len)
68 {
69 	const struct can_mcan_config *mcan_config = dev->config;
70 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
71 
72 	return can_mcan_sys_clear_mram(mcux_config->mram, offset, len);
73 }
74 
mcux_mcan_get_core_clock(const struct device * dev,uint32_t * rate)75 static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
76 {
77 	const struct can_mcan_config *mcan_config = dev->config;
78 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
79 
80 	return clock_control_get_rate(mcux_config->clock_dev, mcux_config->clock_subsys,
81 				      rate);
82 }
83 
mcux_mcan_init(const struct device * dev)84 static int mcux_mcan_init(const struct device *dev)
85 {
86 	const struct can_mcan_config *mcan_config = dev->config;
87 	const struct mcux_mcan_config *mcux_config = mcan_config->custom;
88 	const uintptr_t mrba = mcux_config->mram & MCUX_MCAN_MRBA_BA;
89 	int err;
90 
91 	if (!device_is_ready(mcux_config->clock_dev)) {
92 		LOG_ERR("clock control device not ready");
93 		return -ENODEV;
94 	}
95 
96 	if (!device_is_ready(mcux_config->reset.dev)) {
97 		LOG_ERR("Reset device not ready");
98 		return -ENODEV;
99 	}
100 
101 	err = reset_line_toggle(mcux_config->reset.dev, mcux_config->reset.id);
102 	if (err) {
103 		return err;
104 	}
105 
106 	err = pinctrl_apply_state(mcux_config->pincfg, PINCTRL_STATE_DEFAULT);
107 	if (err) {
108 		return err;
109 	}
110 
111 	err = clock_control_on(mcux_config->clock_dev, mcux_config->clock_subsys);
112 	if (err) {
113 		LOG_ERR("failed to enable clock (err %d)", err);
114 		return -EINVAL;
115 	}
116 
117 	err = can_mcan_write_reg(dev, MCUX_MCAN_MRBA, (uint32_t)mrba);
118 	if (err != 0) {
119 		return -EIO;
120 	}
121 
122 	err = can_mcan_configure_mram(dev, mrba, mcux_config->mram);
123 	if (err != 0) {
124 		return -EIO;
125 	}
126 
127 	err = can_mcan_init(dev);
128 	if (err) {
129 		LOG_ERR("failed to initialize mcan (err %d)", err);
130 		return err;
131 	}
132 
133 	mcux_config->irq_config_func(dev);
134 
135 	return 0;
136 }
137 
138 static DEVICE_API(can, mcux_mcan_driver_api) = {
139 	.get_capabilities = can_mcan_get_capabilities,
140 	.start = can_mcan_start,
141 	.stop = can_mcan_stop,
142 	.set_mode = can_mcan_set_mode,
143 	.set_timing = can_mcan_set_timing,
144 	.send = can_mcan_send,
145 	.add_rx_filter = can_mcan_add_rx_filter,
146 	.remove_rx_filter = can_mcan_remove_rx_filter,
147 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
148 	.recover = can_mcan_recover,
149 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
150 	.get_state = can_mcan_get_state,
151 	.set_state_change_callback = can_mcan_set_state_change_callback,
152 	.get_core_clock = mcux_mcan_get_core_clock,
153 	.get_max_filters = can_mcan_get_max_filters,
154 	/*
155 	 * MCUX MCAN timing limits are specified in the "Nominal bit timing and
156 	 * prescaler register (NBTP)" table in the SoC reference manual.
157 	 *
158 	 * Note that the values here are the "physical" timing limits, whereas
159 	 * the register field limits are physical values minus 1 (which is
160 	 * handled by the register assignments in the common MCAN driver code).
161 	 *
162 	 * Beware that at least some SoC reference manuals contain a bug
163 	 * regarding the minimum values for nominal phase segments. Valid
164 	 * register values are 1 and up.
165 	 */
166 	.timing_min = CAN_MCAN_TIMING_MIN_INITIALIZER,
167 	.timing_max = CAN_MCAN_TIMING_MAX_INITIALIZER,
168 #ifdef CONFIG_CAN_FD_MODE
169 	.set_timing_data = can_mcan_set_timing_data,
170 	/*
171 	 * MCUX MCAN data timing limits are specified in the "Data bit timing
172 	 * and prescaler register (DBTP)" table in the SoC reference manual.
173 	 *
174 	 * Note that the values here are the "physical" timing limits, whereas
175 	 * the register field limits are physical values minus 1 (which is
176 	 * handled by the register assignments in the common MCAN driver code).
177 	 *
178 	 * Beware that at least some SoC reference manuals contain a bug
179 	 * regarding the maximum value for data phase segment 2. Valid register
180 	 * values are 0 to 31.
181 	 */
182 	.timing_data_min = CAN_MCAN_TIMING_DATA_MIN_INITIALIZER,
183 	.timing_data_max = CAN_MCAN_TIMING_DATA_MAX_INITIALIZER,
184 #endif /* CONFIG_CAN_FD_MODE */
185 };
186 
187 static const struct can_mcan_ops mcux_mcan_ops = {
188 	.read_reg = mcux_mcan_read_reg,
189 	.write_reg = mcux_mcan_write_reg,
190 	.read_mram = mcux_mcan_read_mram,
191 	.write_mram = mcux_mcan_write_mram,
192 	.clear_mram = mcux_mcan_clear_mram,
193 };
194 
195 #define MCUX_MCAN_INIT(n)						\
196 	CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n);			\
197 	PINCTRL_DT_INST_DEFINE(n);					\
198 									\
199 	static void mcux_mcan_irq_config_##n(const struct device *dev); \
200 									\
201 	CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, mcux_mcan_cbs_##n);	\
202 	CAN_MCAN_DT_INST_MRAM_DEFINE(n, mcux_mcan_mram_##n);	\
203 									\
204 	static const struct mcux_mcan_config mcux_mcan_config_##n = {	\
205 		.base = CAN_MCAN_DT_INST_MCAN_ADDR(n),			\
206 		.mram = (mem_addr_t)POINTER_TO_UINT(&mcux_mcan_mram_##n), \
207 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),	\
208 		.clock_subsys = (clock_control_subsys_t)		\
209 			DT_INST_CLOCKS_CELL(n, name),			\
210 		.irq_config_func = mcux_mcan_irq_config_##n,		\
211 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),		\
212 		.reset = RESET_DT_SPEC_INST_GET(n),			\
213 	};								\
214 									\
215 	static const struct can_mcan_config can_mcan_config_##n =	\
216 		CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n,	\
217 					    &mcux_mcan_ops,		\
218 					    &mcux_mcan_cbs_##n);	\
219 									\
220 	static struct can_mcan_data can_mcan_data_##n =			\
221 		CAN_MCAN_DATA_INITIALIZER(NULL);			\
222 									\
223 	CAN_DEVICE_DT_INST_DEFINE(n, mcux_mcan_init, NULL,		\
224 				  &can_mcan_data_##n,			\
225 				  &can_mcan_config_##n,			\
226 				  POST_KERNEL,				\
227 				  CONFIG_CAN_INIT_PRIORITY,		\
228 				  &mcux_mcan_driver_api);		\
229 									\
230 	static void mcux_mcan_irq_config_##n(const struct device *dev)	\
231 	{								\
232 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int0, irq),		\
233 			    DT_INST_IRQ_BY_NAME(n, int0, priority),	\
234 			    can_mcan_line_0_isr,			\
235 			    DEVICE_DT_INST_GET(n), 0);			\
236 		irq_enable(DT_INST_IRQ_BY_NAME(n, int0, irq));		\
237 									\
238 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int1, irq),		\
239 			    DT_INST_IRQ_BY_NAME(n, int1, priority),	\
240 			    can_mcan_line_1_isr,			\
241 			    DEVICE_DT_INST_GET(n), 0);			\
242 		irq_enable(DT_INST_IRQ_BY_NAME(n, int1, irq));		\
243 	}
244 
245 DT_INST_FOREACH_STATUS_OKAY(MCUX_MCAN_INIT)
246