1 /*- 2 * Copyright (c) 2013 Luiz Otavio O Souza. 3 * Copyright (c) 2011-2012 Stefan Bethke. 4 * Copyright (c) 2012 Adrian Chadd. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/systm.h> 37 #include <sys/socket.h> 38 39 #include <net/if.h> 40 41 #include <dev/mii/mii.h> 42 43 #include <dev/etherswitch/etherswitch.h> 44 #include <dev/etherswitch/ip17x/ip17x_phy.h> 45 #include <dev/etherswitch/ip17x/ip17x_reg.h> 46 #include <dev/etherswitch/ip17x/ip17x_var.h> 47 #include <dev/etherswitch/ip17x/ip17x_vlans.h> 48 #include <dev/etherswitch/ip17x/ip175c.h> 49 50 /* 51 * IP175C specific functions. 52 */ 53 54 /* 55 * Reset the switch. 56 */ 57 static int 58 ip175c_reset(struct ip17x_softc *sc) 59 { 60 uint32_t data; 61 62 /* Reset all the switch settings. */ 63 if (ip17x_writephy(sc->sc_dev, IP175C_RESET_PHY, IP175C_RESET_REG, 64 0x175c)) 65 return (-1); 66 DELAY(2000); 67 68 /* Force IP175C mode. */ 69 data = ip17x_readphy(sc->sc_dev, IP175C_MODE_PHY, IP175C_MODE_REG); 70 if (data == 0x175a) { 71 if (ip17x_writephy(sc->sc_dev, IP175C_MODE_PHY, IP175C_MODE_REG, 72 0x175c)) 73 return (-1); 74 } 75 76 return (0); 77 } 78 79 static int 80 ip175c_port_vlan_setup(struct ip17x_softc *sc) 81 { 82 struct ip17x_vlan *v; 83 uint32_t ports[IP175X_NUM_PORTS], reg[IP175X_NUM_PORTS/2]; 84 int i, err, phy; 85 86 KASSERT(sc->cpuport == 5, ("cpuport != 5 not supported for IP175C")); 87 KASSERT(sc->numports == 6, ("numports != 6 not supported for IP175C")); 88 89 /* Build the port access masks. */ 90 memset(ports, 0, sizeof(ports)); 91 for (i = 0; i < sc->info.es_nports; i++) { 92 phy = sc->portphy[i]; 93 v = &sc->vlan[i]; 94 ports[phy] = v->ports; 95 } 96 97 /* Move the cpuport bit to its correct place. */ 98 for (i = 0; i < sc->numports; i++) { 99 if (ports[i] & (1 << sc->cpuport)) { 100 ports[i] |= (1 << 7); 101 ports[i] &= ~(1 << sc->cpuport); 102 } 103 } 104 105 /* And now build the switch register data. */ 106 memset(reg, 0, sizeof(reg)); 107 for (i = 0; i < (sc->numports / 2); i++) 108 reg[i] = ports[i * 2] << 8 | ports[i * 2 + 1]; 109 110 /* Update the switch resgisters. */ 111 err = ip17x_writephy(sc->sc_dev, 29, 19, reg[0]); 112 if (err == 0) 113 err = ip17x_writephy(sc->sc_dev, 29, 20, reg[1]); 114 if (err == 0) 115 err = ip17x_updatephy(sc->sc_dev, 29, 21, 0xff00, reg[2]); 116 if (err == 0) 117 err = ip17x_updatephy(sc->sc_dev, 30, 18, 0x00ff, reg[2]); 118 return (err); 119 } 120 121 static int 122 ip175c_dot1q_vlan_setup(struct ip17x_softc *sc) 123 { 124 struct ip17x_vlan *v; 125 uint32_t data; 126 uint32_t vlans[IP17X_MAX_VLANS]; 127 int i, j; 128 129 KASSERT(sc->cpuport == 5, ("cpuport != 5 not supported for IP175C")); 130 KASSERT(sc->numports == 6, ("numports != 6 not supported for IP175C")); 131 132 /* Add and strip VLAN tags. */ 133 data = (sc->addtag & ~(1 << IP175X_CPU_PORT)) << 11; 134 data |= (sc->striptag & ~(1 << IP175X_CPU_PORT)) << 6; 135 if (sc->addtag & (1 << IP175X_CPU_PORT)) 136 data |= (1 << 1); 137 if (sc->striptag & (1 << IP175X_CPU_PORT)) 138 data |= (1 << 0); 139 if (ip17x_writephy(sc->sc_dev, 29, 23, data)) 140 return (-1); 141 142 /* Set the VID_IDX_SEL to 0. */ 143 if (ip17x_updatephy(sc->sc_dev, 30, 9, 0x70, 0)) 144 return (-1); 145 146 /* Calculate the port masks. */ 147 memset(vlans, 0, sizeof(vlans)); 148 for (i = 0; i < IP17X_MAX_VLANS; i++) { 149 v = &sc->vlan[i]; 150 if ((v->vlanid & ETHERSWITCH_VID_VALID) == 0) 151 continue; 152 vlans[v->vlanid & ETHERSWITCH_VID_MASK] = v->ports; 153 } 154 155 for (j = 0, i = 1; i <= IP17X_MAX_VLANS / 2; i++) { 156 data = vlans[j++] & 0x3f; 157 data |= (vlans[j++] & 0x3f) << 8; 158 if (ip17x_writephy(sc->sc_dev, 30, i, data)) 159 return (-1); 160 } 161 162 /* Port default VLAN ID. */ 163 for (i = 0; i < sc->numports; i++) { 164 if (i == IP175X_CPU_PORT) { 165 if (ip17x_writephy(sc->sc_dev, 29, 30, sc->pvid[i])) 166 return (-1); 167 } else { 168 if (ip17x_writephy(sc->sc_dev, 29, 24 + i, sc->pvid[i])) 169 return (-1); 170 } 171 } 172 173 return (0); 174 } 175 176 /* 177 * Set the Switch configuration. 178 */ 179 static int 180 ip175c_hw_setup(struct ip17x_softc *sc) 181 { 182 183 switch (sc->vlan_mode) { 184 case ETHERSWITCH_VLAN_PORT: 185 return (ip175c_port_vlan_setup(sc)); 186 break; 187 case ETHERSWITCH_VLAN_DOT1Q: 188 return (ip175c_dot1q_vlan_setup(sc)); 189 break; 190 } 191 return (-1); 192 } 193 194 /* 195 * Set the switch VLAN mode. 196 */ 197 static int 198 ip175c_set_vlan_mode(struct ip17x_softc *sc, uint32_t mode) 199 { 200 201 switch (mode) { 202 case ETHERSWITCH_VLAN_DOT1Q: 203 /* Enable VLAN tag processing. */ 204 ip17x_updatephy(sc->sc_dev, 30, 9, 0x80, 0x80); 205 sc->vlan_mode = mode; 206 break; 207 case ETHERSWITCH_VLAN_PORT: 208 default: 209 /* Disable VLAN tag processing. */ 210 ip17x_updatephy(sc->sc_dev, 30, 9, 0x80, 0); 211 sc->vlan_mode = ETHERSWITCH_VLAN_PORT; 212 break; 213 }; 214 215 /* Reset vlans. */ 216 ip17x_reset_vlans(sc, sc->vlan_mode); 217 218 /* Update switch configuration. */ 219 ip175c_hw_setup(sc); 220 221 return (0); 222 } 223 224 /* 225 * Get the switch VLAN mode. 226 */ 227 static int 228 ip175c_get_vlan_mode(struct ip17x_softc *sc) 229 { 230 231 return (sc->vlan_mode); 232 } 233 234 void 235 ip175c_attach(struct ip17x_softc *sc) 236 { 237 238 sc->hal.ip17x_reset = ip175c_reset; 239 sc->hal.ip17x_hw_setup = ip175c_hw_setup; 240 sc->hal.ip17x_get_vlan_mode = ip175c_get_vlan_mode; 241 sc->hal.ip17x_set_vlan_mode = ip175c_set_vlan_mode; 242 243 /* Defaults for IP175C. */ 244 sc->cpuport = IP175X_CPU_PORT; 245 sc->numports = IP175X_NUM_PORTS; 246 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOT1Q; 247 248 device_printf(sc->sc_dev, "type: IP175C\n"); 249 } 250