1256752Sbrooks/*-
2256752Sbrooks * Copyright (c) 2013 Bjoern A. Zeeb
3256752Sbrooks * All rights reserved.
4256752Sbrooks *
5256752Sbrooks * This software was developed by SRI International and the University of
6256752Sbrooks * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
7256752Sbrooks * ("MRC2"), as part of the DARPA MRC research programme.
8256752Sbrooks *
9256752Sbrooks * Redistribution and use in source and binary forms, with or without
10256752Sbrooks * modification, are permitted provided that the following conditions
11256752Sbrooks * are met:
12256752Sbrooks * 1. Redistributions of source code must retain the above copyright
13256752Sbrooks *    notice, this list of conditions and the following disclaimer.
14256752Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
15256752Sbrooks *    notice, this list of conditions and the following disclaimer in the
16256752Sbrooks *    documentation and/or other materials provided with the distribution.
17256752Sbrooks *
18256752Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19256752Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20256752Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21256752Sbrooks * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22256752Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23256752Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24256752Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25256752Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26256752Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27256752Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28256752Sbrooks * SUCH DAMAGE.
29256752Sbrooks */
30256752Sbrooks
31256752Sbrooks#include <sys/cdefs.h>
32256752Sbrooks__FBSDID("$FreeBSD$");
33256752Sbrooks
34256752Sbrooks#include <sys/param.h>
35256752Sbrooks#include <sys/bus.h>
36256752Sbrooks#include <sys/kernel.h>
37256752Sbrooks#include <sys/module.h>
38256752Sbrooks#include <sys/rman.h>
39256752Sbrooks#include <sys/socket.h>
40256752Sbrooks#include <sys/systm.h>
41256752Sbrooks
42256752Sbrooks#include <machine/bus.h>
43256752Sbrooks#include <machine/resource.h>
44256752Sbrooks
45256752Sbrooks#include <net/ethernet.h>
46256752Sbrooks#include <net/if.h>
47256752Sbrooks#include <net/if_media.h>
48256752Sbrooks
49256752Sbrooks#include <dev/mii/mii.h>
50256752Sbrooks#include <dev/mii/miivar.h>
51256752Sbrooks
52256752Sbrooks
53256752Sbrooks#include <dev/fdt/fdt_common.h>
54256752Sbrooks#include <dev/ofw/openfirm.h>
55256752Sbrooks#include <dev/ofw/ofw_bus.h>
56256752Sbrooks#include <dev/ofw/ofw_bus_subr.h>
57256752Sbrooks
58256752Sbrooks#include <dev/altera/atse/if_atsereg.h>
59256752Sbrooks
60256752Sbrooks/* "device miibus" required.  See GENERIC if you get errors here. */
61256752Sbrooks#include "miibus_if.h"
62256752Sbrooks
63256752Sbrooksstatic int
64256752Sbrooksatse_probe_fdt(device_t dev)
65256752Sbrooks{
66256752Sbrooks
67266152Sian	if (!ofw_bus_status_okay(dev))
68266152Sian		return (ENXIO);
69266152Sian
70256752Sbrooks	if (ofw_bus_is_compatible(dev, "altera,atse")) {
71256752Sbrooks		device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
72256752Sbrooks		return (BUS_PROBE_DEFAULT);
73256752Sbrooks	}
74256752Sbrooks        return (ENXIO);
75256752Sbrooks}
76256752Sbrooks
77256752Sbrooksstatic int
78256752Sbrooksatse_attach_fdt(device_t dev)
79256752Sbrooks{
80256752Sbrooks	struct atse_softc *sc;
81256752Sbrooks	int error;
82256752Sbrooks
83256752Sbrooks	sc = device_get_softc(dev);
84256752Sbrooks	sc->atse_dev = dev;
85256752Sbrooks	sc->atse_unit = device_get_unit(dev);
86256752Sbrooks
87256752Sbrooks	/*
88256752Sbrooks	 * FDT has the list of our resources.  Given we are using multiple
89256752Sbrooks	 * memory regions and possibly multiple interrupts, we need to attach
90256752Sbrooks	 * them in the order specified in .dts:
91256752Sbrooks	 * MAC, RX and RXC FIFO, TX and TXC FIFO; RX INTR, TX INTR.
92256752Sbrooks	 */
93256752Sbrooks
94256752Sbrooks	/* MAC: Avalon-MM, atse management register region. */
95256752Sbrooks	sc->atse_mem_rid = 0;
96256752Sbrooks	sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
97256752Sbrooks	    &sc->atse_mem_rid, RF_ACTIVE);
98256752Sbrooks	if (sc->atse_mem_res == NULL) {
99256752Sbrooks		device_printf(dev, "failed to map memory for ctrl region\n");
100256752Sbrooks		error = ENXIO;
101256752Sbrooks		goto err;
102256752Sbrooks	}
103256752Sbrooks	if (bootverbose)
104256752Sbrooks		device_printf(sc->atse_dev, "MAC ctrl region at mem %p-%p\n",
105256752Sbrooks		    (void *)rman_get_start(sc->atse_mem_res),
106256752Sbrooks		    (void *)(rman_get_start(sc->atse_mem_res) +
107256752Sbrooks		    rman_get_size(sc->atse_mem_res)));
108256752Sbrooks
109256752Sbrooks	/*
110256752Sbrooks	 * RX and RXC FIFO memory regions.
111256752Sbrooks	 * 0x00: 2 * 32bit FIFO data,
112256752Sbrooks	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
113256752Sbrooks	 */
114256752Sbrooks	sc->atse_rx_mem_rid = 1;
115256752Sbrooks	sc->atse_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
116256752Sbrooks	    &sc->atse_rx_mem_rid, RF_ACTIVE);
117256752Sbrooks	if (sc->atse_rx_mem_res == NULL) {
118256752Sbrooks		device_printf(dev, "failed to map memory for RX FIFO\n");
119256752Sbrooks		error = ENXIO;
120256752Sbrooks		goto err;
121256752Sbrooks	}
122256752Sbrooks	if (bootverbose)
123256752Sbrooks		device_printf(sc->atse_dev, "RX FIFO at mem %p-%p\n",
124256752Sbrooks		    (void *)rman_get_start(sc->atse_rx_mem_res),
125256752Sbrooks		    (void *)(rman_get_start(sc->atse_rx_mem_res) +
126256752Sbrooks		    rman_get_size(sc->atse_rx_mem_res)));
127256752Sbrooks
128256752Sbrooks	sc->atse_rxc_mem_rid = 2;
129256752Sbrooks	sc->atse_rxc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
130256752Sbrooks	    &sc->atse_rxc_mem_rid, RF_ACTIVE);
131256752Sbrooks	if (sc->atse_rxc_mem_res == NULL) {
132256752Sbrooks		device_printf(dev, "failed to map memory for RXC FIFO\n");
133256752Sbrooks		error = ENXIO;
134256752Sbrooks		goto err;
135256752Sbrooks	}
136256752Sbrooks	if (bootverbose)
137256752Sbrooks		device_printf(sc->atse_dev, "RXC FIFO at mem %p-%p\n",
138256752Sbrooks		    (void *)rman_get_start(sc->atse_rxc_mem_res),
139256752Sbrooks		    (void *)(rman_get_start(sc->atse_rxc_mem_res) +
140256752Sbrooks		    rman_get_size(sc->atse_rxc_mem_res)));
141256752Sbrooks
142256752Sbrooks	/*
143256752Sbrooks	 * TX and TXC FIFO memory regions.
144256752Sbrooks	 * 0x00: 2 * 32bit FIFO data,
145256752Sbrooks	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
146256752Sbrooks	 */
147256752Sbrooks	sc->atse_tx_mem_rid = 3;
148256752Sbrooks	sc->atse_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
149256752Sbrooks	    &sc->atse_tx_mem_rid, RF_ACTIVE);
150256752Sbrooks	if (sc->atse_tx_mem_res == NULL) {
151256752Sbrooks		device_printf(dev, "failed to map memory for TX FIFO\n");
152256752Sbrooks		error = ENXIO;
153256752Sbrooks		goto err;
154256752Sbrooks	}
155256752Sbrooks	if (bootverbose)
156256752Sbrooks		device_printf(sc->atse_dev, "TX FIFO at mem %p-%p\n",
157256752Sbrooks		    (void *)rman_get_start(sc->atse_tx_mem_res),
158256752Sbrooks		    (void *)(rman_get_start(sc->atse_tx_mem_res) +
159256752Sbrooks		    rman_get_size(sc->atse_tx_mem_res)));
160256752Sbrooks
161256752Sbrooks	sc->atse_txc_mem_rid = 4;
162256752Sbrooks	sc->atse_txc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
163256752Sbrooks	    &sc->atse_txc_mem_rid, RF_ACTIVE);
164256752Sbrooks	if (sc->atse_txc_mem_res == NULL) {
165256752Sbrooks		device_printf(dev, "failed to map memory for TXC FIFO\n");
166256752Sbrooks		error = ENXIO;
167256752Sbrooks		goto err;
168256752Sbrooks	}
169256752Sbrooks	if (bootverbose)
170256752Sbrooks		device_printf(sc->atse_dev, "TXC FIFO at mem %p-%p\n",
171256752Sbrooks		    (void *)rman_get_start(sc->atse_txc_mem_res),
172256752Sbrooks		    (void *)(rman_get_start(sc->atse_txc_mem_res) +
173256752Sbrooks		    rman_get_size(sc->atse_txc_mem_res)));
174256752Sbrooks
175256752Sbrooks	/* (Optional) RX and TX IRQ. */
176256752Sbrooks	sc->atse_rx_irq_rid = 0;
177256752Sbrooks	sc->atse_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
178256752Sbrooks	    &sc->atse_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
179256752Sbrooks	sc->atse_tx_irq_rid = 1;
180256752Sbrooks	sc->atse_tx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
181256752Sbrooks	    &sc->atse_tx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
182256752Sbrooks
183256752Sbrooks	error = atse_attach(dev);
184256752Sbrooks	if (error)
185256752Sbrooks		goto err;
186256752Sbrooks
187256752Sbrooks	return (0);
188256752Sbrooks
189256752Sbrookserr:
190256752Sbrooks	/* Cleanup. */
191256752Sbrooks	atse_detach_resources(dev);
192256752Sbrooks
193256752Sbrooks	return (error);
194256752Sbrooks}
195256752Sbrooks
196256752Sbrooksstatic device_method_t atse_methods_fdt[] = {
197256752Sbrooks	/* Device interface */
198256752Sbrooks	DEVMETHOD(device_probe,		atse_probe_fdt),
199256752Sbrooks	DEVMETHOD(device_attach,	atse_attach_fdt),
200256752Sbrooks	DEVMETHOD(device_detach,	atse_detach_dev),
201256752Sbrooks
202256752Sbrooks	/* MII interface */
203256752Sbrooks	DEVMETHOD(miibus_readreg,	atse_miibus_readreg),
204256752Sbrooks	DEVMETHOD(miibus_writereg,	atse_miibus_writereg),
205256752Sbrooks	DEVMETHOD(miibus_statchg,	atse_miibus_statchg),
206256752Sbrooks
207256752Sbrooks	DEVMETHOD_END
208256752Sbrooks};
209256752Sbrooks
210256752Sbrooksstatic driver_t atse_driver_fdt = {
211256752Sbrooks	"atse",
212256752Sbrooks	atse_methods_fdt,
213256752Sbrooks	sizeof(struct atse_softc)
214256752Sbrooks};
215256752Sbrooks
216256752SbrooksDRIVER_MODULE(atse, simplebus, atse_driver_fdt, atse_devclass, 0, 0);
217256752SbrooksDRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0);
218256752Sbrooks
219256752Sbrooks/* end */
220