Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Support Infineon TLE62x0 driver chips
0004  *
0005  * Copyright (c) 2007 Simtec Electronics
0006  *  Ben Dooks, <ben@simtec.co.uk>
0007  */
0008 
0009 #include <linux/device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 
0014 #include <linux/spi/spi.h>
0015 #include <linux/spi/tle62x0.h>
0016 
0017 
0018 #define CMD_READ    0x00
0019 #define CMD_SET     0xff
0020 
0021 #define DIAG_NORMAL 0x03
0022 #define DIAG_OVERLOAD   0x02
0023 #define DIAG_OPEN   0x01
0024 #define DIAG_SHORTGND   0x00
0025 
0026 struct tle62x0_state {
0027     struct spi_device   *us;
0028     struct mutex        lock;
0029     unsigned int        nr_gpio;
0030     unsigned int        gpio_state;
0031 
0032     unsigned char       tx_buff[4];
0033     unsigned char       rx_buff[4];
0034 };
0035 
0036 static int to_gpio_num(struct device_attribute *attr);
0037 
0038 static inline int tle62x0_write(struct tle62x0_state *st)
0039 {
0040     unsigned char *buff = st->tx_buff;
0041     unsigned int gpio_state = st->gpio_state;
0042 
0043     buff[0] = CMD_SET;
0044 
0045     if (st->nr_gpio == 16) {
0046         buff[1] = gpio_state >> 8;
0047         buff[2] = gpio_state;
0048     } else {
0049         buff[1] = gpio_state;
0050     }
0051 
0052     dev_dbg(&st->us->dev, "buff %3ph\n", buff);
0053 
0054     return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
0055 }
0056 
0057 static inline int tle62x0_read(struct tle62x0_state *st)
0058 {
0059     unsigned char *txbuff = st->tx_buff;
0060     struct spi_transfer xfer = {
0061         .tx_buf     = txbuff,
0062         .rx_buf     = st->rx_buff,
0063         .len        = (st->nr_gpio * 2) / 8,
0064     };
0065     struct spi_message msg;
0066 
0067     txbuff[0] = CMD_READ;
0068     txbuff[1] = 0x00;
0069     txbuff[2] = 0x00;
0070     txbuff[3] = 0x00;
0071 
0072     spi_message_init(&msg);
0073     spi_message_add_tail(&xfer, &msg);
0074 
0075     return spi_sync(st->us, &msg);
0076 }
0077 
0078 static unsigned char *decode_fault(unsigned int fault_code)
0079 {
0080     fault_code &= 3;
0081 
0082     switch (fault_code) {
0083     case DIAG_NORMAL:
0084         return "N";
0085     case DIAG_OVERLOAD:
0086         return "V";
0087     case DIAG_OPEN:
0088         return "O";
0089     case DIAG_SHORTGND:
0090         return "G";
0091     }
0092 
0093     return "?";
0094 }
0095 
0096 static ssize_t tle62x0_status_show(struct device *dev,
0097         struct device_attribute *attr, char *buf)
0098 {
0099     struct tle62x0_state *st = dev_get_drvdata(dev);
0100     char *bp = buf;
0101     unsigned char *buff = st->rx_buff;
0102     unsigned long fault = 0;
0103     int ptr;
0104     int ret;
0105 
0106     mutex_lock(&st->lock);
0107     ret = tle62x0_read(st);
0108     dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
0109     if (ret < 0) {
0110         mutex_unlock(&st->lock);
0111         return ret;
0112     }
0113 
0114     for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
0115         fault <<= 8;
0116         fault  |= ((unsigned long)buff[ptr]);
0117 
0118         dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
0119     }
0120 
0121     for (ptr = 0; ptr < st->nr_gpio; ptr++) {
0122         bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
0123     }
0124 
0125     *bp++ = '\n';
0126 
0127     mutex_unlock(&st->lock);
0128     return bp - buf;
0129 }
0130 
0131 static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
0132 
0133 static ssize_t tle62x0_gpio_show(struct device *dev,
0134         struct device_attribute *attr, char *buf)
0135 {
0136     struct tle62x0_state *st = dev_get_drvdata(dev);
0137     int gpio_num = to_gpio_num(attr);
0138     int value;
0139 
0140     mutex_lock(&st->lock);
0141     value = (st->gpio_state >> gpio_num) & 1;
0142     mutex_unlock(&st->lock);
0143 
0144     return sysfs_emit(buf, "%d", value);
0145 }
0146 
0147 static ssize_t tle62x0_gpio_store(struct device *dev,
0148         struct device_attribute *attr,
0149         const char *buf, size_t len)
0150 {
0151     struct tle62x0_state *st = dev_get_drvdata(dev);
0152     int gpio_num = to_gpio_num(attr);
0153     unsigned long val;
0154     char *endp;
0155 
0156     val = simple_strtoul(buf, &endp, 0);
0157     if (buf == endp)
0158         return -EINVAL;
0159 
0160     dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
0161 
0162     mutex_lock(&st->lock);
0163 
0164     if (val)
0165         st->gpio_state |= 1 << gpio_num;
0166     else
0167         st->gpio_state &= ~(1 << gpio_num);
0168 
0169     tle62x0_write(st);
0170     mutex_unlock(&st->lock);
0171 
0172     return len;
0173 }
0174 
0175 static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
0176         tle62x0_gpio_show, tle62x0_gpio_store);
0177 static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
0178         tle62x0_gpio_show, tle62x0_gpio_store);
0179 static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
0180         tle62x0_gpio_show, tle62x0_gpio_store);
0181 static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
0182         tle62x0_gpio_show, tle62x0_gpio_store);
0183 static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
0184         tle62x0_gpio_show, tle62x0_gpio_store);
0185 static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
0186         tle62x0_gpio_show, tle62x0_gpio_store);
0187 static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
0188         tle62x0_gpio_show, tle62x0_gpio_store);
0189 static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
0190         tle62x0_gpio_show, tle62x0_gpio_store);
0191 static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
0192         tle62x0_gpio_show, tle62x0_gpio_store);
0193 static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
0194         tle62x0_gpio_show, tle62x0_gpio_store);
0195 static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
0196         tle62x0_gpio_show, tle62x0_gpio_store);
0197 static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
0198         tle62x0_gpio_show, tle62x0_gpio_store);
0199 static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
0200         tle62x0_gpio_show, tle62x0_gpio_store);
0201 static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
0202         tle62x0_gpio_show, tle62x0_gpio_store);
0203 static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
0204         tle62x0_gpio_show, tle62x0_gpio_store);
0205 static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
0206         tle62x0_gpio_show, tle62x0_gpio_store);
0207 
0208 static struct device_attribute *gpio_attrs[] = {
0209     [0]     = &dev_attr_gpio1,
0210     [1]     = &dev_attr_gpio2,
0211     [2]     = &dev_attr_gpio3,
0212     [3]     = &dev_attr_gpio4,
0213     [4]     = &dev_attr_gpio5,
0214     [5]     = &dev_attr_gpio6,
0215     [6]     = &dev_attr_gpio7,
0216     [7]     = &dev_attr_gpio8,
0217     [8]     = &dev_attr_gpio9,
0218     [9]     = &dev_attr_gpio10,
0219     [10]        = &dev_attr_gpio11,
0220     [11]        = &dev_attr_gpio12,
0221     [12]        = &dev_attr_gpio13,
0222     [13]        = &dev_attr_gpio14,
0223     [14]        = &dev_attr_gpio15,
0224     [15]        = &dev_attr_gpio16
0225 };
0226 
0227 static int to_gpio_num(struct device_attribute *attr)
0228 {
0229     int ptr;
0230 
0231     for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
0232         if (gpio_attrs[ptr] == attr)
0233             return ptr;
0234     }
0235 
0236     return -1;
0237 }
0238 
0239 static int tle62x0_probe(struct spi_device *spi)
0240 {
0241     struct tle62x0_state *st;
0242     struct tle62x0_pdata *pdata;
0243     int ptr;
0244     int ret;
0245 
0246     pdata = dev_get_platdata(&spi->dev);
0247     if (pdata == NULL) {
0248         dev_err(&spi->dev, "no device data specified\n");
0249         return -EINVAL;
0250     }
0251 
0252     st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
0253     if (st == NULL)
0254         return -ENOMEM;
0255 
0256     st->us = spi;
0257     st->nr_gpio = pdata->gpio_count;
0258     st->gpio_state = pdata->init_state;
0259 
0260     mutex_init(&st->lock);
0261 
0262     ret = device_create_file(&spi->dev, &dev_attr_status_show);
0263     if (ret) {
0264         dev_err(&spi->dev, "cannot create status attribute\n");
0265         goto err_status;
0266     }
0267 
0268     for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
0269         ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
0270         if (ret) {
0271             dev_err(&spi->dev, "cannot create gpio attribute\n");
0272             goto err_gpios;
0273         }
0274     }
0275 
0276     /* tle62x0_write(st); */
0277     spi_set_drvdata(spi, st);
0278     return 0;
0279 
0280  err_gpios:
0281     while (--ptr >= 0)
0282         device_remove_file(&spi->dev, gpio_attrs[ptr]);
0283 
0284     device_remove_file(&spi->dev, &dev_attr_status_show);
0285 
0286  err_status:
0287     kfree(st);
0288     return ret;
0289 }
0290 
0291 static void tle62x0_remove(struct spi_device *spi)
0292 {
0293     struct tle62x0_state *st = spi_get_drvdata(spi);
0294     int ptr;
0295 
0296     for (ptr = 0; ptr < st->nr_gpio; ptr++)
0297         device_remove_file(&spi->dev, gpio_attrs[ptr]);
0298 
0299     device_remove_file(&spi->dev, &dev_attr_status_show);
0300     kfree(st);
0301 }
0302 
0303 static struct spi_driver tle62x0_driver = {
0304     .driver = {
0305         .name   = "tle62x0",
0306     },
0307     .probe      = tle62x0_probe,
0308     .remove     = tle62x0_remove,
0309 };
0310 
0311 module_spi_driver(tle62x0_driver);
0312 
0313 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
0314 MODULE_DESCRIPTION("TLE62x0 SPI driver");
0315 MODULE_LICENSE("GPL v2");
0316 MODULE_ALIAS("spi:tle62x0");