diff options
author | Tristram Ha <Tristram.Ha@microchip.com> | 2018-11-20 15:55:09 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-20 20:57:12 -0800 |
commit | c2e866911e2540677c31ee009d8f75cdb4c023aa (patch) | |
tree | 943fcc7d7b7fe8bf4fd20cd33f259d2605b9e54d /drivers/net/dsa/microchip/ksz9477_spi.c | |
parent | 74a7194f15b33789f2423391d4c4e26fa96db752 (diff) |
net: dsa: microchip: break KSZ9477 DSA driver into two files
Break KSZ9477 DSA driver into two files in preparation to add more KSZ
switch drivers.
Add common functions in ksz_common.h so that other KSZ switch drivers
can access code in ksz_common.c.
Add ksz_spi.h for common functions used by KSZ switch SPI drivers.
Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
Reviewed-by: Woojung Huh <Woojung.Huh@microchip.com>
Reviewed-by: Pavel Machek <pavel@ucw.cz>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/microchip/ksz9477_spi.c')
-rw-r--r-- | drivers/net/dsa/microchip/ksz9477_spi.c | 143 |
1 files changed, 57 insertions, 86 deletions
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index dc70f486719c..d757ba151cb1 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Microchip KSZ series register access through SPI + * Microchip KSZ9477 series register access through SPI * * Copyright (C) 2017-2018 Microchip Technology Inc. */ @@ -13,6 +13,7 @@ #include <linux/spi/spi.h> #include "ksz_priv.h" +#include "ksz_spi.h" /* SPI frame opcodes */ #define KS_SPIOP_RD 3 @@ -22,8 +23,11 @@ #define SPI_ADDR_MASK (BIT(SPI_ADDR_SHIFT) - 1) #define SPI_TURNAROUND_SHIFT 5 -static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val, - unsigned int len) +/* Enough to read all switch port registers. */ +#define SPI_TX_BUF_LEN 0x100 + +static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val, + unsigned int len) { u32 txbuf; int ret; @@ -37,27 +41,36 @@ static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val, return ret; } -static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data, - unsigned int len) +static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val, + unsigned int len) { - struct spi_device *spi = dev->priv; + u32 *txbuf = (u32 *)val; - return ksz_spi_read_reg(spi, reg, data, len); + *txbuf = reg & SPI_ADDR_MASK; + *txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT); + *txbuf <<= SPI_TURNAROUND_SHIFT; + *txbuf = cpu_to_be32(*txbuf); + + return spi_write(spi, txbuf, 4 + len); } -static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val) +static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data, + unsigned int len) { - return ksz_spi_read(dev, reg, val, 1); + struct spi_device *spi = dev->priv; + + return ksz9477_spi_read_reg(spi, reg, data, len); } -static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val) +static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data, + unsigned int len) { - int ret = ksz_spi_read(dev, reg, (u8 *)val, 2); - - if (!ret) - *val = be16_to_cpu(*val); + struct spi_device *spi = dev->priv; - return ret; + if (len > SPI_TX_BUF_LEN) + len = SPI_TX_BUF_LEN; + memcpy(&dev->txbuf[4], data, len); + return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len); } static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val) @@ -75,72 +88,15 @@ static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val) return ret; } -static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val) -{ - int ret = ksz_spi_read(dev, reg, (u8 *)val, 4); - - if (!ret) - *val = be32_to_cpu(*val); - - return ret; -} - -static int ksz_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val, - unsigned int len) -{ - u32 txbuf; - u8 data[12]; - int i; - - txbuf = reg & SPI_ADDR_MASK; - txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT); - txbuf <<= SPI_TURNAROUND_SHIFT; - txbuf = cpu_to_be32(txbuf); - - data[0] = txbuf & 0xFF; - data[1] = (txbuf & 0xFF00) >> 8; - data[2] = (txbuf & 0xFF0000) >> 16; - data[3] = (txbuf & 0xFF000000) >> 24; - for (i = 0; i < len; i++) - data[i + 4] = val[i]; - - return spi_write(spi, &data, 4 + len); -} - -static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value) -{ - struct spi_device *spi = dev->priv; - - return ksz_spi_write_reg(spi, reg, &value, 1); -} - -static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value) -{ - struct spi_device *spi = dev->priv; - - value = cpu_to_be16(value); - return ksz_spi_write_reg(spi, reg, (u8 *)&value, 2); -} - static int ksz_spi_write24(struct ksz_device *dev, u32 reg, u32 value) { - struct spi_device *spi = dev->priv; - /* make it to big endian 24bit from MSB */ value <<= 8; value = cpu_to_be32(value); - return ksz_spi_write_reg(spi, reg, (u8 *)&value, 3); + return ksz_spi_write(dev, reg, &value, 3); } -static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value) -{ - struct spi_device *spi = dev->priv; - - value = cpu_to_be32(value); - return ksz_spi_write_reg(spi, reg, (u8 *)&value, 4); -} - -static const struct ksz_io_ops ksz_spi_ops = { +static const struct ksz_io_ops ksz9477_spi_ops = { .read8 = ksz_spi_read8, .read16 = ksz_spi_read16, .read24 = ksz_spi_read24, @@ -149,21 +105,27 @@ static const struct ksz_io_ops ksz_spi_ops = { .write16 = ksz_spi_write16, .write24 = ksz_spi_write24, .write32 = ksz_spi_write32, + .get = ksz_spi_get, + .set = ksz_spi_set, }; -static int ksz_spi_probe(struct spi_device *spi) +static int ksz9477_spi_probe(struct spi_device *spi) { struct ksz_device *dev; int ret; - dev = ksz_switch_alloc(&spi->dev, &ksz_spi_ops, spi); + dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi); if (!dev) return -ENOMEM; if (spi->dev.platform_data) dev->pdata = spi->dev.platform_data; - ret = ksz_switch_register(dev); + dev->txbuf = devm_kzalloc(dev->dev, 4 + SPI_TX_BUF_LEN, GFP_KERNEL); + + ret = ksz9477_switch_register(dev); + + /* Main DSA driver may not be started yet. */ if (ret) return ret; @@ -172,7 +134,7 @@ static int ksz_spi_probe(struct spi_device *spi) return 0; } -static int ksz_spi_remove(struct spi_device *spi) +static int ksz9477_spi_remove(struct spi_device *spi) { struct ksz_device *dev = spi_get_drvdata(spi); @@ -182,25 +144,34 @@ static int ksz_spi_remove(struct spi_device *spi) return 0; } -static const struct of_device_id ksz_dt_ids[] = { +static void ksz9477_spi_shutdown(struct spi_device *spi) +{ + struct ksz_device *dev = spi_get_drvdata(spi); + + if (dev && dev->dev_ops->shutdown) + dev->dev_ops->shutdown(dev); +} + +static const struct of_device_id ksz9477_dt_ids[] = { { .compatible = "microchip,ksz9477" }, { .compatible = "microchip,ksz9897" }, {}, }; -MODULE_DEVICE_TABLE(of, ksz_dt_ids); +MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); -static struct spi_driver ksz_spi_driver = { +static struct spi_driver ksz9477_spi_driver = { .driver = { .name = "ksz9477-switch", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(ksz_dt_ids), + .of_match_table = of_match_ptr(ksz9477_dt_ids), }, - .probe = ksz_spi_probe, - .remove = ksz_spi_remove, + .probe = ksz9477_spi_probe, + .remove = ksz9477_spi_remove, + .shutdown = ksz9477_spi_shutdown, }; -module_spi_driver(ksz_spi_driver); +module_spi_driver(ksz9477_spi_driver); MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); -MODULE_DESCRIPTION("Microchip KSZ Series Switch SPI access Driver"); +MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch SPI access Driver"); MODULE_LICENSE("GPL"); |