Commit 51428fd6 authored by David S. Miller's avatar David S. Miller

Merge branch...

Merge branch 'dsa-microchip-Modify-KSZ9477-DSA-driver-in-preparation-to-add-other-KSZ-switch-drivers'

Tristram Ha says:

====================
net: dsa: microchip: Modify KSZ9477 DSA driver in preparation to add other KSZ switch drivers

This series of patches is to modify the original KSZ9477 DSA driver so
that other KSZ switch drivers can be added and use the common code.

There are several steps to accomplish this achievement.  First is to
rename some function names with a prefix to indicate chip specific
function.  Second is to move common code into header that can be shared.
Last is to modify tag_ksz.c so that it can handle many tail tag formats
used by different KSZ switch drivers.

ksz_common.c will contain the common code used by all KSZ switch drivers.
ksz9477.c will contain KSZ9477 code from the original ksz_common.c.
ksz9477_spi.c is renamed from ksz_spi.c.
ksz9477_reg.h is renamed from ksz_9477_reg.h.
ksz_common.h is added to provide common code access to KSZ switch
drivers.
ksz_spi.h is added to provide common SPI access functions to KSZ SPI
drivers.

v4
- Patches were removed to concentrate on changing driver structure without
adding new code.

v3
- The phy_device structure is used to hold port link information
- A structure is passed in ksz_xmit and ksz_rcv instead of function pointer
- Switch offload forwarding is supported

v2
- Initialize reg_mutex before use
- The alu_mutex is only used inside chip specific functions

v1
- Each patch in the set is self-contained
- Use ksz9477 prefix to indicate KSZ9477 specific code
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b1a20048 84bd1908
menuconfig MICROCHIP_KSZ config NET_DSA_MICROCHIP_KSZ_COMMON
tristate "Microchip KSZ series switch support" tristate
menuconfig NET_DSA_MICROCHIP_KSZ9477
tristate "Microchip KSZ9477 series switch support"
depends on NET_DSA depends on NET_DSA
select NET_DSA_TAG_KSZ select NET_DSA_TAG_KSZ
select NET_DSA_MICROCHIP_KSZ_COMMON
help help
This driver adds support for Microchip KSZ switch chips. This driver adds support for Microchip KSZ9477 switch chips.
config MICROCHIP_KSZ_SPI_DRIVER config NET_DSA_MICROCHIP_KSZ9477_SPI
tristate "KSZ series SPI connected switch driver" tristate "KSZ9477 series SPI connected switch driver"
depends on MICROCHIP_KSZ && SPI depends on NET_DSA_MICROCHIP_KSZ9477 && SPI
help help
Select to enable support for registering switches configured through SPI. Select to enable support for registering switches configured through SPI.
obj-$(CONFIG_MICROCHIP_KSZ) += ksz_common.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o
obj-$(CONFIG_MICROCHIP_KSZ_SPI_DRIVER) += ksz_spi.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477) += ksz9477.o
obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI) += ksz9477_spi.o
This diff is collapsed.
/* /* SPDX-License-Identifier: GPL-2.0
* Microchip KSZ9477 register definitions
*
* Copyright (C) 2017
* *
* Permission to use, copy, modify, and/or distribute this software for any * Microchip KSZ9477 register definitions
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * Copyright (C) 2017-2018 Microchip Technology Inc.
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifndef __KSZ9477_REGS_H #ifndef __KSZ9477_REGS_H
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* Microchip KSZ series register access through SPI * Microchip KSZ9477 series register access through SPI
* *
* Copyright (C) 2017 * Copyright (C) 2017-2018 Microchip Technology Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -24,6 +13,7 @@ ...@@ -24,6 +13,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include "ksz_priv.h" #include "ksz_priv.h"
#include "ksz_spi.h"
/* SPI frame opcodes */ /* SPI frame opcodes */
#define KS_SPIOP_RD 3 #define KS_SPIOP_RD 3
...@@ -33,8 +23,11 @@ ...@@ -33,8 +23,11 @@
#define SPI_ADDR_MASK (BIT(SPI_ADDR_SHIFT) - 1) #define SPI_ADDR_MASK (BIT(SPI_ADDR_SHIFT) - 1)
#define SPI_TURNAROUND_SHIFT 5 #define SPI_TURNAROUND_SHIFT 5
static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val, /* Enough to read all switch port registers. */
unsigned int len) #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; u32 txbuf;
int ret; int ret;
...@@ -48,27 +41,36 @@ static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val, ...@@ -48,27 +41,36 @@ static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
return ret; return ret;
} }
static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data, static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
unsigned int len) unsigned int len)
{ {
struct spi_device *spi = dev->priv; u32 *txbuf = (u32 *)val;
*txbuf = reg & SPI_ADDR_MASK;
*txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT);
*txbuf <<= SPI_TURNAROUND_SHIFT;
*txbuf = cpu_to_be32(*txbuf);
return ksz_spi_read_reg(spi, reg, data, len); 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); struct spi_device *spi = dev->priv;
if (!ret)
*val = be16_to_cpu(*val);
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) static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)
...@@ -86,72 +88,15 @@ static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val) ...@@ -86,72 +88,15 @@ static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)
return ret; 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) 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 */ /* make it to big endian 24bit from MSB */
value <<= 8; value <<= 8;
value = cpu_to_be32(value); 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, .read8 = ksz_spi_read8,
.read16 = ksz_spi_read16, .read16 = ksz_spi_read16,
.read24 = ksz_spi_read24, .read24 = ksz_spi_read24,
...@@ -160,21 +105,27 @@ static const struct ksz_io_ops ksz_spi_ops = { ...@@ -160,21 +105,27 @@ static const struct ksz_io_ops ksz_spi_ops = {
.write16 = ksz_spi_write16, .write16 = ksz_spi_write16,
.write24 = ksz_spi_write24, .write24 = ksz_spi_write24,
.write32 = ksz_spi_write32, .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; struct ksz_device *dev;
int ret; int ret;
dev = ksz_switch_alloc(&spi->dev, &ksz_spi_ops, spi); dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
if (spi->dev.platform_data) if (spi->dev.platform_data)
dev->pdata = 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) if (ret)
return ret; return ret;
...@@ -183,7 +134,7 @@ static int ksz_spi_probe(struct spi_device *spi) ...@@ -183,7 +134,7 @@ static int ksz_spi_probe(struct spi_device *spi)
return 0; 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); struct ksz_device *dev = spi_get_drvdata(spi);
...@@ -193,25 +144,34 @@ static int ksz_spi_remove(struct spi_device *spi) ...@@ -193,25 +144,34 @@ static int ksz_spi_remove(struct spi_device *spi)
return 0; 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,ksz9477" },
{ .compatible = "microchip,ksz9897" }, { .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 = { .driver = {
.name = "ksz9477-switch", .name = "ksz9477-switch",
.owner = THIS_MODULE, .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, .probe = ksz9477_spi_probe,
.remove = ksz_spi_remove, .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_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"); MODULE_LICENSE("GPL");
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0
* Microchip switch driver common header
*
* Copyright (C) 2017-2018 Microchip Technology Inc.
*/
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
void ksz_update_port_member(struct ksz_device *dev, int port);
/* Common DSA access functions */
int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *br);
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
struct net_device *br);
void ksz_port_fast_age(struct dsa_switch *ds, int port);
int ksz_port_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb,
void *data);
int ksz_port_mdb_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
void ksz_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
int ksz_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
/* Common register access functions */
static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read8(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read16(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read24(struct ksz_device *dev, u32 reg, u32 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read24(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read32(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write8(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write16(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write24(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write24(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write32(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_get(struct ksz_device *dev, u32 reg, void *data,
size_t len)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->get(dev, reg, data, len);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_set(struct ksz_device *dev, u32 reg, void *data,
size_t len)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->set(dev, reg, data, len);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
u8 *data)
{
ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static inline void ksz_pread16(struct ksz_device *dev, int port, int offset,
u16 *data)
{
ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static inline void ksz_pread32(struct ksz_device *dev, int port, int offset,
u32 *data)
{
ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static inline void ksz_pwrite8(struct ksz_device *dev, int port, int offset,
u8 data)
{
ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static inline void ksz_pwrite16(struct ksz_device *dev, int port, int offset,
u16 data)
{
ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
u32 data)
{
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
}
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
u8 data;
ksz_read8(dev, addr, &data);
if (set)
data |= bits;
else
data &= ~bits;
ksz_write8(dev, addr, data);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
u32 addr;
u8 data;
addr = dev->dev_ops->get_port_addr(port, offset);
ksz_read8(dev, addr, &data);
if (set)
data |= bits;
else
data &= ~bits;
ksz_write8(dev, addr, data);
}
#endif
/* /* SPDX-License-Identifier: GPL-2.0
* Microchip KSZ series switch common definitions
*
* Copyright (C) 2017
* *
* Permission to use, copy, modify, and/or distribute this software for any * Microchip KSZ series switch common definitions
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * Copyright (C) 2017-2018 Microchip Technology Inc.
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifndef __KSZ_PRIV_H #ifndef __KSZ_PRIV_H
...@@ -25,7 +14,7 @@ ...@@ -25,7 +14,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <net/dsa.h> #include <net/dsa.h>
#include "ksz_9477_reg.h" #include "ksz9477_reg.h"
struct ksz_io_ops; struct ksz_io_ops;
...@@ -33,6 +22,27 @@ struct vlan_table { ...@@ -33,6 +22,27 @@ struct vlan_table {
u32 table[3]; u32 table[3];
}; };
struct ksz_port_mib {
u8 cnt_ptr;
u64 *counters;
};
struct ksz_port {
u16 member;
u16 vid_member;
int stp_state;
struct phy_device phydev;
u32 on:1; /* port is not disabled by hardware */
u32 phy:1; /* port has a PHY */
u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1;
u32 link_just_down:1; /* link just goes down */
struct ksz_port_mib mib;
};
struct ksz_device { struct ksz_device {
struct dsa_switch *ds; struct dsa_switch *ds;
struct ksz_platform_data *pdata; struct ksz_platform_data *pdata;
...@@ -43,6 +53,7 @@ struct ksz_device { ...@@ -43,6 +53,7 @@ struct ksz_device {
struct mutex alu_mutex; /* ALU access */ struct mutex alu_mutex; /* ALU access */
struct mutex vlan_mutex; /* vlan access */ struct mutex vlan_mutex; /* vlan access */
const struct ksz_io_ops *ops; const struct ksz_io_ops *ops;
const struct ksz_dev_ops *dev_ops;
struct device *dev; struct device *dev;
...@@ -55,11 +66,37 @@ struct ksz_device { ...@@ -55,11 +66,37 @@ struct ksz_device {
int num_statics; int num_statics;
int cpu_port; /* port connected to CPU */ int cpu_port; /* port connected to CPU */
int cpu_ports; /* port bitmap can be cpu port */ int cpu_ports; /* port bitmap can be cpu port */
int phy_port_cnt;
int port_cnt; int port_cnt;
int reg_mib_cnt;
int mib_cnt;
int mib_port_cnt;
int last_port; /* ports after that not used */
phy_interface_t interface;
u32 regs_size;
struct vlan_table *vlan_cache; struct vlan_table *vlan_cache;
u64 mib_value[TOTAL_SWITCH_COUNTER_NUM]; u64 mib_value[TOTAL_SWITCH_COUNTER_NUM];
u8 *txbuf;
struct ksz_port *ports;
struct timer_list mib_read_timer;
struct work_struct mib_read;
unsigned long mib_read_interval;
u16 br_member;
u16 member;
u16 live_ports;
u16 on_ports; /* ports enabled by DSA */
u16 rx_ports;
u16 tx_ports;
u16 mirror_rx;
u16 mirror_tx;
u32 features; /* chip specific features */
u32 overrides; /* chip functions set by user */
u16 host_mask;
u16 port_mask;
}; };
struct ksz_io_ops { struct ksz_io_ops {
...@@ -71,140 +108,60 @@ struct ksz_io_ops { ...@@ -71,140 +108,60 @@ struct ksz_io_ops {
int (*write16)(struct ksz_device *dev, u32 reg, u16 value); int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
int (*write24)(struct ksz_device *dev, u32 reg, u32 value); int (*write24)(struct ksz_device *dev, u32 reg, u32 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value); int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
int (*phy_read16)(struct ksz_device *dev, int addr, int reg, int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
u16 *value); int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
int (*phy_write16)(struct ksz_device *dev, int addr, int reg, };
u16 value);
struct alu_struct {
/* entry 1 */
u8 is_static:1;
u8 is_src_filter:1;
u8 is_dst_filter:1;
u8 prio_age:3;
u32 _reserv_0_1:23;
u8 mstp:3;
/* entry 2 */
u8 is_override:1;
u8 is_use_fid:1;
u32 _reserv_1_1:23;
u8 port_forward:7;
/* entry 3 & 4*/
u32 _reserv_2_1:9;
u8 fid:7;
u8 mac[ETH_ALEN];
};
struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr,
u8 *fid, u8 *src_port, u8 *timestamp,
u16 *entries);
int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr,
struct alu_struct *alu);
void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr,
struct alu_struct *alu);
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
void (*port_init_cnt)(struct ksz_device *dev, int port);
int (*shutdown)(struct ksz_device *dev);
int (*detect)(struct ksz_device *dev);
int (*init)(struct ksz_device *dev);
void (*exit)(struct ksz_device *dev);
}; };
struct ksz_device *ksz_switch_alloc(struct device *base, struct ksz_device *ksz_switch_alloc(struct device *base,
const struct ksz_io_ops *ops, void *priv); const struct ksz_io_ops *ops, void *priv);
int ksz_switch_detect(struct ksz_device *dev); int ksz_switch_register(struct ksz_device *dev,
int ksz_switch_register(struct ksz_device *dev); const struct ksz_dev_ops *ops);
void ksz_switch_remove(struct ksz_device *dev); void ksz_switch_remove(struct ksz_device *dev);
static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) int ksz9477_switch_register(struct ksz_device *dev);
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read8(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read16(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read24(struct ksz_device *dev, u32 reg, u32 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read24(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->read32(dev, reg, val);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write8(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write16(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write24(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write24(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
mutex_lock(&dev->reg_mutex);
ret = dev->ops->write32(dev, reg, value);
mutex_unlock(&dev->reg_mutex);
return ret;
}
static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
u8 *data)
{
ksz_read8(dev, PORT_CTRL_ADDR(port, offset), data);
}
static inline void ksz_pread16(struct ksz_device *dev, int port, int offset,
u16 *data)
{
ksz_read16(dev, PORT_CTRL_ADDR(port, offset), data);
}
static inline void ksz_pread32(struct ksz_device *dev, int port, int offset,
u32 *data)
{
ksz_read32(dev, PORT_CTRL_ADDR(port, offset), data);
}
static inline void ksz_pwrite8(struct ksz_device *dev, int port, int offset,
u8 data)
{
ksz_write8(dev, PORT_CTRL_ADDR(port, offset), data);
}
static inline void ksz_pwrite16(struct ksz_device *dev, int port, int offset,
u16 data)
{
ksz_write16(dev, PORT_CTRL_ADDR(port, offset), data);
}
static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
u32 data)
{
ksz_write32(dev, PORT_CTRL_ADDR(port, offset), data);
}
#endif #endif
/* SPDX-License-Identifier: GPL-2.0
* Microchip KSZ series SPI access common header
*
* Copyright (C) 2017-2018 Microchip Technology Inc.
* Tristram Ha <Tristram.Ha@microchip.com>
*/
#ifndef __KSZ_SPI_H
#define __KSZ_SPI_H
/* Chip dependent SPI access */
static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
unsigned int len);
static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
unsigned int len);
static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
return ksz_spi_read(dev, reg, val, 1);
}
static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
if (!ret)
*val = be16_to_cpu(*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_write8(struct ksz_device *dev, u32 reg, u8 value)
{
return ksz_spi_write(dev, reg, &value, 1);
}
static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
{
value = cpu_to_be16(value);
return ksz_spi_write(dev, reg, &value, 2);
}
static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
{
value = cpu_to_be32(value);
return ksz_spi_write(dev, reg, &value, 4);
}
static int ksz_spi_get(struct ksz_device *dev, u32 reg, void *data, size_t len)
{
return ksz_spi_read(dev, reg, data, len);
}
static int ksz_spi_set(struct ksz_device *dev, u32 reg, void *data, size_t len)
{
return ksz_spi_write(dev, reg, data, len);
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment