Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // SPI to CAN driver for the Texas Instruments TCAN4x5x
0003 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
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 /* Interrupt bits */
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 /* MCAN Interrupt bits */
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         /* tpulse_width minimum 30us */
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     /* Zero out the MCAN buffers */
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     /* Sanity check */
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     /* Configure the SPI bus */
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         /* sentinel */
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         /* sentinel */
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");