diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2014-04-03 05:28:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-03 16:15:29 -0400 |
commit | 240a12d58e3935945c8c0f767134f3da1ac05371 (patch) | |
tree | 4051f6d3201aca3645612271662f47c0c22bb16c | |
parent | a5e7ac5ce134d8f72f59631011fafa7bbf7ca174 (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.c | 52 |
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 | ||
99 | static inline u8 get_chip_id(u8 val) | 103 | static 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 | ||
254 | static struct bin_attribute ks8995_registers_attr = { | 258 | static 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 | ||