14c66157fSHoratiu Vultur // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
24c66157fSHoratiu Vultur /*
34c66157fSHoratiu Vultur * Copyright (c) 2018 Microsemi Corporation
44c66157fSHoratiu Vultur */
54c66157fSHoratiu Vultur
64c66157fSHoratiu Vultur #include <common.h>
74c66157fSHoratiu Vultur #include <config.h>
84c66157fSHoratiu Vultur #include <dm.h>
94c66157fSHoratiu Vultur #include <dm/of_access.h>
104c66157fSHoratiu Vultur #include <dm/of_addr.h>
114c66157fSHoratiu Vultur #include <fdt_support.h>
124c66157fSHoratiu Vultur #include <linux/io.h>
134c66157fSHoratiu Vultur #include <linux/ioport.h>
144c66157fSHoratiu Vultur #include <miiphy.h>
154c66157fSHoratiu Vultur #include <net.h>
164c66157fSHoratiu Vultur #include <wait_bit.h>
174c66157fSHoratiu Vultur
182fff4a9bSHoratiu Vultur #include "mscc_miim.h"
1936d04f52SHoratiu Vultur #include "mscc_xfer.h"
2045f2748cSHoratiu Vultur #include "mscc_mac_table.h"
214c66157fSHoratiu Vultur
224c66157fSHoratiu Vultur #define PHY_CFG 0x0
234c66157fSHoratiu Vultur #define PHY_CFG_ENA 0xF
244c66157fSHoratiu Vultur #define PHY_CFG_COMMON_RST BIT(4)
254c66157fSHoratiu Vultur #define PHY_CFG_RST (0xF << 5)
264c66157fSHoratiu Vultur #define PHY_STAT 0x4
274c66157fSHoratiu Vultur #define PHY_STAT_SUPERVISOR_COMPLETE BIT(0)
284c66157fSHoratiu Vultur
294c66157fSHoratiu Vultur #define ANA_PORT_VLAN_CFG(x) (0x7000 + 0x100 * (x))
304c66157fSHoratiu Vultur #define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
314c66157fSHoratiu Vultur #define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18)
324c66157fSHoratiu Vultur #define ANA_PORT_PORT_CFG(x) (0x7070 + 0x100 * (x))
334c66157fSHoratiu Vultur #define ANA_PORT_PORT_CFG_RECV_ENA BIT(6)
344c66157fSHoratiu Vultur #define ANA_PGID(x) (0x8c00 + 4 * (x))
354c66157fSHoratiu Vultur
364c66157fSHoratiu Vultur #define SYS_FRM_AGING 0x574
374c66157fSHoratiu Vultur #define SYS_FRM_AGING_ENA BIT(20)
384c66157fSHoratiu Vultur
394c66157fSHoratiu Vultur #define SYS_SYSTEM_RST_CFG 0x508
404c66157fSHoratiu Vultur #define SYS_SYSTEM_RST_MEM_INIT BIT(0)
414c66157fSHoratiu Vultur #define SYS_SYSTEM_RST_MEM_ENA BIT(1)
424c66157fSHoratiu Vultur #define SYS_SYSTEM_RST_CORE_ENA BIT(2)
434c66157fSHoratiu Vultur #define SYS_PORT_MODE(x) (0x514 + 0x4 * (x))
444c66157fSHoratiu Vultur #define SYS_PORT_MODE_INCL_INJ_HDR(x) ((x) << 3)
454c66157fSHoratiu Vultur #define SYS_PORT_MODE_INCL_INJ_HDR_M GENMASK(4, 3)
464c66157fSHoratiu Vultur #define SYS_PORT_MODE_INCL_XTR_HDR(x) ((x) << 1)
474c66157fSHoratiu Vultur #define SYS_PORT_MODE_INCL_XTR_HDR_M GENMASK(2, 1)
484c66157fSHoratiu Vultur #define SYS_PAUSE_CFG(x) (0x608 + 0x4 * (x))
494c66157fSHoratiu Vultur #define SYS_PAUSE_CFG_PAUSE_ENA BIT(0)
504c66157fSHoratiu Vultur
514c66157fSHoratiu Vultur #define QSYS_SWITCH_PORT_MODE(x) (0x11234 + 0x4 * (x))
524c66157fSHoratiu Vultur #define QSYS_SWITCH_PORT_MODE_PORT_ENA BIT(14)
534c66157fSHoratiu Vultur #define QSYS_QMAP 0x112d8
544c66157fSHoratiu Vultur #define QSYS_EGR_NO_SHARING 0x1129c
554c66157fSHoratiu Vultur
564c66157fSHoratiu Vultur /* Port registers */
574c66157fSHoratiu Vultur #define DEV_CLOCK_CFG 0x0
584c66157fSHoratiu Vultur #define DEV_CLOCK_CFG_LINK_SPEED_1000 1
594c66157fSHoratiu Vultur #define DEV_MAC_ENA_CFG 0x1c
604c66157fSHoratiu Vultur #define DEV_MAC_ENA_CFG_RX_ENA BIT(4)
614c66157fSHoratiu Vultur #define DEV_MAC_ENA_CFG_TX_ENA BIT(0)
624c66157fSHoratiu Vultur
634c66157fSHoratiu Vultur #define DEV_MAC_IFG_CFG 0x30
644c66157fSHoratiu Vultur #define DEV_MAC_IFG_CFG_TX_IFG(x) ((x) << 8)
654c66157fSHoratiu Vultur #define DEV_MAC_IFG_CFG_RX_IFG2(x) ((x) << 4)
664c66157fSHoratiu Vultur #define DEV_MAC_IFG_CFG_RX_IFG1(x) (x)
674c66157fSHoratiu Vultur
684c66157fSHoratiu Vultur #define PCS1G_CFG 0x48
694c66157fSHoratiu Vultur #define PCS1G_MODE_CFG_SGMII_MODE_ENA BIT(0)
704c66157fSHoratiu Vultur #define PCS1G_MODE_CFG 0x4c
714c66157fSHoratiu Vultur #define PCS1G_MODE_CFG_UNIDIR_MODE_ENA BIT(4)
724c66157fSHoratiu Vultur #define PCS1G_MODE_CFG_SGMII_MODE_ENA BIT(0)
734c66157fSHoratiu Vultur #define PCS1G_SD_CFG 0x50
744c66157fSHoratiu Vultur #define PCS1G_ANEG_CFG 0x54
754c66157fSHoratiu Vultur #define PCS1G_ANEG_CFG_ADV_ABILITY(x) ((x) << 16)
764c66157fSHoratiu Vultur
774c66157fSHoratiu Vultur #define QS_XTR_GRP_CFG(x) (4 * (x))
784c66157fSHoratiu Vultur #define QS_XTR_GRP_CFG_MODE(x) ((x) << 2)
794c66157fSHoratiu Vultur #define QS_XTR_GRP_CFG_STATUS_WORD_POS BIT(1)
804c66157fSHoratiu Vultur #define QS_XTR_GRP_CFG_BYTE_SWAP BIT(0)
814c66157fSHoratiu Vultur #define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
824c66157fSHoratiu Vultur #define QS_INJ_GRP_CFG_MODE(x) ((x) << 2)
834c66157fSHoratiu Vultur #define QS_INJ_GRP_CFG_BYTE_SWAP BIT(0)
844c66157fSHoratiu Vultur
854c66157fSHoratiu Vultur #define IFH_INJ_BYPASS BIT(31)
864c66157fSHoratiu Vultur #define IFH_TAG_TYPE_C 0
874c66157fSHoratiu Vultur #define MAC_VID 1
884c66157fSHoratiu Vultur #define CPU_PORT 11
894c66157fSHoratiu Vultur #define INTERNAL_PORT_MSK 0xF
904c66157fSHoratiu Vultur #define IFH_LEN 4
914c66157fSHoratiu Vultur #define ETH_ALEN 6
924c66157fSHoratiu Vultur #define PGID_BROADCAST 13
934c66157fSHoratiu Vultur #define PGID_UNICAST 14
944c66157fSHoratiu Vultur #define PGID_SRC 80
954c66157fSHoratiu Vultur
964c66157fSHoratiu Vultur enum ocelot_target {
974c66157fSHoratiu Vultur ANA,
984c66157fSHoratiu Vultur QS,
994c66157fSHoratiu Vultur QSYS,
1004c66157fSHoratiu Vultur REW,
1014c66157fSHoratiu Vultur SYS,
1024c66157fSHoratiu Vultur HSIO,
1034c66157fSHoratiu Vultur PORT0,
1044c66157fSHoratiu Vultur PORT1,
1054c66157fSHoratiu Vultur PORT2,
1064c66157fSHoratiu Vultur PORT3,
1074c66157fSHoratiu Vultur TARGET_MAX,
1084c66157fSHoratiu Vultur };
1094c66157fSHoratiu Vultur
1104c66157fSHoratiu Vultur #define MAX_PORT (PORT3 - PORT0)
1114c66157fSHoratiu Vultur
1124c66157fSHoratiu Vultur enum ocelot_mdio_target {
1134c66157fSHoratiu Vultur MIIM,
1144c66157fSHoratiu Vultur PHY,
1154c66157fSHoratiu Vultur TARGET_MDIO_MAX,
1164c66157fSHoratiu Vultur };
1174c66157fSHoratiu Vultur
1184c66157fSHoratiu Vultur enum ocelot_phy_id {
1194c66157fSHoratiu Vultur INTERNAL,
1204c66157fSHoratiu Vultur EXTERNAL,
1214c66157fSHoratiu Vultur NUM_PHY,
1224c66157fSHoratiu Vultur };
1234c66157fSHoratiu Vultur
1244c66157fSHoratiu Vultur struct ocelot_private {
1254c66157fSHoratiu Vultur void __iomem *regs[TARGET_MAX];
1264c66157fSHoratiu Vultur struct mii_dev *bus[NUM_PHY];
1274c66157fSHoratiu Vultur };
1284c66157fSHoratiu Vultur
12936d04f52SHoratiu Vultur static const unsigned long ocelot_regs_qs[] = {
13036d04f52SHoratiu Vultur [MSCC_QS_XTR_RD] = 0x8,
13136d04f52SHoratiu Vultur [MSCC_QS_XTR_FLUSH] = 0x18,
13236d04f52SHoratiu Vultur [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
13336d04f52SHoratiu Vultur [MSCC_QS_INJ_WR] = 0x2c,
13436d04f52SHoratiu Vultur [MSCC_QS_INJ_CTRL] = 0x34,
13536d04f52SHoratiu Vultur };
13636d04f52SHoratiu Vultur
13745f2748cSHoratiu Vultur static const unsigned long ocelot_regs_ana_table[] = {
13845f2748cSHoratiu Vultur [MSCC_ANA_TABLES_MACHDATA] = 0x8b34,
13945f2748cSHoratiu Vultur [MSCC_ANA_TABLES_MACLDATA] = 0x8b38,
14045f2748cSHoratiu Vultur [MSCC_ANA_TABLES_MACACCESS] = 0x8b3c,
14145f2748cSHoratiu Vultur };
14245f2748cSHoratiu Vultur
143*0b8f34dcSHoratiu Vultur static struct mscc_miim_dev miim[NUM_PHY];
1444c66157fSHoratiu Vultur
mscc_miim_reset(struct mii_dev * bus)1454c66157fSHoratiu Vultur static int mscc_miim_reset(struct mii_dev *bus)
1464c66157fSHoratiu Vultur {
1474c66157fSHoratiu Vultur struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
1484c66157fSHoratiu Vultur
1494c66157fSHoratiu Vultur if (miim->phy_regs) {
1504c66157fSHoratiu Vultur writel(0, miim->phy_regs + PHY_CFG);
1514c66157fSHoratiu Vultur writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
1524c66157fSHoratiu Vultur | PHY_CFG_ENA, miim->phy_regs + PHY_CFG);
1534c66157fSHoratiu Vultur mdelay(500);
1544c66157fSHoratiu Vultur }
1554c66157fSHoratiu Vultur
1564c66157fSHoratiu Vultur return 0;
1574c66157fSHoratiu Vultur }
1584c66157fSHoratiu Vultur
1594c66157fSHoratiu Vultur /* For now only setup the internal mdio bus */
ocelot_mdiobus_init(struct udevice * dev)1604c66157fSHoratiu Vultur static struct mii_dev *ocelot_mdiobus_init(struct udevice *dev)
1614c66157fSHoratiu Vultur {
1624c66157fSHoratiu Vultur unsigned long phy_size[TARGET_MAX];
1634c66157fSHoratiu Vultur phys_addr_t phy_base[TARGET_MAX];
1644c66157fSHoratiu Vultur struct ofnode_phandle_args phandle;
1654c66157fSHoratiu Vultur ofnode eth_node, node, mdio_node;
1664c66157fSHoratiu Vultur struct resource res;
1674c66157fSHoratiu Vultur struct mii_dev *bus;
1684c66157fSHoratiu Vultur fdt32_t faddr;
1694c66157fSHoratiu Vultur int i;
1704c66157fSHoratiu Vultur
1714c66157fSHoratiu Vultur bus = mdio_alloc();
1724c66157fSHoratiu Vultur
1734c66157fSHoratiu Vultur if (!bus)
1744c66157fSHoratiu Vultur return NULL;
1754c66157fSHoratiu Vultur
1764c66157fSHoratiu Vultur /* gathered only the first mdio bus */
1774c66157fSHoratiu Vultur eth_node = dev_read_first_subnode(dev);
1784c66157fSHoratiu Vultur node = ofnode_first_subnode(eth_node);
1794c66157fSHoratiu Vultur ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
1804c66157fSHoratiu Vultur &phandle);
1814c66157fSHoratiu Vultur mdio_node = ofnode_get_parent(phandle.node);
1824c66157fSHoratiu Vultur
1834c66157fSHoratiu Vultur for (i = 0; i < TARGET_MDIO_MAX; i++) {
1844c66157fSHoratiu Vultur if (ofnode_read_resource(mdio_node, i, &res)) {
1854c66157fSHoratiu Vultur pr_err("%s: get OF resource failed\n", __func__);
1864c66157fSHoratiu Vultur return NULL;
1874c66157fSHoratiu Vultur }
1884c66157fSHoratiu Vultur faddr = cpu_to_fdt32(res.start);
1894c66157fSHoratiu Vultur phy_base[i] = ofnode_translate_address(mdio_node, &faddr);
1904c66157fSHoratiu Vultur phy_size[i] = res.end - res.start;
1914c66157fSHoratiu Vultur }
1924c66157fSHoratiu Vultur
1934c66157fSHoratiu Vultur strcpy(bus->name, "miim-internal");
1944c66157fSHoratiu Vultur miim[INTERNAL].phy_regs = ioremap(phy_base[PHY], phy_size[PHY]);
1954c66157fSHoratiu Vultur miim[INTERNAL].regs = ioremap(phy_base[MIIM], phy_size[MIIM]);
1964c66157fSHoratiu Vultur bus->priv = &miim[INTERNAL];
1974c66157fSHoratiu Vultur bus->reset = mscc_miim_reset;
1984c66157fSHoratiu Vultur bus->read = mscc_miim_read;
1994c66157fSHoratiu Vultur bus->write = mscc_miim_write;
2004c66157fSHoratiu Vultur
2014c66157fSHoratiu Vultur if (mdio_register(bus))
2024c66157fSHoratiu Vultur return NULL;
2034c66157fSHoratiu Vultur else
2044c66157fSHoratiu Vultur return bus;
2054c66157fSHoratiu Vultur }
2064c66157fSHoratiu Vultur
mscc_switch_reset(void)2074c66157fSHoratiu Vultur __weak void mscc_switch_reset(void)
2084c66157fSHoratiu Vultur {
2094c66157fSHoratiu Vultur }
2104c66157fSHoratiu Vultur
ocelot_stop(struct udevice * dev)2114c66157fSHoratiu Vultur static void ocelot_stop(struct udevice *dev)
2124c66157fSHoratiu Vultur {
2134c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
2144c66157fSHoratiu Vultur int i;
2154c66157fSHoratiu Vultur
2164c66157fSHoratiu Vultur mscc_switch_reset();
2174c66157fSHoratiu Vultur for (i = 0; i < NUM_PHY; i++)
2184c66157fSHoratiu Vultur if (priv->bus[i])
2194c66157fSHoratiu Vultur mscc_miim_reset(priv->bus[i]);
2204c66157fSHoratiu Vultur }
2214c66157fSHoratiu Vultur
ocelot_cpu_capture_setup(struct ocelot_private * priv)2224c66157fSHoratiu Vultur static void ocelot_cpu_capture_setup(struct ocelot_private *priv)
2234c66157fSHoratiu Vultur {
2244c66157fSHoratiu Vultur int i;
2254c66157fSHoratiu Vultur
2264c66157fSHoratiu Vultur /* map the 8 CPU extraction queues to CPU port 11 */
2274c66157fSHoratiu Vultur writel(0, priv->regs[QSYS] + QSYS_QMAP);
2284c66157fSHoratiu Vultur
2294c66157fSHoratiu Vultur for (i = 0; i <= 1; i++) {
2304c66157fSHoratiu Vultur /*
2314c66157fSHoratiu Vultur * Do byte-swap and expect status after last data word
2324c66157fSHoratiu Vultur * Extraction: Mode: manual extraction) | Byte_swap
2334c66157fSHoratiu Vultur */
2344c66157fSHoratiu Vultur writel(QS_XTR_GRP_CFG_MODE(1) | QS_XTR_GRP_CFG_BYTE_SWAP,
2354c66157fSHoratiu Vultur priv->regs[QS] + QS_XTR_GRP_CFG(i));
2364c66157fSHoratiu Vultur /*
2374c66157fSHoratiu Vultur * Injection: Mode: manual extraction | Byte_swap
2384c66157fSHoratiu Vultur */
2394c66157fSHoratiu Vultur writel(QS_INJ_GRP_CFG_MODE(1) | QS_INJ_GRP_CFG_BYTE_SWAP,
2404c66157fSHoratiu Vultur priv->regs[QS] + QS_INJ_GRP_CFG(i));
2414c66157fSHoratiu Vultur }
2424c66157fSHoratiu Vultur
2434c66157fSHoratiu Vultur for (i = 0; i <= 1; i++)
2444c66157fSHoratiu Vultur /* Enable IFH insertion/parsing on CPU ports */
2454c66157fSHoratiu Vultur writel(SYS_PORT_MODE_INCL_INJ_HDR(1) |
2464c66157fSHoratiu Vultur SYS_PORT_MODE_INCL_XTR_HDR(1),
2474c66157fSHoratiu Vultur priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i));
2484c66157fSHoratiu Vultur /*
2494c66157fSHoratiu Vultur * Setup the CPU port as VLAN aware to support switching frames
2504c66157fSHoratiu Vultur * based on tags
2514c66157fSHoratiu Vultur */
2524c66157fSHoratiu Vultur writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
2534c66157fSHoratiu Vultur MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
2544c66157fSHoratiu Vultur
2554c66157fSHoratiu Vultur /* Disable learning (only RECV_ENA must be set) */
2564c66157fSHoratiu Vultur writel(ANA_PORT_PORT_CFG_RECV_ENA,
2574c66157fSHoratiu Vultur priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
2584c66157fSHoratiu Vultur
2594c66157fSHoratiu Vultur /* Enable switching to/from cpu port */
2604c66157fSHoratiu Vultur setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(CPU_PORT),
2614c66157fSHoratiu Vultur QSYS_SWITCH_PORT_MODE_PORT_ENA);
2624c66157fSHoratiu Vultur
2634c66157fSHoratiu Vultur /* No pause on CPU port - not needed (off by default) */
2644c66157fSHoratiu Vultur clrbits_le32(priv->regs[SYS] + SYS_PAUSE_CFG(CPU_PORT),
2654c66157fSHoratiu Vultur SYS_PAUSE_CFG_PAUSE_ENA);
2664c66157fSHoratiu Vultur
2674c66157fSHoratiu Vultur setbits_le32(priv->regs[QSYS] + QSYS_EGR_NO_SHARING, BIT(CPU_PORT));
2684c66157fSHoratiu Vultur }
2694c66157fSHoratiu Vultur
ocelot_port_init(struct ocelot_private * priv,int port)2704c66157fSHoratiu Vultur static void ocelot_port_init(struct ocelot_private *priv, int port)
2714c66157fSHoratiu Vultur {
2724c66157fSHoratiu Vultur void __iomem *regs = priv->regs[port];
2734c66157fSHoratiu Vultur
2744c66157fSHoratiu Vultur /* Enable PCS */
2754c66157fSHoratiu Vultur writel(PCS1G_MODE_CFG_SGMII_MODE_ENA, regs + PCS1G_CFG);
2764c66157fSHoratiu Vultur
2774c66157fSHoratiu Vultur /* Disable Signal Detect */
2784c66157fSHoratiu Vultur writel(0, regs + PCS1G_SD_CFG);
2794c66157fSHoratiu Vultur
2804c66157fSHoratiu Vultur /* Enable MAC RX and TX */
2814c66157fSHoratiu Vultur writel(DEV_MAC_ENA_CFG_RX_ENA | DEV_MAC_ENA_CFG_TX_ENA,
2824c66157fSHoratiu Vultur regs + DEV_MAC_ENA_CFG);
2834c66157fSHoratiu Vultur
2844c66157fSHoratiu Vultur /* Clear sgmii_mode_ena */
2854c66157fSHoratiu Vultur writel(0, regs + PCS1G_MODE_CFG);
2864c66157fSHoratiu Vultur
2874c66157fSHoratiu Vultur /*
2884c66157fSHoratiu Vultur * Clear sw_resolve_ena(bit 0) and set adv_ability to
2894c66157fSHoratiu Vultur * something meaningful just in case
2904c66157fSHoratiu Vultur */
2914c66157fSHoratiu Vultur writel(PCS1G_ANEG_CFG_ADV_ABILITY(0x20), regs + PCS1G_ANEG_CFG);
2924c66157fSHoratiu Vultur
2934c66157fSHoratiu Vultur /* Set MAC IFG Gaps */
2944c66157fSHoratiu Vultur writel(DEV_MAC_IFG_CFG_TX_IFG(5) | DEV_MAC_IFG_CFG_RX_IFG1(5) |
2954c66157fSHoratiu Vultur DEV_MAC_IFG_CFG_RX_IFG2(1), regs + DEV_MAC_IFG_CFG);
2964c66157fSHoratiu Vultur
2974c66157fSHoratiu Vultur /* Set link speed and release all resets */
2984c66157fSHoratiu Vultur writel(DEV_CLOCK_CFG_LINK_SPEED_1000, regs + DEV_CLOCK_CFG);
2994c66157fSHoratiu Vultur
3004c66157fSHoratiu Vultur /* Make VLAN aware for CPU traffic */
3014c66157fSHoratiu Vultur writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
3024c66157fSHoratiu Vultur MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
3034c66157fSHoratiu Vultur
3044c66157fSHoratiu Vultur /* Enable the port in the core */
3054c66157fSHoratiu Vultur setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port - PORT0),
3064c66157fSHoratiu Vultur QSYS_SWITCH_PORT_MODE_PORT_ENA);
3074c66157fSHoratiu Vultur }
3084c66157fSHoratiu Vultur
ocelot_switch_init(struct ocelot_private * priv)3094c66157fSHoratiu Vultur static int ocelot_switch_init(struct ocelot_private *priv)
3104c66157fSHoratiu Vultur {
3114c66157fSHoratiu Vultur /* Reset switch & memories */
3124c66157fSHoratiu Vultur writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
3134c66157fSHoratiu Vultur priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
3144c66157fSHoratiu Vultur
3154c66157fSHoratiu Vultur /* Wait to complete */
3164c66157fSHoratiu Vultur if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
3174c66157fSHoratiu Vultur SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
3184c66157fSHoratiu Vultur pr_err("Timeout in memory reset\n");
3194c66157fSHoratiu Vultur return -EIO;
3204c66157fSHoratiu Vultur }
3214c66157fSHoratiu Vultur
3224c66157fSHoratiu Vultur /* Enable switch core */
3234c66157fSHoratiu Vultur setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
3244c66157fSHoratiu Vultur SYS_SYSTEM_RST_CORE_ENA);
3254c66157fSHoratiu Vultur
3264c66157fSHoratiu Vultur return 0;
3274c66157fSHoratiu Vultur }
3284c66157fSHoratiu Vultur
ocelot_initialize(struct ocelot_private * priv)3294c66157fSHoratiu Vultur static int ocelot_initialize(struct ocelot_private *priv)
3304c66157fSHoratiu Vultur {
3314c66157fSHoratiu Vultur int ret, i;
3324c66157fSHoratiu Vultur
3334c66157fSHoratiu Vultur /* Initialize switch memories, enable core */
3344c66157fSHoratiu Vultur ret = ocelot_switch_init(priv);
3354c66157fSHoratiu Vultur if (ret)
3364c66157fSHoratiu Vultur return ret;
3374c66157fSHoratiu Vultur /*
3384c66157fSHoratiu Vultur * Disable port-to-port by switching
3394c66157fSHoratiu Vultur * Put fron ports in "port isolation modes" - i.e. they cant send
3404c66157fSHoratiu Vultur * to other ports - via the PGID sorce masks.
3414c66157fSHoratiu Vultur */
3424c66157fSHoratiu Vultur for (i = 0; i <= MAX_PORT; i++)
3434c66157fSHoratiu Vultur writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
3444c66157fSHoratiu Vultur
3454c66157fSHoratiu Vultur /* Flush queues */
34636d04f52SHoratiu Vultur mscc_flush(priv->regs[QS], ocelot_regs_qs);
3474c66157fSHoratiu Vultur
3484c66157fSHoratiu Vultur /* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */
3494c66157fSHoratiu Vultur writel(SYS_FRM_AGING_ENA | (20000000 / 65),
3504c66157fSHoratiu Vultur priv->regs[SYS] + SYS_FRM_AGING);
3514c66157fSHoratiu Vultur
3524c66157fSHoratiu Vultur for (i = PORT0; i <= PORT3; i++)
3534c66157fSHoratiu Vultur ocelot_port_init(priv, i);
3544c66157fSHoratiu Vultur
3554c66157fSHoratiu Vultur ocelot_cpu_capture_setup(priv);
3564c66157fSHoratiu Vultur
3574c66157fSHoratiu Vultur debug("Ports enabled\n");
3584c66157fSHoratiu Vultur
3594c66157fSHoratiu Vultur return 0;
3604c66157fSHoratiu Vultur }
3614c66157fSHoratiu Vultur
ocelot_write_hwaddr(struct udevice * dev)3624c66157fSHoratiu Vultur static int ocelot_write_hwaddr(struct udevice *dev)
3634c66157fSHoratiu Vultur {
3644c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
3654c66157fSHoratiu Vultur struct eth_pdata *pdata = dev_get_platdata(dev);
3664c66157fSHoratiu Vultur
36745f2748cSHoratiu Vultur mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
36845f2748cSHoratiu Vultur pdata->enetaddr, PGID_UNICAST);
3694c66157fSHoratiu Vultur
3704c66157fSHoratiu Vultur writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
3714c66157fSHoratiu Vultur
3724c66157fSHoratiu Vultur return 0;
3734c66157fSHoratiu Vultur }
3744c66157fSHoratiu Vultur
ocelot_start(struct udevice * dev)3754c66157fSHoratiu Vultur static int ocelot_start(struct udevice *dev)
3764c66157fSHoratiu Vultur {
3774c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
3784c66157fSHoratiu Vultur struct eth_pdata *pdata = dev_get_platdata(dev);
3794c66157fSHoratiu Vultur const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
3804c66157fSHoratiu Vultur 0xff };
3814c66157fSHoratiu Vultur int ret;
3824c66157fSHoratiu Vultur
3834c66157fSHoratiu Vultur ret = ocelot_initialize(priv);
3844c66157fSHoratiu Vultur if (ret)
3854c66157fSHoratiu Vultur return ret;
3864c66157fSHoratiu Vultur
3874c66157fSHoratiu Vultur /* Set MAC address tables entries for CPU redirection */
38845f2748cSHoratiu Vultur mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, mac,
38945f2748cSHoratiu Vultur PGID_BROADCAST);
3904c66157fSHoratiu Vultur
3914c66157fSHoratiu Vultur writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
3924c66157fSHoratiu Vultur priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
3934c66157fSHoratiu Vultur
3944c66157fSHoratiu Vultur /* It should be setup latter in ocelot_write_hwaddr */
39545f2748cSHoratiu Vultur mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
39645f2748cSHoratiu Vultur pdata->enetaddr, PGID_UNICAST);
3974c66157fSHoratiu Vultur
3984c66157fSHoratiu Vultur writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
3994c66157fSHoratiu Vultur
4004c66157fSHoratiu Vultur return 0;
4014c66157fSHoratiu Vultur }
4024c66157fSHoratiu Vultur
ocelot_send(struct udevice * dev,void * packet,int length)4034c66157fSHoratiu Vultur static int ocelot_send(struct udevice *dev, void *packet, int length)
4044c66157fSHoratiu Vultur {
4054c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
4064c66157fSHoratiu Vultur u32 ifh[IFH_LEN];
4074c66157fSHoratiu Vultur int port = BIT(0); /* use port 0 */
4084c66157fSHoratiu Vultur u32 *buf = packet;
4094c66157fSHoratiu Vultur
4104c66157fSHoratiu Vultur /*
4114c66157fSHoratiu Vultur * Generate the IFH for frame injection
4124c66157fSHoratiu Vultur *
4134c66157fSHoratiu Vultur * The IFH is a 128bit-value
4144c66157fSHoratiu Vultur * bit 127: bypass the analyzer processing
4154c66157fSHoratiu Vultur * bit 56-67: destination mask
4164c66157fSHoratiu Vultur * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
4174c66157fSHoratiu Vultur * bit 20-27: cpu extraction queue mask
4184c66157fSHoratiu Vultur * bit 16: tag type 0: C-tag, 1: S-tag
4194c66157fSHoratiu Vultur * bit 0-11: VID
4204c66157fSHoratiu Vultur */
4214c66157fSHoratiu Vultur ifh[0] = IFH_INJ_BYPASS;
4224c66157fSHoratiu Vultur ifh[1] = (0xf00 & port) >> 8;
4234c66157fSHoratiu Vultur ifh[2] = (0xff & port) << 24;
4244c66157fSHoratiu Vultur ifh[3] = (IFH_TAG_TYPE_C << 16);
4254c66157fSHoratiu Vultur
42636d04f52SHoratiu Vultur return mscc_send(priv->regs[QS], ocelot_regs_qs,
42736d04f52SHoratiu Vultur ifh, IFH_LEN, buf, length);
4284c66157fSHoratiu Vultur }
4294c66157fSHoratiu Vultur
ocelot_recv(struct udevice * dev,int flags,uchar ** packetp)4304c66157fSHoratiu Vultur static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp)
4314c66157fSHoratiu Vultur {
4324c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
4334c66157fSHoratiu Vultur u32 *rxbuf = (u32 *)net_rx_packets[0];
43436d04f52SHoratiu Vultur int byte_cnt;
4354c66157fSHoratiu Vultur
43636d04f52SHoratiu Vultur byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN,
43736d04f52SHoratiu Vultur false);
4384c66157fSHoratiu Vultur
4394c66157fSHoratiu Vultur *packetp = net_rx_packets[0];
4404c66157fSHoratiu Vultur
4414c66157fSHoratiu Vultur return byte_cnt;
4424c66157fSHoratiu Vultur }
4434c66157fSHoratiu Vultur
ocelot_probe(struct udevice * dev)4444c66157fSHoratiu Vultur static int ocelot_probe(struct udevice *dev)
4454c66157fSHoratiu Vultur {
4464c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
4474c66157fSHoratiu Vultur int ret, i;
4484c66157fSHoratiu Vultur
4494c66157fSHoratiu Vultur struct {
4504c66157fSHoratiu Vultur enum ocelot_target id;
4514c66157fSHoratiu Vultur char *name;
4524c66157fSHoratiu Vultur } reg[] = {
4534c66157fSHoratiu Vultur { SYS, "sys" },
4544c66157fSHoratiu Vultur { REW, "rew" },
4554c66157fSHoratiu Vultur { QSYS, "qsys" },
4564c66157fSHoratiu Vultur { ANA, "ana" },
4574c66157fSHoratiu Vultur { QS, "qs" },
4584c66157fSHoratiu Vultur { HSIO, "hsio" },
4594c66157fSHoratiu Vultur { PORT0, "port0" },
4604c66157fSHoratiu Vultur { PORT1, "port1" },
4614c66157fSHoratiu Vultur { PORT2, "port2" },
4624c66157fSHoratiu Vultur { PORT3, "port3" },
4634c66157fSHoratiu Vultur };
4644c66157fSHoratiu Vultur
4654c66157fSHoratiu Vultur for (i = 0; i < ARRAY_SIZE(reg); i++) {
4664c66157fSHoratiu Vultur priv->regs[reg[i].id] = dev_remap_addr_name(dev, reg[i].name);
4674c66157fSHoratiu Vultur if (!priv->regs[reg[i].id]) {
4684c66157fSHoratiu Vultur pr_err
4694c66157fSHoratiu Vultur ("Error %d: can't get regs base addresses for %s\n",
4704c66157fSHoratiu Vultur ret, reg[i].name);
4714c66157fSHoratiu Vultur return -ENOMEM;
4724c66157fSHoratiu Vultur }
4734c66157fSHoratiu Vultur }
4744c66157fSHoratiu Vultur
4754c66157fSHoratiu Vultur priv->bus[INTERNAL] = ocelot_mdiobus_init(dev);
4764c66157fSHoratiu Vultur
4774c66157fSHoratiu Vultur for (i = 0; i < 4; i++) {
4784c66157fSHoratiu Vultur phy_connect(priv->bus[INTERNAL], i, dev,
4794c66157fSHoratiu Vultur PHY_INTERFACE_MODE_NONE);
4804c66157fSHoratiu Vultur }
4814c66157fSHoratiu Vultur
4824c66157fSHoratiu Vultur return 0;
4834c66157fSHoratiu Vultur }
4844c66157fSHoratiu Vultur
ocelot_remove(struct udevice * dev)4854c66157fSHoratiu Vultur static int ocelot_remove(struct udevice *dev)
4864c66157fSHoratiu Vultur {
4874c66157fSHoratiu Vultur struct ocelot_private *priv = dev_get_priv(dev);
4884c66157fSHoratiu Vultur int i;
4894c66157fSHoratiu Vultur
4904c66157fSHoratiu Vultur for (i = 0; i < NUM_PHY; i++) {
4914c66157fSHoratiu Vultur mdio_unregister(priv->bus[i]);
4924c66157fSHoratiu Vultur mdio_free(priv->bus[i]);
4934c66157fSHoratiu Vultur }
4944c66157fSHoratiu Vultur
4954c66157fSHoratiu Vultur return 0;
4964c66157fSHoratiu Vultur }
4974c66157fSHoratiu Vultur
4984c66157fSHoratiu Vultur static const struct eth_ops ocelot_ops = {
4994c66157fSHoratiu Vultur .start = ocelot_start,
5004c66157fSHoratiu Vultur .stop = ocelot_stop,
5014c66157fSHoratiu Vultur .send = ocelot_send,
5024c66157fSHoratiu Vultur .recv = ocelot_recv,
5034c66157fSHoratiu Vultur .write_hwaddr = ocelot_write_hwaddr,
5044c66157fSHoratiu Vultur };
5054c66157fSHoratiu Vultur
5064c66157fSHoratiu Vultur static const struct udevice_id mscc_ocelot_ids[] = {
5074c66157fSHoratiu Vultur {.compatible = "mscc,vsc7514-switch"},
5084c66157fSHoratiu Vultur { /* Sentinel */ }
5094c66157fSHoratiu Vultur };
5104c66157fSHoratiu Vultur
5114c66157fSHoratiu Vultur U_BOOT_DRIVER(ocelot) = {
5124c66157fSHoratiu Vultur .name = "ocelot-switch",
5134c66157fSHoratiu Vultur .id = UCLASS_ETH,
5144c66157fSHoratiu Vultur .of_match = mscc_ocelot_ids,
5154c66157fSHoratiu Vultur .probe = ocelot_probe,
5164c66157fSHoratiu Vultur .remove = ocelot_remove,
5174c66157fSHoratiu Vultur .ops = &ocelot_ops,
5184c66157fSHoratiu Vultur .priv_auto_alloc_size = sizeof(struct ocelot_private),
5194c66157fSHoratiu Vultur .platdata_auto_alloc_size = sizeof(struct eth_pdata),
5204c66157fSHoratiu Vultur };
521