1296177Sjhibbits/*-
2296177Sjhibbits * Copyright (c) 2012 Semihalf.
3296177Sjhibbits * All rights reserved.
4296177Sjhibbits *
5296177Sjhibbits * Redistribution and use in source and binary forms, with or without
6296177Sjhibbits * modification, are permitted provided that the following conditions
7296177Sjhibbits * are met:
8296177Sjhibbits * 1. Redistributions of source code must retain the above copyright
9296177Sjhibbits *    notice, this list of conditions and the following disclaimer.
10296177Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright
11296177Sjhibbits *    notice, this list of conditions and the following disclaimer in the
12296177Sjhibbits *    documentation and/or other materials provided with the distribution.
13296177Sjhibbits *
14296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15296177Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16296177Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17296177Sjhibbits * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18296177Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19296177Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20296177Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21296177Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22296177Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23296177Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24296177Sjhibbits * SUCH DAMAGE.
25296177Sjhibbits */
26296177Sjhibbits
27296177Sjhibbits#include <sys/cdefs.h>
28296177Sjhibbits__FBSDID("$FreeBSD$");
29296177Sjhibbits
30296177Sjhibbits#include <sys/param.h>
31296177Sjhibbits#include <sys/systm.h>
32296177Sjhibbits#include <sys/kernel.h>
33296177Sjhibbits#include <sys/bus.h>
34296177Sjhibbits#include <sys/module.h>
35296177Sjhibbits#include <sys/socket.h>
36296177Sjhibbits
37296177Sjhibbits#include <powerpc/mpc85xx/mpc85xx.h>
38296177Sjhibbits
39296177Sjhibbits#include <net/if.h>
40296177Sjhibbits#include <net/if_media.h>
41296177Sjhibbits
42296177Sjhibbits#include <dev/mii/mii.h>
43296177Sjhibbits#include <dev/mii/miivar.h>
44296177Sjhibbits
45296177Sjhibbits#include <dev/fdt/fdt_common.h>
46296177Sjhibbits#include <dev/ofw/ofw_bus.h>
47296177Sjhibbits#include <dev/ofw/ofw_bus_subr.h>
48296177Sjhibbits#include <dev/ofw/openfirm.h>
49296177Sjhibbits
50296177Sjhibbits#include "miibus_if.h"
51296177Sjhibbits
52296177Sjhibbits#include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
53296177Sjhibbits#include <contrib/ncsw/inc/xx_ext.h>
54296177Sjhibbits
55296177Sjhibbits#include "if_dtsec.h"
56296177Sjhibbits
57296177Sjhibbits
58296177Sjhibbitsstatic int	dtsec_fdt_probe(device_t dev);
59296177Sjhibbitsstatic int	dtsec_fdt_attach(device_t dev);
60296177Sjhibbits
61296177Sjhibbitsstatic device_method_t dtsec_methods[] = {
62296177Sjhibbits	/* Device interface */
63296177Sjhibbits	DEVMETHOD(device_probe,		dtsec_fdt_probe),
64296177Sjhibbits	DEVMETHOD(device_attach,	dtsec_fdt_attach),
65296177Sjhibbits	DEVMETHOD(device_detach,	dtsec_detach),
66296177Sjhibbits
67296177Sjhibbits	DEVMETHOD(device_shutdown,	dtsec_shutdown),
68296177Sjhibbits	DEVMETHOD(device_suspend,	dtsec_suspend),
69296177Sjhibbits	DEVMETHOD(device_resume,	dtsec_resume),
70296177Sjhibbits
71296177Sjhibbits	/* Bus interface */
72296177Sjhibbits	DEVMETHOD(bus_print_child,	bus_generic_print_child),
73296177Sjhibbits	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
74296177Sjhibbits
75296177Sjhibbits	/* MII interface */
76296177Sjhibbits	DEVMETHOD(miibus_readreg,	dtsec_miibus_readreg),
77296177Sjhibbits	DEVMETHOD(miibus_writereg,	dtsec_miibus_writereg),
78296177Sjhibbits	DEVMETHOD(miibus_statchg,	dtsec_miibus_statchg),
79296177Sjhibbits
80296177Sjhibbits	{ 0, 0 }
81296177Sjhibbits};
82296177Sjhibbits
83296177Sjhibbitsstatic driver_t dtsec_driver = {
84296177Sjhibbits	"dtsec",
85296177Sjhibbits	dtsec_methods,
86296177Sjhibbits	sizeof(struct dtsec_softc),
87296177Sjhibbits};
88296177Sjhibbits
89296177Sjhibbitsstatic devclass_t dtsec_devclass;
90296177SjhibbitsDRIVER_MODULE(dtsec, dpaa, dtsec_driver, dtsec_devclass, 0, 0);
91296177SjhibbitsDRIVER_MODULE(miibus, dtsec, miibus_driver, miibus_devclass, 0, 0);
92296177SjhibbitsMODULE_DEPEND(dtsec, ether, 1, 1, 1);
93296177SjhibbitsMODULE_DEPEND(dtsec, miibus, 1, 1, 1);
94296177Sjhibbits
95296177Sjhibbitsstatic int
96296177Sjhibbitsdtsec_fdt_probe(device_t dev)
97296177Sjhibbits{
98296177Sjhibbits
99296177Sjhibbits	if (!ofw_bus_is_compatible(dev, "fsl,dpa-ethernet"))
100296177Sjhibbits		return (ENXIO);
101296177Sjhibbits
102296177Sjhibbits	device_set_desc(dev, "Freescale Data Path Triple Speed Ethernet "
103296177Sjhibbits	    "Controller");
104296177Sjhibbits
105296177Sjhibbits	return (BUS_PROBE_DEFAULT);
106296177Sjhibbits}
107296177Sjhibbits
108296177Sjhibbitsstatic int
109296177Sjhibbitsdtsec_fdt_attach(device_t dev)
110296177Sjhibbits{
111296177Sjhibbits	struct dtsec_softc *sc;
112296177Sjhibbits	phandle_t node, enet_node, phy_node;
113296177Sjhibbits	phandle_t fman_rxtx_node[2];
114296177Sjhibbits	char phy_type[6];
115296177Sjhibbits
116296177Sjhibbits	sc = device_get_softc(dev);
117296177Sjhibbits	node = ofw_bus_get_node(dev);
118296177Sjhibbits
119296177Sjhibbits	if (OF_getprop(node, "fsl,fman-mac", (void *)&enet_node,
120296177Sjhibbits	    sizeof(enet_node)) == -1) {
121296177Sjhibbits		device_printf(dev, "Could not load fsl,fman-mac property "
122296177Sjhibbits		    "from DTS\n");
123296177Sjhibbits		return (ENXIO);
124296177Sjhibbits	}
125296177Sjhibbits
126296177Sjhibbits	enet_node = OF_instance_to_package(enet_node);
127296177Sjhibbits
128296177Sjhibbits	if (OF_getprop(enet_node, "local-mac-address",
129296177Sjhibbits	    (void *)sc->sc_mac_addr, 6) == -1) {
130296177Sjhibbits		if (device_get_unit(dev) != 0) {
131296177Sjhibbits			device_printf(dev,
132296177Sjhibbits			    "Could not load local-mac-addr property "
133296177Sjhibbits			    "from DTS\n");
134296177Sjhibbits			return (ENXIO);
135296177Sjhibbits		}
136296177Sjhibbits		sc->sc_hidden = true;
137296177Sjhibbits	}
138296177Sjhibbits
139296177Sjhibbits	/* Get link speed */
140296177Sjhibbits	if (fdt_is_compatible(enet_node, "fsl,fman-1g-mac") != 0)
141296177Sjhibbits		sc->sc_eth_dev_type = ETH_DTSEC;
142296177Sjhibbits	else if (fdt_is_compatible(enet_node, "fsl,fman-10g-mac") != 0)
143296177Sjhibbits		sc->sc_eth_dev_type = ETH_10GSEC;
144296177Sjhibbits	else
145296177Sjhibbits		return(ENXIO);
146296177Sjhibbits
147296177Sjhibbits	/* Get MAC memory offset in SoC */
148296177Sjhibbits	if (OF_getprop(enet_node, "reg", (void *)&sc->sc_mac_mem_offset,
149296177Sjhibbits	    sizeof(sc->sc_mac_mem_offset)) <= 0)
150296177Sjhibbits		return (ENXIO);
151296177Sjhibbits
152296177Sjhibbits	/* Get PHY address */
153296177Sjhibbits	if (OF_getprop(enet_node, "phy-handle", (void *)&phy_node,
154296177Sjhibbits	    sizeof(phy_node)) <= 0)
155296177Sjhibbits		return (ENXIO);
156296177Sjhibbits
157296177Sjhibbits	phy_node = OF_instance_to_package(phy_node);
158296177Sjhibbits
159296177Sjhibbits	if (OF_getprop(phy_node, "reg", (void *)&sc->sc_phy_addr,
160296177Sjhibbits	    sizeof(sc->sc_phy_addr)) <= 0)
161296177Sjhibbits		return (ENXIO);
162296177Sjhibbits
163296177Sjhibbits	/* Get PHY connection type */
164296177Sjhibbits	if (OF_getprop(enet_node, "phy-connection-type", (void *)phy_type,
165296177Sjhibbits	    sizeof(phy_type)) <= 0)
166296177Sjhibbits		return (ENXIO);
167296177Sjhibbits
168296177Sjhibbits	if (!strcmp(phy_type, "sgmii"))
169296177Sjhibbits		sc->sc_mac_enet_mode = e_ENET_MODE_SGMII_1000;
170296177Sjhibbits	else if (!strcmp(phy_type, "rgmii"))
171296177Sjhibbits		sc->sc_mac_enet_mode = e_ENET_MODE_RGMII_1000;
172296177Sjhibbits	else if (!strcmp(phy_type, "xgmii"))
173296177Sjhibbits		/* We set 10 Gigabit mode flag however we don't support it */
174296177Sjhibbits		sc->sc_mac_enet_mode = e_ENET_MODE_XGMII_10000;
175296177Sjhibbits	else
176296177Sjhibbits		return (ENXIO);
177296177Sjhibbits
178296177Sjhibbits	/* Get RX/TX port handles */
179296177Sjhibbits	if (OF_getprop(enet_node, "fsl,port-handles", (void *)fman_rxtx_node,
180296177Sjhibbits	    sizeof(fman_rxtx_node)) <= 0)
181296177Sjhibbits		return (ENXIO);
182296177Sjhibbits
183296177Sjhibbits	if (fman_rxtx_node[0] == 0)
184296177Sjhibbits		return (ENXIO);
185296177Sjhibbits
186296177Sjhibbits	if (fman_rxtx_node[1] == 0)
187296177Sjhibbits		return (ENXIO);
188296177Sjhibbits
189296177Sjhibbits	fman_rxtx_node[0] = OF_instance_to_package(fman_rxtx_node[0]);
190296177Sjhibbits	fman_rxtx_node[1] = OF_instance_to_package(fman_rxtx_node[1]);
191296177Sjhibbits
192296177Sjhibbits	if (fdt_is_compatible(fman_rxtx_node[0], "fsl,fman-port-1g-rx") == 0)
193296177Sjhibbits		return (ENXIO);
194296177Sjhibbits
195296177Sjhibbits	if (fdt_is_compatible(fman_rxtx_node[1], "fsl,fman-port-1g-tx") == 0)
196296177Sjhibbits		return (ENXIO);
197296177Sjhibbits
198296177Sjhibbits	/* Get RX port HW id */
199296177Sjhibbits	if (OF_getprop(fman_rxtx_node[0], "reg", (void *)&sc->sc_port_rx_hw_id,
200296177Sjhibbits	    sizeof(sc->sc_port_rx_hw_id)) <= 0)
201296177Sjhibbits		return (ENXIO);
202296177Sjhibbits
203296177Sjhibbits	/* Get TX port HW id */
204296177Sjhibbits	if (OF_getprop(fman_rxtx_node[1], "reg", (void *)&sc->sc_port_tx_hw_id,
205296177Sjhibbits	    sizeof(sc->sc_port_tx_hw_id)) <= 0)
206296177Sjhibbits		return (ENXIO);
207296177Sjhibbits
208296177Sjhibbits	/* Get QMan channel */
209296177Sjhibbits	if (OF_getprop(fman_rxtx_node[1], "fsl,qman-channel-id",
210296177Sjhibbits	    (void *)&sc->sc_port_tx_qman_chan,
211296177Sjhibbits	    sizeof(sc->sc_port_tx_qman_chan)) <= 0)
212296177Sjhibbits		return (ENXIO);
213296177Sjhibbits
214296177Sjhibbits	return (dtsec_attach(dev));
215296177Sjhibbits}
216