treewide: mem: Enable MEMTEST via defconfig
[oweals/u-boot.git] / drivers / net / fsl_enetc_mdio.c
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
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
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
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 */
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
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
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->node))
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
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_alloc_size = 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);