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