1 /* $OpenBSD: if_em_soc.c,v 1.5 2016/01/07 04:37:53 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <dev/pci/if_em.h> 20 #include <dev/pci/if_em_hw.h> 21 #include <dev/pci/if_em_soc.h> 22 #include <dev/pci/gcu_var.h> 23 #include <dev/pci/gcu_reg.h> 24 25 #include "gcu.h" 26 27 void em_media_status(struct ifnet *, struct ifmediareq *); 28 int em_media_change(struct ifnet *); 29 30 void * 31 em_lookup_gcu(struct device *self) 32 { 33 #if NGCU > 0 34 extern struct cfdriver gcu_cd; 35 36 return (device_lookup(&gcu_cd, 0)); 37 #else 38 return (NULL); 39 #endif 40 } 41 42 int 43 em_attach_miibus(struct device *self) 44 { 45 return 0; 46 } 47 48 int 49 gcu_miibus_readreg(struct em_hw *hw, int phy, int reg) 50 { 51 struct em_softc *sc = (struct em_softc *) 52 ((struct em_osdep *)hw->back)->dev; 53 struct gcu_softc *gcu = hw->gcu; 54 uint32_t data = 0; 55 uint32_t done = 0; 56 int i = 0; 57 58 if (gcu == 0) 59 return 0; 60 61 /* format the data to be written to MDIO_COMMAND_REG */ 62 data |= (reg << MDIO_COMMAND_PHY_REG_OFFSET); 63 data |= (phy << MDIO_COMMAND_PHY_ADDR_OFFSET); 64 data |= MDIO_COMMAND_GO_MASK; 65 66 mtx_enter(&gcu->mdio_mtx); 67 bus_space_write_4(gcu->tag, gcu->handle, MDIO_COMMAND_REG, data); 68 69 while (!done && (i++ < GCU_MAX_ATTEMPTS)) { 70 DELAY(GCU_CMD_DELAY); 71 data = bus_space_read_4(gcu->tag, gcu->handle, 72 MDIO_COMMAND_REG); 73 done = !((data & MDIO_COMMAND_GO_MASK) >> 74 MDIO_COMMAND_GO_OFFSET); 75 } 76 mtx_leave(&gcu->mdio_mtx); 77 78 if (i >= GCU_MAX_ATTEMPTS) { 79 printf("%s: phy read timeout: phy %d, reg %d\n", 80 DEVNAME(sc), phy, reg); 81 return (0); 82 } 83 84 mtx_enter(&gcu->mdio_mtx); 85 data = bus_space_read_4(gcu->tag, gcu->handle, MDIO_STATUS_REG); 86 mtx_leave(&gcu->mdio_mtx); 87 88 if((data & MDIO_STATUS_STATUS_MASK) != 0) { 89 printf("%s: unable to read phy %d reg %d\n", 90 DEVNAME(sc), phy, reg); 91 return (0); 92 } 93 return (uint16_t) (data & MDIO_STATUS_READ_DATA_MASK); 94 } 95 96 void 97 gcu_miibus_writereg(struct em_hw *hw, int phy, int reg, int val) 98 { 99 struct em_softc *sc = (struct em_softc *) 100 ((struct em_osdep *)hw->back)->dev; 101 struct gcu_softc *gcu = hw->gcu; 102 uint32_t data, done = 0; 103 int i = 0; 104 105 if (gcu == 0) 106 return; 107 108 /* format the data to be written to the MDIO_COMMAND_REG */ 109 data = val; 110 data |= (reg << MDIO_COMMAND_PHY_REG_OFFSET); 111 data |= (phy << MDIO_COMMAND_PHY_ADDR_OFFSET); 112 data |= MDIO_COMMAND_OPER_MASK | MDIO_COMMAND_GO_MASK; 113 114 mtx_enter(&gcu->mdio_mtx); 115 bus_space_write_4(gcu->tag, gcu->handle, MDIO_COMMAND_REG, data); 116 117 while (!done && (i++ < GCU_MAX_ATTEMPTS)) { 118 DELAY(GCU_CMD_DELAY); 119 data = bus_space_read_4(gcu->tag, gcu->handle, 120 MDIO_COMMAND_REG); 121 done = !((data & MDIO_COMMAND_GO_MASK) >> 122 MDIO_COMMAND_GO_OFFSET); 123 } 124 mtx_leave(&gcu->mdio_mtx); 125 126 if (i >= GCU_MAX_ATTEMPTS) { 127 printf("%s: phy read timeout: phy %d, reg %d\n", 128 DEVNAME(sc), phy, reg); 129 return; 130 } 131 } 132 133 void 134 gcu_miibus_statchg(struct device *dev) 135 { 136 } 137