diff options
Diffstat (limited to 'drivers/net/phy/spi_ks8995.c')
| -rw-r--r-- | drivers/net/phy/spi_ks8995.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index f3bea134602..22b047f1fcd 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -1,5 +1,5 @@ /* - * SPI driver for Micrel/Kendin KS8995M ethernet switch + * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches * * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org> * @@ -15,7 +15,6 @@ #include <linux/types.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/device.h> @@ -71,7 +70,10 @@ #define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ #define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ +#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ + #define KS8995_REGS_SIZE 0x80 +#define KSZ8864_REGS_SIZE 0x100 #define ID1_CHIPID_M 0xf #define ID1_CHIPID_S 4 @@ -95,6 +97,7 @@ struct ks8995_switch { struct spi_device *spi; struct mutex lock; struct ks8995_pdata *pdata; + struct bin_attribute regs_attr; }; static inline u8 get_chip_id(u8 val) @@ -171,14 +174,14 @@ static int ks8995_write(struct ks8995_switch *ks, char *buf, static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) { - return (ks8995_read(ks, buf, addr, 1) != 1); + return ks8995_read(ks, buf, addr, 1) != 1; } static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) { char buf = val; - return (ks8995_write(ks, &buf, addr, 1) != 1); + return ks8995_write(ks, &buf, addr, 1) != 1; } /* ------------------------------------------------------------------------ */ @@ -217,11 +220,11 @@ static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, dev = container_of(kobj, struct device, kobj); ks8995 = dev_get_drvdata(dev); - if (unlikely(off > KS8995_REGS_SIZE)) + if (unlikely(off > ks8995->regs_attr.size)) return 0; - if ((off + count) > KS8995_REGS_SIZE) - count = KS8995_REGS_SIZE - off; + if ((off + count) > ks8995->regs_attr.size) + count = ks8995->regs_attr.size - off; if (unlikely(!count)) return count; @@ -239,11 +242,11 @@ static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, dev = container_of(kobj, struct device, kobj); ks8995 = dev_get_drvdata(dev); - if (unlikely(off >= KS8995_REGS_SIZE)) + if (unlikely(off >= ks8995->regs_attr.size)) return -EFBIG; - if ((off + count) > KS8995_REGS_SIZE) - count = KS8995_REGS_SIZE - off; + if ((off + count) > ks8995->regs_attr.size) + count = ks8995->regs_attr.size - off; if (unlikely(!count)) return count; @@ -252,7 +255,7 @@ static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, } -static struct bin_attribute ks8995_registers_attr = { +static const struct bin_attribute ks8995_registers_attr = { .attr = { .name = "registers", .mode = S_IRUSR | S_IWUSR, @@ -307,25 +310,48 @@ static int ks8995_probe(struct spi_device *spi) goto err_drvdata; } + memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); + if (get_chip_id(ids[1]) != CHIPID_M) { + u8 val; + + /* Check if this is a KSZ8864RMN */ + err = ks8995_read(ks, &val, KSZ8864_REG_ID1, sizeof(val)); + if (err < 0) { + dev_err(&spi->dev, + "unable to read chip id register, err=%d\n", + err); + goto err_drvdata; + } + if ((val & 0x80) == 0) { + dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]); + goto err_drvdata; + } + ks->regs_attr.size = KSZ8864_REGS_SIZE; + } + err = ks8995_reset(ks); if (err) goto err_drvdata; - err = sysfs_create_bin_file(&spi->dev.kobj, &ks8995_registers_attr); + err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); if (err) { dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", err); goto err_drvdata; } - dev_info(&spi->dev, "KS89%02X device found, Chip ID:%01x, " - "Revision:%01x\n", ids[0], - get_chip_id(ids[1]), get_chip_rev(ids[1])); + if (get_chip_id(ids[1]) == CHIPID_M) { + dev_info(&spi->dev, + "KS8995 device found, Chip ID:%x, Revision:%x\n", + get_chip_id(ids[1]), get_chip_rev(ids[1])); + } else { + dev_info(&spi->dev, "KSZ8864 device found, Revision:%x\n", + get_chip_rev(ids[1])); + } return 0; err_drvdata: - spi_set_drvdata(spi, NULL); kfree(ks); return err; } @@ -337,7 +363,6 @@ static int ks8995_remove(struct spi_device *spi) ks8995 = spi_get_drvdata(spi); sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr); - spi_set_drvdata(spi, NULL); kfree(ks8995); return 0; |
