1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011-2012 Stefan Bethke. 5 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32#include <sys/param.h> 33#include <sys/bus.h> 34#include <sys/errno.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/socket.h> 38#include <sys/sockio.h> 39#include <sys/sysctl.h> 40#include <sys/systm.h> 41 42#include <net/if.h> 43#include <net/if_arp.h> 44#include <net/ethernet.h> 45#include <net/if_dl.h> 46#include <net/if_media.h> 47#include <net/if_types.h> 48 49#include <machine/bus.h> 50#include <dev/iicbus/iic.h> 51#include <dev/iicbus/iiconf.h> 52#include <dev/iicbus/iicbus.h> 53#include <dev/mii/mii.h> 54#include <dev/mii/miivar.h> 55#include <dev/mdio/mdio.h> 56 57#include <dev/etherswitch/etherswitch.h> 58 59#include <dev/etherswitch/arswitch/arswitchreg.h> 60#include <dev/etherswitch/arswitch/arswitchvar.h> 61#include <dev/etherswitch/arswitch/arswitch_reg.h> 62#include <dev/etherswitch/arswitch/arswitch_phy.h> /* XXX for probe */ 63#include <dev/etherswitch/arswitch/arswitch_9340.h> 64 65#include "mdio_if.h" 66#include "miibus_if.h" 67#include "etherswitch_if.h" 68 69/* 70 * AR9340 specific functions 71 */ 72static int 73ar9340_hw_setup(struct arswitch_softc *sc) 74{ 75 76 return (0); 77} 78 79static int 80ar9340_atu_learn_default(struct arswitch_softc *sc) 81{ 82 83 /* Enable aging, MAC replacing */ 84 arswitch_writereg(sc->sc_dev, AR934X_REG_AT_CTRL, 85 0x2b /* 5 min age time */ | 86 AR934X_AT_CTRL_AGE_EN | 87 AR934X_AT_CTRL_LEARN_CHANGE); 88 89 /* Enable ARP frame acknowledge */ 90 arswitch_modifyreg(sc->sc_dev, AR934X_REG_QM_CTRL, 91 AR934X_QM_CTRL_ARP_EN, AR934X_QM_CTRL_ARP_EN); 92 93#if 0 94 /* Copy frame to CPU port, not just redirect it */ 95 arswitch_modifyreg(sc->sc_dev, AR934X_REG_QM_CTRL, 96 AR934X_QM_CTRL_ARP_COPY_EN, AR934X_QM_CTRL_ARP_COPY_EN); 97#endif 98 99 return (0); 100} 101 102/* 103 * Initialise other global values for the AR9340. 104 */ 105static int 106ar9340_hw_global_setup(struct arswitch_softc *sc) 107{ 108 109 ARSWITCH_LOCK(sc); 110 111 /* Enable CPU port; disable mirror port */ 112 arswitch_writereg(sc->sc_dev, AR8X16_REG_CPU_PORT, 113 AR8X16_CPU_PORT_EN | AR8X16_CPU_MIRROR_DIS); 114 115 /* Setup TAG priority mapping */ 116 arswitch_writereg(sc->sc_dev, AR8X16_REG_TAG_PRIO, 0xfa50); 117 118 /* Enable Broadcast frames transmitted to the CPU */ 119 arswitch_modifyreg(sc->sc_dev, AR934X_REG_FLOOD_MASK, 120 AR934X_FLOOD_MASK_BC_DP(0), 121 AR934X_FLOOD_MASK_BC_DP(0)); 122 arswitch_modifyreg(sc->sc_dev, AR934X_REG_FLOOD_MASK, 123 AR934X_FLOOD_MASK_MC_DP(0), 124 AR934X_FLOOD_MASK_MC_DP(0)); 125#if 0 126 arswitch_modifyreg(sc->sc_dev, AR934X_REG_FLOOD_MASK, 127 AR934X_FLOOD_MASK_UC_DP(0), 128 AR934X_FLOOD_MASK_UC_DP(0)); 129#endif 130 131 /* Enable MIB counters */ 132 arswitch_modifyreg(sc->sc_dev, AR8X16_REG_MIB_FUNC0, 133 AR934X_MIB_ENABLE, AR934X_MIB_ENABLE); 134 135 /* Setup MTU */ 136 arswitch_modifyreg(sc->sc_dev, AR8X16_REG_GLOBAL_CTRL, 137 AR7240_GLOBAL_CTRL_MTU_MASK, 138 SM(1536, AR7240_GLOBAL_CTRL_MTU_MASK)); 139 140 /* Service Tag */ 141 arswitch_modifyreg(sc->sc_dev, AR8X16_REG_SERVICE_TAG, 142 AR8X16_SERVICE_TAG_MASK, 0); 143 144 /* Settle time */ 145 DELAY(1000); 146 147 /* 148 * Check PHY mode bits. 149 * 150 * This dictates whether the connected port is to be wired 151 * up via GMII or MII. I'm not sure why - this is an internal 152 * wiring issue. 153 */ 154 if (sc->is_gmii) { 155 device_printf(sc->sc_dev, "%s: GMII\n", __func__); 156 arswitch_modifyreg(sc->sc_dev, AR934X_REG_OPER_MODE0, 157 AR934X_OPER_MODE0_MAC_GMII_EN, 158 AR934X_OPER_MODE0_MAC_GMII_EN); 159 } else if (sc->is_mii) { 160 device_printf(sc->sc_dev, "%s: MII\n", __func__); 161 arswitch_modifyreg(sc->sc_dev, AR934X_REG_OPER_MODE0, 162 AR934X_OPER_MODE0_PHY_MII_EN, 163 AR934X_OPER_MODE0_PHY_MII_EN); 164 } else { 165 device_printf(sc->sc_dev, "%s: need is_gmii or is_mii set\n", 166 __func__); 167 ARSWITCH_UNLOCK(sc); 168 return (ENXIO); 169 } 170 171 /* 172 * Whether to connect PHY 4 via MII (ie a switch port) or 173 * treat it as a CPU port. 174 */ 175 if (sc->phy4cpu) { 176 device_printf(sc->sc_dev, "%s: PHY4 - CPU\n", __func__); 177 arswitch_modifyreg(sc->sc_dev, AR934X_REG_OPER_MODE1, 178 AR934X_REG_OPER_MODE1_PHY4_MII_EN, 179 AR934X_REG_OPER_MODE1_PHY4_MII_EN); 180 sc->info.es_nports = 5; 181 } else { 182 device_printf(sc->sc_dev, "%s: PHY4 - Local\n", __func__); 183 sc->info.es_nports = 6; 184 } 185 186 /* Settle time */ 187 DELAY(1000); 188 189 ARSWITCH_UNLOCK(sc); 190 return (0); 191} 192 193/* 194 * The AR9340 switch probes (almost) the same as the AR7240 on-chip switch. 195 * 196 * However, the support is slightly different. 197 * 198 * So instead of checking the PHY revision or mask register contents, 199 * we simply fall back to a hint check. 200 */ 201int 202ar9340_probe(device_t dev) 203{ 204 int is_9340 = 0; 205 206 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 207 "is_9340", &is_9340) != 0) 208 return (ENXIO); 209 210 if (is_9340 == 0) 211 return (ENXIO); 212 213 return (0); 214} 215 216void 217ar9340_attach(struct arswitch_softc *sc) 218{ 219 220 sc->hal.arswitch_hw_setup = ar9340_hw_setup; 221 sc->hal.arswitch_hw_global_setup = ar9340_hw_global_setup; 222 sc->hal.arswitch_atu_learn_default = ar9340_atu_learn_default; 223 /* 224 * Note: the ar9340 table fetch code/registers matche 225 * the ar8216/ar8316 for now because we're not supporting 226 * static entry programming that includes any of the extra 227 * bits in the AR9340. 228 */ 229 230 /* Set the switch vlan capabilities. */ 231 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q | 232 ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG; 233 sc->info.es_nvlangroups = AR8X16_MAX_VLANS; 234} 235