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