source: rtems-libbsd/rtemsbsd/sys/dev/tsec/if_tsec_nexus.c @ 8fe59fe

4.115-freebsd-12freebsd-9.3
Last change on this file since 8fe59fe was 8fe59fe, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 18, 2013 at 11:46:27 AM

if_tsec: Add Nexus support

  • Property mode set to 100644
File size: 8.5 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski
5 * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * From: FreeBSD: head/sys/dev/tsec/if_tsec_ocp.c 188712 2009-02-17 14:59:47Z raj
29 */
30
31/*
32 * FDT 'simple-bus' attachment for Freescale TSEC controller.
33 */
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/endian.h>
40#include <sys/mbuf.h>
41#include <sys/kernel.h>
42#include <sys/module.h>
43#include <sys/socket.h>
44#include <sys/sysctl.h>
45
46#include <sys/bus.h>
47#include <machine/bus.h>
48#include <sys/rman.h>
49#include <machine/resource.h>
50
51#include <net/ethernet.h>
52#include <net/if.h>
53#include <net/if_dl.h>
54#include <net/if_media.h>
55#include <net/if_arp.h>
56
57#include <dev/mii/mii.h>
58#include <dev/mii/miivar.h>
59
60#include <dev/tsec/if_tsec.h>
61#include <dev/tsec/if_tsecreg.h>
62
63#include <rtems/bsd/local/miibus_if.h>
64#ifdef __rtems__
65#include <rtems/bsd/bsd.h>
66#endif /* __rtems__ */
67
68#define TSEC_RID_TXIRQ  0
69#define TSEC_RID_RXIRQ  1
70#define TSEC_RID_ERRIRQ 2
71
72static int tsec_fdt_probe(device_t dev);
73static int tsec_fdt_attach(device_t dev);
74static int tsec_fdt_detach(device_t dev);
75static int tsec_setup_intr(struct tsec_softc *sc, struct resource **ires,
76    void **ihand, int *irid, driver_intr_t handler, const char *iname);
77static void tsec_release_intr(struct tsec_softc *sc, struct resource *ires,
78    void *ihand, int irid, const char *iname);
79
80static device_method_t tsec_methods[] = {
81        /* Device interface */
82        DEVMETHOD(device_probe,         tsec_fdt_probe),
83        DEVMETHOD(device_attach,        tsec_fdt_attach),
84        DEVMETHOD(device_detach,        tsec_fdt_detach),
85
86        DEVMETHOD(device_shutdown,      tsec_shutdown),
87        DEVMETHOD(device_suspend,       tsec_suspend),
88        DEVMETHOD(device_resume,        tsec_resume),
89
90        /* MII interface */
91        DEVMETHOD(miibus_readreg,       tsec_miibus_readreg),
92        DEVMETHOD(miibus_writereg,      tsec_miibus_writereg),
93        DEVMETHOD(miibus_statchg,       tsec_miibus_statchg),
94
95        DEVMETHOD_END
96};
97
98static driver_t tsec_nexus_driver = {
99        "tsec",
100        tsec_methods,
101        sizeof(struct tsec_softc),
102};
103
104DRIVER_MODULE(tsec, nexus, tsec_nexus_driver, tsec_devclass, 0, 0);
105MODULE_DEPEND(tsec, nexus, 1, 1, 1);
106MODULE_DEPEND(tsec, ether, 1, 1, 1);
107
108static int
109tsec_fdt_probe(device_t dev)
110{
111        struct tsec_softc *sc;
112        uint32_t id;
113
114        sc = device_get_softc(dev);
115
116        sc->sc_rrid = 0;
117        sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
118            RF_ACTIVE);
119        if (sc->sc_rres == NULL)
120                return (ENXIO);
121
122        sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
123        sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
124
125        /* Check if we are eTSEC (enhanced TSEC) */
126        id = TSEC_READ(sc, TSEC_REG_ID);
127        sc->is_etsec = ((id >> 16) == TSEC_ETSEC_ID) ? 1 : 0;
128        id |= TSEC_READ(sc, TSEC_REG_ID2);
129
130        bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
131
132        if (id == 0) {
133                device_printf(dev, "could not identify TSEC type\n");
134                return (ENXIO);
135        }
136
137        if (sc->is_etsec)
138                device_set_desc(dev, "Enhanced Three-Speed Ethernet Controller");
139        else
140                device_set_desc(dev, "Three-Speed Ethernet Controller");
141
142        return (BUS_PROBE_DEFAULT);
143}
144
145static int
146tsec_fdt_attach(device_t dev)
147{
148        struct tsec_softc *sc;
149        int error = 0;
150
151        sc = device_get_softc(dev);
152        sc->dev = dev;
153
154        /* FIXME */
155        sc->phy_sc = sc;
156        sc->phyaddr = -1;
157
158        /* Init timer */
159        callout_init(&sc->tsec_callout, 1);
160
161        /* Init locks */
162        mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "TSEC TX lock",
163            MTX_DEF);
164        mtx_init(&sc->receive_lock, device_get_nameunit(dev), "TSEC RX lock",
165            MTX_DEF);
166        mtx_init(&sc->ic_lock, device_get_nameunit(dev), "TSEC IC lock",
167            MTX_DEF);
168
169        /* Allocate IO memory for TSEC registers */
170        sc->sc_rrid = 0;
171        sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
172            RF_ACTIVE);
173        if (sc->sc_rres == NULL) {
174                device_printf(dev, "could not allocate IO memory range!\n");
175                goto fail1;
176        }
177        sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
178        sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
179
180        /* TSEC attach */
181        if (tsec_attach(sc) != 0) {
182                device_printf(dev, "could not be configured\n");
183                goto fail2;
184        }
185
186        /* Set up interrupts (TX/RX/ERR) */
187        sc->sc_transmit_irid = TSEC_RID_TXIRQ;
188        error = tsec_setup_intr(sc, &sc->sc_transmit_ires,
189            &sc->sc_transmit_ihand, &sc->sc_transmit_irid,
190            tsec_transmit_intr, "TX");
191        if (error)
192                goto fail2;
193
194        sc->sc_receive_irid = TSEC_RID_RXIRQ;
195        error = tsec_setup_intr(sc, &sc->sc_receive_ires,
196            &sc->sc_receive_ihand, &sc->sc_receive_irid,
197            tsec_receive_intr, "RX");
198        if (error)
199                goto fail3;
200
201        sc->sc_error_irid = TSEC_RID_ERRIRQ;
202        error = tsec_setup_intr(sc, &sc->sc_error_ires,
203            &sc->sc_error_ihand, &sc->sc_error_irid,
204            tsec_error_intr, "ERR");
205        if (error)
206                goto fail4;
207
208        return (0);
209
210fail4:
211        tsec_release_intr(sc, sc->sc_receive_ires, sc->sc_receive_ihand,
212            sc->sc_receive_irid, "RX");
213fail3:
214        tsec_release_intr(sc, sc->sc_transmit_ires, sc->sc_transmit_ihand,
215            sc->sc_transmit_irid, "TX");
216fail2:
217        bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
218fail1:
219        mtx_destroy(&sc->receive_lock);
220        mtx_destroy(&sc->transmit_lock);
221        return (ENXIO);
222}
223
224static int
225tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, void **ihand,
226    int *irid, driver_intr_t handler, const char *iname)
227{
228        int error;
229
230        *ires = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, irid, RF_ACTIVE);
231        if (*ires == NULL) {
232                device_printf(sc->dev, "could not allocate %s IRQ\n", iname);
233                return (ENXIO);
234        }
235        error = bus_setup_intr(sc->dev, *ires, INTR_TYPE_NET | INTR_MPSAFE,
236            NULL, handler, sc, ihand);
237        if (error) {
238                device_printf(sc->dev, "failed to set up %s IRQ\n", iname);
239                if (bus_release_resource(sc->dev, SYS_RES_IRQ, *irid, *ires))
240                        device_printf(sc->dev, "could not release %s IRQ\n", iname);
241                *ires = NULL;
242                return (error);
243        }
244        return (0);
245}
246
247static void
248tsec_release_intr(struct tsec_softc *sc, struct resource *ires, void *ihand,
249    int irid, const char *iname)
250{
251        int error;
252
253        if (ires == NULL)
254                return;
255
256        error = bus_teardown_intr(sc->dev, ires, ihand);
257        if (error)
258                device_printf(sc->dev, "bus_teardown_intr() failed for %s intr"
259                    ", error %d\n", iname, error);
260
261        error = bus_release_resource(sc->dev, SYS_RES_IRQ, irid, ires);
262        if (error)
263                device_printf(sc->dev, "bus_release_resource() failed for %s "
264                    "intr, error %d\n", iname, error);
265}
266
267static int
268tsec_fdt_detach(device_t dev)
269{
270        struct tsec_softc *sc;
271        int error;
272
273        sc = device_get_softc(dev);
274
275        /* Wait for stopping watchdog */
276        callout_drain(&sc->tsec_callout);
277
278        /* Stop and release all interrupts */
279        tsec_release_intr(sc, sc->sc_transmit_ires, sc->sc_transmit_ihand,
280            sc->sc_transmit_irid, "TX");
281        tsec_release_intr(sc, sc->sc_receive_ires, sc->sc_receive_ihand,
282            sc->sc_receive_irid, "RX");
283        tsec_release_intr(sc, sc->sc_error_ires, sc->sc_error_ihand,
284            sc->sc_error_irid, "ERR");
285
286        /* TSEC detach */
287        tsec_detach(sc);
288
289        /* Free IO memory handler */
290        if (sc->sc_rres) {
291                error = bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid,
292                    sc->sc_rres);
293                if (error)
294                        device_printf(dev, "bus_release_resource() failed for"
295                            " IO memory, error %d\n", error);
296        }
297
298        /* Destroy locks */
299        mtx_destroy(&sc->receive_lock);
300        mtx_destroy(&sc->transmit_lock);
301        mtx_destroy(&sc->ic_lock);
302        return (0);
303}
304
305void
306tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr)
307{
308        rtems_bsd_get_mac_address(device_get_name(sc->dev),
309            device_get_unit(sc->dev), addr);
310}
Note: See TracBrowser for help on using the repository browser.