0001
0002
0003
0004
0005 #include "tcan4x5x.h"
0006
0007 #define TCAN4X5X_EXT_CLK_DEF 40000000
0008
0009 #define TCAN4X5X_DEV_ID0 0x00
0010 #define TCAN4X5X_DEV_ID1 0x04
0011 #define TCAN4X5X_REV 0x08
0012 #define TCAN4X5X_STATUS 0x0C
0013 #define TCAN4X5X_ERROR_STATUS 0x10
0014 #define TCAN4X5X_CONTROL 0x14
0015
0016 #define TCAN4X5X_CONFIG 0x800
0017 #define TCAN4X5X_TS_PRESCALE 0x804
0018 #define TCAN4X5X_TEST_REG 0x808
0019 #define TCAN4X5X_INT_FLAGS 0x820
0020 #define TCAN4X5X_MCAN_INT_REG 0x824
0021 #define TCAN4X5X_INT_EN 0x830
0022
0023
0024 #define TCAN4X5X_CANBUSTERMOPEN_INT_EN BIT(30)
0025 #define TCAN4X5X_CANHCANL_INT_EN BIT(29)
0026 #define TCAN4X5X_CANHBAT_INT_EN BIT(28)
0027 #define TCAN4X5X_CANLGND_INT_EN BIT(27)
0028 #define TCAN4X5X_CANBUSOPEN_INT_EN BIT(26)
0029 #define TCAN4X5X_CANBUSGND_INT_EN BIT(25)
0030 #define TCAN4X5X_CANBUSBAT_INT_EN BIT(24)
0031 #define TCAN4X5X_UVSUP_INT_EN BIT(22)
0032 #define TCAN4X5X_UVIO_INT_EN BIT(21)
0033 #define TCAN4X5X_TSD_INT_EN BIT(19)
0034 #define TCAN4X5X_ECCERR_INT_EN BIT(16)
0035 #define TCAN4X5X_CANINT_INT_EN BIT(15)
0036 #define TCAN4X5X_LWU_INT_EN BIT(14)
0037 #define TCAN4X5X_CANSLNT_INT_EN BIT(10)
0038 #define TCAN4X5X_CANDOM_INT_EN BIT(8)
0039 #define TCAN4X5X_CANBUS_ERR_INT_EN BIT(5)
0040 #define TCAN4X5X_BUS_FAULT BIT(4)
0041 #define TCAN4X5X_MCAN_INT BIT(1)
0042 #define TCAN4X5X_ENABLE_TCAN_INT \
0043 (TCAN4X5X_MCAN_INT | TCAN4X5X_BUS_FAULT | \
0044 TCAN4X5X_CANBUS_ERR_INT_EN | TCAN4X5X_CANINT_INT_EN)
0045
0046
0047 #define TCAN4X5X_MCAN_IR_ARA BIT(29)
0048 #define TCAN4X5X_MCAN_IR_PED BIT(28)
0049 #define TCAN4X5X_MCAN_IR_PEA BIT(27)
0050 #define TCAN4X5X_MCAN_IR_WD BIT(26)
0051 #define TCAN4X5X_MCAN_IR_BO BIT(25)
0052 #define TCAN4X5X_MCAN_IR_EW BIT(24)
0053 #define TCAN4X5X_MCAN_IR_EP BIT(23)
0054 #define TCAN4X5X_MCAN_IR_ELO BIT(22)
0055 #define TCAN4X5X_MCAN_IR_BEU BIT(21)
0056 #define TCAN4X5X_MCAN_IR_BEC BIT(20)
0057 #define TCAN4X5X_MCAN_IR_DRX BIT(19)
0058 #define TCAN4X5X_MCAN_IR_TOO BIT(18)
0059 #define TCAN4X5X_MCAN_IR_MRAF BIT(17)
0060 #define TCAN4X5X_MCAN_IR_TSW BIT(16)
0061 #define TCAN4X5X_MCAN_IR_TEFL BIT(15)
0062 #define TCAN4X5X_MCAN_IR_TEFF BIT(14)
0063 #define TCAN4X5X_MCAN_IR_TEFW BIT(13)
0064 #define TCAN4X5X_MCAN_IR_TEFN BIT(12)
0065 #define TCAN4X5X_MCAN_IR_TFE BIT(11)
0066 #define TCAN4X5X_MCAN_IR_TCF BIT(10)
0067 #define TCAN4X5X_MCAN_IR_TC BIT(9)
0068 #define TCAN4X5X_MCAN_IR_HPM BIT(8)
0069 #define TCAN4X5X_MCAN_IR_RF1L BIT(7)
0070 #define TCAN4X5X_MCAN_IR_RF1F BIT(6)
0071 #define TCAN4X5X_MCAN_IR_RF1W BIT(5)
0072 #define TCAN4X5X_MCAN_IR_RF1N BIT(4)
0073 #define TCAN4X5X_MCAN_IR_RF0L BIT(3)
0074 #define TCAN4X5X_MCAN_IR_RF0F BIT(2)
0075 #define TCAN4X5X_MCAN_IR_RF0W BIT(1)
0076 #define TCAN4X5X_MCAN_IR_RF0N BIT(0)
0077 #define TCAN4X5X_ENABLE_MCAN_INT \
0078 (TCAN4X5X_MCAN_IR_TC | TCAN4X5X_MCAN_IR_RF0N | \
0079 TCAN4X5X_MCAN_IR_RF1N | TCAN4X5X_MCAN_IR_RF0F | \
0080 TCAN4X5X_MCAN_IR_RF1F)
0081
0082 #define TCAN4X5X_MRAM_START 0x8000
0083 #define TCAN4X5X_MCAN_OFFSET 0x1000
0084
0085 #define TCAN4X5X_CLEAR_ALL_INT 0xffffffff
0086 #define TCAN4X5X_SET_ALL_INT 0xffffffff
0087
0088 #define TCAN4X5X_MODE_SEL_MASK (BIT(7) | BIT(6))
0089 #define TCAN4X5X_MODE_SLEEP 0x00
0090 #define TCAN4X5X_MODE_STANDBY BIT(6)
0091 #define TCAN4X5X_MODE_NORMAL BIT(7)
0092
0093 #define TCAN4X5X_DISABLE_WAKE_MSK (BIT(31) | BIT(30))
0094 #define TCAN4X5X_DISABLE_INH_MSK BIT(9)
0095
0096 #define TCAN4X5X_SW_RESET BIT(2)
0097
0098 #define TCAN4X5X_MCAN_CONFIGURED BIT(5)
0099 #define TCAN4X5X_WATCHDOG_EN BIT(3)
0100 #define TCAN4X5X_WD_60_MS_TIMER 0
0101 #define TCAN4X5X_WD_600_MS_TIMER BIT(28)
0102 #define TCAN4X5X_WD_3_S_TIMER BIT(29)
0103 #define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29))
0104
0105 static inline struct tcan4x5x_priv *cdev_to_priv(struct m_can_classdev *cdev)
0106 {
0107 return container_of(cdev, struct tcan4x5x_priv, cdev);
0108 }
0109
0110 static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
0111 {
0112 int wake_state = 0;
0113
0114 if (priv->device_state_gpio)
0115 wake_state = gpiod_get_value(priv->device_state_gpio);
0116
0117 if (priv->device_wake_gpio && wake_state) {
0118 gpiod_set_value(priv->device_wake_gpio, 0);
0119 usleep_range(5, 50);
0120 gpiod_set_value(priv->device_wake_gpio, 1);
0121 }
0122 }
0123
0124 static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
0125 {
0126 int ret = 0;
0127
0128 if (priv->reset_gpio) {
0129 gpiod_set_value(priv->reset_gpio, 1);
0130
0131
0132 usleep_range(30, 100);
0133 gpiod_set_value(priv->reset_gpio, 0);
0134 } else {
0135 ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
0136 TCAN4X5X_SW_RESET);
0137 if (ret)
0138 return ret;
0139 }
0140
0141 usleep_range(700, 1000);
0142
0143 return ret;
0144 }
0145
0146 static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
0147 {
0148 struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
0149 u32 val;
0150
0151 regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val);
0152
0153 return val;
0154 }
0155
0156 static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset,
0157 void *val, size_t val_count)
0158 {
0159 struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
0160
0161 return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
0162 }
0163
0164 static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
0165 {
0166 struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
0167
0168 return regmap_write(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, val);
0169 }
0170
0171 static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
0172 int addr_offset, const void *val, size_t val_count)
0173 {
0174 struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
0175
0176 return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
0177 }
0178
0179 static int tcan4x5x_power_enable(struct regulator *reg, int enable)
0180 {
0181 if (IS_ERR_OR_NULL(reg))
0182 return 0;
0183
0184 if (enable)
0185 return regulator_enable(reg);
0186 else
0187 return regulator_disable(reg);
0188 }
0189
0190 static int tcan4x5x_write_tcan_reg(struct m_can_classdev *cdev,
0191 int reg, int val)
0192 {
0193 struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
0194
0195 return regmap_write(priv->regmap, reg, val);
0196 }
0197
0198 static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev)
0199 {
0200 int ret;
0201
0202 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_STATUS,
0203 TCAN4X5X_CLEAR_ALL_INT);
0204 if (ret)
0205 return ret;
0206
0207 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG,
0208 TCAN4X5X_ENABLE_MCAN_INT);
0209 if (ret)
0210 return ret;
0211
0212 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS,
0213 TCAN4X5X_CLEAR_ALL_INT);
0214 if (ret)
0215 return ret;
0216
0217 return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS,
0218 TCAN4X5X_CLEAR_ALL_INT);
0219 }
0220
0221 static int tcan4x5x_init(struct m_can_classdev *cdev)
0222 {
0223 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
0224 int ret;
0225
0226 tcan4x5x_check_wake(tcan4x5x);
0227
0228 ret = tcan4x5x_clear_interrupts(cdev);
0229 if (ret)
0230 return ret;
0231
0232 ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_EN,
0233 TCAN4X5X_ENABLE_TCAN_INT);
0234 if (ret)
0235 return ret;
0236
0237
0238 ret = m_can_init_ram(cdev);
0239 if (ret)
0240 return ret;
0241
0242 ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
0243 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
0244 if (ret)
0245 return ret;
0246
0247 return ret;
0248 }
0249
0250 static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
0251 {
0252 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
0253
0254 return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
0255 TCAN4X5X_DISABLE_WAKE_MSK, 0x00);
0256 }
0257
0258 static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
0259 {
0260 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
0261
0262 return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
0263 TCAN4X5X_DISABLE_INH_MSK, 0x01);
0264 }
0265
0266 static int tcan4x5x_get_gpios(struct m_can_classdev *cdev)
0267 {
0268 struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev);
0269 int ret;
0270
0271 tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
0272 GPIOD_OUT_HIGH);
0273 if (IS_ERR(tcan4x5x->device_wake_gpio)) {
0274 if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER)
0275 return -EPROBE_DEFER;
0276
0277 tcan4x5x_disable_wake(cdev);
0278 }
0279
0280 tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset",
0281 GPIOD_OUT_LOW);
0282 if (IS_ERR(tcan4x5x->reset_gpio))
0283 tcan4x5x->reset_gpio = NULL;
0284
0285 ret = tcan4x5x_reset(tcan4x5x);
0286 if (ret)
0287 return ret;
0288
0289 tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
0290 "device-state",
0291 GPIOD_IN);
0292 if (IS_ERR(tcan4x5x->device_state_gpio)) {
0293 tcan4x5x->device_state_gpio = NULL;
0294 tcan4x5x_disable_state(cdev);
0295 }
0296
0297 return 0;
0298 }
0299
0300 static struct m_can_ops tcan4x5x_ops = {
0301 .init = tcan4x5x_init,
0302 .read_reg = tcan4x5x_read_reg,
0303 .write_reg = tcan4x5x_write_reg,
0304 .write_fifo = tcan4x5x_write_fifo,
0305 .read_fifo = tcan4x5x_read_fifo,
0306 .clear_interrupts = tcan4x5x_clear_interrupts,
0307 };
0308
0309 static int tcan4x5x_can_probe(struct spi_device *spi)
0310 {
0311 struct tcan4x5x_priv *priv;
0312 struct m_can_classdev *mcan_class;
0313 int freq, ret;
0314
0315 mcan_class = m_can_class_allocate_dev(&spi->dev,
0316 sizeof(struct tcan4x5x_priv));
0317 if (!mcan_class)
0318 return -ENOMEM;
0319
0320 priv = cdev_to_priv(mcan_class);
0321
0322 priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
0323 if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
0324 ret = -EPROBE_DEFER;
0325 goto out_m_can_class_free_dev;
0326 } else {
0327 priv->power = NULL;
0328 }
0329
0330 m_can_class_get_clocks(mcan_class);
0331 if (IS_ERR(mcan_class->cclk)) {
0332 dev_err(&spi->dev, "no CAN clock source defined\n");
0333 freq = TCAN4X5X_EXT_CLK_DEF;
0334 } else {
0335 freq = clk_get_rate(mcan_class->cclk);
0336 }
0337
0338
0339 if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) {
0340 ret = -ERANGE;
0341 goto out_m_can_class_free_dev;
0342 }
0343
0344 priv->spi = spi;
0345
0346 mcan_class->pm_clock_support = 0;
0347 mcan_class->can.clock.freq = freq;
0348 mcan_class->dev = &spi->dev;
0349 mcan_class->ops = &tcan4x5x_ops;
0350 mcan_class->is_peripheral = true;
0351 mcan_class->net->irq = spi->irq;
0352
0353 spi_set_drvdata(spi, priv);
0354
0355
0356 spi->bits_per_word = 8;
0357 ret = spi_setup(spi);
0358 if (ret)
0359 goto out_m_can_class_free_dev;
0360
0361 ret = tcan4x5x_regmap_init(priv);
0362 if (ret)
0363 goto out_m_can_class_free_dev;
0364
0365 ret = tcan4x5x_power_enable(priv->power, 1);
0366 if (ret)
0367 goto out_m_can_class_free_dev;
0368
0369 ret = tcan4x5x_get_gpios(mcan_class);
0370 if (ret)
0371 goto out_power;
0372
0373 ret = tcan4x5x_init(mcan_class);
0374 if (ret)
0375 goto out_power;
0376
0377 ret = m_can_class_register(mcan_class);
0378 if (ret)
0379 goto out_power;
0380
0381 netdev_info(mcan_class->net, "TCAN4X5X successfully initialized.\n");
0382 return 0;
0383
0384 out_power:
0385 tcan4x5x_power_enable(priv->power, 0);
0386 out_m_can_class_free_dev:
0387 m_can_class_free_dev(mcan_class->net);
0388 return ret;
0389 }
0390
0391 static void tcan4x5x_can_remove(struct spi_device *spi)
0392 {
0393 struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
0394
0395 m_can_class_unregister(&priv->cdev);
0396
0397 tcan4x5x_power_enable(priv->power, 0);
0398
0399 m_can_class_free_dev(priv->cdev.net);
0400 }
0401
0402 static const struct of_device_id tcan4x5x_of_match[] = {
0403 {
0404 .compatible = "ti,tcan4x5x",
0405 }, {
0406
0407 },
0408 };
0409 MODULE_DEVICE_TABLE(of, tcan4x5x_of_match);
0410
0411 static const struct spi_device_id tcan4x5x_id_table[] = {
0412 {
0413 .name = "tcan4x5x",
0414 }, {
0415
0416 },
0417 };
0418 MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table);
0419
0420 static struct spi_driver tcan4x5x_can_driver = {
0421 .driver = {
0422 .name = KBUILD_MODNAME,
0423 .of_match_table = tcan4x5x_of_match,
0424 .pm = NULL,
0425 },
0426 .id_table = tcan4x5x_id_table,
0427 .probe = tcan4x5x_can_probe,
0428 .remove = tcan4x5x_can_remove,
0429 };
0430 module_spi_driver(tcan4x5x_can_driver);
0431
0432 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
0433 MODULE_DESCRIPTION("Texas Instruments TCAN4x5x CAN driver");
0434 MODULE_LICENSE("GPL v2");