lantiq: Tune the XWAY subtarget cflags
[openwrt.git] / package / system / spi-ks8995 / src / spi_ks8995.c
1 /*
2  * SPI driver for Micrel/Kendin KS8995M ethernet switch
3  *
4  * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
5  *
6  * This file was based on: drivers/spi/at25.c
7  *      Copyright (C) 2006 David Brownell
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2 as published
11  * by the Free Software Foundation.
12  */
13
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/delay.h>
19 #include <linux/device.h>
20
21 #include <linux/spi/spi.h>
22
23 #define DRV_VERSION     "0.1.1"
24 #define DRV_DESC        "Micrel/Kendin KS8995 Ethernet switch SPI driver"
25
26 /*-------------------------------------------------------------------------*/
27
28 #define KS8995_REG_ID0          0x00    /* Chip ID0 */
29 #define KS8995_REG_ID1          0x01    /* Chip ID1 */
30
31 #define KS8995_REG_GC0          0x02    /* Global Control 0 */
32 #define KS8995_REG_GC1          0x03    /* Global Control 1 */
33 #define KS8995_REG_GC2          0x04    /* Global Control 2 */
34 #define KS8995_REG_GC3          0x05    /* Global Control 3 */
35 #define KS8995_REG_GC4          0x06    /* Global Control 4 */
36 #define KS8995_REG_GC5          0x07    /* Global Control 5 */
37 #define KS8995_REG_GC6          0x08    /* Global Control 6 */
38 #define KS8995_REG_GC7          0x09    /* Global Control 7 */
39 #define KS8995_REG_GC8          0x0a    /* Global Control 8 */
40 #define KS8995_REG_GC9          0x0b    /* Global Control 9 */
41
42 #define KS8995_REG_PC(p,r)      ((0x10 * p) + r)        /* Port Control */
43 #define KS8995_REG_PS(p,r)      ((0x10 * p) + r + 0xe)  /* Port Status */
44
45 #define KS8995_REG_TPC0         0x60    /* TOS Priority Control 0 */
46 #define KS8995_REG_TPC1         0x61    /* TOS Priority Control 1 */
47 #define KS8995_REG_TPC2         0x62    /* TOS Priority Control 2 */
48 #define KS8995_REG_TPC3         0x63    /* TOS Priority Control 3 */
49 #define KS8995_REG_TPC4         0x64    /* TOS Priority Control 4 */
50 #define KS8995_REG_TPC5         0x65    /* TOS Priority Control 5 */
51 #define KS8995_REG_TPC6         0x66    /* TOS Priority Control 6 */
52 #define KS8995_REG_TPC7         0x67    /* TOS Priority Control 7 */
53
54 #define KS8995_REG_MAC0         0x68    /* MAC address 0 */
55 #define KS8995_REG_MAC1         0x69    /* MAC address 1 */
56 #define KS8995_REG_MAC2         0x6a    /* MAC address 2 */
57 #define KS8995_REG_MAC3         0x6b    /* MAC address 3 */
58 #define KS8995_REG_MAC4         0x6c    /* MAC address 4 */
59 #define KS8995_REG_MAC5         0x6d    /* MAC address 5 */
60
61 #define KS8995_REG_IAC0         0x6e    /* Indirect Access Control 0 */
62 #define KS8995_REG_IAC1         0x6f    /* Indirect Access Control 0 */
63
64 #define KS8995_REG_IAD7         0x70    /* Indirect Access Data 7 */
65 #define KS8995_REG_IAD6         0x71    /* Indirect Access Data 6 */
66 #define KS8995_REG_IAD5         0x72    /* Indirect Access Data 5 */
67 #define KS8995_REG_IAD4         0x73    /* Indirect Access Data 4 */
68 #define KS8995_REG_IAD3         0x74    /* Indirect Access Data 3 */
69 #define KS8995_REG_IAD2         0x75    /* Indirect Access Data 2 */
70 #define KS8995_REG_IAD1         0x76    /* Indirect Access Data 1 */
71 #define KS8995_REG_IAD0         0x77    /* Indirect Access Data 0 */
72
73 #define KS8995_REGS_SIZE        0x80
74
75 #define ID1_CHIPID_M    0xf
76 #define ID1_CHIPID_S    4
77 #define ID1_REVISION_M  0x7
78 #define ID1_REVISION_S  1
79 #define ID1_START_SW    1       /* start the switch */
80
81 #define FAMILY_KS8995   0x95
82 #define CHIPID_M        0
83
84 #define KS8995_CMD_WRITE        0x02U
85 #define KS8995_CMD_READ         0x03U
86
87 #define KS8995_RESET_DELAY      10 /* usec */
88
89 /*-------------------------------------------------------------------------*/
90
91 struct ks8995_pdata {
92         /* not yet implemented */
93 };
94
95 struct ks8995_switch {
96         struct spi_device       *spi;
97         struct mutex            lock;
98         struct ks8995_pdata     *pdata;
99 };
100
101 /*-------------------------------------------------------------------------*/
102
103 static inline u8 get_chip_id(u8 val)
104 {
105         return ((val >> ID1_CHIPID_S) & ID1_CHIPID_M);
106 }
107
108 static inline u8 get_chip_rev(u8 val)
109 {
110         return ((val >> ID1_REVISION_S) & ID1_REVISION_M);
111 }
112
113 /*-------------------------------------------------------------------------*/
114
115 static int ks8995_read(struct ks8995_switch *ks, char *buf,
116                 unsigned offset, size_t count)
117 {
118         u8 cmd[2];
119         struct spi_transfer t[2];
120         struct spi_message m;
121         int err;
122
123         spi_message_init(&m);
124
125         memset(&t, 0, sizeof(t));
126
127         t[0].tx_buf = cmd;
128         t[0].len = sizeof(cmd);
129         spi_message_add_tail(&t[0], &m);
130
131         t[1].rx_buf = buf;
132         t[1].len = count;
133         spi_message_add_tail(&t[1], &m);
134
135         cmd[0] = KS8995_CMD_READ;
136         cmd[1] = offset;
137
138         mutex_lock(&ks->lock);
139         err = spi_sync(ks->spi, &m);
140         mutex_unlock(&ks->lock);
141
142         return err ? err : count;
143 }
144
145
146 static int ks8995_write(struct ks8995_switch *ks, char *buf,
147                 unsigned offset, size_t count)
148 {
149         u8 cmd[2];
150         struct spi_transfer t[2];
151         struct spi_message m;
152         int err;
153
154         spi_message_init(&m);
155
156         memset(&t, 0, sizeof(t));
157
158         t[0].tx_buf = cmd;
159         t[0].len = sizeof(cmd);
160         spi_message_add_tail(&t[0], &m);
161
162         t[1].tx_buf = buf;
163         t[1].len = count;
164         spi_message_add_tail(&t[1], &m);
165
166         cmd[0] = KS8995_CMD_WRITE;
167         cmd[1] = offset;
168
169         mutex_lock(&ks->lock);
170         err = spi_sync(ks->spi, &m);
171         mutex_unlock(&ks->lock);
172
173         return err ? err : count;
174 }
175
176 static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf)
177 {
178         return (ks8995_read(ks, buf, addr, 1) != 1);
179 }
180
181 static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val)
182 {
183         char buf = val;
184
185         return (ks8995_write(ks, &buf, addr, 1) != 1);
186 }
187
188 /*-------------------------------------------------------------------------*/
189
190 #if 0
191 static int ks8995_setup(struct spi_device *spi)
192 {
193         struct ks8995_switch *ks;
194         u8 t;
195
196         ks = dev_get_drvdata(&spi->dev);
197
198         ks8995_write_reg(ks, KS8995_REG_GC0, 0x4c);
199         ks8995_write_reg(ks, KS8995_REG_GC1, 0x05);
200
201         ks8995_read_reg(ks, KS8995_REG_GC2, &t);
202         ks8995_write_reg(ks, KS8995_REG_GC2, t | 1);
203
204         ks8995_write_reg(ks, KS8995_REG_GC4, 0x20);
205
206         ks8995_write_reg(ks, KS8995_REG_PC(1,0), 0x61);
207         ks8995_write_reg(ks, KS8995_REG_PC(2,0), 0x61);
208         ks8995_write_reg(ks, KS8995_REG_PC(3,0), 0x61);
209         ks8995_write_reg(ks, KS8995_REG_PC(4,0), 0x61);
210         ks8995_write_reg(ks, KS8995_REG_PC(5,0), 0x61);
211
212         ks8995_write_reg(ks, KS8995_REG_PC(5,11), 0x18);
213
214         ks8995_write_reg(ks, KS8995_REG_TPC0, 0xff);
215         ks8995_write_reg(ks, KS8995_REG_TPC1, 0xff);
216         ks8995_write_reg(ks, KS8995_REG_TPC2, 0xff);
217         ks8995_write_reg(ks, KS8995_REG_TPC3, 0xff);
218         ks8995_write_reg(ks, KS8995_REG_TPC4, 0xff);
219         ks8995_write_reg(ks, KS8995_REG_TPC5, 0xff);
220         ks8995_write_reg(ks, KS8995_REG_TPC6, 0xff);
221         ks8995_write_reg(ks, KS8995_REG_TPC7, 0xfe);
222
223         return 0;
224 }
225 #endif
226
227 static int ks8995_stop(struct ks8995_switch *ks)
228 {
229         return ks8995_write_reg(ks, KS8995_REG_ID1, 0);
230 }
231
232 static int ks8995_start(struct ks8995_switch *ks)
233 {
234         return ks8995_write_reg(ks, KS8995_REG_ID1, 1);
235 }
236
237 static int ks8995_reset(struct ks8995_switch *ks)
238 {
239         int err;
240
241         err = ks8995_stop(ks);
242         if (err)
243                 return err;
244
245         udelay(KS8995_RESET_DELAY);
246
247         return ks8995_start(ks);
248 }
249
250 /*-------------------------------------------------------------------------*/
251
252 static int ks8995_registers_read(struct kobject *kobj,
253         struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
254 {
255         struct device *dev;
256         struct ks8995_switch *ks8995;
257
258         dev = container_of(kobj, struct device, kobj);
259         ks8995 = dev_get_drvdata(dev);
260
261         if (unlikely(off > KS8995_REGS_SIZE))
262                 return 0;
263
264         if ((off + count) > KS8995_REGS_SIZE)
265                 count = KS8995_REGS_SIZE - off;
266
267         if (unlikely(!count))
268                 return count;
269
270         return ks8995_read(ks8995, buf, off, count);
271 }
272
273
274 static int ks8995_registers_write(struct kobject *kobj,
275         struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
276 {
277         struct device *dev;
278         struct ks8995_switch *ks8995;
279
280         dev = container_of(kobj, struct device, kobj);
281         ks8995 = dev_get_drvdata(dev);
282
283         if (unlikely(off >= KS8995_REGS_SIZE))
284                 return -EFBIG;
285
286         if ((off + count) > KS8995_REGS_SIZE)
287                 count = KS8995_REGS_SIZE - off;
288
289         if (unlikely(!count))
290                 return count;
291
292         return ks8995_write(ks8995, buf, off, count);
293 }
294
295
296 static struct bin_attribute ks8995_registers_attr = {
297         .attr = {
298                 .name   = "registers",
299                 .mode   = S_IRUSR | S_IWUSR,
300         },
301         .size   = KS8995_REGS_SIZE,
302         .read   = ks8995_registers_read,
303         .write  = ks8995_registers_write,
304 };
305
306 /*-------------------------------------------------------------------------*/
307
308 static int ks8995_probe(struct spi_device *spi)
309 {
310         struct ks8995_switch    *ks;
311         struct ks8995_pdata     *pdata;
312         u8      ids[2];
313         int     err;
314
315         /* Chip description */
316         pdata = spi->dev.platform_data;
317
318         ks = kzalloc(sizeof(*ks), GFP_KERNEL);
319         if (!ks) {
320                 dev_err(&spi->dev, "no memory for private data\n");
321                 return-ENOMEM;
322         }
323
324         mutex_init(&ks->lock);
325         ks->pdata = pdata;
326         ks->spi = spi_dev_get(spi);
327         dev_set_drvdata(&spi->dev, ks);
328
329         spi->mode = SPI_MODE_0;
330         spi->bits_per_word = 8;
331         err = spi_setup(spi);
332         if (err) {
333                 dev_err(&spi->dev, "spi_setup failed, err=%d \n", err);
334                 goto err_drvdata;
335         }
336
337         err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids));
338         if (err < 0) {
339                 dev_err(&spi->dev, "unable to read id registers, err=%d \n",
340                                 err);
341                 goto err_drvdata;
342         }
343
344         switch (ids[0]) {
345         case FAMILY_KS8995:
346                 break;
347         default:
348                 dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]);
349                 err = -ENODEV;
350                 goto err_drvdata;
351         }
352
353         err = ks8995_reset(ks);
354         if (err)
355                 goto err_drvdata;
356
357         err = sysfs_create_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
358         if (err) {
359                 dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
360                                         err);
361                 goto err_drvdata;
362         }
363
364         dev_info(&spi->dev, "KS89%02X device found, Chip ID:%01x, "
365                         "Revision:%01x\n", ids[0],
366                         get_chip_id(ids[1]), get_chip_rev(ids[1]));
367
368         return 0;
369
370 err_drvdata:
371         dev_set_drvdata(&spi->dev, NULL);
372         kfree(ks);
373         return err;
374 }
375
376 static int ks8995_remove(struct spi_device *spi)
377 {
378         struct ks8995_data      *ks8995;
379
380         ks8995 = dev_get_drvdata(&spi->dev);
381         sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
382
383         dev_set_drvdata(&spi->dev, NULL);
384         kfree(ks8995);
385
386         return 0;
387 }
388
389 /*-------------------------------------------------------------------------*/
390
391 static struct spi_driver ks8995_driver = {
392         .driver = {
393                 .name           = "spi-ks8995",
394                 .bus            = &spi_bus_type,
395                 .owner          = THIS_MODULE,
396         },
397         .probe          = ks8995_probe,
398         .remove         = ks8995_remove,
399 };
400
401 static int __init ks8995_init(void)
402 {
403         printk(KERN_INFO DRV_DESC " version " DRV_VERSION"\n");
404
405         return spi_register_driver(&ks8995_driver);
406 }
407 module_init(ks8995_init);
408
409 static void __exit ks8995_exit(void)
410 {
411         spi_unregister_driver(&ks8995_driver);
412 }
413 module_exit(ks8995_exit);
414
415 MODULE_DESCRIPTION(DRV_DESC);
416 MODULE_VERSION(DRV_VERSION);
417 MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
418 MODULE_LICENSE("GPL v2");
419