1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * ENETC ethernet controller driver
4  * Copyright 2019 NXP
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <pci.h>
11 #include <miiphy.h>
12 #include <asm/io.h>
13 #include <asm/processor.h>
14 #include <miiphy.h>
15 
16 #include "fsl_enetc.h"
17 
enetc_mdio_wait_bsy(struct enetc_mdio_priv * priv)18 static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv)
19 {
20 	int to = 10000;
21 
22 	while ((enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY) &&
23 	       --to)
24 		cpu_relax();
25 	if (!to)
26 		printf("T");
27 }
28 
enetc_mdio_read_priv(struct enetc_mdio_priv * priv,int addr,int devad,int reg)29 int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad,
30 			 int reg)
31 {
32 	if (devad == MDIO_DEVAD_NONE)
33 		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
34 	else
35 		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
36 	enetc_mdio_wait_bsy(priv);
37 
38 	if (devad == MDIO_DEVAD_NONE) {
39 		enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
40 			    (addr << 5) | reg);
41 	} else {
42 		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
43 		enetc_mdio_wait_bsy(priv);
44 
45 		enetc_write(priv, ENETC_MDIO_STAT, reg);
46 		enetc_mdio_wait_bsy(priv);
47 
48 		enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
49 			    (addr << 5) | devad);
50 	}
51 
52 	enetc_mdio_wait_bsy(priv);
53 	if (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_RD_ER)
54 		return ENETC_MDIO_READ_ERR;
55 
56 	return enetc_read(priv, ENETC_MDIO_DATA);
57 }
58 
enetc_mdio_write_priv(struct enetc_mdio_priv * priv,int addr,int devad,int reg,u16 val)59 int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr, int devad,
60 			  int reg, u16 val)
61 {
62 	if (devad == MDIO_DEVAD_NONE)
63 		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
64 	else
65 		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
66 	enetc_mdio_wait_bsy(priv);
67 
68 	if (devad != MDIO_DEVAD_NONE) {
69 		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
70 		enetc_write(priv, ENETC_MDIO_STAT, reg);
71 	} else {
72 		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + reg);
73 	}
74 	enetc_mdio_wait_bsy(priv);
75 
76 	enetc_write(priv, ENETC_MDIO_DATA, val);
77 	enetc_mdio_wait_bsy(priv);
78 
79 	return 0;
80 }
81 
82 /* DM wrappers */
dm_enetc_mdio_read(struct udevice * dev,int addr,int devad,int reg)83 static int dm_enetc_mdio_read(struct udevice *dev, int addr, int devad, int reg)
84 {
85 	struct enetc_mdio_priv *priv = dev_get_priv(dev);
86 
87 	return enetc_mdio_read_priv(priv, addr, devad, reg);
88 }
89 
dm_enetc_mdio_write(struct udevice * dev,int addr,int devad,int reg,u16 val)90 static int dm_enetc_mdio_write(struct udevice *dev, int addr, int devad,
91 			       int reg, u16 val)
92 {
93 	struct enetc_mdio_priv *priv = dev_get_priv(dev);
94 
95 	return enetc_mdio_write_priv(priv, addr, devad, reg, val);
96 }
97 
98 static const struct mdio_ops enetc_mdio_ops = {
99 	.read = dm_enetc_mdio_read,
100 	.write = dm_enetc_mdio_write,
101 };
102 
enetc_mdio_bind(struct udevice * dev)103 static int enetc_mdio_bind(struct udevice *dev)
104 {
105 	char name[16];
106 	static int eth_num_devices;
107 
108 	/*
109 	 * prefer using PCI function numbers to number interfaces, but these
110 	 * are only available if dts nodes are present.  For PCI they are
111 	 * optional, handle that case too.  Just in case some nodes are present
112 	 * and some are not, use different naming scheme - enetc-N based on
113 	 * PCI function # and enetc#N based on interface count
114 	 */
115 	if (ofnode_valid(dev_ofnode(dev)))
116 		sprintf(name, "emdio-%u", PCI_FUNC(pci_get_devfn(dev)));
117 	else
118 		sprintf(name, "emdio#%u", eth_num_devices++);
119 	device_set_name(dev, name);
120 
121 	return 0;
122 }
123 
enetc_mdio_probe(struct udevice * dev)124 static int enetc_mdio_probe(struct udevice *dev)
125 {
126 	struct enetc_mdio_priv *priv = dev_get_priv(dev);
127 
128 	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
129 	if (!priv->regs_base) {
130 		enetc_dbg(dev, "failed to map BAR0\n");
131 		return -EINVAL;
132 	}
133 
134 	priv->regs_base += ENETC_MDIO_BASE;
135 
136 	dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
137 
138 	return 0;
139 }
140 
141 U_BOOT_DRIVER(enetc_mdio) = {
142 	.name	= "enetc_mdio",
143 	.id	= UCLASS_MDIO,
144 	.bind	= enetc_mdio_bind,
145 	.probe	= enetc_mdio_probe,
146 	.ops	= &enetc_mdio_ops,
147 	.priv_auto	= sizeof(struct enetc_mdio_priv),
148 };
149 
150 static struct pci_device_id enetc_mdio_ids[] = {
151 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) },
152 	{ }
153 };
154 
155 U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);
156