]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/enetc/enetc_mdio_pci.c
Import device-tree files from Linux 5.13
[FreeBSD/FreeBSD.git] / sys / dev / enetc / enetc_mdio_pci.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2021 Alstom Group.
5  * Copyright (c) 2021 Semihalf.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/socket.h>
36 #include <sys/rman.h>
37 #include <sys/mutex.h>
38
39 #include <machine/bus.h>
40
41 #include <net/if.h>
42 #include <net/if_var.h>
43 #include <net/if_types.h>
44 #include <net/if_media.h>
45
46 #include <dev/enetc/enetc_hw.h>
47 #include <dev/enetc/enetc_mdio.h>
48 #include <dev/mii/mii.h>
49 #include <dev/mii/miivar.h>
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcivar.h>
54
55 #include "miibus_if.h"
56
57 #define ENETC_MDIO_DEV_ID       0xee01
58 #define ENETC_MDIO_DEV_NAME     "FSL PCIe IE Central MDIO"
59
60 static struct entec_mdio_pci_id {
61         uint16_t vendor;
62         uint16_t device;
63         const char *desc;
64 } enetc_mdio_pci_ids[] = {
65         {PCI_VENDOR_FREESCALE, ENETC_MDIO_DEV_ID, ENETC_MDIO_DEV_NAME},
66 };
67 MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, enetc_mdio_pci,
68     enetc_mdio_pci_ids, nitems(enetc_mdio_pci_ids));
69
70 struct enetc_mdio_pci_softc {
71         device_t                sc_dev;
72         struct mtx              sc_lock;
73         struct resource         *sc_regs;
74 };
75
76 static device_attach_t enetc_mdio_pci_attach;
77 static device_detach_t enetc_mdio_pci_detach;
78 static device_probe_t enetc_mdio_pci_probe;
79
80 static int
81 enetc_mdio_pci_readreg(device_t dev, int phy, int reg)
82 {
83         struct enetc_mdio_pci_softc *sc;
84         uint32_t ret;
85
86         sc = device_get_softc(dev);
87
88         mtx_lock(&sc->sc_lock);
89         ret = enetc_mdio_read(sc->sc_regs, ENETC_EMDIO_BASE, phy, reg);
90         mtx_unlock(&sc->sc_lock);
91
92         return (ret);
93 }
94
95 static int
96 enetc_mdio_pci_writereg(device_t dev, int phy, int reg, int data)
97 {
98         struct enetc_mdio_pci_softc *sc;
99         int err;
100
101         sc = device_get_softc(dev);
102
103         mtx_lock(&sc->sc_lock);
104         err = enetc_mdio_write(sc->sc_regs, ENETC_EMDIO_BASE, phy, reg, data);
105         mtx_unlock(&sc->sc_lock);
106         if (err != 0)
107                 return (err);
108
109         return (0);
110 }
111
112 static int
113 enetc_mdio_pci_probe(device_t dev)
114 {
115         struct entec_mdio_pci_id *id;
116
117         for (id = enetc_mdio_pci_ids; id->vendor != 0; ++id) {
118                 if (pci_get_device(dev) != id->device ||
119                     pci_get_vendor(dev) != id->vendor)
120                         continue;
121
122                 device_set_desc(dev, id->desc);
123
124                 return (BUS_PROBE_DEFAULT);
125         }
126
127         return (ENXIO);
128 }
129
130 static int
131 enetc_mdio_pci_attach(device_t dev)
132 {
133         struct enetc_mdio_pci_softc *sc;
134         int rid;
135
136         sc = device_get_softc(dev);
137         sc->sc_dev = dev;
138
139         /* Init locks */
140         mtx_init(&sc->sc_lock, device_get_nameunit(dev), "MDIO lock", MTX_DEF);
141
142         rid = PCIR_BAR(0);
143         sc->sc_regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
144             RF_ACTIVE);
145         if (sc->sc_regs == NULL) {
146                 device_printf(dev, "can't allocate resources for PCI MDIO \n");
147                 return (ENXIO);
148         }
149
150         OF_device_register_xref(ofw_bus_get_node(dev), dev);
151
152         return (0);
153 }
154
155 static int
156 enetc_mdio_pci_detach(device_t dev)
157 {
158         struct enetc_mdio_pci_softc *sc;
159
160         sc = device_get_softc(dev);
161
162         bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_regs);
163         mtx_destroy(&sc->sc_lock);
164
165         return (0);
166 }
167
168 static device_method_t  enetc_mdio_pci_methods[] ={
169         DEVMETHOD(device_probe, enetc_mdio_pci_probe),
170         DEVMETHOD(device_attach, enetc_mdio_pci_attach),
171         DEVMETHOD(device_detach, enetc_mdio_pci_detach),
172
173         DEVMETHOD(miibus_readreg, enetc_mdio_pci_readreg),
174         DEVMETHOD(miibus_writereg, enetc_mdio_pci_writereg),
175
176         DEVMETHOD_END
177 };
178
179 static driver_t enetc_mdio_pci_driver = {
180         "enetc_mdio_pci",
181         enetc_mdio_pci_methods,
182         sizeof(struct enetc_mdio_pci_softc),
183 };
184
185 static devclass_t enetc_mdio_pci_devclass;
186
187 DRIVER_MODULE(enetc_mdio_pci, pci, enetc_mdio_pci_driver,
188     enetc_mdio_pci_devclass, 0, 0);
189 DRIVER_MODULE(miibus, enetc_mdio_pci, miibus_driver, miibus_devclass,
190     0, 0);
191 MODULE_VERSION(enetc_mdio_pci, 1);