From: Tristram Ha <tristram...@microchip.com> Add KSZ9477 I2C driver support. The code ksz9477.c and ksz_common.c are used together to generate the I2C driver.
Signed-off-by: Tristram Ha <tristram...@microchip.com> --- drivers/net/dsa/microchip/Kconfig | 7 ++ drivers/net/dsa/microchip/Makefile | 1 + drivers/net/dsa/microchip/ksz9477_i2c.c | 120 ++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 drivers/net/dsa/microchip/ksz9477_i2c.c diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig index 385b93f..1798755 100644 --- a/drivers/net/dsa/microchip/Kconfig +++ b/drivers/net/dsa/microchip/Kconfig @@ -9,6 +9,13 @@ menuconfig NET_DSA_MICROCHIP_KSZ9477 help This driver adds support for Microchip KSZ9477 switch chips. +config NET_DSA_MICROCHIP_KSZ9477_I2C + tristate "KSZ9477 series I2C connected switch driver" + depends on NET_DSA_MICROCHIP_KSZ9477 && I2C + select REGMAP_I2C + help + Select to enable support for registering switches configured through I2C. + config NET_DSA_MICROCHIP_KSZ9477_SPI tristate "KSZ9477 series SPI connected switch driver" depends on NET_DSA_MICROCHIP_KSZ9477 && SPI diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile index 3142c18..dbcc5db 100644 --- a/drivers/net/dsa/microchip/Makefile +++ b/drivers/net/dsa/microchip/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477) += ksz9477.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C) += ksz9477_i2c.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI) += ksz9477_spi.o diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c new file mode 100644 index 0000000..d8720ff --- /dev/null +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip KSZ9477 series register access through I2C + * + * Copyright (C) 2018-2019 Microchip Technology Inc. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/i2c.h> + +#include "ksz_priv.h" + +#define REG_SIZE 0x8000 + +#define I2C_REGMAP_VAL 8 +#define I2C_REGMAP_REG 16 + +#define KSZ_REGMAP_COMMON(n, width) \ +{ \ + .name = n, \ + .max_register = REG_SIZE - (width), \ + .reg_bits = I2C_REGMAP_REG, \ + .val_bits = I2C_REGMAP_VAL * (width), \ + .reg_stride = (width), \ + .reg_format_endian = REGMAP_ENDIAN_BIG, \ + .val_format_endian = REGMAP_ENDIAN_BIG, \ +} + +static const struct regmap_config ksz9477_regmap_cfg[] = { + KSZ_REGMAP_COMMON("8", 1), + KSZ_REGMAP_COMMON("16", 2), + KSZ_REGMAP_COMMON("32", 4), +}; + +static int ksz9477_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *i2c_id) +{ + struct ksz_device *dev; + int i; + int ret; + + dev = ksz_switch_alloc(&i2c->dev); + if (!dev) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_cfg); i++) { + dev->regmap[i] = devm_regmap_init_i2c(i2c, + &ksz9477_regmap_cfg[i]); + if (IS_ERR(dev->regmap[i])) { + ret = PTR_ERR(dev->regmap[i]); + dev_err(&i2c->dev, "Failed to initialize regmap: %d\n", + ret); + return ret; + } + } + + if (i2c->dev.platform_data) + dev->pdata = i2c->dev.platform_data; + + ret = ksz9477_switch_register(dev); + + /* Main DSA driver may not be started yet. */ + if (ret) + return ret; + + i2c_set_clientdata(i2c, dev); + + return 0; +} + +static int ksz9477_i2c_remove(struct i2c_client *i2c) +{ + struct ksz_device *dev = i2c_get_clientdata(i2c); + + if (dev) + ksz_switch_remove(dev); + + return 0; +} + +static void ksz9477_i2c_shutdown(struct i2c_client *i2c) +{ + struct ksz_device *dev = i2c_get_clientdata(i2c); + + if (dev && dev->dev_ops->shutdown) + dev->dev_ops->shutdown(dev); +} + +static const struct i2c_device_id ksz9477_i2c_id[] = { + { "ksz9477-switch", 0 }, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ksz9477_i2c_id); + +static const struct of_device_id ksz9477_dt_ids[] = { + { .compatible = "microchip,ksz9477" }, + { .compatible = "microchip,ksz9897" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); + +static struct i2c_driver ksz9477_i2c_driver = { + .driver = { + .name = "ksz9477-switch", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ksz9477_dt_ids), + }, + .probe = ksz9477_i2c_probe, + .remove = ksz9477_i2c_remove, + .shutdown = ksz9477_i2c_shutdown, + .id_table = ksz9477_i2c_id, +}; + +module_i2c_driver(ksz9477_i2c_driver); + +MODULE_AUTHOR("Tristram Ha <tristram...@microchip.com>"); +MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch I2C Driver"); +MODULE_LICENSE("GPL v2"); -- 1.9.1