aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2014-04-03 05:28:10 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-03 16:15:29 -0400
commit240a12d58e3935945c8c0f767134f3da1ac05371 (patch)
tree4051f6d3201aca3645612271662f47c0c22bb16c
parenta5e7ac5ce134d8f72f59631011fafa7bbf7ca174 (diff)
net: Micrel KSZ8864RMN 4-port managed switch support
This patch adds support for the Micrel KSZ8864RMN switch to the spi_ks8995 driver. The KSZ8864RMN switch has a wider 256-byte register space. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/spi_ks8995.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index 4cf5fb922e59..22b047f1fcdc 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * SPI driver for Micrel/Kendin KS8995M ethernet switch 2 * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches
3 * 3 *
4 * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org> 4 * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
5 * 5 *
@@ -70,7 +70,10 @@
70#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ 70#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */
71#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ 71#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */
72 72
73#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */
74
73#define KS8995_REGS_SIZE 0x80 75#define KS8995_REGS_SIZE 0x80
76#define KSZ8864_REGS_SIZE 0x100
74 77
75#define ID1_CHIPID_M 0xf 78#define ID1_CHIPID_M 0xf
76#define ID1_CHIPID_S 4 79#define ID1_CHIPID_S 4
@@ -94,6 +97,7 @@ struct ks8995_switch {
94 struct spi_device *spi; 97 struct spi_device *spi;
95 struct mutex lock; 98 struct mutex lock;
96 struct ks8995_pdata *pdata; 99 struct ks8995_pdata *pdata;
100 struct bin_attribute regs_attr;
97}; 101};
98 102
99static inline u8 get_chip_id(u8 val) 103static inline u8 get_chip_id(u8 val)
@@ -216,11 +220,11 @@ static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj,
216 dev = container_of(kobj, struct device, kobj); 220 dev = container_of(kobj, struct device, kobj);
217 ks8995 = dev_get_drvdata(dev); 221 ks8995 = dev_get_drvdata(dev);
218 222
219 if (unlikely(off > KS8995_REGS_SIZE)) 223 if (unlikely(off > ks8995->regs_attr.size))
220 return 0; 224 return 0;
221 225
222 if ((off + count) > KS8995_REGS_SIZE) 226 if ((off + count) > ks8995->regs_attr.size)
223 count = KS8995_REGS_SIZE - off; 227 count = ks8995->regs_attr.size - off;
224 228
225 if (unlikely(!count)) 229 if (unlikely(!count))
226 return count; 230 return count;
@@ -238,11 +242,11 @@ static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj,
238 dev = container_of(kobj, struct device, kobj); 242 dev = container_of(kobj, struct device, kobj);
239 ks8995 = dev_get_drvdata(dev); 243 ks8995 = dev_get_drvdata(dev);
240 244
241 if (unlikely(off >= KS8995_REGS_SIZE)) 245 if (unlikely(off >= ks8995->regs_attr.size))
242 return -EFBIG; 246 return -EFBIG;
243 247
244 if ((off + count) > KS8995_REGS_SIZE) 248 if ((off + count) > ks8995->regs_attr.size)
245 count = KS8995_REGS_SIZE - off; 249 count = ks8995->regs_attr.size - off;
246 250
247 if (unlikely(!count)) 251 if (unlikely(!count))
248 return count; 252 return count;
@@ -251,7 +255,7 @@ static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj,
251} 255}
252 256
253 257
254static struct bin_attribute ks8995_registers_attr = { 258static const struct bin_attribute ks8995_registers_attr = {
255 .attr = { 259 .attr = {
256 .name = "registers", 260 .name = "registers",
257 .mode = S_IRUSR | S_IWUSR, 261 .mode = S_IRUSR | S_IWUSR,
@@ -306,20 +310,44 @@ static int ks8995_probe(struct spi_device *spi)
306 goto err_drvdata; 310 goto err_drvdata;
307 } 311 }
308 312
313 memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
314 if (get_chip_id(ids[1]) != CHIPID_M) {
315 u8 val;
316
317 /* Check if this is a KSZ8864RMN */
318 err = ks8995_read(ks, &val, KSZ8864_REG_ID1, sizeof(val));
319 if (err < 0) {
320 dev_err(&spi->dev,
321 "unable to read chip id register, err=%d\n",
322 err);
323 goto err_drvdata;
324 }
325 if ((val & 0x80) == 0) {
326 dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]);
327 goto err_drvdata;
328 }
329 ks->regs_attr.size = KSZ8864_REGS_SIZE;
330 }
331
309 err = ks8995_reset(ks); 332 err = ks8995_reset(ks);
310 if (err) 333 if (err)
311 goto err_drvdata; 334 goto err_drvdata;
312 335
313 err = sysfs_create_bin_file(&spi->dev.kobj, &ks8995_registers_attr); 336 err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
314 if (err) { 337 if (err) {
315 dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", 338 dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
316 err); 339 err);
317 goto err_drvdata; 340 goto err_drvdata;
318 } 341 }
319 342
320 dev_info(&spi->dev, "KS89%02X device found, Chip ID:%01x, " 343 if (get_chip_id(ids[1]) == CHIPID_M) {
321 "Revision:%01x\n", ids[0], 344 dev_info(&spi->dev,
322 get_chip_id(ids[1]), get_chip_rev(ids[1])); 345 "KS8995 device found, Chip ID:%x, Revision:%x\n",
346 get_chip_id(ids[1]), get_chip_rev(ids[1]));
347 } else {
348 dev_info(&spi->dev, "KSZ8864 device found, Revision:%x\n",
349 get_chip_rev(ids[1]));
350 }
323 351
324 return 0; 352 return 0;
325 353