xref: /openbsd-src/sys/dev/pci/if_em_soc.c (revision 37d55eb22f55355b07a3d1fb40da3ccbd2414875)
1*37d55eb2Sdlg /*	$OpenBSD: if_em_soc.c,v 1.5 2016/01/07 04:37:53 dlg Exp $	*/
2391fd4d0Sdms 
3391fd4d0Sdms /*
4391fd4d0Sdms  * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
5391fd4d0Sdms  *
6391fd4d0Sdms  * Permission to use, copy, modify, and distribute this software for any
7391fd4d0Sdms  * purpose with or without fee is hereby granted, provided that the above
8391fd4d0Sdms  * copyright notice and this permission notice appear in all copies.
9391fd4d0Sdms  *
10391fd4d0Sdms  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11391fd4d0Sdms  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12391fd4d0Sdms  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13391fd4d0Sdms  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14391fd4d0Sdms  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15391fd4d0Sdms  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16391fd4d0Sdms  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17391fd4d0Sdms  */
18391fd4d0Sdms 
19391fd4d0Sdms #include <dev/pci/if_em.h>
20391fd4d0Sdms #include <dev/pci/if_em_hw.h>
21391fd4d0Sdms #include <dev/pci/if_em_soc.h>
22b48be82aSdlg #include <dev/pci/gcu_var.h>
23391fd4d0Sdms #include <dev/pci/gcu_reg.h>
24391fd4d0Sdms 
25b48be82aSdlg #include "gcu.h"
26b48be82aSdlg 
27391fd4d0Sdms void em_media_status(struct ifnet *, struct ifmediareq *);
28391fd4d0Sdms int em_media_change(struct ifnet *);
29391fd4d0Sdms 
30391fd4d0Sdms void *
em_lookup_gcu(struct device * self)31391fd4d0Sdms em_lookup_gcu(struct device *self)
32391fd4d0Sdms {
33b48be82aSdlg #if NGCU > 0
34b48be82aSdlg 	extern struct cfdriver gcu_cd;
35391fd4d0Sdms 
36b48be82aSdlg 	return (device_lookup(&gcu_cd, 0));
37b48be82aSdlg #else
38b48be82aSdlg 	return (NULL);
39b48be82aSdlg #endif
40391fd4d0Sdms }
41391fd4d0Sdms 
42391fd4d0Sdms int
em_attach_miibus(struct device * self)43391fd4d0Sdms em_attach_miibus(struct device *self)
44391fd4d0Sdms {
45391fd4d0Sdms 	return 0;
46391fd4d0Sdms }
47391fd4d0Sdms 
48391fd4d0Sdms int
gcu_miibus_readreg(struct em_hw * hw,int phy,int reg)49391fd4d0Sdms gcu_miibus_readreg(struct em_hw *hw, int phy, int reg)
50391fd4d0Sdms {
51391fd4d0Sdms 	struct em_softc *sc = (struct em_softc *)
52391fd4d0Sdms 	    ((struct em_osdep *)hw->back)->dev;
53391fd4d0Sdms 	struct gcu_softc *gcu = hw->gcu;
54391fd4d0Sdms 	uint32_t data = 0;
55391fd4d0Sdms 	uint32_t done = 0;
56391fd4d0Sdms 	int i = 0;
57391fd4d0Sdms 
58391fd4d0Sdms 	if (gcu == 0)
59391fd4d0Sdms 		return 0;
60391fd4d0Sdms 
61391fd4d0Sdms 	/* format the data to be written to MDIO_COMMAND_REG */
62391fd4d0Sdms 	data |= (reg << MDIO_COMMAND_PHY_REG_OFFSET);
63391fd4d0Sdms 	data |= (phy << MDIO_COMMAND_PHY_ADDR_OFFSET);
64391fd4d0Sdms 	data |= MDIO_COMMAND_GO_MASK;
65391fd4d0Sdms 
66391fd4d0Sdms 	mtx_enter(&gcu->mdio_mtx);
67391fd4d0Sdms 	bus_space_write_4(gcu->tag, gcu->handle, MDIO_COMMAND_REG, data);
68391fd4d0Sdms 
69391fd4d0Sdms 	while (!done && (i++ < GCU_MAX_ATTEMPTS)) {
70391fd4d0Sdms 		DELAY(GCU_CMD_DELAY);
71391fd4d0Sdms 		data = bus_space_read_4(gcu->tag, gcu->handle,
72391fd4d0Sdms 		    MDIO_COMMAND_REG);
73391fd4d0Sdms 		done = !((data & MDIO_COMMAND_GO_MASK) >>
74391fd4d0Sdms 		    MDIO_COMMAND_GO_OFFSET);
75391fd4d0Sdms 	}
76391fd4d0Sdms 	mtx_leave(&gcu->mdio_mtx);
77391fd4d0Sdms 
78391fd4d0Sdms 	if (i >= GCU_MAX_ATTEMPTS) {
79391fd4d0Sdms 		printf("%s: phy read timeout: phy %d, reg %d\n",
80*37d55eb2Sdlg 		    DEVNAME(sc), phy, reg);
81391fd4d0Sdms 		return (0);
82391fd4d0Sdms 	}
83391fd4d0Sdms 
84391fd4d0Sdms 	mtx_enter(&gcu->mdio_mtx);
85391fd4d0Sdms 	data = bus_space_read_4(gcu->tag, gcu->handle, MDIO_STATUS_REG);
86391fd4d0Sdms 	mtx_leave(&gcu->mdio_mtx);
87391fd4d0Sdms 
88391fd4d0Sdms 	if((data & MDIO_STATUS_STATUS_MASK) != 0) {
89391fd4d0Sdms 		printf("%s: unable to read phy %d reg %d\n",
90*37d55eb2Sdlg 		    DEVNAME(sc), phy, reg);
91391fd4d0Sdms 		return (0);
92391fd4d0Sdms 	}
93391fd4d0Sdms 	return (uint16_t) (data & MDIO_STATUS_READ_DATA_MASK);
94391fd4d0Sdms }
95391fd4d0Sdms 
96391fd4d0Sdms void
gcu_miibus_writereg(struct em_hw * hw,int phy,int reg,int val)97391fd4d0Sdms gcu_miibus_writereg(struct em_hw *hw, int phy, int reg, int val)
98391fd4d0Sdms {
99391fd4d0Sdms 	struct em_softc *sc = (struct em_softc *)
100391fd4d0Sdms 	    ((struct em_osdep *)hw->back)->dev;
101391fd4d0Sdms 	struct gcu_softc *gcu = hw->gcu;
102391fd4d0Sdms 	uint32_t data, done = 0;
103391fd4d0Sdms 	int i = 0;
104391fd4d0Sdms 
105391fd4d0Sdms 	if (gcu == 0)
106391fd4d0Sdms 		return;
107391fd4d0Sdms 
108391fd4d0Sdms 	/* format the data to be written to the MDIO_COMMAND_REG */
109391fd4d0Sdms 	data = val;
110391fd4d0Sdms 	data |= (reg << MDIO_COMMAND_PHY_REG_OFFSET);
111391fd4d0Sdms 	data |= (phy << MDIO_COMMAND_PHY_ADDR_OFFSET);
112391fd4d0Sdms 	data |= MDIO_COMMAND_OPER_MASK | MDIO_COMMAND_GO_MASK;
113391fd4d0Sdms 
114391fd4d0Sdms 	mtx_enter(&gcu->mdio_mtx);
115391fd4d0Sdms 	bus_space_write_4(gcu->tag, gcu->handle, MDIO_COMMAND_REG, data);
116391fd4d0Sdms 
117391fd4d0Sdms 	while (!done && (i++ < GCU_MAX_ATTEMPTS)) {
118391fd4d0Sdms 		DELAY(GCU_CMD_DELAY);
119391fd4d0Sdms 		data = bus_space_read_4(gcu->tag, gcu->handle,
120391fd4d0Sdms 		    MDIO_COMMAND_REG);
121391fd4d0Sdms 		done = !((data & MDIO_COMMAND_GO_MASK) >>
122391fd4d0Sdms 		    MDIO_COMMAND_GO_OFFSET);
123391fd4d0Sdms 	}
124391fd4d0Sdms 	mtx_leave(&gcu->mdio_mtx);
125391fd4d0Sdms 
126391fd4d0Sdms 	if (i >= GCU_MAX_ATTEMPTS) {
127391fd4d0Sdms 		printf("%s: phy read timeout: phy %d, reg %d\n",
128*37d55eb2Sdlg 		    DEVNAME(sc), phy, reg);
129391fd4d0Sdms 		return;
130391fd4d0Sdms 	}
131391fd4d0Sdms }
132391fd4d0Sdms 
133391fd4d0Sdms void
gcu_miibus_statchg(struct device * dev)134391fd4d0Sdms gcu_miibus_statchg(struct device *dev)
135391fd4d0Sdms {
136391fd4d0Sdms }
137