| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
- /*
- * NXP NETC Blocks Control Driver
- *
- * Copyright 2024 NXP
- *
- * This driver is used for pre-initialization of NETC, such as PCS and MII
- * protocols, LDID, warm reset, etc. Therefore, all NETC device drivers can
- * only be probed after the netc-blk-crtl driver has completed initialization.
- * In addition, when the system enters suspend mode, IERB, PRB, and NETCMIX
- * will be powered off, except for WOL. Therefore, when the system resumes,
- * these blocks need to be reinitialized.
- */
- #include <linux/bits.h>
- #include <linux/clk.h>
- #include <linux/debugfs.h>
- #include <linux/delay.h>
- #include <linux/fsl/netc_global.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/of_net.h>
- #include <linux/of_platform.h>
- #include <linux/phy.h>
- #include <linux/platform_device.h>
- #include <linux/seq_file.h>
- /* NETCMIX registers */
- #define IMX95_CFG_LINK_IO_VAR 0x0
- #define IO_VAR_16FF_16G_SERDES 0x1
- #define IO_VAR(port, var) (((var) & 0xf) << ((port) << 2))
- #define IMX95_CFG_LINK_MII_PROT 0x4
- #define CFG_LINK_MII_PORT_0 GENMASK(3, 0)
- #define CFG_LINK_MII_PORT_1 GENMASK(7, 4)
- #define MII_PROT_MII 0x0
- #define MII_PROT_RMII 0x1
- #define MII_PROT_RGMII 0x2
- #define MII_PROT_SERIAL 0x3
- #define MII_PROT(port, prot) (((prot) & 0xf) << ((port) << 2))
- #define IMX95_CFG_LINK_PCS_PROT(a) (0x8 + (a) * 4)
- #define PCS_PROT_1G_SGMII BIT(0)
- #define PCS_PROT_2500M_SGMII BIT(1)
- #define PCS_PROT_XFI BIT(3)
- #define PCS_PROT_SFI BIT(4)
- #define PCS_PROT_10G_SXGMII BIT(6)
- #define IMX94_EXT_PIN_CONTROL 0x10
- #define MAC2_MAC3_SEL BIT(1)
- #define IMX94_NETC_LINK_CFG(a) (0x4c + (a) * 4)
- #define NETC_LINK_CFG_MII_PROT GENMASK(3, 0)
- #define NETC_LINK_CFG_IO_VAR GENMASK(19, 16)
- /* NETC privileged register block register */
- #define PRB_NETCRR 0x100
- #define NETCRR_SR BIT(0)
- #define NETCRR_LOCK BIT(1)
- #define PRB_NETCSR 0x104
- #define NETCSR_ERROR BIT(0)
- #define NETCSR_STATE BIT(1)
- /* NETC integrated endpoint register block register */
- #define IERB_EMDIOFAUXR 0x344
- #define IERB_T0FAUXR 0x444
- #define IERB_ETBCR(a) (0x300c + 0x100 * (a))
- #define IERB_LBCR(a) (0x1010 + 0x40 * (a))
- #define LBCR_MDIO_PHYAD_PRTAD(addr) (((addr) & 0x1f) << 8)
- #define IERB_EFAUXR(a) (0x3044 + 0x100 * (a))
- #define IERB_VFAUXR(a) (0x4004 + 0x40 * (a))
- #define FAUXR_LDID GENMASK(3, 0)
- /* Platform information */
- #define IMX95_ENETC0_BUS_DEVFN 0x0
- #define IMX95_ENETC1_BUS_DEVFN 0x40
- #define IMX95_ENETC2_BUS_DEVFN 0x80
- #define IMX94_ENETC0_BUS_DEVFN 0x100
- #define IMX94_ENETC1_BUS_DEVFN 0x140
- #define IMX94_ENETC2_BUS_DEVFN 0x180
- #define IMX94_TIMER0_BUS_DEVFN 0x1
- #define IMX94_TIMER1_BUS_DEVFN 0x101
- #define IMX94_TIMER2_BUS_DEVFN 0x181
- #define IMX94_ENETC0_LINK 3
- #define IMX94_ENETC1_LINK 4
- #define IMX94_ENETC2_LINK 5
- #define NETC_ENETC_ID(a) (a)
- #define NETC_TIMER_ID(a) (a)
- /* Flags for different platforms */
- #define NETC_HAS_NETCMIX BIT(0)
- struct netc_devinfo {
- u32 flags;
- int (*netcmix_init)(struct platform_device *pdev);
- int (*ierb_init)(struct platform_device *pdev);
- };
- struct netc_blk_ctrl {
- void __iomem *prb;
- void __iomem *ierb;
- void __iomem *netcmix;
- const struct netc_devinfo *devinfo;
- struct platform_device *pdev;
- struct dentry *debugfs_root;
- };
- static void netc_reg_write(void __iomem *base, u32 offset, u32 val)
- {
- netc_write(base + offset, val);
- }
- static u32 netc_reg_read(void __iomem *base, u32 offset)
- {
- return netc_read(base + offset);
- }
- static int netc_of_pci_get_bus_devfn(struct device_node *np)
- {
- u32 reg[5];
- int error;
- error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
- if (error)
- return error;
- return (reg[0] >> 8) & 0xffff;
- }
- static int netc_get_link_mii_protocol(phy_interface_t interface)
- {
- switch (interface) {
- case PHY_INTERFACE_MODE_MII:
- return MII_PROT_MII;
- case PHY_INTERFACE_MODE_RMII:
- return MII_PROT_RMII;
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- return MII_PROT_RGMII;
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_2500BASEX:
- case PHY_INTERFACE_MODE_10GBASER:
- case PHY_INTERFACE_MODE_XGMII:
- case PHY_INTERFACE_MODE_USXGMII:
- return MII_PROT_SERIAL;
- default:
- return -EINVAL;
- }
- }
- static int imx95_netcmix_init(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- struct device_node *np = pdev->dev.of_node;
- phy_interface_t interface;
- int bus_devfn, mii_proto;
- u32 val;
- int err;
- /* Default setting of MII protocol */
- val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII) |
- MII_PROT(2, MII_PROT_SERIAL);
- /* Update the link MII protocol through parsing phy-mode */
- for_each_available_child_of_node_scoped(np, child) {
- for_each_available_child_of_node_scoped(child, gchild) {
- if (!of_device_is_compatible(gchild, "pci1131,e101"))
- continue;
- bus_devfn = netc_of_pci_get_bus_devfn(gchild);
- if (bus_devfn < 0)
- return -EINVAL;
- if (bus_devfn == IMX95_ENETC2_BUS_DEVFN)
- continue;
- err = of_get_phy_mode(gchild, &interface);
- if (err)
- continue;
- mii_proto = netc_get_link_mii_protocol(interface);
- if (mii_proto < 0)
- return -EINVAL;
- switch (bus_devfn) {
- case IMX95_ENETC0_BUS_DEVFN:
- val = u32_replace_bits(val, mii_proto,
- CFG_LINK_MII_PORT_0);
- break;
- case IMX95_ENETC1_BUS_DEVFN:
- val = u32_replace_bits(val, mii_proto,
- CFG_LINK_MII_PORT_1);
- break;
- default:
- return -EINVAL;
- }
- }
- }
- /* Configure Link I/O variant */
- netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR,
- IO_VAR(2, IO_VAR_16FF_16G_SERDES));
- /* Configure Link 2 PCS protocol */
- netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(2),
- PCS_PROT_10G_SXGMII);
- netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val);
- return 0;
- }
- static int imx94_enetc_get_link_id(struct device_node *np)
- {
- int bus_devfn = netc_of_pci_get_bus_devfn(np);
- /* Parse ENETC link number */
- switch (bus_devfn) {
- case IMX94_ENETC0_BUS_DEVFN:
- return IMX94_ENETC0_LINK;
- case IMX94_ENETC1_BUS_DEVFN:
- return IMX94_ENETC1_LINK;
- case IMX94_ENETC2_BUS_DEVFN:
- return IMX94_ENETC2_LINK;
- default:
- return -EINVAL;
- }
- }
- static int imx94_link_config(struct netc_blk_ctrl *priv,
- struct device_node *np, int link_id)
- {
- phy_interface_t interface;
- int mii_proto;
- u32 val;
- /* The node may be disabled and does not have a 'phy-mode'
- * or 'phy-connection-type' property.
- */
- if (of_get_phy_mode(np, &interface))
- return 0;
- mii_proto = netc_get_link_mii_protocol(interface);
- if (mii_proto < 0)
- return mii_proto;
- val = mii_proto & NETC_LINK_CFG_MII_PROT;
- if (val == MII_PROT_SERIAL)
- val = u32_replace_bits(val, IO_VAR_16FF_16G_SERDES,
- NETC_LINK_CFG_IO_VAR);
- netc_reg_write(priv->netcmix, IMX94_NETC_LINK_CFG(link_id), val);
- return 0;
- }
- static int imx94_enetc_link_config(struct netc_blk_ctrl *priv,
- struct device_node *np)
- {
- int link_id = imx94_enetc_get_link_id(np);
- if (link_id < 0)
- return link_id;
- return imx94_link_config(priv, np, link_id);
- }
- static int imx94_netcmix_init(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- struct device_node *np = pdev->dev.of_node;
- u32 val;
- int err;
- for_each_child_of_node_scoped(np, child) {
- for_each_child_of_node_scoped(child, gchild) {
- if (!of_device_is_compatible(gchild, "pci1131,e101"))
- continue;
- err = imx94_enetc_link_config(priv, gchild);
- if (err)
- return err;
- }
- }
- /* ENETC 0 and switch port 2 share the same parallel interface.
- * Currently, the switch is not supported, so this interface is
- * used by ENETC 0 by default.
- */
- val = netc_reg_read(priv->netcmix, IMX94_EXT_PIN_CONTROL);
- val |= MAC2_MAC3_SEL;
- netc_reg_write(priv->netcmix, IMX94_EXT_PIN_CONTROL, val);
- return 0;
- }
- static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv)
- {
- return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK);
- }
- static int netc_lock_ierb(struct netc_blk_ctrl *priv)
- {
- u32 val;
- netc_reg_write(priv->prb, PRB_NETCRR, NETCRR_LOCK);
- return read_poll_timeout(netc_reg_read, val, !(val & NETCSR_STATE),
- 100, 2000, false, priv->prb, PRB_NETCSR);
- }
- static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)
- {
- u32 val;
- netc_reg_write(priv->prb, PRB_NETCRR, 0);
- return read_poll_timeout(netc_reg_read, val, !(val & NETCRR_LOCK),
- 1000, 100000, true, priv->prb, PRB_NETCRR);
- }
- static int netc_get_phy_addr(struct device_node *np)
- {
- struct device_node *mdio_node, *phy_node;
- u32 addr = 0;
- int err = 0;
- mdio_node = of_get_child_by_name(np, "mdio");
- if (!mdio_node)
- return -ENODEV;
- phy_node = of_get_next_child(mdio_node, NULL);
- if (!phy_node) {
- err = -ENODEV;
- goto of_put_mdio_node;
- }
- err = of_property_read_u32(phy_node, "reg", &addr);
- if (err)
- goto of_put_phy_node;
- if (addr >= PHY_MAX_ADDR)
- err = -EINVAL;
- of_put_phy_node:
- of_node_put(phy_node);
- of_put_mdio_node:
- of_node_put(mdio_node);
- return err ? err : addr;
- }
- static int netc_parse_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
- {
- u32 mask = 0;
- for_each_child_of_node_scoped(np, child) {
- u32 addr;
- int err;
- err = of_property_read_u32(child, "reg", &addr);
- if (err)
- return err;
- if (addr >= PHY_MAX_ADDR)
- return -EINVAL;
- mask |= BIT(addr);
- }
- *phy_mask = mask;
- return 0;
- }
- static int netc_get_emdio_phy_mask(struct device_node *np, u32 *phy_mask)
- {
- for_each_child_of_node_scoped(np, child) {
- for_each_child_of_node_scoped(child, gchild) {
- if (!of_device_is_compatible(gchild, "pci1131,ee00"))
- continue;
- return netc_parse_emdio_phy_mask(gchild, phy_mask);
- }
- }
- return 0;
- }
- static int imx95_enetc_mdio_phyaddr_config(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- struct device_node *np = pdev->dev.of_node;
- struct device *dev = &pdev->dev;
- int bus_devfn, addr, err;
- u32 phy_mask = 0;
- err = netc_get_emdio_phy_mask(np, &phy_mask);
- if (err) {
- dev_err(dev, "Failed to get PHY address mask\n");
- return err;
- }
- /* Update the port EMDIO PHY address through parsing phy properties.
- * This is needed when using the port EMDIO but it's harmless when
- * using the central EMDIO. So apply it on all cases.
- */
- for_each_child_of_node_scoped(np, child) {
- for_each_child_of_node_scoped(child, gchild) {
- if (!of_device_is_compatible(gchild, "pci1131,e101"))
- continue;
- bus_devfn = netc_of_pci_get_bus_devfn(gchild);
- if (bus_devfn < 0) {
- dev_err(dev, "Failed to get BDF number\n");
- return bus_devfn;
- }
- addr = netc_get_phy_addr(gchild);
- if (addr < 0) {
- if (addr == -ENODEV)
- continue;
- dev_err(dev, "Failed to get PHY address\n");
- return addr;
- }
- if (phy_mask & BIT(addr)) {
- dev_err(dev,
- "Find same PHY address in EMDIO and ENETC node\n");
- return -EINVAL;
- }
- switch (bus_devfn) {
- case IMX95_ENETC0_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(0),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- case IMX95_ENETC1_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(1),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- case IMX95_ENETC2_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(2),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- default:
- break;
- }
- }
- }
- return 0;
- }
- static int imx95_ierb_init(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- /* EMDIO : No MSI-X intterupt */
- netc_reg_write(priv->ierb, IERB_EMDIOFAUXR, 0);
- /* ENETC0 PF */
- netc_reg_write(priv->ierb, IERB_EFAUXR(0), 0);
- /* ENETC0 VF0 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(0), 1);
- /* ENETC0 VF1 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(1), 2);
- /* ENETC1 PF */
- netc_reg_write(priv->ierb, IERB_EFAUXR(1), 3);
- /* ENETC1 VF0 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(2), 5);
- /* ENETC1 VF1 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(3), 6);
- /* ENETC2 PF */
- netc_reg_write(priv->ierb, IERB_EFAUXR(2), 4);
- /* ENETC2 VF0 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(4), 5);
- /* ENETC2 VF1 */
- netc_reg_write(priv->ierb, IERB_VFAUXR(5), 6);
- /* NETC TIMER */
- netc_reg_write(priv->ierb, IERB_T0FAUXR, 7);
- return imx95_enetc_mdio_phyaddr_config(pdev);
- }
- static int imx94_get_enetc_id(struct device_node *np)
- {
- int bus_devfn = netc_of_pci_get_bus_devfn(np);
- /* Parse ENETC offset */
- switch (bus_devfn) {
- case IMX94_ENETC0_BUS_DEVFN:
- return NETC_ENETC_ID(0);
- case IMX94_ENETC1_BUS_DEVFN:
- return NETC_ENETC_ID(1);
- case IMX94_ENETC2_BUS_DEVFN:
- return NETC_ENETC_ID(2);
- default:
- return -EINVAL;
- }
- }
- static int imx94_get_timer_id(struct device_node *np)
- {
- int bus_devfn = netc_of_pci_get_bus_devfn(np);
- /* Parse NETC PTP timer ID, the timer0 is on bus 0,
- * the timer 1 and timer2 is on bus 1.
- */
- switch (bus_devfn) {
- case IMX94_TIMER0_BUS_DEVFN:
- return NETC_TIMER_ID(0);
- case IMX94_TIMER1_BUS_DEVFN:
- return NETC_TIMER_ID(1);
- case IMX94_TIMER2_BUS_DEVFN:
- return NETC_TIMER_ID(2);
- default:
- return -EINVAL;
- }
- }
- static int imx94_enetc_update_tid(struct netc_blk_ctrl *priv,
- struct device_node *np)
- {
- struct device *dev = &priv->pdev->dev;
- struct device_node *timer_np;
- int eid, tid;
- eid = imx94_get_enetc_id(np);
- if (eid < 0) {
- dev_err(dev, "Failed to get ENETC ID\n");
- return eid;
- }
- timer_np = of_parse_phandle(np, "ptp-timer", 0);
- if (!timer_np) {
- /* If 'ptp-timer' is not present, the timer1 is the default
- * timer of all standalone ENETCs, which is on the same PCIe
- * bus as these ENETCs.
- */
- tid = NETC_TIMER_ID(1);
- goto end;
- }
- tid = imx94_get_timer_id(timer_np);
- of_node_put(timer_np);
- if (tid < 0) {
- dev_err(dev, "Failed to get NETC Timer ID\n");
- return tid;
- }
- end:
- netc_reg_write(priv->ierb, IERB_ETBCR(eid), tid);
- return 0;
- }
- static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
- struct device_node *np,
- u32 phy_mask)
- {
- struct device *dev = &priv->pdev->dev;
- int bus_devfn, addr;
- bus_devfn = netc_of_pci_get_bus_devfn(np);
- if (bus_devfn < 0) {
- dev_err(dev, "Failed to get BDF number\n");
- return bus_devfn;
- }
- addr = netc_get_phy_addr(np);
- if (addr < 0) {
- if (addr == -ENODEV)
- return 0;
- dev_err(dev, "Failed to get PHY address\n");
- return addr;
- }
- if (phy_mask & BIT(addr)) {
- dev_err(dev,
- "Find same PHY address in EMDIO and ENETC node\n");
- return -EINVAL;
- }
- switch (bus_devfn) {
- case IMX94_ENETC0_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC0_LINK),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- case IMX94_ENETC1_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC1_LINK),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- case IMX94_ENETC2_BUS_DEVFN:
- netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC2_LINK),
- LBCR_MDIO_PHYAD_PRTAD(addr));
- break;
- default:
- break;
- }
- return 0;
- }
- static int imx94_ierb_init(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- struct device_node *np = pdev->dev.of_node;
- u32 phy_mask = 0;
- int err;
- err = netc_get_emdio_phy_mask(np, &phy_mask);
- if (err) {
- dev_err(&pdev->dev, "Failed to get PHY address mask\n");
- return err;
- }
- for_each_child_of_node_scoped(np, child) {
- for_each_child_of_node_scoped(child, gchild) {
- if (!of_device_is_compatible(gchild, "pci1131,e101"))
- continue;
- err = imx94_enetc_update_tid(priv, gchild);
- if (err)
- return err;
- err = imx94_enetc_mdio_phyaddr_config(priv, gchild,
- phy_mask);
- if (err)
- return err;
- }
- }
- return 0;
- }
- static int netc_ierb_init(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- const struct netc_devinfo *devinfo = priv->devinfo;
- int err;
- if (netc_ierb_is_locked(priv)) {
- err = netc_unlock_ierb_with_warm_reset(priv);
- if (err) {
- dev_err(&pdev->dev, "Unlock IERB failed.\n");
- return err;
- }
- }
- if (devinfo->ierb_init) {
- err = devinfo->ierb_init(pdev);
- if (err)
- return err;
- }
- err = netc_lock_ierb(priv);
- if (err) {
- dev_err(&pdev->dev, "Lock IERB failed.\n");
- return err;
- }
- return 0;
- }
- #if IS_ENABLED(CONFIG_DEBUG_FS)
- static int netc_prb_show(struct seq_file *s, void *data)
- {
- struct netc_blk_ctrl *priv = s->private;
- u32 val;
- val = netc_reg_read(priv->prb, PRB_NETCRR);
- seq_printf(s, "[PRB NETCRR] Lock:%d SR:%d\n",
- (val & NETCRR_LOCK) ? 1 : 0,
- (val & NETCRR_SR) ? 1 : 0);
- val = netc_reg_read(priv->prb, PRB_NETCSR);
- seq_printf(s, "[PRB NETCSR] State:%d Error:%d\n",
- (val & NETCSR_STATE) ? 1 : 0,
- (val & NETCSR_ERROR) ? 1 : 0);
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(netc_prb);
- static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
- {
- struct dentry *root;
- root = debugfs_create_dir("netc_blk_ctrl", NULL);
- if (IS_ERR(root))
- return;
- priv->debugfs_root = root;
- debugfs_create_file("prb", 0444, root, priv, &netc_prb_fops);
- }
- static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
- {
- debugfs_remove_recursive(priv->debugfs_root);
- priv->debugfs_root = NULL;
- }
- #else
- static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
- {
- }
- static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
- {
- }
- #endif
- static int netc_prb_check_error(struct netc_blk_ctrl *priv)
- {
- if (netc_reg_read(priv->prb, PRB_NETCSR) & NETCSR_ERROR)
- return -1;
- return 0;
- }
- static const struct netc_devinfo imx95_devinfo = {
- .flags = NETC_HAS_NETCMIX,
- .netcmix_init = imx95_netcmix_init,
- .ierb_init = imx95_ierb_init,
- };
- static const struct netc_devinfo imx94_devinfo = {
- .flags = NETC_HAS_NETCMIX,
- .netcmix_init = imx94_netcmix_init,
- .ierb_init = imx94_ierb_init,
- };
- static const struct of_device_id netc_blk_ctrl_match[] = {
- { .compatible = "nxp,imx95-netc-blk-ctrl", .data = &imx95_devinfo },
- { .compatible = "nxp,imx94-netc-blk-ctrl", .data = &imx94_devinfo },
- {},
- };
- MODULE_DEVICE_TABLE(of, netc_blk_ctrl_match);
- static int netc_blk_ctrl_probe(struct platform_device *pdev)
- {
- struct device_node *node = pdev->dev.of_node;
- const struct netc_devinfo *devinfo;
- struct device *dev = &pdev->dev;
- const struct of_device_id *id;
- struct netc_blk_ctrl *priv;
- struct clk *ipg_clk;
- void __iomem *regs;
- int err;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->pdev = pdev;
- ipg_clk = devm_clk_get_optional_enabled(dev, "ipg");
- if (IS_ERR(ipg_clk))
- return dev_err_probe(dev, PTR_ERR(ipg_clk),
- "Set ipg clock failed\n");
- id = of_match_device(netc_blk_ctrl_match, dev);
- if (!id)
- return dev_err_probe(dev, -EINVAL, "Cannot match device\n");
- devinfo = (struct netc_devinfo *)id->data;
- if (!devinfo)
- return dev_err_probe(dev, -EINVAL, "No device information\n");
- priv->devinfo = devinfo;
- regs = devm_platform_ioremap_resource_byname(pdev, "ierb");
- if (IS_ERR(regs))
- return dev_err_probe(dev, PTR_ERR(regs),
- "Missing IERB resource\n");
- priv->ierb = regs;
- regs = devm_platform_ioremap_resource_byname(pdev, "prb");
- if (IS_ERR(regs))
- return dev_err_probe(dev, PTR_ERR(regs),
- "Missing PRB resource\n");
- priv->prb = regs;
- if (devinfo->flags & NETC_HAS_NETCMIX) {
- regs = devm_platform_ioremap_resource_byname(pdev, "netcmix");
- if (IS_ERR(regs))
- return dev_err_probe(dev, PTR_ERR(regs),
- "Missing NETCMIX resource\n");
- priv->netcmix = regs;
- }
- platform_set_drvdata(pdev, priv);
- if (devinfo->netcmix_init) {
- err = devinfo->netcmix_init(pdev);
- if (err)
- return dev_err_probe(dev, err,
- "Initializing NETCMIX failed\n");
- }
- err = netc_ierb_init(pdev);
- if (err)
- return dev_err_probe(dev, err, "Initializing IERB failed\n");
- if (netc_prb_check_error(priv) < 0)
- dev_warn(dev, "The current IERB configuration is invalid\n");
- netc_blk_ctrl_create_debugfs(priv);
- err = of_platform_populate(node, NULL, NULL, dev);
- if (err) {
- netc_blk_ctrl_remove_debugfs(priv);
- return dev_err_probe(dev, err, "of_platform_populate failed\n");
- }
- return 0;
- }
- static void netc_blk_ctrl_remove(struct platform_device *pdev)
- {
- struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
- of_platform_depopulate(&pdev->dev);
- netc_blk_ctrl_remove_debugfs(priv);
- }
- static struct platform_driver netc_blk_ctrl_driver = {
- .driver = {
- .name = "nxp-netc-blk-ctrl",
- .of_match_table = netc_blk_ctrl_match,
- },
- .probe = netc_blk_ctrl_probe,
- .remove = netc_blk_ctrl_remove,
- };
- module_platform_driver(netc_blk_ctrl_driver);
- MODULE_DESCRIPTION("NXP NETC Blocks Control Driver");
- MODULE_LICENSE("Dual BSD/GPL");
|