xref: /linux/drivers/net/can/m_can/tcan4x5x-core.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 // SPI to CAN driver for the Texas Instruments TCAN4x5x
3 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
4 
5 #include "tcan4x5x.h"
6 
7 #define TCAN4X5X_EXT_CLK_DEF 40000000
8 
9 #define TCAN4X5X_DEV_ID1 0x00
10 #define TCAN4X5X_DEV_ID1_TCAN 0x4e414354 /* ASCII TCAN */
11 #define TCAN4X5X_DEV_ID2 0x04
12 #define TCAN4X5X_REV 0x08
13 #define TCAN4X5X_STATUS 0x0C
14 #define TCAN4X5X_ERROR_STATUS_MASK 0x10
15 #define TCAN4X5X_CONTROL 0x14
16 
17 #define TCAN4X5X_CONFIG 0x800
18 #define TCAN4X5X_TS_PRESCALE 0x804
19 #define TCAN4X5X_TEST_REG 0x808
20 #define TCAN4X5X_INT_FLAGS 0x820
21 #define TCAN4X5X_MCAN_INT_REG 0x824
22 #define TCAN4X5X_INT_EN 0x830
23 
24 /* Interrupt bits */
25 #define TCAN4X5X_CANBUSTERMOPEN_INT_EN BIT(30)
26 #define TCAN4X5X_CANHCANL_INT_EN BIT(29)
27 #define TCAN4X5X_CANHBAT_INT_EN BIT(28)
28 #define TCAN4X5X_CANLGND_INT_EN BIT(27)
29 #define TCAN4X5X_CANBUSOPEN_INT_EN BIT(26)
30 #define TCAN4X5X_CANBUSGND_INT_EN BIT(25)
31 #define TCAN4X5X_CANBUSBAT_INT_EN BIT(24)
32 #define TCAN4X5X_UVSUP_INT_EN BIT(22)
33 #define TCAN4X5X_UVIO_INT_EN BIT(21)
34 #define TCAN4X5X_TSD_INT_EN BIT(19)
35 #define TCAN4X5X_ECCERR_INT_EN BIT(16)
36 #define TCAN4X5X_CANINT_INT_EN BIT(15)
37 #define TCAN4X5X_LWU_INT_EN BIT(14)
38 #define TCAN4X5X_CANSLNT_INT_EN BIT(10)
39 #define TCAN4X5X_CANDOM_INT_EN BIT(8)
40 #define TCAN4X5X_CANBUS_ERR_INT_EN BIT(5)
41 #define TCAN4X5X_BUS_FAULT BIT(4)
42 #define TCAN4X5X_MCAN_INT BIT(1)
43 #define TCAN4X5X_ENABLE_TCAN_INT \
44 	(TCAN4X5X_MCAN_INT | TCAN4X5X_BUS_FAULT | \
45 	 TCAN4X5X_CANBUS_ERR_INT_EN | TCAN4X5X_CANINT_INT_EN)
46 
47 /* MCAN Interrupt bits */
48 #define TCAN4X5X_MCAN_IR_ARA BIT(29)
49 #define TCAN4X5X_MCAN_IR_PED BIT(28)
50 #define TCAN4X5X_MCAN_IR_PEA BIT(27)
51 #define TCAN4X5X_MCAN_IR_WD BIT(26)
52 #define TCAN4X5X_MCAN_IR_BO BIT(25)
53 #define TCAN4X5X_MCAN_IR_EW BIT(24)
54 #define TCAN4X5X_MCAN_IR_EP BIT(23)
55 #define TCAN4X5X_MCAN_IR_ELO BIT(22)
56 #define TCAN4X5X_MCAN_IR_BEU BIT(21)
57 #define TCAN4X5X_MCAN_IR_BEC BIT(20)
58 #define TCAN4X5X_MCAN_IR_DRX BIT(19)
59 #define TCAN4X5X_MCAN_IR_TOO BIT(18)
60 #define TCAN4X5X_MCAN_IR_MRAF BIT(17)
61 #define TCAN4X5X_MCAN_IR_TSW BIT(16)
62 #define TCAN4X5X_MCAN_IR_TEFL BIT(15)
63 #define TCAN4X5X_MCAN_IR_TEFF BIT(14)
64 #define TCAN4X5X_MCAN_IR_TEFW BIT(13)
65 #define TCAN4X5X_MCAN_IR_TEFN BIT(12)
66 #define TCAN4X5X_MCAN_IR_TFE BIT(11)
67 #define TCAN4X5X_MCAN_IR_TCF BIT(10)
68 #define TCAN4X5X_MCAN_IR_TC BIT(9)
69 #define TCAN4X5X_MCAN_IR_HPM BIT(8)
70 #define TCAN4X5X_MCAN_IR_RF1L BIT(7)
71 #define TCAN4X5X_MCAN_IR_RF1F BIT(6)
72 #define TCAN4X5X_MCAN_IR_RF1W BIT(5)
73 #define TCAN4X5X_MCAN_IR_RF1N BIT(4)
74 #define TCAN4X5X_MCAN_IR_RF0L BIT(3)
75 #define TCAN4X5X_MCAN_IR_RF0F BIT(2)
76 #define TCAN4X5X_MCAN_IR_RF0W BIT(1)
77 #define TCAN4X5X_MCAN_IR_RF0N BIT(0)
78 #define TCAN4X5X_ENABLE_MCAN_INT \
79 	(TCAN4X5X_MCAN_IR_TC | TCAN4X5X_MCAN_IR_RF0N | \
80 	 TCAN4X5X_MCAN_IR_RF1N | TCAN4X5X_MCAN_IR_RF0F | \
81 	 TCAN4X5X_MCAN_IR_RF1F)
82 
83 #define TCAN4X5X_MRAM_START 0x8000
84 #define TCAN4X5X_MRAM_SIZE 0x800
85 #define TCAN4X5X_MCAN_OFFSET 0x1000
86 
87 #define TCAN4X5X_CLEAR_ALL_INT 0xffffffff
88 #define TCAN4X5X_SET_ALL_INT 0xffffffff
89 
90 #define TCAN4X5X_MODE_SEL_MASK (BIT(7) | BIT(6))
91 #define TCAN4X5X_MODE_SLEEP 0x00
92 #define TCAN4X5X_MODE_STANDBY BIT(6)
93 #define TCAN4X5X_MODE_NORMAL BIT(7)
94 
95 #define TCAN4X5X_DISABLE_WAKE_MSK	(BIT(31) | BIT(30))
96 #define TCAN4X5X_DISABLE_INH_MSK	BIT(9)
97 
98 #define TCAN4X5X_SW_RESET BIT(2)
99 
100 #define TCAN4X5X_MCAN_CONFIGURED BIT(5)
101 #define TCAN4X5X_WATCHDOG_EN BIT(3)
102 #define TCAN4X5X_WD_60_MS_TIMER 0
103 #define TCAN4X5X_WD_600_MS_TIMER BIT(28)
104 #define TCAN4X5X_WD_3_S_TIMER BIT(29)
105 #define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29))
106 
107 struct tcan4x5x_version_info {
108 	const char *name;
109 	u32 id2_register;
110 
111 	bool has_wake_pin;
112 	bool has_state_pin;
113 };
114 
115 enum {
116 	TCAN4552 = 0,
117 	TCAN4553,
118 	TCAN4X5X,
119 };
120 
121 static const struct tcan4x5x_version_info tcan4x5x_versions[] = {
122 	[TCAN4552] = {
123 		.name = "4552",
124 		.id2_register = 0x32353534,
125 	},
126 	[TCAN4553] = {
127 		.name = "4553",
128 		.id2_register = 0x33353534,
129 	},
130 	/* generic version with no id2_register at the end */
131 	[TCAN4X5X] = {
132 		.name = "generic",
133 		.has_wake_pin = true,
134 		.has_state_pin = true,
135 	},
136 };
137 
138 static inline struct tcan4x5x_priv *cdev_to_priv(struct m_can_classdev *cdev)
139 {
140 	return container_of(cdev, struct tcan4x5x_priv, cdev);
141 }
142 
143 static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
144 {
145 	int wake_state = 0;
146 
147 	if (priv->device_state_gpio)
148 		wake_state = gpiod_get_value(priv->device_state_gpio);
149 
150 	if (priv->device_wake_gpio && wake_state) {
151 		gpiod_set_value(priv->device_wake_gpio, 0);
152 		usleep_range(5, 50);
153 		gpiod_set_value(priv->device_wake_gpio, 1);
154 	}
155 }
156 
157 static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
158 {
159 	int ret = 0;
160 
161 	if (priv->reset_gpio) {
162 		gpiod_set_value(priv->reset_gpio, 1);
163 
164 		/* tpulse_width minimum 30us */
165 		usleep_range(30, 100);
166 		gpiod_set_value(priv->reset_gpio, 0);
167 	} else {
168 		ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
169 				   TCAN4X5X_SW_RESET);
170 		if (ret)
171 			return ret;
172 	}
173 
174 	usleep_range(700, 1000);
175 
176 	return ret;
177 }
178 
179 static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
180 {
181 	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
182 	u32 val;
183 
184 	regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val);
185 
186 	return val;
187 }
188 
189 static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset,
190 			      void *val, size_t val_count)
191 {
192 	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
193 
194 	return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
195 }
196 
197 static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
198 {
199 	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
200 
201 	return regmap_write(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, val);
202 }
203 
204 static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
205 			       int addr_offset, const void *val, size_t val_count)
206 {
207 	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
208 
209 	return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
210 }
211 
212 static int tcan4x5x_power_enable(struct regulator *reg, int enable)
213 {
214 	if (IS_ERR_OR_NULL(reg))
215 		return 0;
216 
217 	if (enable)
218 		return regulator_enable(reg);
219 	else
220 		return regulator_disable(reg);
221 }
222 
223 static int tcan4x5x_write_tcan_reg(struct m_can_classdev *cdev,
224 				   int reg, int val)
225 {
226 	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
227 
228 	return regmap_write(priv->regmap, reg, val);
229 }
230 
231 static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev)
232 {
233 	int ret;
234 
235 	ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_STATUS,
236 				      TCAN4X5X_CLEAR_ALL_INT);
237 	if (ret)
238 		return ret;
239 
240 	return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS,
241 				       TCAN4X5X_CLEAR_ALL_INT);
242 }
243 
244 static int tcan4x5x_init(struct m_can_classdev *cdev)
245 {
246 	struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
247 	int ret;
248 
249 	tcan4x5x_check_wake(tcan4x5x);
250 
251 	ret = tcan4x5x_clear_interrupts(cdev);
252 	if (ret)
253 		return ret;
254 
255 	ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_EN,
256 				      TCAN4X5X_ENABLE_TCAN_INT);
257 	if (ret)
258 		return ret;
259 
260 	ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS_MASK,
261 				      TCAN4X5X_CLEAR_ALL_INT);
262 	if (ret)
263 		return ret;
264 
265 	ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
266 				 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
267 	if (ret)
268 		return ret;
269 
270 	return ret;
271 }
272 
273 static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
274 {
275 	struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
276 
277 	return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
278 				  TCAN4X5X_DISABLE_WAKE_MSK, 0x00);
279 }
280 
281 static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
282 {
283 	struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
284 
285 	return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
286 				  TCAN4X5X_DISABLE_INH_MSK, 0x01);
287 }
288 
289 static const struct tcan4x5x_version_info
290 *tcan4x5x_find_version(struct tcan4x5x_priv *priv)
291 {
292 	u32 val;
293 	int ret;
294 
295 	ret = regmap_read(priv->regmap, TCAN4X5X_DEV_ID1, &val);
296 	if (ret)
297 		return ERR_PTR(ret);
298 
299 	if (val != TCAN4X5X_DEV_ID1_TCAN) {
300 		dev_err(&priv->spi->dev, "Not a tcan device %x\n", val);
301 		return ERR_PTR(-ENODEV);
302 	}
303 
304 	ret = regmap_read(priv->regmap, TCAN4X5X_DEV_ID2, &val);
305 	if (ret)
306 		return ERR_PTR(ret);
307 
308 	for (int i = 0; i != ARRAY_SIZE(tcan4x5x_versions); ++i) {
309 		const struct tcan4x5x_version_info *vinfo = &tcan4x5x_versions[i];
310 
311 		if (!vinfo->id2_register || val == vinfo->id2_register) {
312 			dev_info(&priv->spi->dev, "Detected TCAN device version %s\n",
313 				 vinfo->name);
314 			return vinfo;
315 		}
316 	}
317 
318 	return &tcan4x5x_versions[TCAN4X5X];
319 }
320 
321 static int tcan4x5x_get_gpios(struct m_can_classdev *cdev,
322 			      const struct tcan4x5x_version_info *version_info)
323 {
324 	struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
325 	int ret;
326 
327 	if (version_info->has_wake_pin) {
328 		tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
329 							    GPIOD_OUT_HIGH);
330 		if (IS_ERR(tcan4x5x->device_wake_gpio)) {
331 			if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER)
332 				return -EPROBE_DEFER;
333 
334 			tcan4x5x_disable_wake(cdev);
335 		}
336 	}
337 
338 	tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset",
339 						       GPIOD_OUT_LOW);
340 	if (IS_ERR(tcan4x5x->reset_gpio))
341 		tcan4x5x->reset_gpio = NULL;
342 
343 	ret = tcan4x5x_reset(tcan4x5x);
344 	if (ret)
345 		return ret;
346 
347 	if (version_info->has_state_pin) {
348 		tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
349 								      "device-state",
350 								      GPIOD_IN);
351 		if (IS_ERR(tcan4x5x->device_state_gpio)) {
352 			tcan4x5x->device_state_gpio = NULL;
353 			tcan4x5x_disable_state(cdev);
354 		}
355 	}
356 
357 	return 0;
358 }
359 
360 static const struct m_can_ops tcan4x5x_ops = {
361 	.init = tcan4x5x_init,
362 	.read_reg = tcan4x5x_read_reg,
363 	.write_reg = tcan4x5x_write_reg,
364 	.write_fifo = tcan4x5x_write_fifo,
365 	.read_fifo = tcan4x5x_read_fifo,
366 	.clear_interrupts = tcan4x5x_clear_interrupts,
367 };
368 
369 static int tcan4x5x_can_probe(struct spi_device *spi)
370 {
371 	const struct tcan4x5x_version_info *version_info;
372 	struct tcan4x5x_priv *priv;
373 	struct m_can_classdev *mcan_class;
374 	int freq, ret;
375 
376 	mcan_class = m_can_class_allocate_dev(&spi->dev,
377 					      sizeof(struct tcan4x5x_priv));
378 	if (!mcan_class)
379 		return -ENOMEM;
380 
381 	ret = m_can_check_mram_cfg(mcan_class, TCAN4X5X_MRAM_SIZE);
382 	if (ret)
383 		goto out_m_can_class_free_dev;
384 
385 	priv = cdev_to_priv(mcan_class);
386 
387 	priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
388 	if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
389 		ret = -EPROBE_DEFER;
390 		goto out_m_can_class_free_dev;
391 	} else {
392 		priv->power = NULL;
393 	}
394 
395 	m_can_class_get_clocks(mcan_class);
396 	if (IS_ERR(mcan_class->cclk)) {
397 		dev_err(&spi->dev, "no CAN clock source defined\n");
398 		freq = TCAN4X5X_EXT_CLK_DEF;
399 	} else {
400 		freq = clk_get_rate(mcan_class->cclk);
401 	}
402 
403 	/* Sanity check */
404 	if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) {
405 		dev_err(&spi->dev, "Clock frequency is out of supported range %d\n",
406 			freq);
407 		ret = -ERANGE;
408 		goto out_m_can_class_free_dev;
409 	}
410 
411 	priv->spi = spi;
412 
413 	mcan_class->pm_clock_support = 0;
414 	mcan_class->pm_wake_source = device_property_read_bool(&spi->dev, "wakeup-source");
415 	mcan_class->can.clock.freq = freq;
416 	mcan_class->dev = &spi->dev;
417 	mcan_class->ops = &tcan4x5x_ops;
418 	mcan_class->is_peripheral = true;
419 	mcan_class->net->irq = spi->irq;
420 
421 	spi_set_drvdata(spi, priv);
422 
423 	/* Configure the SPI bus */
424 	spi->bits_per_word = 8;
425 	ret = spi_setup(spi);
426 	if (ret) {
427 		dev_err(&spi->dev, "SPI setup failed %pe\n", ERR_PTR(ret));
428 		goto out_m_can_class_free_dev;
429 	}
430 
431 	ret = tcan4x5x_regmap_init(priv);
432 	if (ret) {
433 		dev_err(&spi->dev, "regmap init failed %pe\n", ERR_PTR(ret));
434 		goto out_m_can_class_free_dev;
435 	}
436 
437 	ret = tcan4x5x_power_enable(priv->power, 1);
438 	if (ret) {
439 		dev_err(&spi->dev, "Enabling regulator failed %pe\n",
440 			ERR_PTR(ret));
441 		goto out_m_can_class_free_dev;
442 	}
443 
444 	version_info = tcan4x5x_find_version(priv);
445 	if (IS_ERR(version_info)) {
446 		ret = PTR_ERR(version_info);
447 		goto out_power;
448 	}
449 
450 	ret = tcan4x5x_get_gpios(mcan_class, version_info);
451 	if (ret) {
452 		dev_err(&spi->dev, "Getting gpios failed %pe\n", ERR_PTR(ret));
453 		goto out_power;
454 	}
455 
456 	tcan4x5x_check_wake(priv);
457 
458 	ret = tcan4x5x_write_tcan_reg(mcan_class, TCAN4X5X_INT_EN, 0);
459 	if (ret) {
460 		dev_err(&spi->dev, "Disabling interrupts failed %pe\n", ERR_PTR(ret));
461 		goto out_power;
462 	}
463 
464 	ret = tcan4x5x_clear_interrupts(mcan_class);
465 	if (ret) {
466 		dev_err(&spi->dev, "Clearing interrupts failed %pe\n", ERR_PTR(ret));
467 		goto out_power;
468 	}
469 
470 	if (mcan_class->pm_wake_source)
471 		device_init_wakeup(&spi->dev, true);
472 
473 	ret = m_can_class_register(mcan_class);
474 	if (ret) {
475 		dev_err(&spi->dev, "Failed registering m_can device %pe\n",
476 			ERR_PTR(ret));
477 		goto out_power;
478 	}
479 
480 	netdev_info(mcan_class->net, "TCAN4X5X successfully initialized.\n");
481 	return 0;
482 
483 out_power:
484 	tcan4x5x_power_enable(priv->power, 0);
485  out_m_can_class_free_dev:
486 	m_can_class_free_dev(mcan_class->net);
487 	return ret;
488 }
489 
490 static void tcan4x5x_can_remove(struct spi_device *spi)
491 {
492 	struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
493 
494 	m_can_class_unregister(&priv->cdev);
495 
496 	tcan4x5x_power_enable(priv->power, 0);
497 
498 	m_can_class_free_dev(priv->cdev.net);
499 }
500 
501 static int __maybe_unused tcan4x5x_suspend(struct device *dev)
502 {
503 	struct m_can_classdev *cdev = dev_get_drvdata(dev);
504 	struct spi_device *spi = to_spi_device(dev);
505 
506 	if (cdev->pm_wake_source)
507 		enable_irq_wake(spi->irq);
508 
509 	return m_can_class_suspend(dev);
510 }
511 
512 static int __maybe_unused tcan4x5x_resume(struct device *dev)
513 {
514 	struct m_can_classdev *cdev = dev_get_drvdata(dev);
515 	struct spi_device *spi = to_spi_device(dev);
516 	int ret = m_can_class_resume(dev);
517 
518 	if (cdev->pm_wake_source)
519 		disable_irq_wake(spi->irq);
520 
521 	return ret;
522 }
523 
524 static const struct of_device_id tcan4x5x_of_match[] = {
525 	{
526 		.compatible = "ti,tcan4x5x",
527 	}, {
528 		/* sentinel */
529 	},
530 };
531 MODULE_DEVICE_TABLE(of, tcan4x5x_of_match);
532 
533 static const struct spi_device_id tcan4x5x_id_table[] = {
534 	{
535 		.name = "tcan4x5x",
536 	}, {
537 		/* sentinel */
538 	},
539 };
540 MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table);
541 
542 static const struct dev_pm_ops tcan4x5x_pm_ops = {
543 	SET_SYSTEM_SLEEP_PM_OPS(tcan4x5x_suspend, tcan4x5x_resume)
544 };
545 
546 static struct spi_driver tcan4x5x_can_driver = {
547 	.driver = {
548 		.name = KBUILD_MODNAME,
549 		.of_match_table = tcan4x5x_of_match,
550 		.pm = &tcan4x5x_pm_ops,
551 	},
552 	.id_table = tcan4x5x_id_table,
553 	.probe = tcan4x5x_can_probe,
554 	.remove = tcan4x5x_can_remove,
555 };
556 module_spi_driver(tcan4x5x_can_driver);
557 
558 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
559 MODULE_DESCRIPTION("Texas Instruments TCAN4x5x CAN driver");
560 MODULE_LICENSE("GPL v2");
561