Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/806220/?format=api
{ "id": 806220, "url": "http://patchwork.ozlabs.org/api/patches/806220/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170827123658.GA727@amd/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170827123658.GA727@amd>", "list_archive_url": null, "date": "2017-08-27T12:36:58", "name": "DSA support for Micrel KSZ8895", "commit_ref": null, "pull_url": null, "state": "rfc", "archived": true, "hash": "aea91c7ed17ffab23524bdf0f6aaf703f8e83328", "submitter": { "id": 16176, "url": "http://patchwork.ozlabs.org/api/people/16176/?format=api", "name": "Pavel Machek", "email": "pavel@denx.de" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170827123658.GA727@amd/mbox/", "series": [ { "id": 14, "url": "http://patchwork.ozlabs.org/api/series/14/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=14", "date": "2017-08-27T12:36:58", "name": "DSA support for Micrel KSZ8895", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/14/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/806220/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/806220/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xgDtp2p2Cz9s2G\n\tfor <patchwork-incoming@ozlabs.org>;\n\tSun, 27 Aug 2017 22:37:22 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751377AbdH0MhE (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tSun, 27 Aug 2017 08:37:04 -0400", "from atrey.karlin.mff.cuni.cz ([195.113.26.193]:46557 \"EHLO\n\tatrey.karlin.mff.cuni.cz\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751152AbdH0MhB (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Sun, 27 Aug 2017 08:37:01 -0400", "by atrey.karlin.mff.cuni.cz (Postfix, from userid 512)\n\tid DCB41824E7; Sun, 27 Aug 2017 14:36:58 +0200 (CEST)" ], "Date": "Sun, 27 Aug 2017 14:36:58 +0200", "From": "Pavel Machek <pavel@denx.de>", "To": "Woojung.Huh@microchip.com, nathan.leigh.conrad@gmail.com", "Cc": "vivien.didelot@savoirfairelinux.com, f.fainelli@gmail.com,\n\tnetdev@vger.kernel.org, linux-kernel@vger.kernel.org,\n\tTristram.Ha@micrel.com, andrew@lunn.ch, pavel@denx.de", "Subject": "[PATCH] DSA support for Micrel KSZ8895", "Message-ID": "<20170827123658.GA727@amd>", "References": "<20170816075524.GA18532@amd> <20170816140451.GA13006@lunn.ch>\n\t<9235D6609DB808459E95D78E17F2E43D40AFF8C1@CHN-SV-EXMX02.mchp-main.com>", "MIME-Version": "1.0", "Content-Type": "multipart/signed; micalg=pgp-sha1;\n\tprotocol=\"application/pgp-signature\"; boundary=\"qMm9M+Fa2AknHoGS\"", "Content-Disposition": "inline", "In-Reply-To": "<9235D6609DB808459E95D78E17F2E43D40AFF8C1@CHN-SV-EXMX02.mchp-main.com>", "User-Agent": "Mutt/1.5.23 (2014-03-12)", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Hi!\n\nSo I fought with the driver a bit more, and now I have something that\nkind-of-works.\n\n\"great great hack\" belows worries me.\n\nYeah, disabled code needs to be removed before merge.\n\nNo, tag_ksz part probably is not acceptable. Do you see solution\nbetter than just copying it into tag_ksz1 file?\n\nAny more comments, etc?\n\nHelp would be welcome.\n\nBest regards,\n\t\t\t\t\t\t\t\t\tPavel\n\nSigned-off-by: Pavel Machek <pavel@denx.de>", "diff": "diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig\nindex a8b8f59099ce..7b7d7ddb3488 100644\n--- a/drivers/net/dsa/microchip/Kconfig\n+++ b/drivers/net/dsa/microchip/Kconfig\n@@ -1,12 +1,25 @@\n menuconfig MICROCHIP_KSZ\n-\ttristate \"Microchip KSZ series switch support\"\n+\ttristate \"Microchip KSZ 9477 series switch support\"\n+\tdepends on NET_DSA\n+\tselect NET_DSA_TAG_KSZ\n+\thelp\n+\t This driver adds support for Microchip KSZ switch chips.\n+\n+menuconfig MICROCHIP_KSZ_8895\n+\ttristate \"Microchip KSZ 8895 series switch support\"\n \tdepends on NET_DSA\n \tselect NET_DSA_TAG_KSZ\n \thelp\n \t This driver adds support for Microchip KSZ switch chips.\n \n config MICROCHIP_KSZ_SPI_DRIVER\n-\ttristate \"KSZ series SPI connected switch driver\"\n+\ttristate \"KSZ 9477 series SPI connected switch driver\"\n \tdepends on MICROCHIP_KSZ && SPI\n \thelp\n \t Select to enable support for registering switches configured through SPI.\n+\n+config MICROCHIP_KSZ_8895_SPI_DRIVER\n+\ttristate \"KSZ 8895 series SPI connected switch driver\"\n+\tdepends on MICROCHIP_KSZ_8895 && SPI\n+\thelp\n+\t Select to enable support for registering switches configured through SPI.\ndiff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile\nindex ed335e29fae8..b6a17f79d2d9 100644\n--- a/drivers/net/dsa/microchip/Makefile\n+++ b/drivers/net/dsa/microchip/Makefile\n@@ -1,2 +1,4 @@\n obj-$(CONFIG_MICROCHIP_KSZ)\t += ksz_common.o\n+obj-$(CONFIG_MICROCHIP_KSZ_8895) += ksz_8895.o\n obj-$(CONFIG_MICROCHIP_KSZ_SPI_DRIVER)\t+= ksz_spi.o\n+obj-$(CONFIG_MICROCHIP_KSZ_8895_SPI_DRIVER)\t+= ksz_8895_spi.o\ndiff --git a/drivers/net/dsa/microchip/ksz_8895.c b/drivers/net/dsa/microchip/ksz_8895.c\nnew file mode 100644\nindex 000000000000..d546e08b1281\n--- /dev/null\n+++ b/drivers/net/dsa/microchip/ksz_8895.c\n@@ -0,0 +1,721 @@\n+/*\n+ * Microchip switch driver main logic\n+ *\n+ * Copyright (C) 2017\n+ * Copyright (C) 2017 Pavel Machek <pavel@denx.de>\n+ *\n+ * Permission to use, copy, modify, and/or distribute this software for any\n+ * purpose with or without fee is hereby granted, provided that the above\n+ * copyright notice and this permission notice appear in all copies.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n+ */\n+\n+#include <linux/delay.h>\n+#include <linux/export.h>\n+#include <linux/gpio.h>\n+#include <linux/kernel.h>\n+#include <linux/module.h>\n+#include <linux/platform_data/microchip-ksz.h>\n+#include <linux/phy.h>\n+#include <linux/etherdevice.h>\n+#include <linux/if_bridge.h>\n+#include <net/dsa.h>\n+#include <net/switchdev.h>\n+\n+#include \"ksz_8895_reg.h\"\n+#include \"ksz_priv.h\"\n+\n+static const struct {\n+\tint index;\n+\tchar string[ETH_GSTRING_LEN];\n+} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {\n+\t{ 0x00, \"???\" },\n+};\n+\n+static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)\n+{\n+\tu8 data;\n+\n+\tksz_read8(dev, addr, &data);\n+\tif (set)\n+\t\tdata |= bits;\n+\telse\n+\t\tdata &= ~bits;\n+\tksz_write8(dev, addr, data);\n+}\n+\n+#if 0\n+static void ksz_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)\n+{\n+\tu32 data;\n+\n+\tksz_read32(dev, addr, &data);\n+\tif (set)\n+\t\tdata |= bits;\n+\telse\n+\t\tdata &= ~bits;\n+\tksz_write32(dev, addr, data);\n+}\n+#endif\n+\n+static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,\n+\t\t\t bool set)\n+{\n+\tu32 addr;\n+\tu8 data;\n+\n+\taddr = PORT_CTRL_ADDR(port, offset);\n+\tksz_read8(dev, addr, &data);\n+\n+\tif (set)\n+\t\tdata |= bits;\n+\telse\n+\t\tdata &= ~bits;\n+\n+\tksz_write8(dev, addr, data);\n+}\n+\n+#if 0\n+static void ksz_port_cfg32(struct ksz_device *dev, int port, int offset,\n+\t\t\t u32 bits, bool set)\n+{\n+\tu32 addr;\n+\tu32 data;\n+\n+\taddr = PORT_CTRL_ADDR(port, offset);\n+\tksz_read32(dev, addr, &data);\n+\n+\tif (set)\n+\t\tdata |= bits;\n+\telse\n+\t\tdata &= ~bits;\n+\n+\tksz_write32(dev, addr, data);\n+}\n+#endif\n+\n+#define NOTIMPL() do { NOTIMPLV(); return -EJUKEBOX; } while (0)\n+#define NOTIMPLV() do { printk(\"Not implemented -- %s\\n\", __func__); } while (0)\n+\n+static int ksz_reset_switch(struct dsa_switch *ds)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+#if 0\n+\t/* This seems to break the code. */\n+\tksz_write8(dev, REG_POWER_MANAGEMENT_1, SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S);\n+ ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0);\n+#endif\n+\treturn 0;\n+}\n+\n+#define PORT_MAC_LOOPBACK_my 0x80\n+#define REG_PORT_CTRL_LOOPBACK 0x0f\n+\n+static void port_setup(struct ksz_device *dev, int port, bool cpu_port)\n+{\n+\tprintk(\"Port setup %d, %d\\n\", port, cpu_port);\n+\n+\tif (cpu_port && port != 4)\n+\t\tprintk(\"!!! tail tagging only works on port 5\\n\");\n+\tif (cpu_port) {\n+\t\tprintk(\"enable tail tagging\\n\");\n+\t\tksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true);\n+\t}\n+\n+\tksz_port_cfg(dev, port, REG_PORT_CTRL_LOOPBACK, PORT_MAC_LOOPBACK_my, false);\n+#ifdef FIXME\n+\t/* set back pressure */\n+\tksz_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, true);\n+\n+\t/* set flow control */\n+\tksz_port_cfg(dev, port, REG_PORT_CTRL_0,\n+\t\t PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, true);\n+\n+\t/* enable broadcast storm limit */\n+\tksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);\n+\n+\t/* disable DiffServ priority */\n+\tksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_PRIO_ENABLE, false);\n+\n+\t/* replace priority */\n+\tksz_port_cfg(dev, port, REG_PORT_MRI_MAC_CTRL, PORT_USER_PRIO_CEILING,\n+\t\t false);\n+\tksz_port_cfg32(dev, port, REG_PORT_MTI_QUEUE_CTRL_0__4,\n+\t\t MTI_PVID_REPLACE, false);\n+\n+\t/* enable 802.1p priority */\n+\tksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);\n+\n+\t/* configure MAC to 1G & RGMII mode */\n+\tksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);\n+\tdata8 |= PORT_RGMII_ID_EG_ENABLE;\n+\tdata8 &= ~PORT_MII_NOT_1GBIT;\n+\tdata8 &= ~PORT_MII_SEL_M;\n+\tdata8 |= PORT_RGMII_SEL;\n+\tksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8);\n+\n+\t/* clear pending interrupts */\n+\tksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16);\n+#endif\n+}\n+\n+static void ksz_config_cpu_port(struct dsa_switch *ds)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\tint i;\n+\n+\tds->num_ports = dev->port_cnt;\n+\n+\tfor (i = 0; i < ds->num_ports; i++) {\n+\t\tif (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {\n+\t\t\tdev->cpu_port = i;\n+\n+\t\t\t/* enable cpu port */\n+\t\t\tport_setup(dev, i, true);\n+\t\t}\n+\t}\n+}\n+\n+#if 0\n+/*\n+ * sw_init_vlan - initialize switch VLAN\n+ *\n+ * Everyone can communicate with CPU, ports do not communicate with each other\n+ */\n+static void sw_init_vlan(struct ksz_device *dev)\n+{\n+\tint port;\n+\t\n+\tfor (port = 0; port < dev->port_cnt; port++) {\n+\t\t//port_get_def_vid(sw, port, &info->port_cfg[port].vid);\n+\t\t//port_r(sw, port, P_MIRROR_CTRL, &data);\n+\n+\t\tksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_VLAN_MEMBERSHIP, false);\n+\t\tksz_port_cfg(dev, port, P_MIRROR_CTRL, 1<<port, true);\t\t\n+#if 0\n+\t\tport_cfg(sw, port, P_INS_SRC_PVID_CTRL,\n+\t\t\t(PORT_INS_TAG_FOR_PORT_5 | PORT_INS_TAG_FOR_PORT_4 |\n+\t\t\tPORT_INS_TAG_FOR_PORT_3 | PORT_INS_TAG_FOR_PORT_2),\n+\t\t\ttrue);\n+#endif\n+\t}\n+\tksz_port_cfg(dev, dev->port_cnt-1, P_MIRROR_CTRL, PORT_VLAN_MEMBERSHIP, true);\n+}\n+\n+static void sw_init_bridge(struct ksz_device *dev)\n+{\n+\tint port;\n+\n+\tfor (port = 0; port < dev->port_cnt; port++) {\n+\t\tksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_VLAN_MEMBERSHIP, true);\n+\t}\n+}\n+#endif\n+\n+static void br_update(struct dsa_switch *ds)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\tint i,j;\n+\tint mask[5];\n+\tu8 val;\n+\n+\tfor (i = 0; i < dev->port_cnt; i++) {\n+\t\tmask[i] = 0;\n+\t}\n+\n+\tfor (i = 0; i < dev->port_cnt; i++) {\n+\t\tfor (j = 0; j < dev->port_cnt; j++) {\n+\t\t\t//printk(\"port %d bridge %lx\\n\", i, (unsigned long) ds->ports[i].bridge_dev);\n+\t\t\tif (ds->ports[i].bridge_dev &&\n+\t\t\t (ds->ports[i].bridge_dev == ds->ports[j].bridge_dev))\n+\t\t\t\tmask[i] |= 1<<j;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < dev->port_cnt-1; i++) {\n+\t\tprintk(\"port %d mask %x\\n\", i, mask[i]);\n+\t\tksz_pread8(dev, i, P_MIRROR_CTRL, &val);\n+\t\tval &= ~PORT_VLAN_MEMBERSHIP;\n+\t\tval |= mask[i] | 0x10 | (1 << i);\n+\t\tksz_pwrite8(dev, i, P_MIRROR_CTRL, val);\n+\t}\n+\n+\tksz_pread8(dev, dev->port_cnt-1, P_MIRROR_CTRL, &val);\n+\tval &= ~PORT_VLAN_MEMBERSHIP;\n+\tval |= mask[i] | 0x1f;\n+\tksz_pwrite8(dev, dev->port_cnt-1, P_MIRROR_CTRL, val);\n+\n+}\n+\n+\n+/* bridge_change -- need to get it here */\n+\n+int ksz_br_join(struct dsa_switch *ds, int port, struct net_device *br)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\n+\tbr_update(ds);\n+\treturn 0;\n+}\n+\n+void ksz_br_leave(struct dsa_switch *ds, int port, struct net_device *br)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\n+//\tsw_init_vlan(dev);\n+\t\n+\tbr_update(ds);\n+}\n+\n+\n+\n+static int ksz_setup(struct dsa_switch *ds)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\tint ret = 0;\n+\n+\tdev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),\n+\t\t\t\t dev->num_vlans, GFP_KERNEL);\n+\tif (!dev->vlan_cache)\n+\t\treturn -ENOMEM;\n+\n+\tret = ksz_reset_switch(ds);\n+\tif (ret) {\n+\t\tdev_err(ds->dev, \"failed to reset switch\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\t/* accept packet up to 2000bytes */\n+\t//ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true);\n+\n+\tksz_config_cpu_port(ds);\n+\n+\tksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true);\n+\n+\t/* queue based egress rate limit */\n+\t//ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);\n+\n+\t//sw_init_broad_storm(sw);\n+ //sw_init_prio(sw);\n+ //sw_init_prio_rate(sw);\n+\t//sw_init_vlan(ds); FIXME!!!\n+\n+\t/* start switch */\n+\tksz_cfg(dev, REG_CHIP_ID1, SW_START, true);\n+\n+\treturn 0;\n+}\n+\n+static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds)\n+{\n+\treturn DSA_TAG_PROTO_KSZ;\n+}\n+\n+#include \"ksz_mdio_emulation.c\"\n+\n+static int ksz_enable_port(struct dsa_switch *ds, int port,\n+\t\t\t struct phy_device *phy)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\n+\t/* setup slave port */\n+\tport_setup(dev, port, false);\n+\n+\treturn 0;\n+}\n+\n+\n+static void ksz_disable_port(struct dsa_switch *ds, int port,\n+\t\t\t struct phy_device *phy)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\n+\t/* there is no port disable */\n+\tksz_port_cfg(dev, port, REG_PORT_CTRL_LOOPBACK, PORT_MAC_LOOPBACK_my, true);\n+}\n+\n+static int ksz_sset_count(struct dsa_switch *ds)\n+{\n+\treturn TOTAL_SWITCH_COUNTER_NUM;\n+}\n+\n+static void ksz_get_strings(struct dsa_switch *ds, int port, uint8_t *buf)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {\n+\t\tmemcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string,\n+\t\t ETH_GSTRING_LEN);\n+\t}\n+}\n+\n+static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,\n+\t\t\t\t uint64_t *buf)\n+{\n+\tNOTIMPLV();\n+}\n+\n+#if 0\n+static void ksz_dump(struct ksz_device *dev)\n+{\n+\tint i;\n+\tu8 v;\n+\n+\tprintk(\"ksz: dumping:\\n\");\n+\tfor (i = 0; i < 0x100; i++) {\n+\t\tif (!(i % 0x10))\n+\t\t\tprintk(\"\\n %x: \", i);\n+\t\tksz_read8(dev, i, &v);\n+\t\tprintk(\"%02x \", v);\n+\t}\n+\tprintk(\"\\nksz: dump done\\n\");\n+}\n+#endif\n+\n+static void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)\n+{\n+\tstruct ksz_device *dev = ds->priv;\n+\tu8 data;\n+\n+\tprintk(\"port %d state %d\\n\", port, state);\n+\tksz_pread8(dev, port, P_STP_CTRL, &data);\n+\tdata &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);\n+\n+\tswitch (state) {\n+\tcase BR_STATE_DISABLED:\n+\t\tprintk(\"port %d state %d disable\\n\", port, state);\t\t\t\t\n+\t\tdata |= PORT_LEARN_DISABLE;\n+\t\tbreak;\n+\tcase BR_STATE_LISTENING:\n+\t\tprintk(\"port %d state %d listen\\n\", port, state);\n+\t\tdata |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);\n+\t\tbreak;\n+\tcase BR_STATE_LEARNING:\n+\t\tprintk(\"port %d state %d learn\\n\", port, state);\n+\t\tdata |= PORT_RX_ENABLE;\n+\t\tbreak;\n+\tcase BR_STATE_FORWARDING:\n+\t\tprintk(\"port %d state %d forwarding\\n\", port, state);\t\t\n+\t\tdata |= (PORT_TX_ENABLE | PORT_RX_ENABLE);\n+\t\tbreak;\n+\tcase BR_STATE_BLOCKING:\n+\t\tprintk(\"port %d state %d blocking\\n\", port, state);\n+\t\tdata |= PORT_LEARN_DISABLE;\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(ds->dev, \"invalid STP state: %d\\n\", state);\n+\t\treturn;\n+\t}\n+\t/* FIXME: great great hack */\n+\tdata |= (PORT_RX_ENABLE | PORT_TX_ENABLE);\n+\t\n+\n+\tksz_pwrite8(dev, port, P_STP_CTRL, data);\n+\t//ksz_dump(dev);\n+}\n+\n+static void ksz_port_fast_age(struct dsa_switch *ds, int port)\n+{\n+\tNOTIMPLV();\n+\t\n+}\n+\n+static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag)\n+{\n+\tNOTIMPL();\n+\treturn 0;\n+}\n+\n+static int ksz_port_vlan_prepare(struct dsa_switch *ds, int port,\n+\t\t\t\t const struct switchdev_obj_port_vlan *vlan,\n+\t\t\t\t struct switchdev_trans *trans)\n+{\n+\t/* nothing needed */\n+\n+\treturn 0;\n+}\n+\n+static void ksz_port_vlan_add(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_vlan *vlan,\n+\t\t\t struct switchdev_trans *trans)\n+{\n+\tNOTIMPLV();\n+}\n+\n+static int ksz_port_vlan_del(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_vlan *vlan)\n+{\n+\tNOTIMPL();\n+\n+\treturn 0;\n+}\n+\n+static int ksz_port_vlan_dump(struct dsa_switch *ds, int port,\n+\t\t\t struct switchdev_obj_port_vlan *vlan,\n+\t\t\t switchdev_obj_dump_cb_t *cb)\n+{\n+\tNOTIMPL();\n+}\n+\n+static int ksz_port_fdb_prepare(struct dsa_switch *ds, int port,\n+\t\t\t\tconst struct switchdev_obj_port_fdb *fdb,\n+\t\t\t\tstruct switchdev_trans *trans)\n+{\n+\t/* nothing needed */\n+\n+\treturn 0;\n+}\n+\n+struct alu_struct {\n+\t/* entry 1 */\n+\tu8\tis_static:1;\n+\tu8\tis_src_filter:1;\n+\tu8\tis_dst_filter:1;\n+\tu8\tprio_age:3;\n+\tu32\t_reserv_0_1:23;\n+\tu8\tmstp:3;\n+\t/* entry 2 */\n+\tu8\tis_override:1;\n+\tu8\tis_use_fid:1;\n+\tu32\t_reserv_1_1:23;\n+\tu8\tport_forward:7;\n+\t/* entry 3 & 4*/\n+\tu32\t_reserv_2_1:9;\n+\tu8\tfid:7;\n+\tu8\tmac[ETH_ALEN];\n+};\n+\n+static void ksz_port_fdb_add(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_fdb *fdb,\n+\t\t\t struct switchdev_trans *trans)\n+{\n+\tNOTIMPLV();\n+}\n+\n+static int ksz_port_fdb_del(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_fdb *fdb)\n+{\n+\tNOTIMPL();\n+}\n+\n+static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,\n+\t\t\t struct switchdev_obj_port_fdb *fdb,\n+\t\t\t switchdev_obj_dump_cb_t *cb)\n+{\n+\tNOTIMPL();\n+}\n+\n+static int ksz_port_mdb_prepare(struct dsa_switch *ds, int port,\n+\t\t\t\tconst struct switchdev_obj_port_mdb *mdb,\n+\t\t\t\tstruct switchdev_trans *trans)\n+{\n+\t/* nothing to do */\n+\treturn 0;\n+}\n+\n+static void ksz_port_mdb_add(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_mdb *mdb,\n+\t\t\t struct switchdev_trans *trans)\n+{\n+\tNOTIMPLV();\n+}\n+\n+static int ksz_port_mdb_del(struct dsa_switch *ds, int port,\n+\t\t\t const struct switchdev_obj_port_mdb *mdb)\n+{\n+\tNOTIMPL();\n+}\n+\n+static int ksz_port_mdb_dump(struct dsa_switch *ds, int port,\n+\t\t\t struct switchdev_obj_port_mdb *mdb,\n+\t\t\t switchdev_obj_dump_cb_t *cb)\n+{\n+\t/* this is not called by switch layer */\n+\treturn 0;\n+}\n+\n+static int ksz_port_mirror_add(struct dsa_switch *ds, int port,\n+\t\t\t struct dsa_mall_mirror_tc_entry *mirror,\n+\t\t\t bool ingress)\n+{\n+\tNOTIMPL();\n+\n+}\n+\n+static void ksz_port_mirror_del(struct dsa_switch *ds, int port,\n+\t\t\t\tstruct dsa_mall_mirror_tc_entry *mirror)\n+{\n+\tNOTIMPLV();\n+}\n+\n+static const struct dsa_switch_ops ksz_switch_ops = {\n+\t.get_tag_protocol\t= ksz_get_tag_protocol,\n+\t.setup\t\t\t= ksz_setup,\n+\t.phy_read\t\t= ksz_phy_read16,\n+\t.phy_write\t\t= ksz_phy_write16,\n+\t.port_enable\t\t= ksz_enable_port,\n+\t.port_disable\t\t= ksz_disable_port,\n+\t.get_strings\t\t= ksz_get_strings,\n+\t.get_ethtool_stats\t= ksz_get_ethtool_stats,\n+\t.get_sset_count\t\t= ksz_sset_count,\n+\t.port_bridge_join\t= ksz_br_join,\n+\t.port_bridge_leave\t= ksz_br_leave,\n+\t.port_stp_state_set\t= ksz_port_stp_state_set,\n+\t.port_fast_age\t\t= ksz_port_fast_age,\n+\t.port_vlan_filtering\t= ksz_port_vlan_filtering,\n+\t.port_vlan_prepare\t= ksz_port_vlan_prepare,\n+\t.port_vlan_add\t\t= ksz_port_vlan_add,\n+\t.port_vlan_del\t\t= ksz_port_vlan_del,\n+\t.port_vlan_dump\t\t= ksz_port_vlan_dump,\n+\t.port_fdb_prepare\t= ksz_port_fdb_prepare,\n+\t.port_fdb_dump\t\t= ksz_port_fdb_dump,\n+\t.port_fdb_add\t\t= ksz_port_fdb_add,\n+\t.port_fdb_del\t\t= ksz_port_fdb_del,\n+\t.port_mdb_prepare = ksz_port_mdb_prepare,\n+\t.port_mdb_add = ksz_port_mdb_add,\n+\t.port_mdb_del = ksz_port_mdb_del,\n+\t.port_mdb_dump = ksz_port_mdb_dump,\n+\t.port_mirror_add\t= ksz_port_mirror_add,\n+\t.port_mirror_del\t= ksz_port_mirror_del,\n+};\n+\n+struct ksz_chip_data {\n+\tu32 chip_id;\n+\tconst char *dev_name;\n+\tint num_vlans;\n+\tint num_alus;\n+\tint num_statics;\n+\tint cpu_ports;\n+\tint port_cnt;\n+};\n+\n+static const struct ksz_chip_data ksz_switch_chips[] = {\n+\t{\n+\t\t.chip_id = 0x95600c04,\n+\t\t.dev_name = \"KSZ8895\",\n+\t\t.num_vlans = 4096, /* FIXME ? */\n+\t\t.num_alus = 4096,\n+\t\t.num_statics = 16,\n+\t\t.cpu_ports = 0x10,\t/* can be configured as cpu port */\n+\t\t.port_cnt = 5,\t\t/* total physical port count */\n+\t},\n+};\n+\n+static int ksz_switch_init(struct ksz_device *dev)\n+{\n+\tint i;\n+\n+\tmutex_init(&dev->reg_mutex);\n+\tmutex_init(&dev->stats_mutex);\n+\tmutex_init(&dev->alu_mutex);\n+\tmutex_init(&dev->vlan_mutex);\n+\n+\tdev->ds->ops = &ksz_switch_ops;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) {\n+\t\tconst struct ksz_chip_data *chip = &ksz_switch_chips[i];\n+\n+\t\tif (dev->chip_id == chip->chip_id) {\n+\t\t\tdev->name = chip->dev_name;\n+\t\t\tdev->num_vlans = chip->num_vlans;\n+\t\t\tdev->num_alus = chip->num_alus;\n+\t\t\tdev->num_statics = chip->num_statics;\n+\t\t\tdev->port_cnt = chip->port_cnt;\n+\t\t\tdev->cpu_ports = chip->cpu_ports;\n+\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t\n+\tprintk(\"ksz_switch_init: detected %s\\n\", dev->name);\n+\n+\t/* no switch found */\n+\tif (!dev->port_cnt)\n+\t\treturn -ENODEV;\n+\n+\treturn 0;\n+}\n+\n+struct ksz_device *ksz_switch_alloc(struct device *base,\n+\t\t\t\t const struct ksz_io_ops *ops,\n+\t\t\t\t void *priv)\n+{\n+\tstruct dsa_switch *ds;\n+\tstruct ksz_device *swdev;\n+\n+\tds = dsa_switch_alloc(base, DSA_MAX_PORTS);\n+\tif (!ds)\n+\t\treturn NULL;\n+\n+\tswdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL);\n+\tif (!swdev)\n+\t\treturn NULL;\n+\n+\tds->priv = swdev;\n+\tswdev->dev = base;\n+\n+\tswdev->ds = ds;\n+\tswdev->priv = priv;\n+\tswdev->ops = ops;\n+\n+\treturn swdev;\n+}\n+EXPORT_SYMBOL(ksz_switch_alloc);\n+\n+int ksz_switch_detect(struct ksz_device *dev)\n+{\n+\tu8 data8;\n+\tu32 id32;\n+\tint ret;\n+\n+\t/* read chip id */\n+\tret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);\n+\tif (ret)\n+\t\treturn ret;\n+\t\n+\tret = ksz_read8(dev, 0, &data8);\n+\tret = ksz_read8(dev, 1, &data8);\n+\tret = ksz_read8(dev, 2, &data8);\n+\tret = ksz_read8(dev, 3, &data8);\n+\t\n+\tdev->chip_id = id32;\n+\n+\treturn 0;\n+}\n+EXPORT_SYMBOL(ksz_switch_detect);\n+\n+int ksz_switch_register(struct ksz_device *dev)\n+{\n+\tint ret;\n+\n+\tif (dev->pdata)\n+\t\tdev->chip_id = dev->pdata->chip_id;\n+\n+\tif (ksz_switch_detect(dev))\n+\t\treturn -EINVAL;\n+\n+\tret = ksz_switch_init(dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\n+\treturn dsa_register_switch(dev->ds);\n+}\n+EXPORT_SYMBOL(ksz_switch_register);\n+\n+void ksz_switch_remove(struct ksz_device *dev)\n+{\n+\tdsa_unregister_switch(dev->ds);\n+}\n+EXPORT_SYMBOL(ksz_switch_remove);\n+\n+MODULE_AUTHOR(\"Woojung Huh <Woojung.Huh@microchip.com>\");\n+MODULE_DESCRIPTION(\"Microchip KSZ Series Switch DSA Driver\");\n+MODULE_LICENSE(\"GPL\");\ndiff --git a/drivers/net/dsa/microchip/ksz_8895_reg.h b/drivers/net/dsa/microchip/ksz_8895_reg.h\nnew file mode 100644\nindex 000000000000..b6490c42448e\n--- /dev/null\n+++ b/drivers/net/dsa/microchip/ksz_8895_reg.h\n@@ -0,0 +1,769 @@\n+/*\n+ * Microchip KSZ9477 register definitions\n+ *\n+ * Copyright (C) 2017\n+ *\n+ * Permission to use, copy, modify, and/or distribute this software for any\n+ * purpose with or without fee is hereby granted, provided that the above\n+ * copyright notice and this permission notice appear in all copies.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n+ */\n+\n+#ifndef __KSZ9477_REGS_H\n+#define __KSZ9477_REGS_H\n+\n+#define KS_PRIO_M\t\t\t0x3\n+#define KS_PRIO_S\t\t\t2\n+\n+/* 0 - Operation */\n+#define REG_CHIP_ID0__1\t\t\t0x0000\n+\n+#define REG_CHIP_ID1__1\t\t\t0x0001\n+\n+#define SW_START 1\n+\n+#define FAMILY_ID\t\t\t0x95\n+#define FAMILY_ID_94\t\t\t0x94\n+#define FAMILY_ID_95\t\t\t0x95\n+#define FAMILY_ID_85\t\t\t0x85\n+#define FAMILY_ID_98\t\t\t0x98\n+#define FAMILY_ID_88\t\t\t0x88\n+\n+#define TOTAL_SWITCH_COUNTER_NUM\t1\n+#define PORT_CTRL_ADDR(port, addr)\t((addr) | (((port) + 1) << 4))\n+\n+#define ADDR_SHIFT\t\t\t14\n+#define ADDR_8\t\t\t\t1\n+#define ADDR_16\t\t\t\t2\n+#define ADDR_24\t\t\t\t3\n+#define ADDR_32\t\t\t\t4\n+\n+#define BANK_SHIFT\t\t\t12\n+\n+#define PHY_REG(addr, reg)\t\t\\\n+\t(((addr) << ADDR_SHIFT) | (reg))\n+\n+#define PHY_BANK_REG(addr, bank, reg)\t\\\n+\t(((addr) << ADDR_SHIFT) | ((bank) << BANK_SHIFT) | (reg))\n+\n+/* Use PHY access if no direct access. */\n+#ifndef SW_R8\n+#define SW_R8(s, r)\tphy_read(s->phydev, PHY_REG(ADDR_8, r))\n+#define SW_W8(s, r, v)\tphy_write(s->phydev, PHY_REG(ADDR_8, r), v)\n+#define SW_R16(s, r)\tphy_read(s->phydev, PHY_REG(ADDR_16, r))\n+#define SW_W16(s, r, v)\tphy_write(s->phydev, PHY_REG(ADDR_16, r), v)\n+#define SW_R32(s, r)\tphy_read(s->phydev, PHY_REG(ADDR_32, r))\n+#define SW_W32(s, r, v) \\\n+\tdo { \\\n+\t\tphy_write(s->phydev, PHY_REG(ADDR_32, (r) + 2), (v) >> 16); \\\n+\t\tphy_write(s->phydev, PHY_REG(ADDR_32, r), v); \\\n+\t} while (0)\n+#define SW_LOCK(s)\t\t\t\t\\\n+\tdo {\t\t\t\t\t\\\n+\t\tmutex_lock(s->hwlock);\t\t\\\n+\t} while (0)\n+#define SW_UNLOCK(s)\t\t\t\t\\\n+\tdo {\t\t\t\t\t\\\n+\t\tmutex_unlock(s->hwlock);\t\\\n+\t} while (0)\n+#endif\n+\n+\n+#define KS_PORT_M\t\t\t0x1F\n+\n+#define REG_CHIP_ID0\t\t\t0x00\n+\n+#define FAMILY_ID\t\t\t0x95\n+\n+#define REG_CHIP_ID1\t\t\t0x01\n+\n+#define SW_CHIP_ID_M\t\t\t0xF0\n+#define SW_CHIP_ID_S\t\t\t4\n+#define SW_REVISION_M\t\t\t0x0E\n+#define SW_REVISION_S\t\t\t1\n+\n+#define CHIP_ID_95\t\t\t0x40\n+#define CHIP_ID_95R\t\t\t0x60\n+\n+#define REG_SW_CTRL_0\t\t\t0x02\n+\n+#define SW_NEW_BACKOFF\t\t\t(1 << 7)\n+#define SW_FLUSH_DYN_MAC_TABLE\t\t(1 << 5)\n+#define SW_FLUSH_STA_MAC_TABLE\t\t(1 << 4)\n+#define SW_UNH_MODE\t\t\t(1 << 1)\n+#define SW_LINK_AUTO_AGING\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_1\t\t\t0x03\n+\n+#define SW_PASS_ALL\t\t\t(1 << 7)\n+#define SW_2K_PACKET\t\t\t(1 << 6)\n+#define SW_TX_FLOW_CTRL_DISABLE\t\t(1 << 5)\n+#define SW_RX_FLOW_CTRL_DISABLE\t\t(1 << 4)\n+#define SW_CHECK_LENGTH\t\t\t(1 << 3)\n+#define SW_AGING_ENABLE\t\t\t(1 << 2)\n+#define SW_FAST_AGING\t\t\t(1 << 1)\n+#define SW_AGGR_BACKOFF\t\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_2\t\t\t0x04\n+\n+#define UNICAST_VLAN_BOUNDARY\t\t(1 << 7)\n+#define MULTICAST_STORM_DISABLE\t\t(1 << 6)\n+#define SW_BACK_PRESSURE\t\t(1 << 5)\n+#define FAIR_FLOW_CTRL\t\t\t(1 << 4)\n+#define NO_EXC_COLLISION_DROP\t\t(1 << 3)\n+#define SW_HUGE_PACKET\t\t\t(1 << 2)\n+#define SW_LEGAL_PACKET\t\t\t(1 << 1)\n+\n+#define REG_SW_CTRL_3\t\t\t0x05\n+#define SW_VLAN_ENABLE\t\t\t(1 << 7)\n+#define SW_IGMP_SNOOP\t\t\t(1 << 6)\n+#define SW_DIRECT\t\t\t(1 << 5)\n+#define SW_PRE_TAG\t\t\t(1 << 4)\n+#define SW_VLAN_TAG\t\t\t(1 << 1)\n+#define SW_MIRROR_RX_TX\t\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_4\t\t\t0x06\n+\n+#define SW_HALF_DUPLEX_FLOW_CTRL\t(1 << 7)\n+#define SW_HALF_DUPLEX\t\t\t(1 << 6)\n+#define SW_FLOW_CTRL\t\t\t(1 << 5)\n+#define SW_10_MBIT\t\t\t(1 << 4)\n+#define SW_REPLACE_VID\t\t\t(1 << 3)\n+#define BROADCAST_STORM_RATE_HI\t\t0x07\n+\n+#define REG_SW_CTRL_5\t\t\t0x07\n+\n+#define BROADCAST_STORM_RATE_LO\t\t0xFF\n+#define BROADCAST_STORM_RATE\t\t0x07FF\n+\n+#define REG_SW_CTRL_9\t\t\t0x0B\n+\n+#define SW_DATA_SAMPLING_NEG\t\t(1 << 6)\n+#define SW_PHY_POWER_SAVE_DISABLE\t(1 << 3)\n+#define SW_LED_MODE_1\t\t\t(1 << 1)\n+#define SW_SPI_SAMPLING_RISING\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_10\t\t\t0x0C\n+\n+#define SPI_CLK_125_MHZ\t\t\t0x20\n+#define SPI_CLK_83_33_MHZ\t\t0x10\n+#define SPI_CLK_41_67_MHZ\t\t0x00\n+#define SW_TAIL_TAG_ENABLE\t\t(1 << 1)\n+#define SW_PASS_PAUSE\t\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_11\t\t\t0x0D\n+\n+#define REG_POWER_MANAGEMENT_1\t\t0x0E\n+\n+#define SW_PLL_POWER_DOWN\t\t(1 << 5)\n+#define SW_POWER_MANAGEMENT_MODE_M\t0x3\n+#define SW_POWER_MANAGEMENT_MODE_S\t3\n+#define SW_POWER_NORMAL\t\t\t0\n+#define SW_ENERGY_DETECTION\t\t1\n+#define SW_SOFTWARE_POWER_DOWN\t\t2\n+#define SW_POWER_SAVING\t\t\t3\n+\n+#define REG_POWER_MANAGEMENT_2\t\t0x0F\n+\n+\n+#define REG_PORT_1_CTRL_0\t\t0x10\n+#define REG_PORT_2_CTRL_0\t\t0x20\n+#define REG_PORT_3_CTRL_0\t\t0x30\n+#define REG_PORT_4_CTRL_0\t\t0x40\n+#define REG_PORT_5_CTRL_0\t\t0x50\n+\n+#define PORT_BROADCAST_STORM\t\t(1 << 7)\n+#define PORT_DIFFSERV_ENABLE\t\t(1 << 6)\n+#define PORT_802_1P_ENABLE\t\t(1 << 5)\n+#define PORT_BASED_PRIO_S\t\t3\n+#define PORT_BASED_PRIO_M\t\t(KS_PRIO_M << PORT_BASED_PRIO_S)\n+#define PORT_PORT_PRIO_0\t\t0\n+#define PORT_PORT_PRIO_1\t\t1\n+#define PORT_PORT_PRIO_2\t\t2\n+#define PORT_PORT_PRIO_3\t\t3\n+#define PORT_INSERT_TAG\t\t\t(1 << 2)\n+#define PORT_REMOVE_TAG\t\t\t(1 << 1)\n+#define PORT_QUEUE_SPLIT_L\t\t(1 << 0)\n+\n+#define REG_PORT_1_CTRL_1\t\t0x11\n+#define REG_PORT_2_CTRL_1\t\t0x21\n+#define REG_PORT_3_CTRL_1\t\t0x31\n+#define REG_PORT_4_CTRL_1\t\t0x41\n+#define REG_PORT_5_CTRL_1\t\t0x51\n+\n+#define PORT_MIRROR_SNIFFER\t\t(1 << 7)\n+#define PORT_MIRROR_RX\t\t\t(1 << 6)\n+#define PORT_MIRROR_TX\t\t\t(1 << 5)\n+#define PORT_VLAN_MEMBERSHIP\t\tKS_PORT_M\n+\n+#define REG_PORT_1_CTRL_2\t\t0x12\n+#define REG_PORT_2_CTRL_2\t\t0x22\n+#define REG_PORT_3_CTRL_2\t\t0x32\n+#define REG_PORT_4_CTRL_2\t\t0x42\n+#define REG_PORT_5_CTRL_2\t\t0x52\n+\n+#define PORT_802_1P_REMAPPING\t\t(1 << 7)\n+#define PORT_INGRESS_FILTER\t\t(1 << 6)\n+#define PORT_DISCARD_NON_VID\t\t(1 << 5)\n+#define PORT_FORCE_FLOW_CTRL\t\t(1 << 4)\n+#define PORT_BACK_PRESSURE\t\t(1 << 3)\n+#define PORT_TX_ENABLE\t\t\t(1 << 2)\n+#define PORT_RX_ENABLE\t\t\t(1 << 1)\n+#define PORT_LEARN_DISABLE\t\t(1 << 0)\n+\n+#define REG_PORT_1_CTRL_3\t\t0x13\n+#define REG_PORT_2_CTRL_3\t\t0x23\n+#define REG_PORT_3_CTRL_3\t\t0x33\n+#define REG_PORT_4_CTRL_3\t\t0x43\n+#define REG_PORT_5_CTRL_3\t\t0x53\n+#define REG_PORT_1_CTRL_4\t\t0x14\n+#define REG_PORT_2_CTRL_4\t\t0x24\n+#define REG_PORT_3_CTRL_4\t\t0x34\n+#define REG_PORT_4_CTRL_4\t\t0x44\n+#define REG_PORT_5_CTRL_4\t\t0x54\n+\n+#define PORT_DEFAULT_VID\t\t0x0001\n+\n+#define REG_PORT_1_STATUS_0\t\t0x19\n+#define REG_PORT_2_STATUS_0\t\t0x29\n+#define REG_PORT_3_STATUS_0\t\t0x39\n+#define REG_PORT_4_STATUS_0\t\t0x49\n+#define REG_PORT_5_STATUS_0\t\t0x59\n+\n+#define PORT_HP_MDIX\t\t\t(1 << 7)\n+#define PORT_REVERSED_POLARITY\t\t(1 << 5)\n+#define PORT_TX_FLOW_CTRL\t\t(1 << 4)\n+#define PORT_RX_FLOW_CTRL\t\t(1 << 3)\n+#define PORT_STAT_SPEED_100MBIT\t\t(1 << 2)\n+#define PORT_STAT_FULL_DUPLEX\t\t(1 << 1)\n+\n+#define REG_PORT_1_LINK_MD_CTRL\t\t0x1A\n+#define REG_PORT_2_LINK_MD_CTRL\t\t0x2A\n+#define REG_PORT_3_LINK_MD_CTRL\t\t0x3A\n+#define REG_PORT_4_LINK_MD_CTRL\t\t0x4A\n+#define REG_PORT_5_LINK_MD_CTRL\t\t0x5A\n+\n+#define PORT_CABLE_10M_SHORT\t\t(1 << 7)\n+#define PORT_CABLE_DIAG_RESULT_M\t0x3\n+#define PORT_CABLE_DIAG_RESULT_S\t5\n+#define PORT_CABLE_STAT_NORMAL\t\t0\n+#define PORT_CABLE_STAT_OPEN\t\t1\n+#define PORT_CABLE_STAT_SHORT\t\t2\n+#define PORT_CABLE_STAT_FAILED\t\t3\n+#define PORT_START_CABLE_DIAG\t\t(1 << 4)\n+#define PORT_FORCE_LINK\t\t\t(1 << 3)\n+#define PORT_POWER_SAVING\t\t(1 << 2)\n+#define PORT_PHY_REMOTE_LOOPBACK\t(1 << 1)\n+#define PORT_CABLE_FAULT_COUNTER_H\t0x01\n+\n+#define REG_PORT_1_LINK_MD_RESULT\t0x1B\n+#define REG_PORT_2_LINK_MD_RESULT\t0x2B\n+#define REG_PORT_3_LINK_MD_RESULT\t0x3B\n+#define REG_PORT_4_LINK_MD_RESULT\t0x4B\n+#define REG_PORT_5_LINK_MD_RESULT\t0x5B\n+\n+#define PORT_CABLE_FAULT_COUNTER_L\t0xFF\n+#define PORT_CABLE_FAULT_COUNTER\t0x1FF\n+\n+#define REG_PORT_1_CTRL_5\t\t0x1C\n+#define REG_PORT_2_CTRL_5\t\t0x2C\n+#define REG_PORT_3_CTRL_5\t\t0x3C\n+#define REG_PORT_4_CTRL_5\t\t0x4C\n+#define REG_PORT_5_CTRL_5\t\t0x5C\n+\n+#define PORT_AUTO_NEG_DISABLE\t\t(1 << 7)\n+#define PORT_FORCE_100_MBIT\t\t(1 << 6)\n+#define PORT_FORCE_FULL_DUPLEX\t\t(1 << 5)\n+#define PORT_AUTO_NEG_SYM_PAUSE\t\t(1 << 4)\n+#define PORT_AUTO_NEG_100BTX_FD\t\t(1 << 3)\n+#define PORT_AUTO_NEG_100BTX\t\t(1 << 2)\n+#define PORT_AUTO_NEG_10BT_FD\t\t(1 << 1)\n+#define PORT_AUTO_NEG_10BT\t\t(1 << 0)\n+\n+#define REG_PORT_1_CTRL_6\t\t0x1D\n+#define REG_PORT_2_CTRL_6\t\t0x2D\n+#define REG_PORT_3_CTRL_6\t\t0x3D\n+#define REG_PORT_4_CTRL_6\t\t0x4D\n+#define REG_PORT_5_CTRL_6\t\t0x5D\n+\n+#define PORT_LED_OFF\t\t\t(1 << 7)\n+#define PORT_TX_DISABLE\t\t\t(1 << 6)\n+#define PORT_AUTO_NEG_RESTART\t\t(1 << 5)\n+#define PORT_POWER_DOWN\t\t\t(1 << 3)\n+#define PORT_AUTO_MDIX_DISABLE\t\t(1 << 2)\n+#define PORT_FORCE_MDIX\t\t\t(1 << 1)\n+#define PORT_MAC_LOOPBACK\t\t(1 << 0)\n+\n+#define REG_PORT_1_STATUS_1\t\t0x1E\n+#define REG_PORT_2_STATUS_1\t\t0x2E\n+#define REG_PORT_3_STATUS_1\t\t0x3E\n+#define REG_PORT_4_STATUS_1\t\t0x4E\n+#define REG_PORT_5_STATUS_1\t\t0x5E\n+\n+#define PORT_MDIX_STATUS\t\t(1 << 7)\n+#define PORT_AUTO_NEG_COMPLETE\t\t(1 << 6)\n+#define PORT_STAT_LINK_GOOD\t\t(1 << 5)\n+#define PORT_REMOTE_SYM_PAUSE\t\t(1 << 4)\n+#define PORT_REMOTE_100BTX_FD\t\t(1 << 3)\n+#define PORT_REMOTE_100BTX\t\t(1 << 2)\n+#define PORT_REMOTE_10BT_FD\t\t(1 << 1)\n+#define PORT_REMOTE_10BT\t\t(1 << 0)\n+\n+#define REG_PORT_1_STATUS_2\t\t0x1F\n+#define REG_PORT_2_STATUS_2\t\t0x2F\n+#define REG_PORT_3_STATUS_2\t\t0x3F\n+#define REG_PORT_4_STATUS_2\t\t0x4F\n+#define REG_PORT_5_STATUS_2\t\t0x5F\n+\n+#define PORT_PHY_LOOPBACK\t\t(1 << 7)\n+#define PORT_PHY_ISOLATE\t\t(1 << 5)\n+#define PORT_PHY_SOFT_RESET\t\t(1 << 4)\n+#define PORT_PHY_FORCE_LINK\t\t(1 << 3)\n+#define PORT_PHY_MODE_M\t\t\t0x7\n+#define PHY_MODE_IN_AUTO_NEG\t\t1\n+#define PHY_MODE_10BT_HALF\t\t2\n+#define PHY_MODE_100BT_HALF\t\t3\n+#define PHY_MODE_10BT_FULL\t\t5\n+#define PHY_MODE_100BT_FULL\t\t6\n+#define PHY_MODE_ISOLDATE\t\t7\n+\n+#define REG_PORT_CTRL_0\t\t\t0x00\n+#define REG_PORT_CTRL_1\t\t\t0x01\n+#define REG_PORT_CTRL_2\t\t\t0x02\n+#define REG_PORT_CTRL_VID\t\t0x03\n+\n+#define REG_PORT_STATUS_0\t\t0x09\n+#define REG_PORT_LINK_MD_CTRL\t\t0x0A\n+#define REG_PORT_LINK_MD_RESULT\t\t0x0B\n+#define REG_PORT_CTRL_5\t\t\t0x0C\n+#define REG_PORT_CTRL_6\t\t\t0x0D\n+#define REG_PORT_STATUS_1\t\t0x0E\n+#define REG_PORT_STATUS_2\t\t0x0F\n+\n+#define REG_PORT_CTRL_8\t\t\t0xA0\n+#define REG_PORT_CTRL_9\t\t\t0xA1\n+#define REG_PORT_RATE_CTRL_3\t\t0xA2\n+#define REG_PORT_RATE_CTRL_2\t\t0xA3\n+#define REG_PORT_RATE_CTRL_1\t\t0xA4\n+#define REG_PORT_RATE_CTRL_0\t\t0xA5\n+#define REG_PORT_RATE_LIMIT\t\t0xA6\n+#define REG_PORT_IN_RATE_0\t\t0xA7\n+#define REG_PORT_IN_RATE_1\t\t0xA8\n+#define REG_PORT_IN_RATE_2\t\t0xA9\n+#define REG_PORT_IN_RATE_3\t\t0xAA\n+#define REG_PORT_OUT_RATE_0\t\t0xAB\n+#define REG_PORT_OUT_RATE_1\t\t0xAC\n+#define REG_PORT_OUT_RATE_2\t\t0xAD\n+#define REG_PORT_OUT_RATE_3\t\t0xAE\n+\n+#define REG_SW_MAC_ADDR_0\t\t0x68\n+#define REG_SW_MAC_ADDR_1\t\t0x69\n+#define REG_SW_MAC_ADDR_2\t\t0x6A\n+#define REG_SW_MAC_ADDR_3\t\t0x6B\n+#define REG_SW_MAC_ADDR_4\t\t0x6C\n+#define REG_SW_MAC_ADDR_5\t\t0x6D\n+\n+#define REG_IND_CTRL_0\t\t\t0x6E\n+\n+#define TABLE_READ\t\t\t(1 << 4)\n+#define TABLE_SELECT_S\t\t\t2\n+#define TABLE_STATIC_MAC\t\t(0 << TABLE_SELECT_S)\n+#define TABLE_VLAN\t\t\t(1 << TABLE_SELECT_S)\n+#define TABLE_DYNAMIC_MAC\t\t(2 << TABLE_SELECT_S)\n+#define TABLE_MIB\t\t\t(3 << TABLE_SELECT_S)\n+\n+#define REG_IND_CTRL_1\t\t\t0x6F\n+\n+#define TABLE_ENTRY_MASK\t\t0x03FF\n+\n+#define REG_IND_DATA_8\t\t\t0x70\n+#define REG_IND_DATA_7\t\t\t0x71\n+#define REG_IND_DATA_6\t\t\t0x72\n+#define REG_IND_DATA_5\t\t\t0x73\n+#define REG_IND_DATA_4\t\t\t0x74\n+#define REG_IND_DATA_3\t\t\t0x75\n+#define REG_IND_DATA_2\t\t\t0x76\n+#define REG_IND_DATA_1\t\t\t0x77\n+#define REG_IND_DATA_0\t\t\t0x78\n+\n+#define REG_IND_DATA_CHECK\t\tREG_IND_DATA_6\n+#define REG_IND_MIB_CHECK\t\tREG_IND_DATA_3\n+#define REG_IND_DATA_HI\t\t\tREG_IND_DATA_7\n+#define REG_IND_DATA_LO\t\t\tREG_IND_DATA_3\n+\n+#define REG_INT_STATUS\t\t\t0x7C\n+#define REG_INT_ENABLE\t\t\t0x7D\n+\n+#define INT_PORT_5\t\t\t(1 << 4)\n+#define INT_PORT_4\t\t\t(1 << 3)\n+#define INT_PORT_3\t\t\t(1 << 2)\n+#define INT_PORT_2\t\t\t(1 << 1)\n+#define INT_PORT_1\t\t\t(1 << 0)\n+\n+#define REG_SW_CTRL_12\t\t\t0x80\n+#define REG_SW_CTRL_13\t\t\t0x81\n+\n+#define SWITCH_802_1P_MASK\t\t3\n+#define SWITCH_802_1P_BASE\t\t3\n+#define SWITCH_802_1P_SHIFT\t\t2\n+\n+#define SW_802_1P_MAP_M\t\t\tKS_PRIO_M\n+#define SW_802_1P_MAP_S\t\t\tKS_PRIO_S\n+\n+#define REG_SWITCH_CTRL_14\t\t0x82\n+\n+#define SW_PRIO_MAPPING_M\t\tKS_PRIO_M\n+#define SW_PRIO_MAPPING_S\t\t6\n+#define SW_PRIO_MAP_3_HI\t\t0\n+#define SW_PRIO_MAP_2_HI\t\t2\n+#define SW_PRIO_MAP_0_LO\t\t3\n+\n+#define REG_SW_CTRL_15\t\t\t0x83\n+#define REG_SW_CTRL_16\t\t\t0x84\n+\n+#define SW_DRIVE_STRENGTH_M\t\t0x3\n+#define SW_DRIVE_STRENGTH_4MA\t\t0\n+#define SW_DRIVE_STRENGTH_8MA\t\t1\n+#define SW_DRIVE_STRENGTH_10MA\t\t2\n+#define SW_DRIVE_STRENGTH_14MA\t\t3\n+#define SW_MII_DRIVE_STRENGTH_S\t\t6\n+\n+#define REG_SW_CTRL_17\t\t\t0x85\n+#define REG_SW_CTRL_18\t\t\t0x86\n+\n+#define SW_SELF_ADDR_FILTER_ENABLE\t(1 << 6)\n+\n+#define REG_SW_UNK_UCAST_CTRL\t\t0x83\n+#define REG_SW_UNK_MCAST_CTRL\t\t0x84\n+#define REG_SW_UNK_VID_CTRL\t\t0x85\n+#define REG_SW_UNK_IP_MCAST_CTRL\t0x86\n+\n+#define SW_UNK_FWD_ENABLE\t\t(1 << 5)\n+#define SW_UNK_FWD_MAP\t\t\tKS_PORT_M\n+\n+#define REG_SW_CTRL_19\t\t\t0x87\n+\n+#define SW_IN_RATE_LIMIT_PERIOD_M\t0x3\n+#define SW_IN_RATE_LIMIT_PERIOD_S\t4\n+#define SW_IN_RATE_LIMIT_16_MS\t\t0\n+#define SW_IN_RATE_LIMIT_64_MS\t\t1\n+#define SW_IN_RATE_LIMIT_256_MS\t\t2\n+#define SW_QUEUE_BASED_OUT_RATE_LIMIT\t(1 << 3)\n+#define SW_INS_TAG_ENABLE\t\t(1 << 2)\n+\n+#define REG_TOS_PRIO_CTRL_0\t\t0x90\n+#define REG_TOS_PRIO_CTRL_1\t\t0x91\n+#define REG_TOS_PRIO_CTRL_2\t\t0x92\n+#define REG_TOS_PRIO_CTRL_3\t\t0x93\n+#define REG_TOS_PRIO_CTRL_4\t\t0x94\n+#define REG_TOS_PRIO_CTRL_5\t\t0x95\n+#define REG_TOS_PRIO_CTRL_6\t\t0x96\n+#define REG_TOS_PRIO_CTRL_7\t\t0x97\n+#define REG_TOS_PRIO_CTRL_8\t\t0x98\n+#define REG_TOS_PRIO_CTRL_9\t\t0x99\n+#define REG_TOS_PRIO_CTRL_10\t\t0x9A\n+#define REG_TOS_PRIO_CTRL_11\t\t0x9B\n+#define REG_TOS_PRIO_CTRL_12\t\t0x9C\n+#define REG_TOS_PRIO_CTRL_13\t\t0x9D\n+#define REG_TOS_PRIO_CTRL_14\t\t0x9E\n+#define REG_TOS_PRIO_CTRL_15\t\t0x9F\n+\n+#define TOS_PRIO_M\t\t\tKS_PRIO_M\n+#define TOS_PRIO_S\t\t\tKS_PRIO_S\n+\n+\n+#define REG_PORT_1_CTRL_8\t\t0xB0\n+#define REG_PORT_2_CTRL_8\t\t0xC0\n+#define REG_PORT_3_CTRL_8\t\t0xD0\n+#define REG_PORT_4_CTRL_8\t\t0xE0\n+#define REG_PORT_5_CTRL_8\t\t0xF0\n+\n+#define PORT_INS_TAG_FOR_PORT_5_S\t3\n+#define PORT_INS_TAG_FOR_PORT_5\t\t(1 << 3)\n+#define PORT_INS_TAG_FOR_PORT_4\t\t(1 << 2)\n+#define PORT_INS_TAG_FOR_PORT_3\t\t(1 << 1)\n+#define PORT_INS_TAG_FOR_PORT_2\t\t(1 << 0)\n+\n+#define REG_PORT_1_CTRL_9\t\t0xB1\n+#define REG_PORT_2_CTRL_9\t\t0xC1\n+#define REG_PORT_3_CTRL_9\t\t0xD1\n+#define REG_PORT_4_CTRL_9\t\t0xE1\n+#define REG_PORT_5_CTRL_9\t\t0xF1\n+\n+#define PORT_QUEUE_SPLIT_H\t\t(1 << 1)\n+#define PORT_QUEUE_SPLIT_1\t\t0\n+#define PORT_QUEUE_SPLIT_2\t\t1\n+#define PORT_QUEUE_SPLIT_4\t\t2\n+#define PORT_DROP_TAG\t\t\t(1 << 0)\n+\n+#define REG_PORT_1_CTRL_10\t\t0xB2\n+#define REG_PORT_2_CTRL_10\t\t0xC2\n+#define REG_PORT_3_CTRL_10\t\t0xD2\n+#define REG_PORT_4_CTRL_10\t\t0xE2\n+#define REG_PORT_5_CTRL_10\t\t0xF2\n+#define REG_PORT_1_CTRL_11\t\t0xB3\n+#define REG_PORT_2_CTRL_11\t\t0xC3\n+#define REG_PORT_3_CTRL_11\t\t0xD3\n+#define REG_PORT_4_CTRL_11\t\t0xE3\n+#define REG_PORT_5_CTRL_11\t\t0xF3\n+#define REG_PORT_1_CTRL_12\t\t0xB4\n+#define REG_PORT_2_CTRL_12\t\t0xC4\n+#define REG_PORT_3_CTRL_12\t\t0xD4\n+#define REG_PORT_4_CTRL_12\t\t0xE4\n+#define REG_PORT_5_CTRL_12\t\t0xF4\n+#define REG_PORT_1_CTRL_13\t\t0xB5\n+#define REG_PORT_2_CTRL_13\t\t0xC5\n+#define REG_PORT_3_CTRL_13\t\t0xD5\n+#define REG_PORT_4_CTRL_13\t\t0xE5\n+#define REG_PORT_5_CTRL_13\t\t0xF5\n+\n+#define REG_PORT_1_RATE_CTRL_3\t\t0xB2\n+#define REG_PORT_1_RATE_CTRL_2\t\t0xB3\n+#define REG_PORT_1_RATE_CTRL_1\t\t0xB4\n+#define REG_PORT_1_RATE_CTRL_0\t\t0xB5\n+#define REG_PORT_2_RATE_CTRL_3\t\t0xC2\n+#define REG_PORT_2_RATE_CTRL_2\t\t0xC3\n+#define REG_PORT_2_RATE_CTRL_1\t\t0xC4\n+#define REG_PORT_2_RATE_CTRL_0\t\t0xC5\n+#define REG_PORT_3_RATE_CTRL_3\t\t0xD2\n+#define REG_PORT_3_RATE_CTRL_2\t\t0xD3\n+#define REG_PORT_3_RATE_CTRL_1\t\t0xD4\n+#define REG_PORT_3_RATE_CTRL_0\t\t0xD5\n+#define REG_PORT_4_RATE_CTRL_3\t\t0xE2\n+#define REG_PORT_4_RATE_CTRL_2\t\t0xE3\n+#define REG_PORT_4_RATE_CTRL_1\t\t0xE4\n+#define REG_PORT_4_RATE_CTRL_0\t\t0xE5\n+#define REG_PORT_5_RATE_CTRL_3\t\t0xF2\n+#define REG_PORT_5_RATE_CTRL_2\t\t0xF3\n+#define REG_PORT_5_RATE_CTRL_1\t\t0xF4\n+#define REG_PORT_5_RATE_CTRL_0\t\t0xF5\n+\n+#define RATE_CTRL_ENABLE\t\t(1 << 7)\n+#define RATE_RATIO_M\t\t\t((1 << 7) - 1)\n+\n+#define REG_PORT_1_RATE_LIMIT\t\t0xB6\n+#define REG_PORT_2_RATE_LIMIT\t\t0xC6\n+#define REG_PORT_3_RATE_LIMIT\t\t0xD6\n+#define REG_PORT_4_RATE_LIMIT\t\t0xE6\n+#define REG_PORT_5_RATE_LIMIT\t\t0xF6\n+\n+#define PORT_IN_FLOW_CTRL_S\t\t4\n+#define PORT_IN_LIMIT_MODE_M\t\t0x3\n+#define PORT_IN_LIMIT_MODE_S\t\t2\n+#define PORT_COUNT_IFG_S\t\t1\n+#define PORT_COUNT_PREAMBLE_S\t\t0\n+#define PORT_IN_FLOW_CTRL\t\t(1 << PORT_IN_FLOW_CTRL_S)\n+#define PORT_IN_ALL\t\t\t0\n+#define PORT_IN_UNICAST\t\t\t1\n+#define PORT_IN_MULTICAST\t\t2\n+#define PORT_IN_BROADCAST\t\t3\n+#define PORT_COUNT_IFG\t\t\t(1 << PORT_COUNT_IFG_S)\n+#define PORT_COUNT_PREAMBLE\t\t(1 << PORT_COUNT_PREAMBLE_S)\n+\n+#define REG_PORT_1_IN_RATE_0\t\t0xB7\n+#define REG_PORT_2_IN_RATE_0\t\t0xC7\n+#define REG_PORT_3_IN_RATE_0\t\t0xD7\n+#define REG_PORT_4_IN_RATE_0\t\t0xE7\n+#define REG_PORT_5_IN_RATE_0\t\t0xF7\n+#define REG_PORT_1_IN_RATE_1\t\t0xB8\n+#define REG_PORT_2_IN_RATE_1\t\t0xC8\n+#define REG_PORT_3_IN_RATE_1\t\t0xD8\n+#define REG_PORT_4_IN_RATE_1\t\t0xE8\n+#define REG_PORT_5_IN_RATE_1\t\t0xF8\n+#define REG_PORT_1_IN_RATE_2\t\t0xB9\n+#define REG_PORT_2_IN_RATE_2\t\t0xC9\n+#define REG_PORT_3_IN_RATE_2\t\t0xD9\n+#define REG_PORT_4_IN_RATE_2\t\t0xE9\n+#define REG_PORT_5_IN_RATE_2\t\t0xF9\n+#define REG_PORT_1_IN_RATE_3\t\t0xBA\n+#define REG_PORT_2_IN_RATE_3\t\t0xCA\n+#define REG_PORT_3_IN_RATE_3\t\t0xDA\n+#define REG_PORT_4_IN_RATE_3\t\t0xEA\n+#define REG_PORT_5_IN_RATE_3\t\t0xFA\n+\n+#define PORT_RATE_LIMIT_M\t\t((1 << 7) - 1)\n+\n+#define REG_PORT_1_OUT_RATE_0\t\t0xBB\n+#define REG_PORT_2_OUT_RATE_0\t\t0xCB\n+#define REG_PORT_3_OUT_RATE_0\t\t0xDB\n+#define REG_PORT_4_OUT_RATE_0\t\t0xEB\n+#define REG_PORT_5_OUT_RATE_0\t\t0xFB\n+#define REG_PORT_1_OUT_RATE_1\t\t0xBC\n+#define REG_PORT_2_OUT_RATE_1\t\t0xCC\n+#define REG_PORT_3_OUT_RATE_1\t\t0xDC\n+#define REG_PORT_4_OUT_RATE_1\t\t0xEC\n+#define REG_PORT_5_OUT_RATE_1\t\t0xFC\n+#define REG_PORT_1_OUT_RATE_2\t\t0xBD\n+#define REG_PORT_2_OUT_RATE_2\t\t0xCD\n+#define REG_PORT_3_OUT_RATE_2\t\t0xDD\n+#define REG_PORT_4_OUT_RATE_2\t\t0xED\n+#define REG_PORT_5_OUT_RATE_2\t\t0xFD\n+#define REG_PORT_1_OUT_RATE_3\t\t0xBE\n+#define REG_PORT_2_OUT_RATE_3\t\t0xCE\n+#define REG_PORT_3_OUT_RATE_3\t\t0xDE\n+#define REG_PORT_4_OUT_RATE_3\t\t0xEE\n+#define REG_PORT_5_OUT_RATE_3\t\t0xFE\n+\n+\n+#define REG_SW_CFG\t\t\t0xEF\n+\n+#define SW_PORT_3_FIBER\t\t\t(1 << 7)\n+\n+/* KSZ8864 */\n+\n+#define REG_PHY_PORT_CTRL_1\t\t0xCF\n+\n+#define PORT_HALF_DUPLEX\t\t(1 << 7)\n+#define PORT_FLOW_CTRL\t\t\t(1 << 6)\n+#define PORT_10_MBIT\t\t\t(1 << 5)\n+\n+#define REG_PHY_PORT_CTRL_2\t\t0xDF\n+\n+#define PORT_MII_MAC_MODE\t\t(1 << 6)\n+\n+#define REG_KSZ8864_CHIP_ID\t\t0xFE\n+\n+#define SW_KSZ8864\t\t\t(1 << 7)\n+\n+\n+#ifndef PHY_REG_CTRL\n+#define PHY_REG_CTRL\t\t\t0\n+\n+#define PHY_RESET\t\t\t(1 << 15)\n+#define PHY_LOOPBACK\t\t\t(1 << 14)\n+#define PHY_SPEED_100MBIT\t\t(1 << 13)\n+#define PHY_AUTO_NEG_ENABLE\t\t(1 << 12)\n+#define PHY_POWER_DOWN\t\t\t(1 << 11)\n+#define PHY_MII_DISABLE\t\t\t(1 << 10)\n+#define PHY_AUTO_NEG_RESTART\t\t(1 << 9)\n+#define PHY_FULL_DUPLEX\t\t\t(1 << 8)\n+#define PHY_COLLISION_TEST_NOT\t\t(1 << 7)\n+#define PHY_HP_MDIX\t\t\t(1 << 5)\n+#define PHY_FORCE_MDIX\t\t\t(1 << 4)\n+#define PHY_AUTO_MDIX_DISABLE\t\t(1 << 3)\n+#define PHY_REMOTE_FAULT_DISABLE\t(1 << 2)\n+#define PHY_TRANSMIT_DISABLE\t\t(1 << 1)\n+#define PHY_LED_DISABLE\t\t\t(1 << 0)\n+\n+#define PHY_REG_STATUS\t\t\t1\n+\n+#define PHY_100BT4_CAPABLE\t\t(1 << 15)\n+#define PHY_100BTX_FD_CAPABLE\t\t(1 << 14)\n+#define PHY_100BTX_CAPABLE\t\t(1 << 13)\n+#define PHY_10BT_FD_CAPABLE\t\t(1 << 12)\n+#define PHY_10BT_CAPABLE\t\t(1 << 11)\n+#define PHY_MII_SUPPRESS_CAPABLE_NOT\t(1 << 6)\n+#define PHY_AUTO_NEG_ACKNOWLEDGE\t(1 << 5)\n+#define PHY_REMOTE_FAULT\t\t(1 << 4)\n+#define PHY_AUTO_NEG_CAPABLE\t\t(1 << 3)\n+#define PHY_LINK_STATUS\t\t\t(1 << 2)\n+#define PHY_JABBER_DETECT_NOT\t\t(1 << 1)\n+#define PHY_EXTENDED_CAPABILITY\t\t(1 << 0)\n+\n+#define PHY_REG_ID_1\t\t\t2\n+#define PHY_REG_ID_2\t\t\t3\n+\n+#define KSZ8895_ID_HI\t\t\t0x0022\n+#define KSZ8895_ID_LO\t\t\t0x1450\n+\n+#define PHY_REG_AUTO_NEGOTIATION\t4\n+\n+#define PHY_AUTO_NEG_NEXT_PAGE_NOT\t(1 << 15)\n+#define PHY_AUTO_NEG_REMOTE_FAULT_NOT\t(1 << 13)\n+#define PHY_AUTO_NEG_SYM_PAUSE\t\t(1 << 10)\n+#define PHY_AUTO_NEG_100BT4\t\t(1 << 9)\n+#define PHY_AUTO_NEG_100BTX_FD\t\t(1 << 8)\n+#define PHY_AUTO_NEG_100BTX\t\t(1 << 7)\n+#define PHY_AUTO_NEG_10BT_FD\t\t(1 << 6)\n+#define PHY_AUTO_NEG_10BT\t\t(1 << 5)\n+#define PHY_AUTO_NEG_SELECTOR\t\t0x001F\n+#define PHY_AUTO_NEG_802_3\t\t0x0001\n+\n+#define PHY_REG_REMOTE_CAPABILITY\t5\n+\n+#define PHY_REMOTE_NEXT_PAGE_NOT\t(1 << 15)\n+#define PHY_REMOTE_ACKNOWLEDGE_NOT\t(1 << 14)\n+#define PHY_REMOTE_REMOTE_FAULT_NOT\t(1 << 13)\n+#define PHY_REMOTE_SYM_PAUSE\t\t(1 << 10)\n+#define PHY_REMOTE_100BTX_FD\t\t(1 << 8)\n+#define PHY_REMOTE_100BTX\t\t(1 << 7)\n+#define PHY_REMOTE_10BT_FD\t\t(1 << 6)\n+#define PHY_REMOTE_10BT\t\t\t(1 << 5)\n+\n+#define PHY_REG_LINK_MD\t\t\t0x1D\n+\n+#define PHY_START_CABLE_DIAG\t\t(1 << 15)\n+#define PHY_CABLE_DIAG_RESULT\t\t0x6000\n+#define PHY_CABLE_STAT_NORMAL\t\t0x0000\n+#define PHY_CABLE_STAT_OPEN\t\t0x2000\n+#define PHY_CABLE_STAT_SHORT\t\t0x4000\n+#define PHY_CABLE_STAT_FAILED\t\t0x6000\n+#define PHY_CABLE_10M_SHORT\t\t(1 << 12)\n+#define PHY_CABLE_FAULT_COUNTER\t\t0x01FF\n+\n+#define PHY_REG_PHY_CTRL\t\t0x1F\n+\n+#define PHY_MODE_M\t\t\t0x7\n+#define PHY_MODE_S\t\t\t8\n+#define PHY_STAT_REVERSED_POLARITY\t(1 << 5)\n+#define PHY_STAT_MDIX\t\t\t(1 << 4)\n+#define PHY_FORCE_LINK\t\t\t(1 << 3)\n+#define PHY_POWER_SAVING_ENABLE\t\t(1 << 2)\n+#define PHY_REMOTE_LOOPBACK\t\t(1 << 1)\n+#endif\n+\n+\n+/* Default values are used in ksz_sw.h if these are not defined. */\n+#define PRIO_QUEUES\t\t\t4\n+\n+#define KS_PRIO_IN_REG\t\t\t4\n+\n+#define SWITCH_PORT_NUM\t\t\t4\n+\n+#define SW_D\t\t\t\tu8\n+#define SW_R(sw, addr)\t\t\t(sw)->reg->r8(sw, addr)\n+#define SW_W(sw, addr, val)\t\t(sw)->reg->w8(sw, addr, val)\n+#define SW_SIZE\t\t\t\t(1)\n+#define SW_SIZE_STR\t\t\t\"%02x\"\n+\n+\n+#define P_BCAST_STORM_CTRL\t\tREG_PORT_CTRL_0\n+#define P_PRIO_CTRL\t\t\tREG_PORT_CTRL_0\n+#define P_TAG_CTRL\t\t\tREG_PORT_CTRL_0\n+#define P_MIRROR_CTRL\t\t\tREG_PORT_CTRL_1\n+#define P_802_1P_CTRL\t\t\tREG_PORT_CTRL_2\n+#define P_STP_CTRL\t\t\tREG_PORT_CTRL_2\n+#define P_LOCAL_CTRL\t\t\tREG_PORT_CTRL_5\n+#define P_REMOTE_STATUS\t\t\tREG_PORT_STATUS_1\n+#define P_FORCE_CTRL\t\t\tREG_PORT_CTRL_5\n+#define P_NEG_RESTART_CTRL\t\tREG_PORT_CTRL_6\n+#define P_SPEED_STATUS\t\t\tREG_PORT_STATUS_0\n+#define P_LINK_STATUS\t\t\tREG_PORT_STATUS_1\n+#define P_INS_SRC_PVID_CTRL\t\tREG_PORT_CTRL_8\n+#define P_DROP_TAG_CTRL\t\t\tREG_PORT_CTRL_9\n+#define P_RATE_LIMIT_CTRL\t\tREG_PORT_RATE_LIMIT\n+\n+#define S_FLUSH_TABLE_CTRL\t\tREG_SW_CTRL_0\n+#define S_LINK_AGING_CTRL\t\tREG_SW_CTRL_0\n+#define S_HUGE_PACKET_CTRL\t\tREG_SW_CTRL_2\n+#define S_MIRROR_CTRL\t\t\tREG_SW_CTRL_3\n+#define S_REPLACE_VID_CTRL\t\tREG_SW_CTRL_4\n+#define S_PASS_PAUSE_CTRL\t\tREG_SW_CTRL_10\n+#define S_TAIL_TAG_CTRL\t\t\tREG_SW_CTRL_10\n+#define S_802_1P_PRIO_CTRL\t\tREG_SW_CTRL_12\n+#define S_TOS_PRIO_CTRL\t\t\tREG_TOS_PRIO_CTRL_0\n+#define S_IPV6_MLD_CTRL\t\t\tREG_SW_CTRL_21\n+\n+#define IND_ACC_TABLE(table)\t\t((table) << 8)\n+\n+#define TAIL_TAG_OVERRIDE\t\t(1 << 6)\n+#define TAIL_TAG_LOOKUP\t\t\t(1 << 7)\n+\n+#endif /* KSZ9477_REGS_H */\ndiff --git a/drivers/net/dsa/microchip/ksz_8895_spi.c b/drivers/net/dsa/microchip/ksz_8895_spi.c\nnew file mode 100644\nindex 000000000000..b1c9571c8e99\n--- /dev/null\n+++ b/drivers/net/dsa/microchip/ksz_8895_spi.c\n@@ -0,0 +1,275 @@\n+/*\n+ * Microchip KSZ series register access through SPI\n+ *\n+ * Copyright (C) 2017 Woojung Huh <Woojung.Huh@microchip.com>\n+ * Copyright (C) 2017 Pavel Machek <pavel@denx.de>\n+ *\n+ * Permission to use, copy, modify, and/or distribute this software for any\n+ * purpose with or without fee is hereby granted, provided that the above\n+ * copyright notice and this permission notice appear in all copies.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n+ */\n+\n+#include <asm/unaligned.h>\n+\n+#include <linux/delay.h>\n+#include <linux/kernel.h>\n+#include <linux/module.h>\n+#include <linux/spi/spi.h>\n+\n+#include \"ksz_8895_reg.h\"\n+#include \"ksz_priv.h\"\n+\n+/* SPI frame opcodes */\n+#define KS_SPIOP_RD\t\t\t3\n+#define KS_SPIOP_WR\t\t\t2\n+\n+static int ksz_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,\n+\t\t\t unsigned int len)\n+{\n+\tint ret;\n+\n+\tu8 buf[2];\n+\n+\tbuf[0] = KS_SPIOP_RD;\n+\tbuf[1] = reg;\n+\n+\tret = spi_write_then_read(spi, buf, 2, val, len);\n+\treturn ret;\n+}\n+\n+static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,\n+\t\t\tunsigned int len)\n+{\n+\tstruct spi_device *spi = dev->priv;\n+\n+\treturn ksz_spi_read_reg(spi, reg, data, len);\n+}\n+\n+static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)\n+{\n+\treturn ksz_spi_read(dev, reg, val, 1);\n+}\n+\n+static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)\n+{\n+\tint ret = ksz_spi_read(dev, reg, (u8 *)val, 2);\n+\n+\tif (!ret)\n+\t\t*val = be16_to_cpu(*val);\n+\n+\treturn ret;\n+}\n+\n+static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)\n+{\n+\tint ret;\n+\n+\t*val = 0;\n+\tret = ksz_spi_read(dev, reg, (u8 *)val, 3);\n+\tif (!ret) {\n+\t\t*val = be32_to_cpu(*val);\n+\t\t/* convert to 24bit */\n+\t\t*val >>= 8;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)\n+{\n+\tint ret = ksz_spi_read(dev, reg, (u8 *)val, 4);\n+\n+\tif (!ret)\n+\t\t*val = be32_to_cpu(*val);\n+\n+\treturn ret;\n+}\n+\n+static int ksz_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,\n+\t\t\t unsigned int len)\n+{\n+\tu8 data[12];\n+\n+\tint i;\n+\t\n+\tdata[0] = KS_SPIOP_WR;\n+\tdata[1] = reg;\n+\tfor (i = 0; i < len; i++)\n+\t\tdata[i + 2] = val[i];\n+\n+\treturn spi_write(spi, &data, 2 + len);\n+}\n+\n+static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)\n+{\n+\tstruct spi_device *spi = dev->priv;\n+\n+\treturn ksz_spi_write_reg(spi, reg, &value, 1);\n+}\n+\n+static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)\n+{\n+\tstruct spi_device *spi = dev->priv;\n+\n+\tvalue = cpu_to_be16(value);\n+\treturn ksz_spi_write_reg(spi, reg, (u8 *)&value, 2);\n+}\n+\n+static int ksz_spi_write24(struct ksz_device *dev, u32 reg, u32 value)\n+{\n+\tstruct spi_device *spi = dev->priv;\n+\n+\t/* make it to big endian 24bit from MSB */\n+\tvalue <<= 8;\n+\tvalue = cpu_to_be32(value);\n+\treturn ksz_spi_write_reg(spi, reg, (u8 *)&value, 3);\n+}\n+\n+static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)\n+{\n+\tstruct spi_device *spi = dev->priv;\n+\n+\tvalue = cpu_to_be32(value);\n+\treturn ksz_spi_write_reg(spi, reg, (u8 *)&value, 4);\n+}\n+\n+static const struct ksz_io_ops ksz_spi_ops = {\n+\t.read8 = ksz_spi_read8,\n+\t.read16 = ksz_spi_read16,\n+\t.read24 = ksz_spi_read24,\n+\t.read32 = ksz_spi_read32,\n+\t.write8 = ksz_spi_write8,\n+\t.write16 = ksz_spi_write16,\n+\t.write24 = ksz_spi_write24,\n+\t.write32 = ksz_spi_write32,\n+};\n+\n+static int ksz_spi_sysfs_read(struct ksz_device *dev, char *buf,\n+\t\t unsigned offset, size_t count)\n+{\n+\tint err = 0;\n+\tint i;\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tksz_read8(dev, i+offset, buf+i+offset);\n+\t}\n+\n+\treturn err ? err : count;\n+}\n+\n+static int ksz_spi_sysfs_write(struct ksz_device *dev, char *buf,\n+\t\t unsigned offset, size_t count)\n+{\n+\tint err = -EINVAL;\n+\n+\treturn err ? err : count;\n+}\n+\n+static ssize_t ksz_spi_registers_read(struct file *filp, struct kobject *kobj,\n+\tstruct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)\n+{\n+\tstruct device *dev;\n+\tstruct ksz_device *ks;\n+\n+\tdev = container_of(kobj, struct device, kobj);\n+\tks = dev_get_drvdata(dev);\n+\n+\treturn ksz_spi_sysfs_read(ks, buf, off, count);\n+}\n+\n+static ssize_t ksz_spi_registers_write(struct file *filp, struct kobject *kobj,\n+\tstruct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)\n+{\n+\tstruct device *dev;\n+\tstruct ksz_device *ks;\n+\n+\tdev = container_of(kobj, struct device, kobj);\n+\tks = dev_get_drvdata(dev);\n+\n+\treturn ksz_spi_sysfs_write(ks, buf, off, count);\n+}\n+\n+static const struct bin_attribute ksz_spi_registers_attr = {\n+\t.attr = {\n+\t\t.name = \"registers\",\n+\t\t.mode = S_IRUSR | S_IWUSR,\n+\t},\n+\t.size = 0x100,\n+\t.read = ksz_spi_registers_read,\n+\t.write = ksz_spi_registers_write,\n+};\n+\n+static int ksz_spi_probe(struct spi_device *spi)\n+{\n+\tstruct ksz_device *dev;\n+\tint ret;\n+\n+\tdev = ksz_switch_alloc(&spi->dev, &ksz_spi_ops, spi);\n+\tif (!dev)\n+\t\treturn -ENOMEM;\n+\n+\tif (spi->dev.platform_data)\n+\t\tdev->pdata = spi->dev.platform_data;\n+\n+\tret = ksz_switch_register(dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmemcpy(&dev->regs_attr, &ksz_spi_registers_attr, sizeof(dev->regs_attr));\n+ dev->regs_attr.size = 0x100;\n+\n+ sysfs_attr_init(&dev->regs_attr.attr);\n+ ret = sysfs_create_bin_file(&spi->dev.kobj, &dev->regs_attr);\n+\n+ if (ret) {\n+ dev_err(&spi->dev, \"unable to create sysfs file, err=%d\\n\",\n+ ret);\n+ return ret;\n+ }\n+\t\n+\tspi_set_drvdata(spi, dev);\n+\n+\treturn 0;\n+}\n+\n+static int ksz_spi_remove(struct spi_device *spi)\n+{\n+\tstruct ksz_device *dev = spi_get_drvdata(spi);\n+\n+\tif (dev)\n+\t\tksz_switch_remove(dev);\n+\n+\tsysfs_remove_bin_file(&spi->dev.kobj, &dev->regs_attr);\n+\t\n+\treturn 0;\n+}\n+\n+static const struct of_device_id ksz_dt_ids[] = {\n+\t{ .compatible = \"microchip,ksz8895\" },\t\n+\t{},\n+};\n+MODULE_DEVICE_TABLE(of, ksz_dt_ids);\n+\n+static struct spi_driver ksz_spi_driver = {\n+\t.driver = {\n+\t\t.name\t= \"ksz8895-switch\",\n+\t\t.owner\t= THIS_MODULE,\n+\t\t.of_match_table = of_match_ptr(ksz_dt_ids),\n+\t},\n+\t.probe\t= ksz_spi_probe,\n+\t.remove\t= ksz_spi_remove,\n+};\n+\n+module_spi_driver(ksz_spi_driver);\n+\n+MODULE_AUTHOR(\"Pavel Machek <pavel@denx.de>\");\n+MODULE_DESCRIPTION(\"Microchip KSZ Series Switch SPI access Driver\");\n+MODULE_LICENSE(\"GPL\");\ndiff --git a/drivers/net/dsa/microchip/ksz_9477_reg.h b/drivers/net/dsa/microchip/ksz_9477_reg.h\nindex 6aa6752035a1..af4d29c2ba4f 100644\n--- a/drivers/net/dsa/microchip/ksz_9477_reg.h\n+++ b/drivers/net/dsa/microchip/ksz_9477_reg.h\n@@ -16,6 +16,7 @@\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n \n+#error This is not switch we have\n #ifndef __KSZ9477_REGS_H\n #define __KSZ9477_REGS_H\n \ndiff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c\nindex b313ecdf2919..6741d05d0ac4 100644\n--- a/drivers/net/dsa/microchip/ksz_common.c\n+++ b/drivers/net/dsa/microchip/ksz_common.c\n@@ -28,6 +28,7 @@\n #include <net/dsa.h>\n #include <net/switchdev.h>\n \n+#include \"ksz_9477_reg.h\"\n #include \"ksz_priv.h\"\n \n static const struct {\ndiff --git a/drivers/net/dsa/microchip/ksz_mdio_emulation.c b/drivers/net/dsa/microchip/ksz_mdio_emulation.c\nnew file mode 100644\nindex 000000000000..a4e24506bed8\n--- /dev/null\n+++ b/drivers/net/dsa/microchip/ksz_mdio_emulation.c\n@@ -0,0 +1,286 @@\n+/**\n+ * Micrel KSZ8895 SPI driver\n+ *\n+ * Copyright (c) 2015 Micrel, Inc.\n+ *\n+ * GPLv2\n+ */\n+\n+#define PHY_ID_KSZ8895\t\t((KSZ8895_ID_HI << 16) | KSZ8895_ID_LO)\n+\n+/**\n+ * sw_r_phy - read data from PHY register\n+ * @sw:\t\tThe switch instance.\n+ * @phy:\tPHY address to read.\n+ * @reg:\tPHY register to read.\n+ * @val:\tBuffer to store the read data.\n+ *\n+ * This routine reads data from the PHY register.\n+ */\n+static void sw_r_phy(struct ksz_device *sw, u16 phy, u16 reg, u16 *val)\n+{\n+\tu8 ctrl;\n+\tu8 restart;\n+\tu8 link;\n+\tu8 speed;\n+\tu8 force;\n+\tu8 p = phy;\n+\tu16 data = 0;\n+\n+\tswitch (reg) {\n+\tcase PHY_REG_CTRL:\n+\t\tksz_pread8(sw, p, P_LOCAL_CTRL, &ctrl);\n+\t\tksz_pread8(sw, p, P_NEG_RESTART_CTRL, &restart);\n+\t\tksz_pread8(sw, p, P_SPEED_STATUS, &speed);\n+\t\tksz_pread8(sw, p, P_FORCE_CTRL, &force);\n+\t\tif (restart & PORT_PHY_LOOPBACK)\n+\t\t\tdata |= PHY_LOOPBACK;\n+\t\tif (force & PORT_FORCE_100_MBIT)\n+\t\t\tdata |= PHY_SPEED_100MBIT;\n+\t\tif (!(force & PORT_AUTO_NEG_DISABLE))\n+\t\t\tdata |= PHY_AUTO_NEG_ENABLE;\n+\t\tif (restart & PORT_POWER_DOWN)\n+\t\t\tdata |= PHY_POWER_DOWN;\n+\t\tif (restart & PORT_AUTO_NEG_RESTART)\n+\t\t\tdata |= PHY_AUTO_NEG_RESTART;\n+\t\tif (force & PORT_FORCE_FULL_DUPLEX)\n+\t\t\tdata |= PHY_FULL_DUPLEX;\n+\t\tif (speed & PORT_HP_MDIX)\n+\t\t\tdata |= PHY_HP_MDIX;\n+\t\tif (restart & PORT_FORCE_MDIX)\n+\t\t\tdata |= PHY_FORCE_MDIX;\n+\t\tif (restart & PORT_AUTO_MDIX_DISABLE)\n+\t\t\tdata |= PHY_AUTO_MDIX_DISABLE;\n+\t\tif (restart & PORT_TX_DISABLE)\n+\t\t\tdata |= PHY_TRANSMIT_DISABLE;\n+\t\tif (restart & PORT_LED_OFF)\n+\t\t\tdata |= PHY_LED_DISABLE;\n+\t\tbreak;\n+\tcase PHY_REG_STATUS:\n+\t\tksz_pread8(sw, p, P_LINK_STATUS, &link);\n+\t\tksz_pread8(sw, p, P_SPEED_STATUS, &speed);\n+\t\tdata = PHY_100BTX_FD_CAPABLE |\n+\t\t\tPHY_100BTX_CAPABLE |\n+\t\t\tPHY_10BT_FD_CAPABLE |\n+\t\t\tPHY_10BT_CAPABLE |\n+\t\t\tPHY_AUTO_NEG_CAPABLE;\n+\t\tif (link & PORT_AUTO_NEG_COMPLETE)\n+\t\t\tdata |= PHY_AUTO_NEG_ACKNOWLEDGE;\n+\t\tif (link & PORT_STAT_LINK_GOOD)\n+\t\t\tdata |= PHY_LINK_STATUS;\n+\t\tbreak;\n+\tcase PHY_REG_ID_1:\n+\t\tdata = KSZ8895_ID_HI;\n+\t\tbreak;\n+\tcase PHY_REG_ID_2:\n+\t\tdata = KSZ8895_ID_LO;\n+\t\tbreak;\n+\tcase PHY_REG_AUTO_NEGOTIATION:\n+\t\tksz_pread8(sw, p, P_LOCAL_CTRL, &ctrl);\n+\t\tdata = PHY_AUTO_NEG_802_3;\n+\t\tif (ctrl & PORT_AUTO_NEG_SYM_PAUSE)\n+\t\t\tdata |= PHY_AUTO_NEG_SYM_PAUSE;\n+\t\tif (ctrl & PORT_AUTO_NEG_100BTX_FD)\n+\t\t\tdata |= PHY_AUTO_NEG_100BTX_FD;\n+\t\tif (ctrl & PORT_AUTO_NEG_100BTX)\n+\t\t\tdata |= PHY_AUTO_NEG_100BTX;\n+\t\tif (ctrl & PORT_AUTO_NEG_10BT_FD)\n+\t\t\tdata |= PHY_AUTO_NEG_10BT_FD;\n+\t\tif (ctrl & PORT_AUTO_NEG_10BT)\n+\t\t\tdata |= PHY_AUTO_NEG_10BT;\n+\t\tbreak;\n+\tcase PHY_REG_REMOTE_CAPABILITY:\n+\t\tksz_pread8(sw, p, P_REMOTE_STATUS, &link);\n+\t\tdata = PHY_AUTO_NEG_802_3;\n+\t\tif (link & PORT_REMOTE_SYM_PAUSE)\n+\t\t\tdata |= PHY_AUTO_NEG_SYM_PAUSE;\n+\t\tif (link & PORT_REMOTE_100BTX_FD)\n+\t\t\tdata |= PHY_AUTO_NEG_100BTX_FD;\n+\t\tif (link & PORT_REMOTE_100BTX)\n+\t\t\tdata |= PHY_AUTO_NEG_100BTX;\n+\t\tif (link & PORT_REMOTE_10BT_FD)\n+\t\t\tdata |= PHY_AUTO_NEG_10BT_FD;\n+\t\tif (link & PORT_REMOTE_10BT)\n+\t\t\tdata |= PHY_AUTO_NEG_10BT;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\t*val = data;\n+} /* sw_r_phy */\n+\n+/**\n+ * sw_w_phy - write data to PHY register\n+ * @hw:\t\tThe switch instance.\n+ * @phy:\tPHY address to write.\n+ * @reg:\tPHY register to write.\n+ * @val:\tWord data to write.\n+ *\n+ * This routine writes data to the PHY register.\n+ */\n+static void sw_w_phy(struct ksz_device *sw, u16 phy, u16 reg, u16 val)\n+{\n+\tu8 ctrl;\n+\tu8 restart;\n+\tu8 speed;\n+\tu8 data;\n+\tu8 p = phy;\n+\n+\tswitch (reg) {\n+\tcase PHY_REG_CTRL:\n+\t\tksz_pread8(sw, p, P_SPEED_STATUS, &speed);\n+\t\tdata = speed;\n+\t\tif (val & PHY_HP_MDIX)\n+\t\t\tdata |= PORT_HP_MDIX;\n+\t\telse\n+\t\t\tdata &= ~PORT_HP_MDIX;\n+\t\tif (data != speed)\n+\t\t\tksz_pwrite8(sw, p, P_SPEED_STATUS, data);\n+\t\tksz_pread8(sw, p, P_FORCE_CTRL, &ctrl);\n+\t\tdata = ctrl;\n+\t\tif (!(val & PHY_AUTO_NEG_ENABLE))\n+\t\t\tdata |= PORT_AUTO_NEG_DISABLE;\n+\t\telse\n+\t\t\tdata &= ~PORT_AUTO_NEG_DISABLE;\n+\t\tif (val & PHY_SPEED_100MBIT)\n+\t\t\tdata |= PORT_FORCE_100_MBIT;\n+\t\telse\n+\t\t\tdata &= ~PORT_FORCE_100_MBIT;\n+\t\tif (val & PHY_FULL_DUPLEX)\n+\t\t\tdata |= PORT_FORCE_FULL_DUPLEX;\n+\t\telse\n+\t\t\tdata &= ~PORT_FORCE_FULL_DUPLEX;\n+\t\tif (data != ctrl)\n+\t\t\tksz_pwrite8(sw, p, P_FORCE_CTRL, data);\n+\t\tksz_pread8(sw, p, P_NEG_RESTART_CTRL, &restart);\n+\t\tdata = restart;\n+\t\tif (val & PHY_LED_DISABLE)\n+\t\t\tdata |= PORT_LED_OFF;\n+\t\telse\n+\t\t\tdata &= ~PORT_LED_OFF;\n+\t\tif (val & PHY_TRANSMIT_DISABLE)\n+\t\t\tdata |= PORT_TX_DISABLE;\n+\t\telse\n+\t\t\tdata &= ~PORT_TX_DISABLE;\n+\t\tif (val & PHY_AUTO_NEG_RESTART)\n+\t\t\tdata |= PORT_AUTO_NEG_RESTART;\n+\t\telse\n+\t\t\tdata &= ~(PORT_AUTO_NEG_RESTART);\n+\t\tif (val & PHY_POWER_DOWN)\n+\t\t\tdata |= PORT_POWER_DOWN;\n+\t\telse\n+\t\t\tdata &= ~PORT_POWER_DOWN;\n+\t\tif (val & PHY_AUTO_MDIX_DISABLE)\n+\t\t\tdata |= PORT_AUTO_MDIX_DISABLE;\n+\t\telse\n+\t\t\tdata &= ~PORT_AUTO_MDIX_DISABLE;\n+\t\tif (val & PHY_FORCE_MDIX)\n+\t\t\tdata |= PORT_FORCE_MDIX;\n+\t\telse\n+\t\t\tdata &= ~PORT_FORCE_MDIX;\n+\t\tif (val & PHY_LOOPBACK)\n+\t\t\tdata |= PORT_PHY_LOOPBACK;\n+\t\telse\n+\t\t\tdata &= ~PORT_PHY_LOOPBACK;\n+\t\tif (data != restart)\n+\t\t\tksz_pwrite8(sw, p, P_NEG_RESTART_CTRL, data);\n+\t\tbreak;\n+\tcase PHY_REG_AUTO_NEGOTIATION:\n+\t\tksz_pread8(sw, p, P_LOCAL_CTRL, &ctrl);\n+\t\tdata = ctrl;\n+\t\tdata &= ~(PORT_AUTO_NEG_SYM_PAUSE |\n+\t\t\tPORT_AUTO_NEG_100BTX_FD |\n+\t\t\tPORT_AUTO_NEG_100BTX |\n+\t\t\tPORT_AUTO_NEG_10BT_FD |\n+\t\t\tPORT_AUTO_NEG_10BT);\n+\t\tif (val & PHY_AUTO_NEG_SYM_PAUSE)\n+\t\t\tdata |= PORT_AUTO_NEG_SYM_PAUSE;\n+\t\tif (val & PHY_AUTO_NEG_100BTX_FD)\n+\t\t\tdata |= PORT_AUTO_NEG_100BTX_FD;\n+\t\tif (val & PHY_AUTO_NEG_100BTX)\n+\t\t\tdata |= PORT_AUTO_NEG_100BTX;\n+\t\tif (val & PHY_AUTO_NEG_10BT_FD)\n+\t\t\tdata |= PORT_AUTO_NEG_10BT_FD;\n+\t\tif (val & PHY_AUTO_NEG_10BT)\n+\t\t\tdata |= PORT_AUTO_NEG_10BT;\n+\t\tif (data != ctrl)\n+\t\t\tksz_pwrite8(sw, p, P_LOCAL_CTRL, data);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+} /* sw_w_phy */\n+\n+static int ksz_mii_addr(int *reg, int *bank)\n+{\n+\tint ret;\n+\n+\tret = (*reg & 0xC000) >> ADDR_SHIFT;\n+\t*bank = (*reg & 0x3000) >> BANK_SHIFT;\n+\t*reg &= 0x0FFF;\n+\treturn ret;\n+}\n+\n+static int ksz_phy_read16(struct dsa_switch *ds, int phy_id, int regnum)\n+{\n+\tstruct ksz_device *sw = ds->priv;\n+\tint addr;\n+\tint bank;\n+\tu16 data;\n+\tint ret = 0xffff;\n+\n+\tif (phy_id > SWITCH_PORT_NUM + 1)\n+\t\treturn 0xffff;\n+\n+\taddr = ksz_mii_addr(®num, &bank);\n+\tBUG_ON(addr >= 6);\n+\n+\tswitch (addr) {\n+\tcase ADDR_8:\n+\tcase ADDR_16:\n+\tcase ADDR_32:\n+\t\tBUG();\n+\n+\tdefault:\n+\t\tif (regnum < 6) {\n+\t\t\tsw_r_phy(sw, phy_id, regnum, &data);\n+\t\t\tret = data;\n+\t\t} else\n+\t\t\tret = 0;\n+\t}\n+\n+\treturn ret;\n+} /* ksz_mii_read */\n+\n+static int ksz_phy_write16(struct dsa_switch *ds, int phy_id, int regnum, u16 val)\n+{\n+\tstruct ksz_device *sw = ds->priv;\n+\tint addr;\n+\tint bank;\n+\tint reg;\n+\n+\tif (phy_id > SWITCH_PORT_NUM + 1)\n+\t\treturn -EINVAL;\n+\n+\tBUG_ON(regnum >= 6);\n+\treg = regnum;\n+\taddr = ksz_mii_addr(®num, &bank);\n+\n+\tswitch (addr) {\n+\tcase ADDR_8:\n+\tcase ADDR_16:\n+\tcase ADDR_32:\n+\t\tBUG();\n+\tdefault:\n+\t\tif (regnum < 6) {\n+\t\t\t/* PHY device driver resets or powers down the PHY. */\n+\t\t\tif (0 == regnum &&\n+\t\t\t (val & (PHY_RESET | PHY_POWER_DOWN)))\n+\t\t\t\tbreak;\n+\t\t\tsw_w_phy(sw, phy_id, regnum, val);\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+} /* ksz_mii_write */\ndiff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h\nindex 2a98dbd51456..1c73cdb8bbca 100644\n--- a/drivers/net/dsa/microchip/ksz_priv.h\n+++ b/drivers/net/dsa/microchip/ksz_priv.h\n@@ -25,8 +25,6 @@\n #include <linux/etherdevice.h>\n #include <net/dsa.h>\n \n-#include \"ksz_9477_reg.h\"\n-\n struct ksz_io_ops;\n \n struct vlan_table {\n@@ -60,6 +58,8 @@ struct ksz_device {\n \tstruct vlan_table *vlan_cache;\n \n \tu64 mib_value[TOTAL_SWITCH_COUNTER_NUM];\n+\t\n+\tstruct bin_attribute regs_attr;\n };\n \n struct ksz_io_ops {\n@@ -174,6 +174,7 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)\n static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,\n \t\t\t u8 *data)\n {\n+\t//printk(\"pread8 %d %d -> %d\\n\", port, offset, PORT_CTRL_ADDR(port, offset));\n \tksz_read8(dev, PORT_CTRL_ADDR(port, offset), data);\n }\n \ndiff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c\nindex c51946983bed..22ee313052dc 100644\n--- a/drivers/net/dsa/microchip/ksz_spi.c\n+++ b/drivers/net/dsa/microchip/ksz_spi.c\n@@ -23,6 +23,7 @@\n #include <linux/module.h>\n #include <linux/spi/spi.h>\n \n+#include \"ksz_9477_reg.h\"\n #include \"ksz_priv.h\"\n \n /* SPI frame opcodes */\ndiff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c\nindex de66ca8e6201..6eb094d5bb02 100644\n--- a/net/dsa/tag_ksz.c\n+++ b/net/dsa/tag_ksz.c\n@@ -29,7 +29,7 @@\n *\t (eg, 0x00=port1, 0x02=port3, 0x06=port7)\n */\n \n-#define\tKSZ_INGRESS_TAG_LEN\t2\n+#define\tKSZ_INGRESS_TAG_LEN\t1\n #define\tKSZ_EGRESS_TAG_LEN\t1\n \n static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)\n@@ -69,8 +69,7 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)\n \t}\n \n \ttag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);\n-\ttag[0] = 0;\n-\ttag[1] = 1 << p->dp->index; /* destination port */\n+\ttag[0] = 1 << p->dp->index; /* destination port */\n \n \treturn nskb;\n }\n", "prefixes": [] }