--- zzzz-none-000/linux-3.10.107/drivers/net/phy/spi_ks8995.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/net/phy/spi_ks8995.c 2021-02-04 17:41:59.000000000 +0000 @@ -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 * @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -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 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 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; } /* ------------------------------------------------------------------------ */ @@ -206,8 +209,6 @@ return ks8995_start(ks); } -/* ------------------------------------------------------------------------ */ - static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -217,19 +218,9 @@ dev = container_of(kobj, struct device, kobj); ks8995 = dev_get_drvdata(dev); - if (unlikely(off > KS8995_REGS_SIZE)) - return 0; - - if ((off + count) > KS8995_REGS_SIZE) - count = KS8995_REGS_SIZE - off; - - if (unlikely(!count)) - return count; - return ks8995_read(ks8995, buf, off, count); } - static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -239,20 +230,10 @@ dev = container_of(kobj, struct device, kobj); ks8995 = dev_get_drvdata(dev); - if (unlikely(off >= KS8995_REGS_SIZE)) - return -EFBIG; - - if ((off + count) > KS8995_REGS_SIZE) - count = KS8995_REGS_SIZE - off; - - if (unlikely(!count)) - return count; - return ks8995_write(ks8995, buf, off, count); } - -static struct bin_attribute ks8995_registers_attr = { +static const struct bin_attribute ks8995_registers_attr = { .attr = { .name = "registers", .mode = S_IRUSR | S_IWUSR, @@ -274,7 +255,7 @@ /* Chip description */ pdata = spi->dev.platform_data; - ks = kzalloc(sizeof(*ks), GFP_KERNEL); + ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); if (!ks) return -ENOMEM; @@ -288,14 +269,14 @@ err = spi_setup(spi); if (err) { dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); - goto err_drvdata; + return err; } err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids)); if (err < 0) { dev_err(&spi->dev, "unable to read id registers, err=%d\n", err); - goto err_drvdata; + return err; } switch (ids[0]) { @@ -303,42 +284,56 @@ break; default: dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]); - err = -ENODEV; - goto err_drvdata; + return -ENODEV; + } + + 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); + return err; + } + if ((val & 0x80) == 0) { + dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]); + return err; + } + ks->regs_attr.size = KSZ8864_REGS_SIZE; } err = ks8995_reset(ks); if (err) - goto err_drvdata; + return err; - 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; + return err; } - 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; } static int ks8995_remove(struct spi_device *spi) { - struct ks8995_data *ks8995; - - ks8995 = spi_get_drvdata(spi); - sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr); + struct ks8995_switch *ks = spi_get_drvdata(spi); - spi_set_drvdata(spi, NULL); - kfree(ks8995); + sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); return 0; } @@ -348,25 +343,12 @@ static struct spi_driver ks8995_driver = { .driver = { .name = "spi-ks8995", - .owner = THIS_MODULE, }, .probe = ks8995_probe, .remove = ks8995_remove, }; -static int __init ks8995_init(void) -{ - pr_info(DRV_DESC " version " DRV_VERSION "\n"); - - return spi_register_driver(&ks8995_driver); -} -module_init(ks8995_init); - -static void __exit ks8995_exit(void) -{ - spi_unregister_driver(&ks8995_driver); -} -module_exit(ks8995_exit); +module_spi_driver(ks8995_driver); MODULE_DESCRIPTION(DRV_DESC); MODULE_VERSION(DRV_VERSION);