1 // SPDX-License-Identifier: GPL-2.0-only
3 * Support Infineon TLE62x0 driver chips
5 * Copyright (c) 2007 Simtec Electronics
6 * Ben Dooks, <ben@simtec.co.uk>
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
14 #include <linux/spi/spi.h>
15 #include <linux/spi/tle62x0.h>
21 #define DIAG_NORMAL 0x03
22 #define DIAG_OVERLOAD 0x02
23 #define DIAG_OPEN 0x01
24 #define DIAG_SHORTGND 0x00
26 struct tle62x0_state
{
27 struct spi_device
*us
;
30 unsigned int gpio_state
;
32 unsigned char tx_buff
[4];
33 unsigned char rx_buff
[4];
36 static int to_gpio_num(struct device_attribute
*attr
);
38 static inline int tle62x0_write(struct tle62x0_state
*st
)
40 unsigned char *buff
= st
->tx_buff
;
41 unsigned int gpio_state
= st
->gpio_state
;
45 if (st
->nr_gpio
== 16) {
46 buff
[1] = gpio_state
>> 8;
52 dev_dbg(&st
->us
->dev
, "buff %3ph\n", buff
);
54 return spi_write(st
->us
, buff
, (st
->nr_gpio
== 16) ? 3 : 2);
57 static inline int tle62x0_read(struct tle62x0_state
*st
)
59 unsigned char *txbuff
= st
->tx_buff
;
60 struct spi_transfer xfer
= {
62 .rx_buf
= st
->rx_buff
,
63 .len
= (st
->nr_gpio
* 2) / 8,
65 struct spi_message msg
;
72 spi_message_init(&msg
);
73 spi_message_add_tail(&xfer
, &msg
);
75 return spi_sync(st
->us
, &msg
);
78 static unsigned char *decode_fault(unsigned int fault_code
)
96 static ssize_t
tle62x0_status_show(struct device
*dev
,
97 struct device_attribute
*attr
, char *buf
)
99 struct tle62x0_state
*st
= dev_get_drvdata(dev
);
101 unsigned char *buff
= st
->rx_buff
;
102 unsigned long fault
= 0;
106 mutex_lock(&st
->lock
);
107 ret
= tle62x0_read(st
);
108 dev_dbg(dev
, "tle62x0_read() returned %d\n", ret
);
110 mutex_unlock(&st
->lock
);
114 for (ptr
= 0; ptr
< (st
->nr_gpio
* 2)/8; ptr
+= 1) {
116 fault
|= ((unsigned long)buff
[ptr
]);
118 dev_dbg(dev
, "byte %d is %02x\n", ptr
, buff
[ptr
]);
121 for (ptr
= 0; ptr
< st
->nr_gpio
; ptr
++) {
122 bp
+= sprintf(bp
, "%s ", decode_fault(fault
>> (ptr
* 2)));
127 mutex_unlock(&st
->lock
);
131 static DEVICE_ATTR(status_show
, S_IRUGO
, tle62x0_status_show
, NULL
);
133 static ssize_t
tle62x0_gpio_show(struct device
*dev
,
134 struct device_attribute
*attr
, char *buf
)
136 struct tle62x0_state
*st
= dev_get_drvdata(dev
);
137 int gpio_num
= to_gpio_num(attr
);
140 mutex_lock(&st
->lock
);
141 value
= (st
->gpio_state
>> gpio_num
) & 1;
142 mutex_unlock(&st
->lock
);
144 return snprintf(buf
, PAGE_SIZE
, "%d", value
);
147 static ssize_t
tle62x0_gpio_store(struct device
*dev
,
148 struct device_attribute
*attr
,
149 const char *buf
, size_t len
)
151 struct tle62x0_state
*st
= dev_get_drvdata(dev
);
152 int gpio_num
= to_gpio_num(attr
);
156 val
= simple_strtoul(buf
, &endp
, 0);
160 dev_dbg(dev
, "setting gpio %d to %ld\n", gpio_num
, val
);
162 mutex_lock(&st
->lock
);
165 st
->gpio_state
|= 1 << gpio_num
;
167 st
->gpio_state
&= ~(1 << gpio_num
);
170 mutex_unlock(&st
->lock
);
175 static DEVICE_ATTR(gpio1
, S_IWUSR
|S_IRUGO
,
176 tle62x0_gpio_show
, tle62x0_gpio_store
);
177 static DEVICE_ATTR(gpio2
, S_IWUSR
|S_IRUGO
,
178 tle62x0_gpio_show
, tle62x0_gpio_store
);
179 static DEVICE_ATTR(gpio3
, S_IWUSR
|S_IRUGO
,
180 tle62x0_gpio_show
, tle62x0_gpio_store
);
181 static DEVICE_ATTR(gpio4
, S_IWUSR
|S_IRUGO
,
182 tle62x0_gpio_show
, tle62x0_gpio_store
);
183 static DEVICE_ATTR(gpio5
, S_IWUSR
|S_IRUGO
,
184 tle62x0_gpio_show
, tle62x0_gpio_store
);
185 static DEVICE_ATTR(gpio6
, S_IWUSR
|S_IRUGO
,
186 tle62x0_gpio_show
, tle62x0_gpio_store
);
187 static DEVICE_ATTR(gpio7
, S_IWUSR
|S_IRUGO
,
188 tle62x0_gpio_show
, tle62x0_gpio_store
);
189 static DEVICE_ATTR(gpio8
, S_IWUSR
|S_IRUGO
,
190 tle62x0_gpio_show
, tle62x0_gpio_store
);
191 static DEVICE_ATTR(gpio9
, S_IWUSR
|S_IRUGO
,
192 tle62x0_gpio_show
, tle62x0_gpio_store
);
193 static DEVICE_ATTR(gpio10
, S_IWUSR
|S_IRUGO
,
194 tle62x0_gpio_show
, tle62x0_gpio_store
);
195 static DEVICE_ATTR(gpio11
, S_IWUSR
|S_IRUGO
,
196 tle62x0_gpio_show
, tle62x0_gpio_store
);
197 static DEVICE_ATTR(gpio12
, S_IWUSR
|S_IRUGO
,
198 tle62x0_gpio_show
, tle62x0_gpio_store
);
199 static DEVICE_ATTR(gpio13
, S_IWUSR
|S_IRUGO
,
200 tle62x0_gpio_show
, tle62x0_gpio_store
);
201 static DEVICE_ATTR(gpio14
, S_IWUSR
|S_IRUGO
,
202 tle62x0_gpio_show
, tle62x0_gpio_store
);
203 static DEVICE_ATTR(gpio15
, S_IWUSR
|S_IRUGO
,
204 tle62x0_gpio_show
, tle62x0_gpio_store
);
205 static DEVICE_ATTR(gpio16
, S_IWUSR
|S_IRUGO
,
206 tle62x0_gpio_show
, tle62x0_gpio_store
);
208 static struct device_attribute
*gpio_attrs
[] = {
209 [0] = &dev_attr_gpio1
,
210 [1] = &dev_attr_gpio2
,
211 [2] = &dev_attr_gpio3
,
212 [3] = &dev_attr_gpio4
,
213 [4] = &dev_attr_gpio5
,
214 [5] = &dev_attr_gpio6
,
215 [6] = &dev_attr_gpio7
,
216 [7] = &dev_attr_gpio8
,
217 [8] = &dev_attr_gpio9
,
218 [9] = &dev_attr_gpio10
,
219 [10] = &dev_attr_gpio11
,
220 [11] = &dev_attr_gpio12
,
221 [12] = &dev_attr_gpio13
,
222 [13] = &dev_attr_gpio14
,
223 [14] = &dev_attr_gpio15
,
224 [15] = &dev_attr_gpio16
227 static int to_gpio_num(struct device_attribute
*attr
)
231 for (ptr
= 0; ptr
< ARRAY_SIZE(gpio_attrs
); ptr
++) {
232 if (gpio_attrs
[ptr
] == attr
)
239 static int tle62x0_probe(struct spi_device
*spi
)
241 struct tle62x0_state
*st
;
242 struct tle62x0_pdata
*pdata
;
246 pdata
= dev_get_platdata(&spi
->dev
);
248 dev_err(&spi
->dev
, "no device data specified\n");
252 st
= kzalloc(sizeof(struct tle62x0_state
), GFP_KERNEL
);
257 st
->nr_gpio
= pdata
->gpio_count
;
258 st
->gpio_state
= pdata
->init_state
;
260 mutex_init(&st
->lock
);
262 ret
= device_create_file(&spi
->dev
, &dev_attr_status_show
);
264 dev_err(&spi
->dev
, "cannot create status attribute\n");
268 for (ptr
= 0; ptr
< pdata
->gpio_count
; ptr
++) {
269 ret
= device_create_file(&spi
->dev
, gpio_attrs
[ptr
]);
271 dev_err(&spi
->dev
, "cannot create gpio attribute\n");
276 /* tle62x0_write(st); */
277 spi_set_drvdata(spi
, st
);
282 device_remove_file(&spi
->dev
, gpio_attrs
[ptr
]);
284 device_remove_file(&spi
->dev
, &dev_attr_status_show
);
291 static int tle62x0_remove(struct spi_device
*spi
)
293 struct tle62x0_state
*st
= spi_get_drvdata(spi
);
296 for (ptr
= 0; ptr
< st
->nr_gpio
; ptr
++)
297 device_remove_file(&spi
->dev
, gpio_attrs
[ptr
]);
299 device_remove_file(&spi
->dev
, &dev_attr_status_show
);
304 static struct spi_driver tle62x0_driver
= {
308 .probe
= tle62x0_probe
,
309 .remove
= tle62x0_remove
,
312 module_spi_driver(tle62x0_driver
);
314 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
315 MODULE_DESCRIPTION("TLE62x0 SPI driver");
316 MODULE_LICENSE("GPL v2");
317 MODULE_ALIAS("spi:tle62x0");