xref: /linux/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c (revision c771600c6af14749609b49565ffb4cac2959710d)
1*fe5ba6bfSWei Fang // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2*fe5ba6bfSWei Fang /*
3*fe5ba6bfSWei Fang  * NXP NETC Blocks Control Driver
4*fe5ba6bfSWei Fang  *
5*fe5ba6bfSWei Fang  * Copyright 2024 NXP
6*fe5ba6bfSWei Fang  *
7*fe5ba6bfSWei Fang  * This driver is used for pre-initialization of NETC, such as PCS and MII
8*fe5ba6bfSWei Fang  * protocols, LDID, warm reset, etc. Therefore, all NETC device drivers can
9*fe5ba6bfSWei Fang  * only be probed after the netc-blk-crtl driver has completed initialization.
10*fe5ba6bfSWei Fang  * In addition, when the system enters suspend mode, IERB, PRB, and NETCMIX
11*fe5ba6bfSWei Fang  * will be powered off, except for WOL. Therefore, when the system resumes,
12*fe5ba6bfSWei Fang  * these blocks need to be reinitialized.
13*fe5ba6bfSWei Fang  */
14*fe5ba6bfSWei Fang 
15*fe5ba6bfSWei Fang #include <linux/bits.h>
16*fe5ba6bfSWei Fang #include <linux/clk.h>
17*fe5ba6bfSWei Fang #include <linux/debugfs.h>
18*fe5ba6bfSWei Fang #include <linux/delay.h>
19*fe5ba6bfSWei Fang #include <linux/fsl/netc_global.h>
20*fe5ba6bfSWei Fang #include <linux/module.h>
21*fe5ba6bfSWei Fang #include <linux/of.h>
22*fe5ba6bfSWei Fang #include <linux/of_device.h>
23*fe5ba6bfSWei Fang #include <linux/of_net.h>
24*fe5ba6bfSWei Fang #include <linux/of_platform.h>
25*fe5ba6bfSWei Fang #include <linux/phy.h>
26*fe5ba6bfSWei Fang #include <linux/platform_device.h>
27*fe5ba6bfSWei Fang #include <linux/seq_file.h>
28*fe5ba6bfSWei Fang 
29*fe5ba6bfSWei Fang /* NETCMIX registers */
30*fe5ba6bfSWei Fang #define IMX95_CFG_LINK_IO_VAR		0x0
31*fe5ba6bfSWei Fang #define  IO_VAR_16FF_16G_SERDES		0x1
32*fe5ba6bfSWei Fang #define  IO_VAR(port, var)		(((var) & 0xf) << ((port) << 2))
33*fe5ba6bfSWei Fang 
34*fe5ba6bfSWei Fang #define IMX95_CFG_LINK_MII_PROT		0x4
35*fe5ba6bfSWei Fang #define CFG_LINK_MII_PORT_0		GENMASK(3, 0)
36*fe5ba6bfSWei Fang #define CFG_LINK_MII_PORT_1		GENMASK(7, 4)
37*fe5ba6bfSWei Fang #define  MII_PROT_MII			0x0
38*fe5ba6bfSWei Fang #define  MII_PROT_RMII			0x1
39*fe5ba6bfSWei Fang #define  MII_PROT_RGMII			0x2
40*fe5ba6bfSWei Fang #define  MII_PROT_SERIAL		0x3
41*fe5ba6bfSWei Fang #define  MII_PROT(port, prot)		(((prot) & 0xf) << ((port) << 2))
42*fe5ba6bfSWei Fang 
43*fe5ba6bfSWei Fang #define IMX95_CFG_LINK_PCS_PROT(a)	(0x8 + (a) * 4)
44*fe5ba6bfSWei Fang #define PCS_PROT_1G_SGMII		BIT(0)
45*fe5ba6bfSWei Fang #define PCS_PROT_2500M_SGMII		BIT(1)
46*fe5ba6bfSWei Fang #define PCS_PROT_XFI			BIT(3)
47*fe5ba6bfSWei Fang #define PCS_PROT_SFI			BIT(4)
48*fe5ba6bfSWei Fang #define PCS_PROT_10G_SXGMII		BIT(6)
49*fe5ba6bfSWei Fang 
50*fe5ba6bfSWei Fang /* NETC privileged register block register */
51*fe5ba6bfSWei Fang #define PRB_NETCRR			0x100
52*fe5ba6bfSWei Fang #define  NETCRR_SR			BIT(0)
53*fe5ba6bfSWei Fang #define  NETCRR_LOCK			BIT(1)
54*fe5ba6bfSWei Fang 
55*fe5ba6bfSWei Fang #define PRB_NETCSR			0x104
56*fe5ba6bfSWei Fang #define  NETCSR_ERROR			BIT(0)
57*fe5ba6bfSWei Fang #define  NETCSR_STATE			BIT(1)
58*fe5ba6bfSWei Fang 
59*fe5ba6bfSWei Fang /* NETC integrated endpoint register block register */
60*fe5ba6bfSWei Fang #define IERB_EMDIOFAUXR			0x344
61*fe5ba6bfSWei Fang #define IERB_T0FAUXR			0x444
62*fe5ba6bfSWei Fang #define IERB_EFAUXR(a)			(0x3044 + 0x100 * (a))
63*fe5ba6bfSWei Fang #define IERB_VFAUXR(a)			(0x4004 + 0x40 * (a))
64*fe5ba6bfSWei Fang #define FAUXR_LDID			GENMASK(3, 0)
65*fe5ba6bfSWei Fang 
66*fe5ba6bfSWei Fang /* Platform information */
67*fe5ba6bfSWei Fang #define IMX95_ENETC0_BUS_DEVFN		0x0
68*fe5ba6bfSWei Fang #define IMX95_ENETC1_BUS_DEVFN		0x40
69*fe5ba6bfSWei Fang #define IMX95_ENETC2_BUS_DEVFN		0x80
70*fe5ba6bfSWei Fang 
71*fe5ba6bfSWei Fang /* Flags for different platforms */
72*fe5ba6bfSWei Fang #define NETC_HAS_NETCMIX		BIT(0)
73*fe5ba6bfSWei Fang 
74*fe5ba6bfSWei Fang struct netc_devinfo {
75*fe5ba6bfSWei Fang 	u32 flags;
76*fe5ba6bfSWei Fang 	int (*netcmix_init)(struct platform_device *pdev);
77*fe5ba6bfSWei Fang 	int (*ierb_init)(struct platform_device *pdev);
78*fe5ba6bfSWei Fang };
79*fe5ba6bfSWei Fang 
80*fe5ba6bfSWei Fang struct netc_blk_ctrl {
81*fe5ba6bfSWei Fang 	void __iomem *prb;
82*fe5ba6bfSWei Fang 	void __iomem *ierb;
83*fe5ba6bfSWei Fang 	void __iomem *netcmix;
84*fe5ba6bfSWei Fang 
85*fe5ba6bfSWei Fang 	const struct netc_devinfo *devinfo;
86*fe5ba6bfSWei Fang 	struct platform_device *pdev;
87*fe5ba6bfSWei Fang 	struct dentry *debugfs_root;
88*fe5ba6bfSWei Fang };
89*fe5ba6bfSWei Fang 
90*fe5ba6bfSWei Fang static void netc_reg_write(void __iomem *base, u32 offset, u32 val)
91*fe5ba6bfSWei Fang {
92*fe5ba6bfSWei Fang 	netc_write(base + offset, val);
93*fe5ba6bfSWei Fang }
94*fe5ba6bfSWei Fang 
95*fe5ba6bfSWei Fang static u32 netc_reg_read(void __iomem *base, u32 offset)
96*fe5ba6bfSWei Fang {
97*fe5ba6bfSWei Fang 	return netc_read(base + offset);
98*fe5ba6bfSWei Fang }
99*fe5ba6bfSWei Fang 
100*fe5ba6bfSWei Fang static int netc_of_pci_get_bus_devfn(struct device_node *np)
101*fe5ba6bfSWei Fang {
102*fe5ba6bfSWei Fang 	u32 reg[5];
103*fe5ba6bfSWei Fang 	int error;
104*fe5ba6bfSWei Fang 
105*fe5ba6bfSWei Fang 	error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
106*fe5ba6bfSWei Fang 	if (error)
107*fe5ba6bfSWei Fang 		return error;
108*fe5ba6bfSWei Fang 
109*fe5ba6bfSWei Fang 	return (reg[0] >> 8) & 0xffff;
110*fe5ba6bfSWei Fang }
111*fe5ba6bfSWei Fang 
112*fe5ba6bfSWei Fang static int netc_get_link_mii_protocol(phy_interface_t interface)
113*fe5ba6bfSWei Fang {
114*fe5ba6bfSWei Fang 	switch (interface) {
115*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_MII:
116*fe5ba6bfSWei Fang 		return MII_PROT_MII;
117*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_RMII:
118*fe5ba6bfSWei Fang 		return MII_PROT_RMII;
119*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_RGMII:
120*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_RGMII_ID:
121*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_RGMII_RXID:
122*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_RGMII_TXID:
123*fe5ba6bfSWei Fang 		return MII_PROT_RGMII;
124*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_SGMII:
125*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_2500BASEX:
126*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_10GBASER:
127*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_XGMII:
128*fe5ba6bfSWei Fang 	case PHY_INTERFACE_MODE_USXGMII:
129*fe5ba6bfSWei Fang 		return MII_PROT_SERIAL;
130*fe5ba6bfSWei Fang 	default:
131*fe5ba6bfSWei Fang 		return -EINVAL;
132*fe5ba6bfSWei Fang 	}
133*fe5ba6bfSWei Fang }
134*fe5ba6bfSWei Fang 
135*fe5ba6bfSWei Fang static int imx95_netcmix_init(struct platform_device *pdev)
136*fe5ba6bfSWei Fang {
137*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
138*fe5ba6bfSWei Fang 	struct device_node *np = pdev->dev.of_node;
139*fe5ba6bfSWei Fang 	phy_interface_t interface;
140*fe5ba6bfSWei Fang 	int bus_devfn, mii_proto;
141*fe5ba6bfSWei Fang 	u32 val;
142*fe5ba6bfSWei Fang 	int err;
143*fe5ba6bfSWei Fang 
144*fe5ba6bfSWei Fang 	/* Default setting of MII protocol */
145*fe5ba6bfSWei Fang 	val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII) |
146*fe5ba6bfSWei Fang 	      MII_PROT(2, MII_PROT_SERIAL);
147*fe5ba6bfSWei Fang 
148*fe5ba6bfSWei Fang 	/* Update the link MII protocol through parsing phy-mode */
149*fe5ba6bfSWei Fang 	for_each_available_child_of_node_scoped(np, child) {
150*fe5ba6bfSWei Fang 		for_each_available_child_of_node_scoped(child, gchild) {
151*fe5ba6bfSWei Fang 			if (!of_device_is_compatible(gchild, "pci1131,e101"))
152*fe5ba6bfSWei Fang 				continue;
153*fe5ba6bfSWei Fang 
154*fe5ba6bfSWei Fang 			bus_devfn = netc_of_pci_get_bus_devfn(gchild);
155*fe5ba6bfSWei Fang 			if (bus_devfn < 0)
156*fe5ba6bfSWei Fang 				return -EINVAL;
157*fe5ba6bfSWei Fang 
158*fe5ba6bfSWei Fang 			if (bus_devfn == IMX95_ENETC2_BUS_DEVFN)
159*fe5ba6bfSWei Fang 				continue;
160*fe5ba6bfSWei Fang 
161*fe5ba6bfSWei Fang 			err = of_get_phy_mode(gchild, &interface);
162*fe5ba6bfSWei Fang 			if (err)
163*fe5ba6bfSWei Fang 				continue;
164*fe5ba6bfSWei Fang 
165*fe5ba6bfSWei Fang 			mii_proto = netc_get_link_mii_protocol(interface);
166*fe5ba6bfSWei Fang 			if (mii_proto < 0)
167*fe5ba6bfSWei Fang 				return -EINVAL;
168*fe5ba6bfSWei Fang 
169*fe5ba6bfSWei Fang 			switch (bus_devfn) {
170*fe5ba6bfSWei Fang 			case IMX95_ENETC0_BUS_DEVFN:
171*fe5ba6bfSWei Fang 				val = u32_replace_bits(val, mii_proto,
172*fe5ba6bfSWei Fang 						       CFG_LINK_MII_PORT_0);
173*fe5ba6bfSWei Fang 				break;
174*fe5ba6bfSWei Fang 			case IMX95_ENETC1_BUS_DEVFN:
175*fe5ba6bfSWei Fang 				val = u32_replace_bits(val, mii_proto,
176*fe5ba6bfSWei Fang 						       CFG_LINK_MII_PORT_1);
177*fe5ba6bfSWei Fang 				break;
178*fe5ba6bfSWei Fang 			default:
179*fe5ba6bfSWei Fang 				return -EINVAL;
180*fe5ba6bfSWei Fang 			}
181*fe5ba6bfSWei Fang 		}
182*fe5ba6bfSWei Fang 	}
183*fe5ba6bfSWei Fang 
184*fe5ba6bfSWei Fang 	/* Configure Link I/O variant */
185*fe5ba6bfSWei Fang 	netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR,
186*fe5ba6bfSWei Fang 		       IO_VAR(2, IO_VAR_16FF_16G_SERDES));
187*fe5ba6bfSWei Fang 	/* Configure Link 2 PCS protocol */
188*fe5ba6bfSWei Fang 	netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(2),
189*fe5ba6bfSWei Fang 		       PCS_PROT_10G_SXGMII);
190*fe5ba6bfSWei Fang 	netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val);
191*fe5ba6bfSWei Fang 
192*fe5ba6bfSWei Fang 	return 0;
193*fe5ba6bfSWei Fang }
194*fe5ba6bfSWei Fang 
195*fe5ba6bfSWei Fang static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv)
196*fe5ba6bfSWei Fang {
197*fe5ba6bfSWei Fang 	return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK);
198*fe5ba6bfSWei Fang }
199*fe5ba6bfSWei Fang 
200*fe5ba6bfSWei Fang static int netc_lock_ierb(struct netc_blk_ctrl *priv)
201*fe5ba6bfSWei Fang {
202*fe5ba6bfSWei Fang 	u32 val;
203*fe5ba6bfSWei Fang 
204*fe5ba6bfSWei Fang 	netc_reg_write(priv->prb, PRB_NETCRR, NETCRR_LOCK);
205*fe5ba6bfSWei Fang 
206*fe5ba6bfSWei Fang 	return read_poll_timeout(netc_reg_read, val, !(val & NETCSR_STATE),
207*fe5ba6bfSWei Fang 				 100, 2000, false, priv->prb, PRB_NETCSR);
208*fe5ba6bfSWei Fang }
209*fe5ba6bfSWei Fang 
210*fe5ba6bfSWei Fang static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)
211*fe5ba6bfSWei Fang {
212*fe5ba6bfSWei Fang 	u32 val;
213*fe5ba6bfSWei Fang 
214*fe5ba6bfSWei Fang 	netc_reg_write(priv->prb, PRB_NETCRR, 0);
215*fe5ba6bfSWei Fang 
216*fe5ba6bfSWei Fang 	return read_poll_timeout(netc_reg_read, val, !(val & NETCRR_LOCK),
217*fe5ba6bfSWei Fang 				 1000, 100000, true, priv->prb, PRB_NETCRR);
218*fe5ba6bfSWei Fang }
219*fe5ba6bfSWei Fang 
220*fe5ba6bfSWei Fang static int imx95_ierb_init(struct platform_device *pdev)
221*fe5ba6bfSWei Fang {
222*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
223*fe5ba6bfSWei Fang 
224*fe5ba6bfSWei Fang 	/* EMDIO : No MSI-X intterupt */
225*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_EMDIOFAUXR, 0);
226*fe5ba6bfSWei Fang 	/* ENETC0 PF */
227*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_EFAUXR(0), 0);
228*fe5ba6bfSWei Fang 	/* ENETC0 VF0 */
229*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(0), 1);
230*fe5ba6bfSWei Fang 	/* ENETC0 VF1 */
231*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(1), 2);
232*fe5ba6bfSWei Fang 	/* ENETC1 PF */
233*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_EFAUXR(1), 3);
234*fe5ba6bfSWei Fang 	/* ENETC1 VF0 */
235*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(2), 5);
236*fe5ba6bfSWei Fang 	/* ENETC1 VF1 */
237*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(3), 6);
238*fe5ba6bfSWei Fang 	/* ENETC2 PF */
239*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_EFAUXR(2), 4);
240*fe5ba6bfSWei Fang 	/* ENETC2 VF0 */
241*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(4), 5);
242*fe5ba6bfSWei Fang 	/* ENETC2 VF1 */
243*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_VFAUXR(5), 6);
244*fe5ba6bfSWei Fang 	/* NETC TIMER */
245*fe5ba6bfSWei Fang 	netc_reg_write(priv->ierb, IERB_T0FAUXR, 7);
246*fe5ba6bfSWei Fang 
247*fe5ba6bfSWei Fang 	return 0;
248*fe5ba6bfSWei Fang }
249*fe5ba6bfSWei Fang 
250*fe5ba6bfSWei Fang static int netc_ierb_init(struct platform_device *pdev)
251*fe5ba6bfSWei Fang {
252*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
253*fe5ba6bfSWei Fang 	const struct netc_devinfo *devinfo = priv->devinfo;
254*fe5ba6bfSWei Fang 	int err;
255*fe5ba6bfSWei Fang 
256*fe5ba6bfSWei Fang 	if (netc_ierb_is_locked(priv)) {
257*fe5ba6bfSWei Fang 		err = netc_unlock_ierb_with_warm_reset(priv);
258*fe5ba6bfSWei Fang 		if (err) {
259*fe5ba6bfSWei Fang 			dev_err(&pdev->dev, "Unlock IERB failed.\n");
260*fe5ba6bfSWei Fang 			return err;
261*fe5ba6bfSWei Fang 		}
262*fe5ba6bfSWei Fang 	}
263*fe5ba6bfSWei Fang 
264*fe5ba6bfSWei Fang 	if (devinfo->ierb_init) {
265*fe5ba6bfSWei Fang 		err = devinfo->ierb_init(pdev);
266*fe5ba6bfSWei Fang 		if (err)
267*fe5ba6bfSWei Fang 			return err;
268*fe5ba6bfSWei Fang 	}
269*fe5ba6bfSWei Fang 
270*fe5ba6bfSWei Fang 	err = netc_lock_ierb(priv);
271*fe5ba6bfSWei Fang 	if (err) {
272*fe5ba6bfSWei Fang 		dev_err(&pdev->dev, "Lock IERB failed.\n");
273*fe5ba6bfSWei Fang 		return err;
274*fe5ba6bfSWei Fang 	}
275*fe5ba6bfSWei Fang 
276*fe5ba6bfSWei Fang 	return 0;
277*fe5ba6bfSWei Fang }
278*fe5ba6bfSWei Fang 
279*fe5ba6bfSWei Fang #if IS_ENABLED(CONFIG_DEBUG_FS)
280*fe5ba6bfSWei Fang static int netc_prb_show(struct seq_file *s, void *data)
281*fe5ba6bfSWei Fang {
282*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv = s->private;
283*fe5ba6bfSWei Fang 	u32 val;
284*fe5ba6bfSWei Fang 
285*fe5ba6bfSWei Fang 	val = netc_reg_read(priv->prb, PRB_NETCRR);
286*fe5ba6bfSWei Fang 	seq_printf(s, "[PRB NETCRR] Lock:%d SR:%d\n",
287*fe5ba6bfSWei Fang 		   (val & NETCRR_LOCK) ? 1 : 0,
288*fe5ba6bfSWei Fang 		   (val & NETCRR_SR) ? 1 : 0);
289*fe5ba6bfSWei Fang 
290*fe5ba6bfSWei Fang 	val = netc_reg_read(priv->prb, PRB_NETCSR);
291*fe5ba6bfSWei Fang 	seq_printf(s, "[PRB NETCSR] State:%d Error:%d\n",
292*fe5ba6bfSWei Fang 		   (val & NETCSR_STATE) ? 1 : 0,
293*fe5ba6bfSWei Fang 		   (val & NETCSR_ERROR) ? 1 : 0);
294*fe5ba6bfSWei Fang 
295*fe5ba6bfSWei Fang 	return 0;
296*fe5ba6bfSWei Fang }
297*fe5ba6bfSWei Fang DEFINE_SHOW_ATTRIBUTE(netc_prb);
298*fe5ba6bfSWei Fang 
299*fe5ba6bfSWei Fang static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
300*fe5ba6bfSWei Fang {
301*fe5ba6bfSWei Fang 	struct dentry *root;
302*fe5ba6bfSWei Fang 
303*fe5ba6bfSWei Fang 	root = debugfs_create_dir("netc_blk_ctrl", NULL);
304*fe5ba6bfSWei Fang 	if (IS_ERR(root))
305*fe5ba6bfSWei Fang 		return;
306*fe5ba6bfSWei Fang 
307*fe5ba6bfSWei Fang 	priv->debugfs_root = root;
308*fe5ba6bfSWei Fang 
309*fe5ba6bfSWei Fang 	debugfs_create_file("prb", 0444, root, priv, &netc_prb_fops);
310*fe5ba6bfSWei Fang }
311*fe5ba6bfSWei Fang 
312*fe5ba6bfSWei Fang static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
313*fe5ba6bfSWei Fang {
314*fe5ba6bfSWei Fang 	debugfs_remove_recursive(priv->debugfs_root);
315*fe5ba6bfSWei Fang 	priv->debugfs_root = NULL;
316*fe5ba6bfSWei Fang }
317*fe5ba6bfSWei Fang 
318*fe5ba6bfSWei Fang #else
319*fe5ba6bfSWei Fang 
320*fe5ba6bfSWei Fang static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
321*fe5ba6bfSWei Fang {
322*fe5ba6bfSWei Fang }
323*fe5ba6bfSWei Fang 
324*fe5ba6bfSWei Fang static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
325*fe5ba6bfSWei Fang {
326*fe5ba6bfSWei Fang }
327*fe5ba6bfSWei Fang #endif
328*fe5ba6bfSWei Fang 
329*fe5ba6bfSWei Fang static int netc_prb_check_error(struct netc_blk_ctrl *priv)
330*fe5ba6bfSWei Fang {
331*fe5ba6bfSWei Fang 	if (netc_reg_read(priv->prb, PRB_NETCSR) & NETCSR_ERROR)
332*fe5ba6bfSWei Fang 		return -1;
333*fe5ba6bfSWei Fang 
334*fe5ba6bfSWei Fang 	return 0;
335*fe5ba6bfSWei Fang }
336*fe5ba6bfSWei Fang 
337*fe5ba6bfSWei Fang static const struct netc_devinfo imx95_devinfo = {
338*fe5ba6bfSWei Fang 	.flags = NETC_HAS_NETCMIX,
339*fe5ba6bfSWei Fang 	.netcmix_init = imx95_netcmix_init,
340*fe5ba6bfSWei Fang 	.ierb_init = imx95_ierb_init,
341*fe5ba6bfSWei Fang };
342*fe5ba6bfSWei Fang 
343*fe5ba6bfSWei Fang static const struct of_device_id netc_blk_ctrl_match[] = {
344*fe5ba6bfSWei Fang 	{ .compatible = "nxp,imx95-netc-blk-ctrl", .data = &imx95_devinfo },
345*fe5ba6bfSWei Fang 	{},
346*fe5ba6bfSWei Fang };
347*fe5ba6bfSWei Fang MODULE_DEVICE_TABLE(of, netc_blk_ctrl_match);
348*fe5ba6bfSWei Fang 
349*fe5ba6bfSWei Fang static int netc_blk_ctrl_probe(struct platform_device *pdev)
350*fe5ba6bfSWei Fang {
351*fe5ba6bfSWei Fang 	struct device_node *node = pdev->dev.of_node;
352*fe5ba6bfSWei Fang 	const struct netc_devinfo *devinfo;
353*fe5ba6bfSWei Fang 	struct device *dev = &pdev->dev;
354*fe5ba6bfSWei Fang 	const struct of_device_id *id;
355*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv;
356*fe5ba6bfSWei Fang 	struct clk *ipg_clk;
357*fe5ba6bfSWei Fang 	void __iomem *regs;
358*fe5ba6bfSWei Fang 	int err;
359*fe5ba6bfSWei Fang 
360*fe5ba6bfSWei Fang 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
361*fe5ba6bfSWei Fang 	if (!priv)
362*fe5ba6bfSWei Fang 		return -ENOMEM;
363*fe5ba6bfSWei Fang 
364*fe5ba6bfSWei Fang 	priv->pdev = pdev;
365*fe5ba6bfSWei Fang 	ipg_clk = devm_clk_get_optional_enabled(dev, "ipg");
366*fe5ba6bfSWei Fang 	if (IS_ERR(ipg_clk))
367*fe5ba6bfSWei Fang 		return dev_err_probe(dev, PTR_ERR(ipg_clk),
368*fe5ba6bfSWei Fang 				     "Set ipg clock failed\n");
369*fe5ba6bfSWei Fang 
370*fe5ba6bfSWei Fang 	id = of_match_device(netc_blk_ctrl_match, dev);
371*fe5ba6bfSWei Fang 	if (!id)
372*fe5ba6bfSWei Fang 		return dev_err_probe(dev, -EINVAL, "Cannot match device\n");
373*fe5ba6bfSWei Fang 
374*fe5ba6bfSWei Fang 	devinfo = (struct netc_devinfo *)id->data;
375*fe5ba6bfSWei Fang 	if (!devinfo)
376*fe5ba6bfSWei Fang 		return dev_err_probe(dev, -EINVAL, "No device information\n");
377*fe5ba6bfSWei Fang 
378*fe5ba6bfSWei Fang 	priv->devinfo = devinfo;
379*fe5ba6bfSWei Fang 	regs = devm_platform_ioremap_resource_byname(pdev, "ierb");
380*fe5ba6bfSWei Fang 	if (IS_ERR(regs))
381*fe5ba6bfSWei Fang 		return dev_err_probe(dev, PTR_ERR(regs),
382*fe5ba6bfSWei Fang 				     "Missing IERB resource\n");
383*fe5ba6bfSWei Fang 
384*fe5ba6bfSWei Fang 	priv->ierb = regs;
385*fe5ba6bfSWei Fang 	regs = devm_platform_ioremap_resource_byname(pdev, "prb");
386*fe5ba6bfSWei Fang 	if (IS_ERR(regs))
387*fe5ba6bfSWei Fang 		return dev_err_probe(dev, PTR_ERR(regs),
388*fe5ba6bfSWei Fang 				     "Missing PRB resource\n");
389*fe5ba6bfSWei Fang 
390*fe5ba6bfSWei Fang 	priv->prb = regs;
391*fe5ba6bfSWei Fang 	if (devinfo->flags & NETC_HAS_NETCMIX) {
392*fe5ba6bfSWei Fang 		regs = devm_platform_ioremap_resource_byname(pdev, "netcmix");
393*fe5ba6bfSWei Fang 		if (IS_ERR(regs))
394*fe5ba6bfSWei Fang 			return dev_err_probe(dev, PTR_ERR(regs),
395*fe5ba6bfSWei Fang 					     "Missing NETCMIX resource\n");
396*fe5ba6bfSWei Fang 		priv->netcmix = regs;
397*fe5ba6bfSWei Fang 	}
398*fe5ba6bfSWei Fang 
399*fe5ba6bfSWei Fang 	platform_set_drvdata(pdev, priv);
400*fe5ba6bfSWei Fang 	if (devinfo->netcmix_init) {
401*fe5ba6bfSWei Fang 		err = devinfo->netcmix_init(pdev);
402*fe5ba6bfSWei Fang 		if (err)
403*fe5ba6bfSWei Fang 			return dev_err_probe(dev, err,
404*fe5ba6bfSWei Fang 					     "Initializing NETCMIX failed\n");
405*fe5ba6bfSWei Fang 	}
406*fe5ba6bfSWei Fang 
407*fe5ba6bfSWei Fang 	err = netc_ierb_init(pdev);
408*fe5ba6bfSWei Fang 	if (err)
409*fe5ba6bfSWei Fang 		return dev_err_probe(dev, err, "Initializing IERB failed\n");
410*fe5ba6bfSWei Fang 
411*fe5ba6bfSWei Fang 	if (netc_prb_check_error(priv) < 0)
412*fe5ba6bfSWei Fang 		dev_warn(dev, "The current IERB configuration is invalid\n");
413*fe5ba6bfSWei Fang 
414*fe5ba6bfSWei Fang 	netc_blk_ctrl_create_debugfs(priv);
415*fe5ba6bfSWei Fang 
416*fe5ba6bfSWei Fang 	err = of_platform_populate(node, NULL, NULL, dev);
417*fe5ba6bfSWei Fang 	if (err) {
418*fe5ba6bfSWei Fang 		netc_blk_ctrl_remove_debugfs(priv);
419*fe5ba6bfSWei Fang 		return dev_err_probe(dev, err, "of_platform_populate failed\n");
420*fe5ba6bfSWei Fang 	}
421*fe5ba6bfSWei Fang 
422*fe5ba6bfSWei Fang 	return 0;
423*fe5ba6bfSWei Fang }
424*fe5ba6bfSWei Fang 
425*fe5ba6bfSWei Fang static void netc_blk_ctrl_remove(struct platform_device *pdev)
426*fe5ba6bfSWei Fang {
427*fe5ba6bfSWei Fang 	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
428*fe5ba6bfSWei Fang 
429*fe5ba6bfSWei Fang 	of_platform_depopulate(&pdev->dev);
430*fe5ba6bfSWei Fang 	netc_blk_ctrl_remove_debugfs(priv);
431*fe5ba6bfSWei Fang }
432*fe5ba6bfSWei Fang 
433*fe5ba6bfSWei Fang static struct platform_driver netc_blk_ctrl_driver = {
434*fe5ba6bfSWei Fang 	.driver = {
435*fe5ba6bfSWei Fang 		.name = "nxp-netc-blk-ctrl",
436*fe5ba6bfSWei Fang 		.of_match_table = netc_blk_ctrl_match,
437*fe5ba6bfSWei Fang 	},
438*fe5ba6bfSWei Fang 	.probe = netc_blk_ctrl_probe,
439*fe5ba6bfSWei Fang 	.remove = netc_blk_ctrl_remove,
440*fe5ba6bfSWei Fang };
441*fe5ba6bfSWei Fang 
442*fe5ba6bfSWei Fang module_platform_driver(netc_blk_ctrl_driver);
443*fe5ba6bfSWei Fang 
444*fe5ba6bfSWei Fang MODULE_DESCRIPTION("NXP NETC Blocks Control Driver");
445*fe5ba6bfSWei Fang MODULE_LICENSE("Dual BSD/GPL");
446