tcan4x5x-core.c (11104B)
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_ID0 0x00 10#define TCAN4X5X_DEV_ID1 0x04 11#define TCAN4X5X_REV 0x08 12#define TCAN4X5X_STATUS 0x0C 13#define TCAN4X5X_ERROR_STATUS 0x10 14#define TCAN4X5X_CONTROL 0x14 15 16#define TCAN4X5X_CONFIG 0x800 17#define TCAN4X5X_TS_PRESCALE 0x804 18#define TCAN4X5X_TEST_REG 0x808 19#define TCAN4X5X_INT_FLAGS 0x820 20#define TCAN4X5X_MCAN_INT_REG 0x824 21#define TCAN4X5X_INT_EN 0x830 22 23/* Interrupt bits */ 24#define TCAN4X5X_CANBUSTERMOPEN_INT_EN BIT(30) 25#define TCAN4X5X_CANHCANL_INT_EN BIT(29) 26#define TCAN4X5X_CANHBAT_INT_EN BIT(28) 27#define TCAN4X5X_CANLGND_INT_EN BIT(27) 28#define TCAN4X5X_CANBUSOPEN_INT_EN BIT(26) 29#define TCAN4X5X_CANBUSGND_INT_EN BIT(25) 30#define TCAN4X5X_CANBUSBAT_INT_EN BIT(24) 31#define TCAN4X5X_UVSUP_INT_EN BIT(22) 32#define TCAN4X5X_UVIO_INT_EN BIT(21) 33#define TCAN4X5X_TSD_INT_EN BIT(19) 34#define TCAN4X5X_ECCERR_INT_EN BIT(16) 35#define TCAN4X5X_CANINT_INT_EN BIT(15) 36#define TCAN4X5X_LWU_INT_EN BIT(14) 37#define TCAN4X5X_CANSLNT_INT_EN BIT(10) 38#define TCAN4X5X_CANDOM_INT_EN BIT(8) 39#define TCAN4X5X_CANBUS_ERR_INT_EN BIT(5) 40#define TCAN4X5X_BUS_FAULT BIT(4) 41#define TCAN4X5X_MCAN_INT BIT(1) 42#define TCAN4X5X_ENABLE_TCAN_INT \ 43 (TCAN4X5X_MCAN_INT | TCAN4X5X_BUS_FAULT | \ 44 TCAN4X5X_CANBUS_ERR_INT_EN | TCAN4X5X_CANINT_INT_EN) 45 46/* MCAN Interrupt bits */ 47#define TCAN4X5X_MCAN_IR_ARA BIT(29) 48#define TCAN4X5X_MCAN_IR_PED BIT(28) 49#define TCAN4X5X_MCAN_IR_PEA BIT(27) 50#define TCAN4X5X_MCAN_IR_WD BIT(26) 51#define TCAN4X5X_MCAN_IR_BO BIT(25) 52#define TCAN4X5X_MCAN_IR_EW BIT(24) 53#define TCAN4X5X_MCAN_IR_EP BIT(23) 54#define TCAN4X5X_MCAN_IR_ELO BIT(22) 55#define TCAN4X5X_MCAN_IR_BEU BIT(21) 56#define TCAN4X5X_MCAN_IR_BEC BIT(20) 57#define TCAN4X5X_MCAN_IR_DRX BIT(19) 58#define TCAN4X5X_MCAN_IR_TOO BIT(18) 59#define TCAN4X5X_MCAN_IR_MRAF BIT(17) 60#define TCAN4X5X_MCAN_IR_TSW BIT(16) 61#define TCAN4X5X_MCAN_IR_TEFL BIT(15) 62#define TCAN4X5X_MCAN_IR_TEFF BIT(14) 63#define TCAN4X5X_MCAN_IR_TEFW BIT(13) 64#define TCAN4X5X_MCAN_IR_TEFN BIT(12) 65#define TCAN4X5X_MCAN_IR_TFE BIT(11) 66#define TCAN4X5X_MCAN_IR_TCF BIT(10) 67#define TCAN4X5X_MCAN_IR_TC BIT(9) 68#define TCAN4X5X_MCAN_IR_HPM BIT(8) 69#define TCAN4X5X_MCAN_IR_RF1L BIT(7) 70#define TCAN4X5X_MCAN_IR_RF1F BIT(6) 71#define TCAN4X5X_MCAN_IR_RF1W BIT(5) 72#define TCAN4X5X_MCAN_IR_RF1N BIT(4) 73#define TCAN4X5X_MCAN_IR_RF0L BIT(3) 74#define TCAN4X5X_MCAN_IR_RF0F BIT(2) 75#define TCAN4X5X_MCAN_IR_RF0W BIT(1) 76#define TCAN4X5X_MCAN_IR_RF0N BIT(0) 77#define TCAN4X5X_ENABLE_MCAN_INT \ 78 (TCAN4X5X_MCAN_IR_TC | TCAN4X5X_MCAN_IR_RF0N | \ 79 TCAN4X5X_MCAN_IR_RF1N | TCAN4X5X_MCAN_IR_RF0F | \ 80 TCAN4X5X_MCAN_IR_RF1F) 81 82#define TCAN4X5X_MRAM_START 0x8000 83#define TCAN4X5X_MCAN_OFFSET 0x1000 84 85#define TCAN4X5X_CLEAR_ALL_INT 0xffffffff 86#define TCAN4X5X_SET_ALL_INT 0xffffffff 87 88#define TCAN4X5X_MODE_SEL_MASK (BIT(7) | BIT(6)) 89#define TCAN4X5X_MODE_SLEEP 0x00 90#define TCAN4X5X_MODE_STANDBY BIT(6) 91#define TCAN4X5X_MODE_NORMAL BIT(7) 92 93#define TCAN4X5X_DISABLE_WAKE_MSK (BIT(31) | BIT(30)) 94#define TCAN4X5X_DISABLE_INH_MSK BIT(9) 95 96#define TCAN4X5X_SW_RESET BIT(2) 97 98#define TCAN4X5X_MCAN_CONFIGURED BIT(5) 99#define TCAN4X5X_WATCHDOG_EN BIT(3) 100#define TCAN4X5X_WD_60_MS_TIMER 0 101#define TCAN4X5X_WD_600_MS_TIMER BIT(28) 102#define TCAN4X5X_WD_3_S_TIMER BIT(29) 103#define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29)) 104 105static inline struct tcan4x5x_priv *cdev_to_priv(struct m_can_classdev *cdev) 106{ 107 return container_of(cdev, struct tcan4x5x_priv, cdev); 108} 109 110static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv) 111{ 112 int wake_state = 0; 113 114 if (priv->device_state_gpio) 115 wake_state = gpiod_get_value(priv->device_state_gpio); 116 117 if (priv->device_wake_gpio && wake_state) { 118 gpiod_set_value(priv->device_wake_gpio, 0); 119 usleep_range(5, 50); 120 gpiod_set_value(priv->device_wake_gpio, 1); 121 } 122} 123 124static int tcan4x5x_reset(struct tcan4x5x_priv *priv) 125{ 126 int ret = 0; 127 128 if (priv->reset_gpio) { 129 gpiod_set_value(priv->reset_gpio, 1); 130 131 /* tpulse_width minimum 30us */ 132 usleep_range(30, 100); 133 gpiod_set_value(priv->reset_gpio, 0); 134 } else { 135 ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG, 136 TCAN4X5X_SW_RESET); 137 if (ret) 138 return ret; 139 } 140 141 usleep_range(700, 1000); 142 143 return ret; 144} 145 146static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg) 147{ 148 struct tcan4x5x_priv *priv = cdev_to_priv(cdev); 149 u32 val; 150 151 regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val); 152 153 return val; 154} 155 156static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset, 157 void *val, size_t val_count) 158{ 159 struct tcan4x5x_priv *priv = cdev_to_priv(cdev); 160 161 return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count); 162} 163 164static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val) 165{ 166 struct tcan4x5x_priv *priv = cdev_to_priv(cdev); 167 168 return regmap_write(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, val); 169} 170 171static int tcan4x5x_write_fifo(struct m_can_classdev *cdev, 172 int addr_offset, const void *val, size_t val_count) 173{ 174 struct tcan4x5x_priv *priv = cdev_to_priv(cdev); 175 176 return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count); 177} 178 179static int tcan4x5x_power_enable(struct regulator *reg, int enable) 180{ 181 if (IS_ERR_OR_NULL(reg)) 182 return 0; 183 184 if (enable) 185 return regulator_enable(reg); 186 else 187 return regulator_disable(reg); 188} 189 190static int tcan4x5x_write_tcan_reg(struct m_can_classdev *cdev, 191 int reg, int val) 192{ 193 struct tcan4x5x_priv *priv = cdev_to_priv(cdev); 194 195 return regmap_write(priv->regmap, reg, val); 196} 197 198static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) 199{ 200 int ret; 201 202 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_STATUS, 203 TCAN4X5X_CLEAR_ALL_INT); 204 if (ret) 205 return ret; 206 207 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG, 208 TCAN4X5X_ENABLE_MCAN_INT); 209 if (ret) 210 return ret; 211 212 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, 213 TCAN4X5X_CLEAR_ALL_INT); 214 if (ret) 215 return ret; 216 217 return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS, 218 TCAN4X5X_CLEAR_ALL_INT); 219} 220 221static int tcan4x5x_init(struct m_can_classdev *cdev) 222{ 223 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); 224 int ret; 225 226 tcan4x5x_check_wake(tcan4x5x); 227 228 ret = tcan4x5x_clear_interrupts(cdev); 229 if (ret) 230 return ret; 231 232 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_EN, 233 TCAN4X5X_ENABLE_TCAN_INT); 234 if (ret) 235 return ret; 236 237 /* Zero out the MCAN buffers */ 238 ret = m_can_init_ram(cdev); 239 if (ret) 240 return ret; 241 242 ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, 243 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL); 244 if (ret) 245 return ret; 246 247 return ret; 248} 249 250static int tcan4x5x_disable_wake(struct m_can_classdev *cdev) 251{ 252 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); 253 254 return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, 255 TCAN4X5X_DISABLE_WAKE_MSK, 0x00); 256} 257 258static int tcan4x5x_disable_state(struct m_can_classdev *cdev) 259{ 260 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); 261 262 return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, 263 TCAN4X5X_DISABLE_INH_MSK, 0x01); 264} 265 266static int tcan4x5x_get_gpios(struct m_can_classdev *cdev) 267{ 268 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); 269 int ret; 270 271 tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake", 272 GPIOD_OUT_HIGH); 273 if (IS_ERR(tcan4x5x->device_wake_gpio)) { 274 if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER) 275 return -EPROBE_DEFER; 276 277 tcan4x5x_disable_wake(cdev); 278 } 279 280 tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset", 281 GPIOD_OUT_LOW); 282 if (IS_ERR(tcan4x5x->reset_gpio)) 283 tcan4x5x->reset_gpio = NULL; 284 285 ret = tcan4x5x_reset(tcan4x5x); 286 if (ret) 287 return ret; 288 289 tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, 290 "device-state", 291 GPIOD_IN); 292 if (IS_ERR(tcan4x5x->device_state_gpio)) { 293 tcan4x5x->device_state_gpio = NULL; 294 tcan4x5x_disable_state(cdev); 295 } 296 297 return 0; 298} 299 300static struct m_can_ops tcan4x5x_ops = { 301 .init = tcan4x5x_init, 302 .read_reg = tcan4x5x_read_reg, 303 .write_reg = tcan4x5x_write_reg, 304 .write_fifo = tcan4x5x_write_fifo, 305 .read_fifo = tcan4x5x_read_fifo, 306 .clear_interrupts = tcan4x5x_clear_interrupts, 307}; 308 309static int tcan4x5x_can_probe(struct spi_device *spi) 310{ 311 struct tcan4x5x_priv *priv; 312 struct m_can_classdev *mcan_class; 313 int freq, ret; 314 315 mcan_class = m_can_class_allocate_dev(&spi->dev, 316 sizeof(struct tcan4x5x_priv)); 317 if (!mcan_class) 318 return -ENOMEM; 319 320 priv = cdev_to_priv(mcan_class); 321 322 priv->power = devm_regulator_get_optional(&spi->dev, "vsup"); 323 if (PTR_ERR(priv->power) == -EPROBE_DEFER) { 324 ret = -EPROBE_DEFER; 325 goto out_m_can_class_free_dev; 326 } else { 327 priv->power = NULL; 328 } 329 330 m_can_class_get_clocks(mcan_class); 331 if (IS_ERR(mcan_class->cclk)) { 332 dev_err(&spi->dev, "no CAN clock source defined\n"); 333 freq = TCAN4X5X_EXT_CLK_DEF; 334 } else { 335 freq = clk_get_rate(mcan_class->cclk); 336 } 337 338 /* Sanity check */ 339 if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) { 340 ret = -ERANGE; 341 goto out_m_can_class_free_dev; 342 } 343 344 priv->spi = spi; 345 346 mcan_class->pm_clock_support = 0; 347 mcan_class->can.clock.freq = freq; 348 mcan_class->dev = &spi->dev; 349 mcan_class->ops = &tcan4x5x_ops; 350 mcan_class->is_peripheral = true; 351 mcan_class->net->irq = spi->irq; 352 353 spi_set_drvdata(spi, priv); 354 355 /* Configure the SPI bus */ 356 spi->bits_per_word = 8; 357 ret = spi_setup(spi); 358 if (ret) 359 goto out_m_can_class_free_dev; 360 361 ret = tcan4x5x_regmap_init(priv); 362 if (ret) 363 goto out_m_can_class_free_dev; 364 365 ret = tcan4x5x_power_enable(priv->power, 1); 366 if (ret) 367 goto out_m_can_class_free_dev; 368 369 ret = tcan4x5x_get_gpios(mcan_class); 370 if (ret) 371 goto out_power; 372 373 ret = tcan4x5x_init(mcan_class); 374 if (ret) 375 goto out_power; 376 377 ret = m_can_class_register(mcan_class); 378 if (ret) 379 goto out_power; 380 381 netdev_info(mcan_class->net, "TCAN4X5X successfully initialized.\n"); 382 return 0; 383 384out_power: 385 tcan4x5x_power_enable(priv->power, 0); 386 out_m_can_class_free_dev: 387 m_can_class_free_dev(mcan_class->net); 388 return ret; 389} 390 391static void tcan4x5x_can_remove(struct spi_device *spi) 392{ 393 struct tcan4x5x_priv *priv = spi_get_drvdata(spi); 394 395 m_can_class_unregister(&priv->cdev); 396 397 tcan4x5x_power_enable(priv->power, 0); 398 399 m_can_class_free_dev(priv->cdev.net); 400} 401 402static const struct of_device_id tcan4x5x_of_match[] = { 403 { 404 .compatible = "ti,tcan4x5x", 405 }, { 406 /* sentinel */ 407 }, 408}; 409MODULE_DEVICE_TABLE(of, tcan4x5x_of_match); 410 411static const struct spi_device_id tcan4x5x_id_table[] = { 412 { 413 .name = "tcan4x5x", 414 }, { 415 /* sentinel */ 416 }, 417}; 418MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table); 419 420static struct spi_driver tcan4x5x_can_driver = { 421 .driver = { 422 .name = KBUILD_MODNAME, 423 .of_match_table = tcan4x5x_of_match, 424 .pm = NULL, 425 }, 426 .id_table = tcan4x5x_id_table, 427 .probe = tcan4x5x_can_probe, 428 .remove = tcan4x5x_can_remove, 429}; 430module_spi_driver(tcan4x5x_can_driver); 431 432MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 433MODULE_DESCRIPTION("Texas Instruments TCAN4x5x CAN driver"); 434MODULE_LICENSE("GPL v2");