1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This file was based on: drivers/spi/at25.c
8*4882a593Smuzhiyun * Copyright (C) 2006 David Brownell
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/device.h>
18*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
19*4882a593Smuzhiyun #include <linux/of.h>
20*4882a593Smuzhiyun #include <linux/of_gpio.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <linux/spi/spi.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define DRV_VERSION "0.1.1"
25*4882a593Smuzhiyun #define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver"
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /* ------------------------------------------------------------------------ */
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define KS8995_REG_ID0 0x00 /* Chip ID0 */
30*4882a593Smuzhiyun #define KS8995_REG_ID1 0x01 /* Chip ID1 */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define KS8995_REG_GC0 0x02 /* Global Control 0 */
33*4882a593Smuzhiyun #define KS8995_REG_GC1 0x03 /* Global Control 1 */
34*4882a593Smuzhiyun #define KS8995_REG_GC2 0x04 /* Global Control 2 */
35*4882a593Smuzhiyun #define KS8995_REG_GC3 0x05 /* Global Control 3 */
36*4882a593Smuzhiyun #define KS8995_REG_GC4 0x06 /* Global Control 4 */
37*4882a593Smuzhiyun #define KS8995_REG_GC5 0x07 /* Global Control 5 */
38*4882a593Smuzhiyun #define KS8995_REG_GC6 0x08 /* Global Control 6 */
39*4882a593Smuzhiyun #define KS8995_REG_GC7 0x09 /* Global Control 7 */
40*4882a593Smuzhiyun #define KS8995_REG_GC8 0x0a /* Global Control 8 */
41*4882a593Smuzhiyun #define KS8995_REG_GC9 0x0b /* Global Control 9 */
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */
44*4882a593Smuzhiyun #define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */
47*4882a593Smuzhiyun #define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */
48*4882a593Smuzhiyun #define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */
49*4882a593Smuzhiyun #define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */
50*4882a593Smuzhiyun #define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */
51*4882a593Smuzhiyun #define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */
52*4882a593Smuzhiyun #define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */
53*4882a593Smuzhiyun #define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define KS8995_REG_MAC0 0x68 /* MAC address 0 */
56*4882a593Smuzhiyun #define KS8995_REG_MAC1 0x69 /* MAC address 1 */
57*4882a593Smuzhiyun #define KS8995_REG_MAC2 0x6a /* MAC address 2 */
58*4882a593Smuzhiyun #define KS8995_REG_MAC3 0x6b /* MAC address 3 */
59*4882a593Smuzhiyun #define KS8995_REG_MAC4 0x6c /* MAC address 4 */
60*4882a593Smuzhiyun #define KS8995_REG_MAC5 0x6d /* MAC address 5 */
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */
63*4882a593Smuzhiyun #define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */
64*4882a593Smuzhiyun #define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */
65*4882a593Smuzhiyun #define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */
66*4882a593Smuzhiyun #define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */
67*4882a593Smuzhiyun #define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */
68*4882a593Smuzhiyun #define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */
69*4882a593Smuzhiyun #define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */
70*4882a593Smuzhiyun #define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */
71*4882a593Smuzhiyun #define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define KS8995_REGS_SIZE 0x80
76*4882a593Smuzhiyun #define KSZ8864_REGS_SIZE 0x100
77*4882a593Smuzhiyun #define KSZ8795_REGS_SIZE 0x100
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define ID1_CHIPID_M 0xf
80*4882a593Smuzhiyun #define ID1_CHIPID_S 4
81*4882a593Smuzhiyun #define ID1_REVISION_M 0x7
82*4882a593Smuzhiyun #define ID1_REVISION_S 1
83*4882a593Smuzhiyun #define ID1_START_SW 1 /* start the switch */
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun #define FAMILY_KS8995 0x95
86*4882a593Smuzhiyun #define FAMILY_KSZ8795 0x87
87*4882a593Smuzhiyun #define CHIPID_M 0
88*4882a593Smuzhiyun #define KS8995_CHIP_ID 0x00
89*4882a593Smuzhiyun #define KSZ8864_CHIP_ID 0x01
90*4882a593Smuzhiyun #define KSZ8795_CHIP_ID 0x09
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun #define KS8995_CMD_WRITE 0x02U
93*4882a593Smuzhiyun #define KS8995_CMD_READ 0x03U
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define KS8995_RESET_DELAY 10 /* usec */
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun enum ks8995_chip_variant {
98*4882a593Smuzhiyun ks8995,
99*4882a593Smuzhiyun ksz8864,
100*4882a593Smuzhiyun ksz8795,
101*4882a593Smuzhiyun max_variant
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun struct ks8995_chip_params {
105*4882a593Smuzhiyun char *name;
106*4882a593Smuzhiyun int family_id;
107*4882a593Smuzhiyun int chip_id;
108*4882a593Smuzhiyun int regs_size;
109*4882a593Smuzhiyun int addr_width;
110*4882a593Smuzhiyun int addr_shift;
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun static const struct ks8995_chip_params ks8995_chip[] = {
114*4882a593Smuzhiyun [ks8995] = {
115*4882a593Smuzhiyun .name = "KS8995MA",
116*4882a593Smuzhiyun .family_id = FAMILY_KS8995,
117*4882a593Smuzhiyun .chip_id = KS8995_CHIP_ID,
118*4882a593Smuzhiyun .regs_size = KS8995_REGS_SIZE,
119*4882a593Smuzhiyun .addr_width = 8,
120*4882a593Smuzhiyun .addr_shift = 0,
121*4882a593Smuzhiyun },
122*4882a593Smuzhiyun [ksz8864] = {
123*4882a593Smuzhiyun .name = "KSZ8864RMN",
124*4882a593Smuzhiyun .family_id = FAMILY_KS8995,
125*4882a593Smuzhiyun .chip_id = KSZ8864_CHIP_ID,
126*4882a593Smuzhiyun .regs_size = KSZ8864_REGS_SIZE,
127*4882a593Smuzhiyun .addr_width = 8,
128*4882a593Smuzhiyun .addr_shift = 0,
129*4882a593Smuzhiyun },
130*4882a593Smuzhiyun [ksz8795] = {
131*4882a593Smuzhiyun .name = "KSZ8795CLX",
132*4882a593Smuzhiyun .family_id = FAMILY_KSZ8795,
133*4882a593Smuzhiyun .chip_id = KSZ8795_CHIP_ID,
134*4882a593Smuzhiyun .regs_size = KSZ8795_REGS_SIZE,
135*4882a593Smuzhiyun .addr_width = 12,
136*4882a593Smuzhiyun .addr_shift = 1,
137*4882a593Smuzhiyun },
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun struct ks8995_pdata {
141*4882a593Smuzhiyun int reset_gpio;
142*4882a593Smuzhiyun enum of_gpio_flags reset_gpio_flags;
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun struct ks8995_switch {
146*4882a593Smuzhiyun struct spi_device *spi;
147*4882a593Smuzhiyun struct mutex lock;
148*4882a593Smuzhiyun struct ks8995_pdata *pdata;
149*4882a593Smuzhiyun struct bin_attribute regs_attr;
150*4882a593Smuzhiyun const struct ks8995_chip_params *chip;
151*4882a593Smuzhiyun int revision_id;
152*4882a593Smuzhiyun };
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun static const struct spi_device_id ks8995_id[] = {
155*4882a593Smuzhiyun {"ks8995", ks8995},
156*4882a593Smuzhiyun {"ksz8864", ksz8864},
157*4882a593Smuzhiyun {"ksz8795", ksz8795},
158*4882a593Smuzhiyun { }
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, ks8995_id);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun static const struct of_device_id ks8895_spi_of_match[] = {
163*4882a593Smuzhiyun { .compatible = "micrel,ks8995" },
164*4882a593Smuzhiyun { .compatible = "micrel,ksz8864" },
165*4882a593Smuzhiyun { .compatible = "micrel,ksz8795" },
166*4882a593Smuzhiyun { },
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ks8895_spi_of_match);
169*4882a593Smuzhiyun
get_chip_id(u8 val)170*4882a593Smuzhiyun static inline u8 get_chip_id(u8 val)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun return (val >> ID1_CHIPID_S) & ID1_CHIPID_M;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
get_chip_rev(u8 val)175*4882a593Smuzhiyun static inline u8 get_chip_rev(u8 val)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun return (val >> ID1_REVISION_S) & ID1_REVISION_M;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /* create_spi_cmd - create a chip specific SPI command header
181*4882a593Smuzhiyun * @ks: pointer to switch instance
182*4882a593Smuzhiyun * @cmd: SPI command for switch
183*4882a593Smuzhiyun * @address: register address for command
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * Different chip families use different bit pattern to address the switches
186*4882a593Smuzhiyun * registers:
187*4882a593Smuzhiyun *
188*4882a593Smuzhiyun * KS8995: 8bit command + 8bit address
189*4882a593Smuzhiyun * KSZ8795: 3bit command + 12bit address + 1bit TR (?)
190*4882a593Smuzhiyun */
create_spi_cmd(struct ks8995_switch * ks,int cmd,unsigned address)191*4882a593Smuzhiyun static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd,
192*4882a593Smuzhiyun unsigned address)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun u16 result = cmd;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /* make room for address (incl. address shift) */
197*4882a593Smuzhiyun result <<= ks->chip->addr_width + ks->chip->addr_shift;
198*4882a593Smuzhiyun /* add address */
199*4882a593Smuzhiyun result |= address << ks->chip->addr_shift;
200*4882a593Smuzhiyun /* SPI protocol needs big endian */
201*4882a593Smuzhiyun return cpu_to_be16(result);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun /* ------------------------------------------------------------------------ */
ks8995_read(struct ks8995_switch * ks,char * buf,unsigned offset,size_t count)204*4882a593Smuzhiyun static int ks8995_read(struct ks8995_switch *ks, char *buf,
205*4882a593Smuzhiyun unsigned offset, size_t count)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun __be16 cmd;
208*4882a593Smuzhiyun struct spi_transfer t[2];
209*4882a593Smuzhiyun struct spi_message m;
210*4882a593Smuzhiyun int err;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset);
213*4882a593Smuzhiyun spi_message_init(&m);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun memset(&t, 0, sizeof(t));
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun t[0].tx_buf = &cmd;
218*4882a593Smuzhiyun t[0].len = sizeof(cmd);
219*4882a593Smuzhiyun spi_message_add_tail(&t[0], &m);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun t[1].rx_buf = buf;
222*4882a593Smuzhiyun t[1].len = count;
223*4882a593Smuzhiyun spi_message_add_tail(&t[1], &m);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun mutex_lock(&ks->lock);
226*4882a593Smuzhiyun err = spi_sync(ks->spi, &m);
227*4882a593Smuzhiyun mutex_unlock(&ks->lock);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return err ? err : count;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
ks8995_write(struct ks8995_switch * ks,char * buf,unsigned offset,size_t count)232*4882a593Smuzhiyun static int ks8995_write(struct ks8995_switch *ks, char *buf,
233*4882a593Smuzhiyun unsigned offset, size_t count)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun __be16 cmd;
236*4882a593Smuzhiyun struct spi_transfer t[2];
237*4882a593Smuzhiyun struct spi_message m;
238*4882a593Smuzhiyun int err;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset);
241*4882a593Smuzhiyun spi_message_init(&m);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun memset(&t, 0, sizeof(t));
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun t[0].tx_buf = &cmd;
246*4882a593Smuzhiyun t[0].len = sizeof(cmd);
247*4882a593Smuzhiyun spi_message_add_tail(&t[0], &m);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun t[1].tx_buf = buf;
250*4882a593Smuzhiyun t[1].len = count;
251*4882a593Smuzhiyun spi_message_add_tail(&t[1], &m);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun mutex_lock(&ks->lock);
254*4882a593Smuzhiyun err = spi_sync(ks->spi, &m);
255*4882a593Smuzhiyun mutex_unlock(&ks->lock);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return err ? err : count;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ks8995_read_reg(struct ks8995_switch * ks,u8 addr,u8 * buf)260*4882a593Smuzhiyun static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun return ks8995_read(ks, buf, addr, 1) != 1;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
ks8995_write_reg(struct ks8995_switch * ks,u8 addr,u8 val)265*4882a593Smuzhiyun static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun char buf = val;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return ks8995_write(ks, &buf, addr, 1) != 1;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* ------------------------------------------------------------------------ */
273*4882a593Smuzhiyun
ks8995_stop(struct ks8995_switch * ks)274*4882a593Smuzhiyun static int ks8995_stop(struct ks8995_switch *ks)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun return ks8995_write_reg(ks, KS8995_REG_ID1, 0);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
ks8995_start(struct ks8995_switch * ks)279*4882a593Smuzhiyun static int ks8995_start(struct ks8995_switch *ks)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun return ks8995_write_reg(ks, KS8995_REG_ID1, 1);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
ks8995_reset(struct ks8995_switch * ks)284*4882a593Smuzhiyun static int ks8995_reset(struct ks8995_switch *ks)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun int err;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun err = ks8995_stop(ks);
289*4882a593Smuzhiyun if (err)
290*4882a593Smuzhiyun return err;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun udelay(KS8995_RESET_DELAY);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun return ks8995_start(ks);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
ks8995_registers_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)297*4882a593Smuzhiyun static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj,
298*4882a593Smuzhiyun struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun struct device *dev;
301*4882a593Smuzhiyun struct ks8995_switch *ks8995;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun dev = kobj_to_dev(kobj);
304*4882a593Smuzhiyun ks8995 = dev_get_drvdata(dev);
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return ks8995_read(ks8995, buf, off, count);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
ks8995_registers_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)309*4882a593Smuzhiyun static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj,
310*4882a593Smuzhiyun struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct device *dev;
313*4882a593Smuzhiyun struct ks8995_switch *ks8995;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun dev = kobj_to_dev(kobj);
316*4882a593Smuzhiyun ks8995 = dev_get_drvdata(dev);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun return ks8995_write(ks8995, buf, off, count);
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* ks8995_get_revision - get chip revision
322*4882a593Smuzhiyun * @ks: pointer to switch instance
323*4882a593Smuzhiyun *
324*4882a593Smuzhiyun * Verify chip family and id and get chip revision.
325*4882a593Smuzhiyun */
ks8995_get_revision(struct ks8995_switch * ks)326*4882a593Smuzhiyun static int ks8995_get_revision(struct ks8995_switch *ks)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun int err;
329*4882a593Smuzhiyun u8 id0, id1, ksz8864_id;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* read family id */
332*4882a593Smuzhiyun err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0);
333*4882a593Smuzhiyun if (err) {
334*4882a593Smuzhiyun err = -EIO;
335*4882a593Smuzhiyun goto err_out;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun /* verify family id */
339*4882a593Smuzhiyun if (id0 != ks->chip->family_id) {
340*4882a593Smuzhiyun dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n",
341*4882a593Smuzhiyun ks->chip->family_id, id0);
342*4882a593Smuzhiyun err = -ENODEV;
343*4882a593Smuzhiyun goto err_out;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun switch (ks->chip->family_id) {
347*4882a593Smuzhiyun case FAMILY_KS8995:
348*4882a593Smuzhiyun /* try reading chip id at CHIP ID1 */
349*4882a593Smuzhiyun err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1);
350*4882a593Smuzhiyun if (err) {
351*4882a593Smuzhiyun err = -EIO;
352*4882a593Smuzhiyun goto err_out;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /* verify chip id */
356*4882a593Smuzhiyun if ((get_chip_id(id1) == CHIPID_M) &&
357*4882a593Smuzhiyun (get_chip_id(id1) == ks->chip->chip_id)) {
358*4882a593Smuzhiyun /* KS8995MA */
359*4882a593Smuzhiyun ks->revision_id = get_chip_rev(id1);
360*4882a593Smuzhiyun } else if (get_chip_id(id1) != CHIPID_M) {
361*4882a593Smuzhiyun /* KSZ8864RMN */
362*4882a593Smuzhiyun err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id);
363*4882a593Smuzhiyun if (err) {
364*4882a593Smuzhiyun err = -EIO;
365*4882a593Smuzhiyun goto err_out;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if ((ksz8864_id & 0x80) &&
369*4882a593Smuzhiyun (ks->chip->chip_id == KSZ8864_CHIP_ID)) {
370*4882a593Smuzhiyun ks->revision_id = get_chip_rev(id1);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun } else {
374*4882a593Smuzhiyun dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n",
375*4882a593Smuzhiyun id1);
376*4882a593Smuzhiyun err = -ENODEV;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun break;
379*4882a593Smuzhiyun case FAMILY_KSZ8795:
380*4882a593Smuzhiyun /* try reading chip id at CHIP ID1 */
381*4882a593Smuzhiyun err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1);
382*4882a593Smuzhiyun if (err) {
383*4882a593Smuzhiyun err = -EIO;
384*4882a593Smuzhiyun goto err_out;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (get_chip_id(id1) == ks->chip->chip_id) {
388*4882a593Smuzhiyun ks->revision_id = get_chip_rev(id1);
389*4882a593Smuzhiyun } else {
390*4882a593Smuzhiyun dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n",
391*4882a593Smuzhiyun id1);
392*4882a593Smuzhiyun err = -ENODEV;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun break;
395*4882a593Smuzhiyun default:
396*4882a593Smuzhiyun dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0);
397*4882a593Smuzhiyun err = -ENODEV;
398*4882a593Smuzhiyun break;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun err_out:
401*4882a593Smuzhiyun return err;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /* ks8995_parse_dt - setup platform data from devicetree
405*4882a593Smuzhiyun * @ks: pointer to switch instance
406*4882a593Smuzhiyun *
407*4882a593Smuzhiyun * Parses supported DT properties and sets up platform data
408*4882a593Smuzhiyun * accordingly.
409*4882a593Smuzhiyun */
ks8995_parse_dt(struct ks8995_switch * ks)410*4882a593Smuzhiyun static void ks8995_parse_dt(struct ks8995_switch *ks)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun struct device_node *np = ks->spi->dev.of_node;
413*4882a593Smuzhiyun struct ks8995_pdata *pdata = ks->pdata;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun if (!np)
416*4882a593Smuzhiyun return;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0,
419*4882a593Smuzhiyun &pdata->reset_gpio_flags);
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun static const struct bin_attribute ks8995_registers_attr = {
423*4882a593Smuzhiyun .attr = {
424*4882a593Smuzhiyun .name = "registers",
425*4882a593Smuzhiyun .mode = 0600,
426*4882a593Smuzhiyun },
427*4882a593Smuzhiyun .size = KS8995_REGS_SIZE,
428*4882a593Smuzhiyun .read = ks8995_registers_read,
429*4882a593Smuzhiyun .write = ks8995_registers_write,
430*4882a593Smuzhiyun };
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun /* ------------------------------------------------------------------------ */
ks8995_probe(struct spi_device * spi)433*4882a593Smuzhiyun static int ks8995_probe(struct spi_device *spi)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun struct ks8995_switch *ks;
436*4882a593Smuzhiyun int err;
437*4882a593Smuzhiyun int variant = spi_get_device_id(spi)->driver_data;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (variant >= max_variant) {
440*4882a593Smuzhiyun dev_err(&spi->dev, "bad chip variant %d\n", variant);
441*4882a593Smuzhiyun return -ENODEV;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL);
445*4882a593Smuzhiyun if (!ks)
446*4882a593Smuzhiyun return -ENOMEM;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun mutex_init(&ks->lock);
449*4882a593Smuzhiyun ks->spi = spi;
450*4882a593Smuzhiyun ks->chip = &ks8995_chip[variant];
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (ks->spi->dev.of_node) {
453*4882a593Smuzhiyun ks->pdata = devm_kzalloc(&spi->dev, sizeof(*ks->pdata),
454*4882a593Smuzhiyun GFP_KERNEL);
455*4882a593Smuzhiyun if (!ks->pdata)
456*4882a593Smuzhiyun return -ENOMEM;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun ks->pdata->reset_gpio = -1;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun ks8995_parse_dt(ks);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun if (!ks->pdata)
464*4882a593Smuzhiyun ks->pdata = spi->dev.platform_data;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /* de-assert switch reset */
467*4882a593Smuzhiyun if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio)) {
468*4882a593Smuzhiyun unsigned long flags;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun flags = (ks->pdata->reset_gpio_flags == OF_GPIO_ACTIVE_LOW ?
471*4882a593Smuzhiyun GPIOF_ACTIVE_LOW : 0);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun err = devm_gpio_request_one(&spi->dev,
474*4882a593Smuzhiyun ks->pdata->reset_gpio,
475*4882a593Smuzhiyun flags, "switch-reset");
476*4882a593Smuzhiyun if (err) {
477*4882a593Smuzhiyun dev_err(&spi->dev,
478*4882a593Smuzhiyun "failed to get reset-gpios: %d\n", err);
479*4882a593Smuzhiyun return -EIO;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 0);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun spi_set_drvdata(spi, ks);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun spi->mode = SPI_MODE_0;
488*4882a593Smuzhiyun spi->bits_per_word = 8;
489*4882a593Smuzhiyun err = spi_setup(spi);
490*4882a593Smuzhiyun if (err) {
491*4882a593Smuzhiyun dev_err(&spi->dev, "spi_setup failed, err=%d\n", err);
492*4882a593Smuzhiyun return err;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun err = ks8995_get_revision(ks);
496*4882a593Smuzhiyun if (err)
497*4882a593Smuzhiyun return err;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
500*4882a593Smuzhiyun ks->regs_attr.size = ks->chip->regs_size;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun err = ks8995_reset(ks);
503*4882a593Smuzhiyun if (err)
504*4882a593Smuzhiyun return err;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun sysfs_attr_init(&ks->regs_attr.attr);
507*4882a593Smuzhiyun err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
508*4882a593Smuzhiyun if (err) {
509*4882a593Smuzhiyun dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
510*4882a593Smuzhiyun err);
511*4882a593Smuzhiyun return err;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n",
515*4882a593Smuzhiyun ks->chip->name, ks->chip->chip_id, ks->revision_id);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
ks8995_remove(struct spi_device * spi)520*4882a593Smuzhiyun static int ks8995_remove(struct spi_device *spi)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct ks8995_switch *ks = spi_get_drvdata(spi);
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun /* assert reset */
527*4882a593Smuzhiyun if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio))
528*4882a593Smuzhiyun gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1);
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun return 0;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun /* ------------------------------------------------------------------------ */
534*4882a593Smuzhiyun static struct spi_driver ks8995_driver = {
535*4882a593Smuzhiyun .driver = {
536*4882a593Smuzhiyun .name = "spi-ks8995",
537*4882a593Smuzhiyun .of_match_table = of_match_ptr(ks8895_spi_of_match),
538*4882a593Smuzhiyun },
539*4882a593Smuzhiyun .probe = ks8995_probe,
540*4882a593Smuzhiyun .remove = ks8995_remove,
541*4882a593Smuzhiyun .id_table = ks8995_id,
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun module_spi_driver(ks8995_driver);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun MODULE_DESCRIPTION(DRV_DESC);
547*4882a593Smuzhiyun MODULE_VERSION(DRV_VERSION);
548*4882a593Smuzhiyun MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
549*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
550