1*8aa9ebccSVladimir Oltean // SPDX-License-Identifier: GPL-2.0 2*8aa9ebccSVladimir Oltean /* Copyright (c) 2018, Sensor-Technik Wiedemann GmbH 3*8aa9ebccSVladimir Oltean * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 4*8aa9ebccSVladimir Oltean */ 5*8aa9ebccSVladimir Oltean 6*8aa9ebccSVladimir Oltean #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7*8aa9ebccSVladimir Oltean 8*8aa9ebccSVladimir Oltean #include <linux/delay.h> 9*8aa9ebccSVladimir Oltean #include <linux/module.h> 10*8aa9ebccSVladimir Oltean #include <linux/printk.h> 11*8aa9ebccSVladimir Oltean #include <linux/spi/spi.h> 12*8aa9ebccSVladimir Oltean #include <linux/errno.h> 13*8aa9ebccSVladimir Oltean #include <linux/gpio/consumer.h> 14*8aa9ebccSVladimir Oltean #include <linux/of.h> 15*8aa9ebccSVladimir Oltean #include <linux/of_net.h> 16*8aa9ebccSVladimir Oltean #include <linux/of_mdio.h> 17*8aa9ebccSVladimir Oltean #include <linux/of_device.h> 18*8aa9ebccSVladimir Oltean #include <linux/netdev_features.h> 19*8aa9ebccSVladimir Oltean #include <linux/netdevice.h> 20*8aa9ebccSVladimir Oltean #include <linux/if_bridge.h> 21*8aa9ebccSVladimir Oltean #include <linux/if_ether.h> 22*8aa9ebccSVladimir Oltean #include "sja1105.h" 23*8aa9ebccSVladimir Oltean 24*8aa9ebccSVladimir Oltean static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, 25*8aa9ebccSVladimir Oltean unsigned int startup_delay) 26*8aa9ebccSVladimir Oltean { 27*8aa9ebccSVladimir Oltean gpiod_set_value_cansleep(gpio, 1); 28*8aa9ebccSVladimir Oltean /* Wait for minimum reset pulse length */ 29*8aa9ebccSVladimir Oltean msleep(pulse_len); 30*8aa9ebccSVladimir Oltean gpiod_set_value_cansleep(gpio, 0); 31*8aa9ebccSVladimir Oltean /* Wait until chip is ready after reset */ 32*8aa9ebccSVladimir Oltean msleep(startup_delay); 33*8aa9ebccSVladimir Oltean } 34*8aa9ebccSVladimir Oltean 35*8aa9ebccSVladimir Oltean static void 36*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(struct sja1105_l2_forwarding_entry *l2_fwd, 37*8aa9ebccSVladimir Oltean int from, int to, bool allow) 38*8aa9ebccSVladimir Oltean { 39*8aa9ebccSVladimir Oltean if (allow) { 40*8aa9ebccSVladimir Oltean l2_fwd[from].bc_domain |= BIT(to); 41*8aa9ebccSVladimir Oltean l2_fwd[from].reach_port |= BIT(to); 42*8aa9ebccSVladimir Oltean l2_fwd[from].fl_domain |= BIT(to); 43*8aa9ebccSVladimir Oltean } else { 44*8aa9ebccSVladimir Oltean l2_fwd[from].bc_domain &= ~BIT(to); 45*8aa9ebccSVladimir Oltean l2_fwd[from].reach_port &= ~BIT(to); 46*8aa9ebccSVladimir Oltean l2_fwd[from].fl_domain &= ~BIT(to); 47*8aa9ebccSVladimir Oltean } 48*8aa9ebccSVladimir Oltean } 49*8aa9ebccSVladimir Oltean 50*8aa9ebccSVladimir Oltean /* Structure used to temporarily transport device tree 51*8aa9ebccSVladimir Oltean * settings into sja1105_setup 52*8aa9ebccSVladimir Oltean */ 53*8aa9ebccSVladimir Oltean struct sja1105_dt_port { 54*8aa9ebccSVladimir Oltean phy_interface_t phy_mode; 55*8aa9ebccSVladimir Oltean sja1105_mii_role_t role; 56*8aa9ebccSVladimir Oltean }; 57*8aa9ebccSVladimir Oltean 58*8aa9ebccSVladimir Oltean static int sja1105_init_mac_settings(struct sja1105_private *priv) 59*8aa9ebccSVladimir Oltean { 60*8aa9ebccSVladimir Oltean struct sja1105_mac_config_entry default_mac = { 61*8aa9ebccSVladimir Oltean /* Enable all 8 priority queues on egress. 62*8aa9ebccSVladimir Oltean * Every queue i holds top[i] - base[i] frames. 63*8aa9ebccSVladimir Oltean * Sum of top[i] - base[i] is 511 (max hardware limit). 64*8aa9ebccSVladimir Oltean */ 65*8aa9ebccSVladimir Oltean .top = {0x3F, 0x7F, 0xBF, 0xFF, 0x13F, 0x17F, 0x1BF, 0x1FF}, 66*8aa9ebccSVladimir Oltean .base = {0x0, 0x40, 0x80, 0xC0, 0x100, 0x140, 0x180, 0x1C0}, 67*8aa9ebccSVladimir Oltean .enabled = {true, true, true, true, true, true, true, true}, 68*8aa9ebccSVladimir Oltean /* Keep standard IFG of 12 bytes on egress. */ 69*8aa9ebccSVladimir Oltean .ifg = 0, 70*8aa9ebccSVladimir Oltean /* Always put the MAC speed in automatic mode, where it can be 71*8aa9ebccSVladimir Oltean * retrieved from the PHY object through phylib and 72*8aa9ebccSVladimir Oltean * sja1105_adjust_port_config. 73*8aa9ebccSVladimir Oltean */ 74*8aa9ebccSVladimir Oltean .speed = SJA1105_SPEED_AUTO, 75*8aa9ebccSVladimir Oltean /* No static correction for 1-step 1588 events */ 76*8aa9ebccSVladimir Oltean .tp_delin = 0, 77*8aa9ebccSVladimir Oltean .tp_delout = 0, 78*8aa9ebccSVladimir Oltean /* Disable aging for critical TTEthernet traffic */ 79*8aa9ebccSVladimir Oltean .maxage = 0xFF, 80*8aa9ebccSVladimir Oltean /* Internal VLAN (pvid) to apply to untagged ingress */ 81*8aa9ebccSVladimir Oltean .vlanprio = 0, 82*8aa9ebccSVladimir Oltean .vlanid = 0, 83*8aa9ebccSVladimir Oltean .ing_mirr = false, 84*8aa9ebccSVladimir Oltean .egr_mirr = false, 85*8aa9ebccSVladimir Oltean /* Don't drop traffic with other EtherType than ETH_P_IP */ 86*8aa9ebccSVladimir Oltean .drpnona664 = false, 87*8aa9ebccSVladimir Oltean /* Don't drop double-tagged traffic */ 88*8aa9ebccSVladimir Oltean .drpdtag = false, 89*8aa9ebccSVladimir Oltean /* Don't drop untagged traffic */ 90*8aa9ebccSVladimir Oltean .drpuntag = false, 91*8aa9ebccSVladimir Oltean /* Don't retag 802.1p (VID 0) traffic with the pvid */ 92*8aa9ebccSVladimir Oltean .retag = false, 93*8aa9ebccSVladimir Oltean /* Enable learning and I/O on user ports by default. */ 94*8aa9ebccSVladimir Oltean .dyn_learn = true, 95*8aa9ebccSVladimir Oltean .egress = false, 96*8aa9ebccSVladimir Oltean .ingress = false, 97*8aa9ebccSVladimir Oltean }; 98*8aa9ebccSVladimir Oltean struct sja1105_mac_config_entry *mac; 99*8aa9ebccSVladimir Oltean struct sja1105_table *table; 100*8aa9ebccSVladimir Oltean int i; 101*8aa9ebccSVladimir Oltean 102*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_MAC_CONFIG]; 103*8aa9ebccSVladimir Oltean 104*8aa9ebccSVladimir Oltean /* Discard previous MAC Configuration Table */ 105*8aa9ebccSVladimir Oltean if (table->entry_count) { 106*8aa9ebccSVladimir Oltean kfree(table->entries); 107*8aa9ebccSVladimir Oltean table->entry_count = 0; 108*8aa9ebccSVladimir Oltean } 109*8aa9ebccSVladimir Oltean 110*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_NUM_PORTS, 111*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 112*8aa9ebccSVladimir Oltean if (!table->entries) 113*8aa9ebccSVladimir Oltean return -ENOMEM; 114*8aa9ebccSVladimir Oltean 115*8aa9ebccSVladimir Oltean /* Override table based on phylib DT bindings */ 116*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_NUM_PORTS; 117*8aa9ebccSVladimir Oltean 118*8aa9ebccSVladimir Oltean mac = table->entries; 119*8aa9ebccSVladimir Oltean 120*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) 121*8aa9ebccSVladimir Oltean mac[i] = default_mac; 122*8aa9ebccSVladimir Oltean 123*8aa9ebccSVladimir Oltean return 0; 124*8aa9ebccSVladimir Oltean } 125*8aa9ebccSVladimir Oltean 126*8aa9ebccSVladimir Oltean static int sja1105_init_mii_settings(struct sja1105_private *priv, 127*8aa9ebccSVladimir Oltean struct sja1105_dt_port *ports) 128*8aa9ebccSVladimir Oltean { 129*8aa9ebccSVladimir Oltean struct device *dev = &priv->spidev->dev; 130*8aa9ebccSVladimir Oltean struct sja1105_xmii_params_entry *mii; 131*8aa9ebccSVladimir Oltean struct sja1105_table *table; 132*8aa9ebccSVladimir Oltean int i; 133*8aa9ebccSVladimir Oltean 134*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_XMII_PARAMS]; 135*8aa9ebccSVladimir Oltean 136*8aa9ebccSVladimir Oltean /* Discard previous xMII Mode Parameters Table */ 137*8aa9ebccSVladimir Oltean if (table->entry_count) { 138*8aa9ebccSVladimir Oltean kfree(table->entries); 139*8aa9ebccSVladimir Oltean table->entry_count = 0; 140*8aa9ebccSVladimir Oltean } 141*8aa9ebccSVladimir Oltean 142*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_XMII_PARAMS_COUNT, 143*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 144*8aa9ebccSVladimir Oltean if (!table->entries) 145*8aa9ebccSVladimir Oltean return -ENOMEM; 146*8aa9ebccSVladimir Oltean 147*8aa9ebccSVladimir Oltean /* Override table based on phylib DT bindings */ 148*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_XMII_PARAMS_COUNT; 149*8aa9ebccSVladimir Oltean 150*8aa9ebccSVladimir Oltean mii = table->entries; 151*8aa9ebccSVladimir Oltean 152*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) { 153*8aa9ebccSVladimir Oltean switch (ports[i].phy_mode) { 154*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_MII: 155*8aa9ebccSVladimir Oltean mii->xmii_mode[i] = XMII_MODE_MII; 156*8aa9ebccSVladimir Oltean break; 157*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_RMII: 158*8aa9ebccSVladimir Oltean mii->xmii_mode[i] = XMII_MODE_RMII; 159*8aa9ebccSVladimir Oltean break; 160*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_RGMII: 161*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_RGMII_ID: 162*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_RGMII_RXID: 163*8aa9ebccSVladimir Oltean case PHY_INTERFACE_MODE_RGMII_TXID: 164*8aa9ebccSVladimir Oltean mii->xmii_mode[i] = XMII_MODE_RGMII; 165*8aa9ebccSVladimir Oltean break; 166*8aa9ebccSVladimir Oltean default: 167*8aa9ebccSVladimir Oltean dev_err(dev, "Unsupported PHY mode %s!\n", 168*8aa9ebccSVladimir Oltean phy_modes(ports[i].phy_mode)); 169*8aa9ebccSVladimir Oltean } 170*8aa9ebccSVladimir Oltean 171*8aa9ebccSVladimir Oltean mii->phy_mac[i] = ports[i].role; 172*8aa9ebccSVladimir Oltean } 173*8aa9ebccSVladimir Oltean return 0; 174*8aa9ebccSVladimir Oltean } 175*8aa9ebccSVladimir Oltean 176*8aa9ebccSVladimir Oltean static int sja1105_init_static_fdb(struct sja1105_private *priv) 177*8aa9ebccSVladimir Oltean { 178*8aa9ebccSVladimir Oltean struct sja1105_table *table; 179*8aa9ebccSVladimir Oltean 180*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP]; 181*8aa9ebccSVladimir Oltean 182*8aa9ebccSVladimir Oltean if (table->entry_count) { 183*8aa9ebccSVladimir Oltean kfree(table->entries); 184*8aa9ebccSVladimir Oltean table->entry_count = 0; 185*8aa9ebccSVladimir Oltean } 186*8aa9ebccSVladimir Oltean return 0; 187*8aa9ebccSVladimir Oltean } 188*8aa9ebccSVladimir Oltean 189*8aa9ebccSVladimir Oltean static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) 190*8aa9ebccSVladimir Oltean { 191*8aa9ebccSVladimir Oltean struct sja1105_table *table; 192*8aa9ebccSVladimir Oltean struct sja1105_l2_lookup_params_entry default_l2_lookup_params = { 193*8aa9ebccSVladimir Oltean /* TODO Learned FDB entries are never forgotten */ 194*8aa9ebccSVladimir Oltean .maxage = 0, 195*8aa9ebccSVladimir Oltean /* All entries within a FDB bin are available for learning */ 196*8aa9ebccSVladimir Oltean .dyn_tbsz = SJA1105ET_FDB_BIN_SIZE, 197*8aa9ebccSVladimir Oltean /* 2^8 + 2^5 + 2^3 + 2^2 + 2^1 + 1 in Koopman notation */ 198*8aa9ebccSVladimir Oltean .poly = 0x97, 199*8aa9ebccSVladimir Oltean /* This selects between Independent VLAN Learning (IVL) and 200*8aa9ebccSVladimir Oltean * Shared VLAN Learning (SVL) 201*8aa9ebccSVladimir Oltean */ 202*8aa9ebccSVladimir Oltean .shared_learn = false, 203*8aa9ebccSVladimir Oltean /* Don't discard management traffic based on ENFPORT - 204*8aa9ebccSVladimir Oltean * we don't perform SMAC port enforcement anyway, so 205*8aa9ebccSVladimir Oltean * what we are setting here doesn't matter. 206*8aa9ebccSVladimir Oltean */ 207*8aa9ebccSVladimir Oltean .no_enf_hostprt = false, 208*8aa9ebccSVladimir Oltean /* Don't learn SMAC for mac_fltres1 and mac_fltres0. 209*8aa9ebccSVladimir Oltean * Maybe correlate with no_linklocal_learn from bridge driver? 210*8aa9ebccSVladimir Oltean */ 211*8aa9ebccSVladimir Oltean .no_mgmt_learn = true, 212*8aa9ebccSVladimir Oltean }; 213*8aa9ebccSVladimir Oltean 214*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS]; 215*8aa9ebccSVladimir Oltean 216*8aa9ebccSVladimir Oltean if (table->entry_count) { 217*8aa9ebccSVladimir Oltean kfree(table->entries); 218*8aa9ebccSVladimir Oltean table->entry_count = 0; 219*8aa9ebccSVladimir Oltean } 220*8aa9ebccSVladimir Oltean 221*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 222*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 223*8aa9ebccSVladimir Oltean if (!table->entries) 224*8aa9ebccSVladimir Oltean return -ENOMEM; 225*8aa9ebccSVladimir Oltean 226*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT; 227*8aa9ebccSVladimir Oltean 228*8aa9ebccSVladimir Oltean /* This table only has a single entry */ 229*8aa9ebccSVladimir Oltean ((struct sja1105_l2_lookup_params_entry *)table->entries)[0] = 230*8aa9ebccSVladimir Oltean default_l2_lookup_params; 231*8aa9ebccSVladimir Oltean 232*8aa9ebccSVladimir Oltean return 0; 233*8aa9ebccSVladimir Oltean } 234*8aa9ebccSVladimir Oltean 235*8aa9ebccSVladimir Oltean static int sja1105_init_static_vlan(struct sja1105_private *priv) 236*8aa9ebccSVladimir Oltean { 237*8aa9ebccSVladimir Oltean struct sja1105_table *table; 238*8aa9ebccSVladimir Oltean struct sja1105_vlan_lookup_entry pvid = { 239*8aa9ebccSVladimir Oltean .ving_mirr = 0, 240*8aa9ebccSVladimir Oltean .vegr_mirr = 0, 241*8aa9ebccSVladimir Oltean .vmemb_port = 0, 242*8aa9ebccSVladimir Oltean .vlan_bc = 0, 243*8aa9ebccSVladimir Oltean .tag_port = 0, 244*8aa9ebccSVladimir Oltean .vlanid = 0, 245*8aa9ebccSVladimir Oltean }; 246*8aa9ebccSVladimir Oltean int i; 247*8aa9ebccSVladimir Oltean 248*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; 249*8aa9ebccSVladimir Oltean 250*8aa9ebccSVladimir Oltean /* The static VLAN table will only contain the initial pvid of 0. 251*8aa9ebccSVladimir Oltean */ 252*8aa9ebccSVladimir Oltean if (table->entry_count) { 253*8aa9ebccSVladimir Oltean kfree(table->entries); 254*8aa9ebccSVladimir Oltean table->entry_count = 0; 255*8aa9ebccSVladimir Oltean } 256*8aa9ebccSVladimir Oltean 257*8aa9ebccSVladimir Oltean table->entries = kcalloc(1, table->ops->unpacked_entry_size, 258*8aa9ebccSVladimir Oltean GFP_KERNEL); 259*8aa9ebccSVladimir Oltean if (!table->entries) 260*8aa9ebccSVladimir Oltean return -ENOMEM; 261*8aa9ebccSVladimir Oltean 262*8aa9ebccSVladimir Oltean table->entry_count = 1; 263*8aa9ebccSVladimir Oltean 264*8aa9ebccSVladimir Oltean /* VLAN ID 0: all DT-defined ports are members; no restrictions on 265*8aa9ebccSVladimir Oltean * forwarding; always transmit priority-tagged frames as untagged. 266*8aa9ebccSVladimir Oltean */ 267*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) { 268*8aa9ebccSVladimir Oltean pvid.vmemb_port |= BIT(i); 269*8aa9ebccSVladimir Oltean pvid.vlan_bc |= BIT(i); 270*8aa9ebccSVladimir Oltean pvid.tag_port &= ~BIT(i); 271*8aa9ebccSVladimir Oltean } 272*8aa9ebccSVladimir Oltean 273*8aa9ebccSVladimir Oltean ((struct sja1105_vlan_lookup_entry *)table->entries)[0] = pvid; 274*8aa9ebccSVladimir Oltean return 0; 275*8aa9ebccSVladimir Oltean } 276*8aa9ebccSVladimir Oltean 277*8aa9ebccSVladimir Oltean static int sja1105_init_l2_forwarding(struct sja1105_private *priv) 278*8aa9ebccSVladimir Oltean { 279*8aa9ebccSVladimir Oltean struct sja1105_l2_forwarding_entry *l2fwd; 280*8aa9ebccSVladimir Oltean struct sja1105_table *table; 281*8aa9ebccSVladimir Oltean int i, j; 282*8aa9ebccSVladimir Oltean 283*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING]; 284*8aa9ebccSVladimir Oltean 285*8aa9ebccSVladimir Oltean if (table->entry_count) { 286*8aa9ebccSVladimir Oltean kfree(table->entries); 287*8aa9ebccSVladimir Oltean table->entry_count = 0; 288*8aa9ebccSVladimir Oltean } 289*8aa9ebccSVladimir Oltean 290*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_COUNT, 291*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 292*8aa9ebccSVladimir Oltean if (!table->entries) 293*8aa9ebccSVladimir Oltean return -ENOMEM; 294*8aa9ebccSVladimir Oltean 295*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_L2_FORWARDING_COUNT; 296*8aa9ebccSVladimir Oltean 297*8aa9ebccSVladimir Oltean l2fwd = table->entries; 298*8aa9ebccSVladimir Oltean 299*8aa9ebccSVladimir Oltean /* First 5 entries define the forwarding rules */ 300*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) { 301*8aa9ebccSVladimir Oltean unsigned int upstream = dsa_upstream_port(priv->ds, i); 302*8aa9ebccSVladimir Oltean 303*8aa9ebccSVladimir Oltean for (j = 0; j < SJA1105_NUM_TC; j++) 304*8aa9ebccSVladimir Oltean l2fwd[i].vlan_pmap[j] = j; 305*8aa9ebccSVladimir Oltean 306*8aa9ebccSVladimir Oltean if (i == upstream) 307*8aa9ebccSVladimir Oltean continue; 308*8aa9ebccSVladimir Oltean 309*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(l2fwd, i, upstream, true); 310*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(l2fwd, upstream, i, true); 311*8aa9ebccSVladimir Oltean } 312*8aa9ebccSVladimir Oltean /* Next 8 entries define VLAN PCP mapping from ingress to egress. 313*8aa9ebccSVladimir Oltean * Create a one-to-one mapping. 314*8aa9ebccSVladimir Oltean */ 315*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_TC; i++) 316*8aa9ebccSVladimir Oltean for (j = 0; j < SJA1105_NUM_PORTS; j++) 317*8aa9ebccSVladimir Oltean l2fwd[SJA1105_NUM_PORTS + i].vlan_pmap[j] = i; 318*8aa9ebccSVladimir Oltean 319*8aa9ebccSVladimir Oltean return 0; 320*8aa9ebccSVladimir Oltean } 321*8aa9ebccSVladimir Oltean 322*8aa9ebccSVladimir Oltean static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) 323*8aa9ebccSVladimir Oltean { 324*8aa9ebccSVladimir Oltean struct sja1105_l2_forwarding_params_entry default_l2fwd_params = { 325*8aa9ebccSVladimir Oltean /* Disallow dynamic reconfiguration of vlan_pmap */ 326*8aa9ebccSVladimir Oltean .max_dynp = 0, 327*8aa9ebccSVladimir Oltean /* Use a single memory partition for all ingress queues */ 328*8aa9ebccSVladimir Oltean .part_spc = { SJA1105_MAX_FRAME_MEMORY, 0, 0, 0, 0, 0, 0, 0 }, 329*8aa9ebccSVladimir Oltean }; 330*8aa9ebccSVladimir Oltean struct sja1105_table *table; 331*8aa9ebccSVladimir Oltean 332*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; 333*8aa9ebccSVladimir Oltean 334*8aa9ebccSVladimir Oltean if (table->entry_count) { 335*8aa9ebccSVladimir Oltean kfree(table->entries); 336*8aa9ebccSVladimir Oltean table->entry_count = 0; 337*8aa9ebccSVladimir Oltean } 338*8aa9ebccSVladimir Oltean 339*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT, 340*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 341*8aa9ebccSVladimir Oltean if (!table->entries) 342*8aa9ebccSVladimir Oltean return -ENOMEM; 343*8aa9ebccSVladimir Oltean 344*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT; 345*8aa9ebccSVladimir Oltean 346*8aa9ebccSVladimir Oltean /* This table only has a single entry */ 347*8aa9ebccSVladimir Oltean ((struct sja1105_l2_forwarding_params_entry *)table->entries)[0] = 348*8aa9ebccSVladimir Oltean default_l2fwd_params; 349*8aa9ebccSVladimir Oltean 350*8aa9ebccSVladimir Oltean return 0; 351*8aa9ebccSVladimir Oltean } 352*8aa9ebccSVladimir Oltean 353*8aa9ebccSVladimir Oltean static int sja1105_init_general_params(struct sja1105_private *priv) 354*8aa9ebccSVladimir Oltean { 355*8aa9ebccSVladimir Oltean struct sja1105_general_params_entry default_general_params = { 356*8aa9ebccSVladimir Oltean /* Disallow dynamic changing of the mirror port */ 357*8aa9ebccSVladimir Oltean .mirr_ptacu = 0, 358*8aa9ebccSVladimir Oltean .switchid = priv->ds->index, 359*8aa9ebccSVladimir Oltean /* Priority queue for link-local frames trapped to CPU */ 360*8aa9ebccSVladimir Oltean .hostprio = 0, 361*8aa9ebccSVladimir Oltean .mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A, 362*8aa9ebccSVladimir Oltean .mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK, 363*8aa9ebccSVladimir Oltean .incl_srcpt1 = true, 364*8aa9ebccSVladimir Oltean .send_meta1 = false, 365*8aa9ebccSVladimir Oltean .mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B, 366*8aa9ebccSVladimir Oltean .mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK, 367*8aa9ebccSVladimir Oltean .incl_srcpt0 = true, 368*8aa9ebccSVladimir Oltean .send_meta0 = false, 369*8aa9ebccSVladimir Oltean /* The destination for traffic matching mac_fltres1 and 370*8aa9ebccSVladimir Oltean * mac_fltres0 on all ports except host_port. Such traffic 371*8aa9ebccSVladimir Oltean * receieved on host_port itself would be dropped, except 372*8aa9ebccSVladimir Oltean * by installing a temporary 'management route' 373*8aa9ebccSVladimir Oltean */ 374*8aa9ebccSVladimir Oltean .host_port = dsa_upstream_port(priv->ds, 0), 375*8aa9ebccSVladimir Oltean /* Same as host port */ 376*8aa9ebccSVladimir Oltean .mirr_port = dsa_upstream_port(priv->ds, 0), 377*8aa9ebccSVladimir Oltean /* Link-local traffic received on casc_port will be forwarded 378*8aa9ebccSVladimir Oltean * to host_port without embedding the source port and device ID 379*8aa9ebccSVladimir Oltean * info in the destination MAC address (presumably because it 380*8aa9ebccSVladimir Oltean * is a cascaded port and a downstream SJA switch already did 381*8aa9ebccSVladimir Oltean * that). Default to an invalid port (to disable the feature) 382*8aa9ebccSVladimir Oltean * and overwrite this if we find any DSA (cascaded) ports. 383*8aa9ebccSVladimir Oltean */ 384*8aa9ebccSVladimir Oltean .casc_port = SJA1105_NUM_PORTS, 385*8aa9ebccSVladimir Oltean /* No TTEthernet */ 386*8aa9ebccSVladimir Oltean .vllupformat = 0, 387*8aa9ebccSVladimir Oltean .vlmarker = 0, 388*8aa9ebccSVladimir Oltean .vlmask = 0, 389*8aa9ebccSVladimir Oltean /* Only update correctionField for 1-step PTP (L2 transport) */ 390*8aa9ebccSVladimir Oltean .ignore2stf = 0, 391*8aa9ebccSVladimir Oltean .tpid = ETH_P_8021Q, 392*8aa9ebccSVladimir Oltean .tpid2 = ETH_P_8021Q, 393*8aa9ebccSVladimir Oltean }; 394*8aa9ebccSVladimir Oltean struct sja1105_table *table; 395*8aa9ebccSVladimir Oltean int i; 396*8aa9ebccSVladimir Oltean 397*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) 398*8aa9ebccSVladimir Oltean if (dsa_is_dsa_port(priv->ds, i)) 399*8aa9ebccSVladimir Oltean default_general_params.casc_port = i; 400*8aa9ebccSVladimir Oltean 401*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; 402*8aa9ebccSVladimir Oltean 403*8aa9ebccSVladimir Oltean if (table->entry_count) { 404*8aa9ebccSVladimir Oltean kfree(table->entries); 405*8aa9ebccSVladimir Oltean table->entry_count = 0; 406*8aa9ebccSVladimir Oltean } 407*8aa9ebccSVladimir Oltean 408*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_GENERAL_PARAMS_COUNT, 409*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 410*8aa9ebccSVladimir Oltean if (!table->entries) 411*8aa9ebccSVladimir Oltean return -ENOMEM; 412*8aa9ebccSVladimir Oltean 413*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT; 414*8aa9ebccSVladimir Oltean 415*8aa9ebccSVladimir Oltean /* This table only has a single entry */ 416*8aa9ebccSVladimir Oltean ((struct sja1105_general_params_entry *)table->entries)[0] = 417*8aa9ebccSVladimir Oltean default_general_params; 418*8aa9ebccSVladimir Oltean 419*8aa9ebccSVladimir Oltean return 0; 420*8aa9ebccSVladimir Oltean } 421*8aa9ebccSVladimir Oltean 422*8aa9ebccSVladimir Oltean #define SJA1105_RATE_MBPS(speed) (((speed) * 64000) / 1000) 423*8aa9ebccSVladimir Oltean 424*8aa9ebccSVladimir Oltean static inline void 425*8aa9ebccSVladimir Oltean sja1105_setup_policer(struct sja1105_l2_policing_entry *policing, 426*8aa9ebccSVladimir Oltean int index) 427*8aa9ebccSVladimir Oltean { 428*8aa9ebccSVladimir Oltean policing[index].sharindx = index; 429*8aa9ebccSVladimir Oltean policing[index].smax = 65535; /* Burst size in bytes */ 430*8aa9ebccSVladimir Oltean policing[index].rate = SJA1105_RATE_MBPS(1000); 431*8aa9ebccSVladimir Oltean policing[index].maxlen = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN; 432*8aa9ebccSVladimir Oltean policing[index].partition = 0; 433*8aa9ebccSVladimir Oltean } 434*8aa9ebccSVladimir Oltean 435*8aa9ebccSVladimir Oltean static int sja1105_init_l2_policing(struct sja1105_private *priv) 436*8aa9ebccSVladimir Oltean { 437*8aa9ebccSVladimir Oltean struct sja1105_l2_policing_entry *policing; 438*8aa9ebccSVladimir Oltean struct sja1105_table *table; 439*8aa9ebccSVladimir Oltean int i, j, k; 440*8aa9ebccSVladimir Oltean 441*8aa9ebccSVladimir Oltean table = &priv->static_config.tables[BLK_IDX_L2_POLICING]; 442*8aa9ebccSVladimir Oltean 443*8aa9ebccSVladimir Oltean /* Discard previous L2 Policing Table */ 444*8aa9ebccSVladimir Oltean if (table->entry_count) { 445*8aa9ebccSVladimir Oltean kfree(table->entries); 446*8aa9ebccSVladimir Oltean table->entry_count = 0; 447*8aa9ebccSVladimir Oltean } 448*8aa9ebccSVladimir Oltean 449*8aa9ebccSVladimir Oltean table->entries = kcalloc(SJA1105_MAX_L2_POLICING_COUNT, 450*8aa9ebccSVladimir Oltean table->ops->unpacked_entry_size, GFP_KERNEL); 451*8aa9ebccSVladimir Oltean if (!table->entries) 452*8aa9ebccSVladimir Oltean return -ENOMEM; 453*8aa9ebccSVladimir Oltean 454*8aa9ebccSVladimir Oltean table->entry_count = SJA1105_MAX_L2_POLICING_COUNT; 455*8aa9ebccSVladimir Oltean 456*8aa9ebccSVladimir Oltean policing = table->entries; 457*8aa9ebccSVladimir Oltean 458*8aa9ebccSVladimir Oltean /* k sweeps through all unicast policers (0-39). 459*8aa9ebccSVladimir Oltean * bcast sweeps through policers 40-44. 460*8aa9ebccSVladimir Oltean */ 461*8aa9ebccSVladimir Oltean for (i = 0, k = 0; i < SJA1105_NUM_PORTS; i++) { 462*8aa9ebccSVladimir Oltean int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + i; 463*8aa9ebccSVladimir Oltean 464*8aa9ebccSVladimir Oltean for (j = 0; j < SJA1105_NUM_TC; j++, k++) 465*8aa9ebccSVladimir Oltean sja1105_setup_policer(policing, k); 466*8aa9ebccSVladimir Oltean 467*8aa9ebccSVladimir Oltean /* Set up this port's policer for broadcast traffic */ 468*8aa9ebccSVladimir Oltean sja1105_setup_policer(policing, bcast); 469*8aa9ebccSVladimir Oltean } 470*8aa9ebccSVladimir Oltean return 0; 471*8aa9ebccSVladimir Oltean } 472*8aa9ebccSVladimir Oltean 473*8aa9ebccSVladimir Oltean static int sja1105_static_config_load(struct sja1105_private *priv, 474*8aa9ebccSVladimir Oltean struct sja1105_dt_port *ports) 475*8aa9ebccSVladimir Oltean { 476*8aa9ebccSVladimir Oltean int rc; 477*8aa9ebccSVladimir Oltean 478*8aa9ebccSVladimir Oltean sja1105_static_config_free(&priv->static_config); 479*8aa9ebccSVladimir Oltean rc = sja1105_static_config_init(&priv->static_config, 480*8aa9ebccSVladimir Oltean priv->info->static_ops, 481*8aa9ebccSVladimir Oltean priv->info->device_id); 482*8aa9ebccSVladimir Oltean if (rc) 483*8aa9ebccSVladimir Oltean return rc; 484*8aa9ebccSVladimir Oltean 485*8aa9ebccSVladimir Oltean /* Build static configuration */ 486*8aa9ebccSVladimir Oltean rc = sja1105_init_mac_settings(priv); 487*8aa9ebccSVladimir Oltean if (rc < 0) 488*8aa9ebccSVladimir Oltean return rc; 489*8aa9ebccSVladimir Oltean rc = sja1105_init_mii_settings(priv, ports); 490*8aa9ebccSVladimir Oltean if (rc < 0) 491*8aa9ebccSVladimir Oltean return rc; 492*8aa9ebccSVladimir Oltean rc = sja1105_init_static_fdb(priv); 493*8aa9ebccSVladimir Oltean if (rc < 0) 494*8aa9ebccSVladimir Oltean return rc; 495*8aa9ebccSVladimir Oltean rc = sja1105_init_static_vlan(priv); 496*8aa9ebccSVladimir Oltean if (rc < 0) 497*8aa9ebccSVladimir Oltean return rc; 498*8aa9ebccSVladimir Oltean rc = sja1105_init_l2_lookup_params(priv); 499*8aa9ebccSVladimir Oltean if (rc < 0) 500*8aa9ebccSVladimir Oltean return rc; 501*8aa9ebccSVladimir Oltean rc = sja1105_init_l2_forwarding(priv); 502*8aa9ebccSVladimir Oltean if (rc < 0) 503*8aa9ebccSVladimir Oltean return rc; 504*8aa9ebccSVladimir Oltean rc = sja1105_init_l2_forwarding_params(priv); 505*8aa9ebccSVladimir Oltean if (rc < 0) 506*8aa9ebccSVladimir Oltean return rc; 507*8aa9ebccSVladimir Oltean rc = sja1105_init_l2_policing(priv); 508*8aa9ebccSVladimir Oltean if (rc < 0) 509*8aa9ebccSVladimir Oltean return rc; 510*8aa9ebccSVladimir Oltean rc = sja1105_init_general_params(priv); 511*8aa9ebccSVladimir Oltean if (rc < 0) 512*8aa9ebccSVladimir Oltean return rc; 513*8aa9ebccSVladimir Oltean 514*8aa9ebccSVladimir Oltean /* Send initial configuration to hardware via SPI */ 515*8aa9ebccSVladimir Oltean return sja1105_static_config_upload(priv); 516*8aa9ebccSVladimir Oltean } 517*8aa9ebccSVladimir Oltean 518*8aa9ebccSVladimir Oltean static int sja1105_parse_ports_node(struct sja1105_private *priv, 519*8aa9ebccSVladimir Oltean struct sja1105_dt_port *ports, 520*8aa9ebccSVladimir Oltean struct device_node *ports_node) 521*8aa9ebccSVladimir Oltean { 522*8aa9ebccSVladimir Oltean struct device *dev = &priv->spidev->dev; 523*8aa9ebccSVladimir Oltean struct device_node *child; 524*8aa9ebccSVladimir Oltean 525*8aa9ebccSVladimir Oltean for_each_child_of_node(ports_node, child) { 526*8aa9ebccSVladimir Oltean struct device_node *phy_node; 527*8aa9ebccSVladimir Oltean int phy_mode; 528*8aa9ebccSVladimir Oltean u32 index; 529*8aa9ebccSVladimir Oltean 530*8aa9ebccSVladimir Oltean /* Get switch port number from DT */ 531*8aa9ebccSVladimir Oltean if (of_property_read_u32(child, "reg", &index) < 0) { 532*8aa9ebccSVladimir Oltean dev_err(dev, "Port number not defined in device tree " 533*8aa9ebccSVladimir Oltean "(property \"reg\")\n"); 534*8aa9ebccSVladimir Oltean return -ENODEV; 535*8aa9ebccSVladimir Oltean } 536*8aa9ebccSVladimir Oltean 537*8aa9ebccSVladimir Oltean /* Get PHY mode from DT */ 538*8aa9ebccSVladimir Oltean phy_mode = of_get_phy_mode(child); 539*8aa9ebccSVladimir Oltean if (phy_mode < 0) { 540*8aa9ebccSVladimir Oltean dev_err(dev, "Failed to read phy-mode or " 541*8aa9ebccSVladimir Oltean "phy-interface-type property for port %d\n", 542*8aa9ebccSVladimir Oltean index); 543*8aa9ebccSVladimir Oltean return -ENODEV; 544*8aa9ebccSVladimir Oltean } 545*8aa9ebccSVladimir Oltean ports[index].phy_mode = phy_mode; 546*8aa9ebccSVladimir Oltean 547*8aa9ebccSVladimir Oltean phy_node = of_parse_phandle(child, "phy-handle", 0); 548*8aa9ebccSVladimir Oltean if (!phy_node) { 549*8aa9ebccSVladimir Oltean if (!of_phy_is_fixed_link(child)) { 550*8aa9ebccSVladimir Oltean dev_err(dev, "phy-handle or fixed-link " 551*8aa9ebccSVladimir Oltean "properties missing!\n"); 552*8aa9ebccSVladimir Oltean return -ENODEV; 553*8aa9ebccSVladimir Oltean } 554*8aa9ebccSVladimir Oltean /* phy-handle is missing, but fixed-link isn't. 555*8aa9ebccSVladimir Oltean * So it's a fixed link. Default to PHY role. 556*8aa9ebccSVladimir Oltean */ 557*8aa9ebccSVladimir Oltean ports[index].role = XMII_PHY; 558*8aa9ebccSVladimir Oltean } else { 559*8aa9ebccSVladimir Oltean /* phy-handle present => put port in MAC role */ 560*8aa9ebccSVladimir Oltean ports[index].role = XMII_MAC; 561*8aa9ebccSVladimir Oltean of_node_put(phy_node); 562*8aa9ebccSVladimir Oltean } 563*8aa9ebccSVladimir Oltean 564*8aa9ebccSVladimir Oltean /* The MAC/PHY role can be overridden with explicit bindings */ 565*8aa9ebccSVladimir Oltean if (of_property_read_bool(child, "sja1105,role-mac")) 566*8aa9ebccSVladimir Oltean ports[index].role = XMII_MAC; 567*8aa9ebccSVladimir Oltean else if (of_property_read_bool(child, "sja1105,role-phy")) 568*8aa9ebccSVladimir Oltean ports[index].role = XMII_PHY; 569*8aa9ebccSVladimir Oltean } 570*8aa9ebccSVladimir Oltean 571*8aa9ebccSVladimir Oltean return 0; 572*8aa9ebccSVladimir Oltean } 573*8aa9ebccSVladimir Oltean 574*8aa9ebccSVladimir Oltean static int sja1105_parse_dt(struct sja1105_private *priv, 575*8aa9ebccSVladimir Oltean struct sja1105_dt_port *ports) 576*8aa9ebccSVladimir Oltean { 577*8aa9ebccSVladimir Oltean struct device *dev = &priv->spidev->dev; 578*8aa9ebccSVladimir Oltean struct device_node *switch_node = dev->of_node; 579*8aa9ebccSVladimir Oltean struct device_node *ports_node; 580*8aa9ebccSVladimir Oltean int rc; 581*8aa9ebccSVladimir Oltean 582*8aa9ebccSVladimir Oltean ports_node = of_get_child_by_name(switch_node, "ports"); 583*8aa9ebccSVladimir Oltean if (!ports_node) { 584*8aa9ebccSVladimir Oltean dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); 585*8aa9ebccSVladimir Oltean return -ENODEV; 586*8aa9ebccSVladimir Oltean } 587*8aa9ebccSVladimir Oltean 588*8aa9ebccSVladimir Oltean rc = sja1105_parse_ports_node(priv, ports, ports_node); 589*8aa9ebccSVladimir Oltean of_node_put(ports_node); 590*8aa9ebccSVladimir Oltean 591*8aa9ebccSVladimir Oltean return rc; 592*8aa9ebccSVladimir Oltean } 593*8aa9ebccSVladimir Oltean 594*8aa9ebccSVladimir Oltean /* Convert back and forth MAC speed from Mbps to SJA1105 encoding */ 595*8aa9ebccSVladimir Oltean static int sja1105_speed[] = { 596*8aa9ebccSVladimir Oltean [SJA1105_SPEED_AUTO] = 0, 597*8aa9ebccSVladimir Oltean [SJA1105_SPEED_10MBPS] = 10, 598*8aa9ebccSVladimir Oltean [SJA1105_SPEED_100MBPS] = 100, 599*8aa9ebccSVladimir Oltean [SJA1105_SPEED_1000MBPS] = 1000, 600*8aa9ebccSVladimir Oltean }; 601*8aa9ebccSVladimir Oltean 602*8aa9ebccSVladimir Oltean static sja1105_speed_t sja1105_get_speed_cfg(unsigned int speed_mbps) 603*8aa9ebccSVladimir Oltean { 604*8aa9ebccSVladimir Oltean int i; 605*8aa9ebccSVladimir Oltean 606*8aa9ebccSVladimir Oltean for (i = SJA1105_SPEED_AUTO; i <= SJA1105_SPEED_1000MBPS; i++) 607*8aa9ebccSVladimir Oltean if (sja1105_speed[i] == speed_mbps) 608*8aa9ebccSVladimir Oltean return i; 609*8aa9ebccSVladimir Oltean return -EINVAL; 610*8aa9ebccSVladimir Oltean } 611*8aa9ebccSVladimir Oltean 612*8aa9ebccSVladimir Oltean /* Set link speed and enable/disable traffic I/O in the MAC configuration 613*8aa9ebccSVladimir Oltean * for a specific port. 614*8aa9ebccSVladimir Oltean * 615*8aa9ebccSVladimir Oltean * @speed_mbps: If 0, leave the speed unchanged, else adapt MAC to PHY speed. 616*8aa9ebccSVladimir Oltean * @enabled: Manage Rx and Tx settings for this port. Overrides the static 617*8aa9ebccSVladimir Oltean * configuration settings. 618*8aa9ebccSVladimir Oltean */ 619*8aa9ebccSVladimir Oltean static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, 620*8aa9ebccSVladimir Oltean int speed_mbps, bool enabled) 621*8aa9ebccSVladimir Oltean { 622*8aa9ebccSVladimir Oltean struct sja1105_xmii_params_entry *mii; 623*8aa9ebccSVladimir Oltean struct sja1105_mac_config_entry *mac; 624*8aa9ebccSVladimir Oltean struct device *dev = priv->ds->dev; 625*8aa9ebccSVladimir Oltean sja1105_phy_interface_t phy_mode; 626*8aa9ebccSVladimir Oltean sja1105_speed_t speed; 627*8aa9ebccSVladimir Oltean int rc; 628*8aa9ebccSVladimir Oltean 629*8aa9ebccSVladimir Oltean mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries; 630*8aa9ebccSVladimir Oltean mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; 631*8aa9ebccSVladimir Oltean 632*8aa9ebccSVladimir Oltean speed = sja1105_get_speed_cfg(speed_mbps); 633*8aa9ebccSVladimir Oltean if (speed_mbps && speed < 0) { 634*8aa9ebccSVladimir Oltean dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); 635*8aa9ebccSVladimir Oltean return -EINVAL; 636*8aa9ebccSVladimir Oltean } 637*8aa9ebccSVladimir Oltean 638*8aa9ebccSVladimir Oltean /* If requested, overwrite SJA1105_SPEED_AUTO from the static MAC 639*8aa9ebccSVladimir Oltean * configuration table, since this will be used for the clocking setup, 640*8aa9ebccSVladimir Oltean * and we no longer need to store it in the static config (already told 641*8aa9ebccSVladimir Oltean * hardware we want auto during upload phase). 642*8aa9ebccSVladimir Oltean */ 643*8aa9ebccSVladimir Oltean if (speed_mbps) 644*8aa9ebccSVladimir Oltean mac[port].speed = speed; 645*8aa9ebccSVladimir Oltean else 646*8aa9ebccSVladimir Oltean mac[port].speed = SJA1105_SPEED_AUTO; 647*8aa9ebccSVladimir Oltean 648*8aa9ebccSVladimir Oltean /* On P/Q/R/S, one can read from the device via the MAC reconfiguration 649*8aa9ebccSVladimir Oltean * tables. On E/T, MAC reconfig tables are not readable, only writable. 650*8aa9ebccSVladimir Oltean * We have to *know* what the MAC looks like. For the sake of keeping 651*8aa9ebccSVladimir Oltean * the code common, we'll use the static configuration tables as a 652*8aa9ebccSVladimir Oltean * reasonable approximation for both E/T and P/Q/R/S. 653*8aa9ebccSVladimir Oltean */ 654*8aa9ebccSVladimir Oltean mac[port].ingress = enabled; 655*8aa9ebccSVladimir Oltean mac[port].egress = enabled; 656*8aa9ebccSVladimir Oltean 657*8aa9ebccSVladimir Oltean /* Write to the dynamic reconfiguration tables */ 658*8aa9ebccSVladimir Oltean rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, 659*8aa9ebccSVladimir Oltean port, &mac[port], true); 660*8aa9ebccSVladimir Oltean if (rc < 0) { 661*8aa9ebccSVladimir Oltean dev_err(dev, "Failed to write MAC config: %d\n", rc); 662*8aa9ebccSVladimir Oltean return rc; 663*8aa9ebccSVladimir Oltean } 664*8aa9ebccSVladimir Oltean 665*8aa9ebccSVladimir Oltean /* Reconfigure the PLLs for the RGMII interfaces (required 125 MHz at 666*8aa9ebccSVladimir Oltean * gigabit, 25 MHz at 100 Mbps and 2.5 MHz at 10 Mbps). For MII and 667*8aa9ebccSVladimir Oltean * RMII no change of the clock setup is required. Actually, changing 668*8aa9ebccSVladimir Oltean * the clock setup does interrupt the clock signal for a certain time 669*8aa9ebccSVladimir Oltean * which causes trouble for all PHYs relying on this signal. 670*8aa9ebccSVladimir Oltean */ 671*8aa9ebccSVladimir Oltean if (!enabled) 672*8aa9ebccSVladimir Oltean return 0; 673*8aa9ebccSVladimir Oltean 674*8aa9ebccSVladimir Oltean phy_mode = mii->xmii_mode[port]; 675*8aa9ebccSVladimir Oltean if (phy_mode != XMII_MODE_RGMII) 676*8aa9ebccSVladimir Oltean return 0; 677*8aa9ebccSVladimir Oltean 678*8aa9ebccSVladimir Oltean return sja1105_clocking_setup_port(priv, port); 679*8aa9ebccSVladimir Oltean } 680*8aa9ebccSVladimir Oltean 681*8aa9ebccSVladimir Oltean static void sja1105_adjust_link(struct dsa_switch *ds, int port, 682*8aa9ebccSVladimir Oltean struct phy_device *phydev) 683*8aa9ebccSVladimir Oltean { 684*8aa9ebccSVladimir Oltean struct sja1105_private *priv = ds->priv; 685*8aa9ebccSVladimir Oltean 686*8aa9ebccSVladimir Oltean if (!phydev->link) 687*8aa9ebccSVladimir Oltean sja1105_adjust_port_config(priv, port, 0, false); 688*8aa9ebccSVladimir Oltean else 689*8aa9ebccSVladimir Oltean sja1105_adjust_port_config(priv, port, phydev->speed, true); 690*8aa9ebccSVladimir Oltean } 691*8aa9ebccSVladimir Oltean 692*8aa9ebccSVladimir Oltean static int sja1105_bridge_member(struct dsa_switch *ds, int port, 693*8aa9ebccSVladimir Oltean struct net_device *br, bool member) 694*8aa9ebccSVladimir Oltean { 695*8aa9ebccSVladimir Oltean struct sja1105_l2_forwarding_entry *l2_fwd; 696*8aa9ebccSVladimir Oltean struct sja1105_private *priv = ds->priv; 697*8aa9ebccSVladimir Oltean int i, rc; 698*8aa9ebccSVladimir Oltean 699*8aa9ebccSVladimir Oltean l2_fwd = priv->static_config.tables[BLK_IDX_L2_FORWARDING].entries; 700*8aa9ebccSVladimir Oltean 701*8aa9ebccSVladimir Oltean for (i = 0; i < SJA1105_NUM_PORTS; i++) { 702*8aa9ebccSVladimir Oltean /* Add this port to the forwarding matrix of the 703*8aa9ebccSVladimir Oltean * other ports in the same bridge, and viceversa. 704*8aa9ebccSVladimir Oltean */ 705*8aa9ebccSVladimir Oltean if (!dsa_is_user_port(ds, i)) 706*8aa9ebccSVladimir Oltean continue; 707*8aa9ebccSVladimir Oltean /* For the ports already under the bridge, only one thing needs 708*8aa9ebccSVladimir Oltean * to be done, and that is to add this port to their 709*8aa9ebccSVladimir Oltean * reachability domain. So we can perform the SPI write for 710*8aa9ebccSVladimir Oltean * them immediately. However, for this port itself (the one 711*8aa9ebccSVladimir Oltean * that is new to the bridge), we need to add all other ports 712*8aa9ebccSVladimir Oltean * to its reachability domain. So we do that incrementally in 713*8aa9ebccSVladimir Oltean * this loop, and perform the SPI write only at the end, once 714*8aa9ebccSVladimir Oltean * the domain contains all other bridge ports. 715*8aa9ebccSVladimir Oltean */ 716*8aa9ebccSVladimir Oltean if (i == port) 717*8aa9ebccSVladimir Oltean continue; 718*8aa9ebccSVladimir Oltean if (dsa_to_port(ds, i)->bridge_dev != br) 719*8aa9ebccSVladimir Oltean continue; 720*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(l2_fwd, i, port, member); 721*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(l2_fwd, port, i, member); 722*8aa9ebccSVladimir Oltean 723*8aa9ebccSVladimir Oltean rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_FORWARDING, 724*8aa9ebccSVladimir Oltean i, &l2_fwd[i], true); 725*8aa9ebccSVladimir Oltean if (rc < 0) 726*8aa9ebccSVladimir Oltean return rc; 727*8aa9ebccSVladimir Oltean } 728*8aa9ebccSVladimir Oltean 729*8aa9ebccSVladimir Oltean return sja1105_dynamic_config_write(priv, BLK_IDX_L2_FORWARDING, 730*8aa9ebccSVladimir Oltean port, &l2_fwd[port], true); 731*8aa9ebccSVladimir Oltean } 732*8aa9ebccSVladimir Oltean 733*8aa9ebccSVladimir Oltean static int sja1105_bridge_join(struct dsa_switch *ds, int port, 734*8aa9ebccSVladimir Oltean struct net_device *br) 735*8aa9ebccSVladimir Oltean { 736*8aa9ebccSVladimir Oltean return sja1105_bridge_member(ds, port, br, true); 737*8aa9ebccSVladimir Oltean } 738*8aa9ebccSVladimir Oltean 739*8aa9ebccSVladimir Oltean static void sja1105_bridge_leave(struct dsa_switch *ds, int port, 740*8aa9ebccSVladimir Oltean struct net_device *br) 741*8aa9ebccSVladimir Oltean { 742*8aa9ebccSVladimir Oltean sja1105_bridge_member(ds, port, br, false); 743*8aa9ebccSVladimir Oltean } 744*8aa9ebccSVladimir Oltean 745*8aa9ebccSVladimir Oltean static enum dsa_tag_protocol 746*8aa9ebccSVladimir Oltean sja1105_get_tag_protocol(struct dsa_switch *ds, int port) 747*8aa9ebccSVladimir Oltean { 748*8aa9ebccSVladimir Oltean return DSA_TAG_PROTO_NONE; 749*8aa9ebccSVladimir Oltean } 750*8aa9ebccSVladimir Oltean 751*8aa9ebccSVladimir Oltean /* The programming model for the SJA1105 switch is "all-at-once" via static 752*8aa9ebccSVladimir Oltean * configuration tables. Some of these can be dynamically modified at runtime, 753*8aa9ebccSVladimir Oltean * but not the xMII mode parameters table. 754*8aa9ebccSVladimir Oltean * Furthermode, some PHYs may not have crystals for generating their clocks 755*8aa9ebccSVladimir Oltean * (e.g. RMII). Instead, their 50MHz clock is supplied via the SJA1105 port's 756*8aa9ebccSVladimir Oltean * ref_clk pin. So port clocking needs to be initialized early, before 757*8aa9ebccSVladimir Oltean * connecting to PHYs is attempted, otherwise they won't respond through MDIO. 758*8aa9ebccSVladimir Oltean * Setting correct PHY link speed does not matter now. 759*8aa9ebccSVladimir Oltean * But dsa_slave_phy_setup is called later than sja1105_setup, so the PHY 760*8aa9ebccSVladimir Oltean * bindings are not yet parsed by DSA core. We need to parse early so that we 761*8aa9ebccSVladimir Oltean * can populate the xMII mode parameters table. 762*8aa9ebccSVladimir Oltean */ 763*8aa9ebccSVladimir Oltean static int sja1105_setup(struct dsa_switch *ds) 764*8aa9ebccSVladimir Oltean { 765*8aa9ebccSVladimir Oltean struct sja1105_dt_port ports[SJA1105_NUM_PORTS]; 766*8aa9ebccSVladimir Oltean struct sja1105_private *priv = ds->priv; 767*8aa9ebccSVladimir Oltean int rc; 768*8aa9ebccSVladimir Oltean 769*8aa9ebccSVladimir Oltean rc = sja1105_parse_dt(priv, ports); 770*8aa9ebccSVladimir Oltean if (rc < 0) { 771*8aa9ebccSVladimir Oltean dev_err(ds->dev, "Failed to parse DT: %d\n", rc); 772*8aa9ebccSVladimir Oltean return rc; 773*8aa9ebccSVladimir Oltean } 774*8aa9ebccSVladimir Oltean /* Create and send configuration down to device */ 775*8aa9ebccSVladimir Oltean rc = sja1105_static_config_load(priv, ports); 776*8aa9ebccSVladimir Oltean if (rc < 0) { 777*8aa9ebccSVladimir Oltean dev_err(ds->dev, "Failed to load static config: %d\n", rc); 778*8aa9ebccSVladimir Oltean return rc; 779*8aa9ebccSVladimir Oltean } 780*8aa9ebccSVladimir Oltean /* Configure the CGU (PHY link modes and speeds) */ 781*8aa9ebccSVladimir Oltean rc = sja1105_clocking_setup(priv); 782*8aa9ebccSVladimir Oltean if (rc < 0) { 783*8aa9ebccSVladimir Oltean dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc); 784*8aa9ebccSVladimir Oltean return rc; 785*8aa9ebccSVladimir Oltean } 786*8aa9ebccSVladimir Oltean 787*8aa9ebccSVladimir Oltean return 0; 788*8aa9ebccSVladimir Oltean } 789*8aa9ebccSVladimir Oltean 790*8aa9ebccSVladimir Oltean static const struct dsa_switch_ops sja1105_switch_ops = { 791*8aa9ebccSVladimir Oltean .get_tag_protocol = sja1105_get_tag_protocol, 792*8aa9ebccSVladimir Oltean .setup = sja1105_setup, 793*8aa9ebccSVladimir Oltean .adjust_link = sja1105_adjust_link, 794*8aa9ebccSVladimir Oltean .port_bridge_join = sja1105_bridge_join, 795*8aa9ebccSVladimir Oltean .port_bridge_leave = sja1105_bridge_leave, 796*8aa9ebccSVladimir Oltean }; 797*8aa9ebccSVladimir Oltean 798*8aa9ebccSVladimir Oltean static int sja1105_check_device_id(struct sja1105_private *priv) 799*8aa9ebccSVladimir Oltean { 800*8aa9ebccSVladimir Oltean const struct sja1105_regs *regs = priv->info->regs; 801*8aa9ebccSVladimir Oltean u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; 802*8aa9ebccSVladimir Oltean struct device *dev = &priv->spidev->dev; 803*8aa9ebccSVladimir Oltean u64 device_id; 804*8aa9ebccSVladimir Oltean u64 part_no; 805*8aa9ebccSVladimir Oltean int rc; 806*8aa9ebccSVladimir Oltean 807*8aa9ebccSVladimir Oltean rc = sja1105_spi_send_int(priv, SPI_READ, regs->device_id, 808*8aa9ebccSVladimir Oltean &device_id, SJA1105_SIZE_DEVICE_ID); 809*8aa9ebccSVladimir Oltean if (rc < 0) 810*8aa9ebccSVladimir Oltean return rc; 811*8aa9ebccSVladimir Oltean 812*8aa9ebccSVladimir Oltean if (device_id != priv->info->device_id) { 813*8aa9ebccSVladimir Oltean dev_err(dev, "Expected device ID 0x%llx but read 0x%llx\n", 814*8aa9ebccSVladimir Oltean priv->info->device_id, device_id); 815*8aa9ebccSVladimir Oltean return -ENODEV; 816*8aa9ebccSVladimir Oltean } 817*8aa9ebccSVladimir Oltean 818*8aa9ebccSVladimir Oltean rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->prod_id, 819*8aa9ebccSVladimir Oltean prod_id, SJA1105_SIZE_DEVICE_ID); 820*8aa9ebccSVladimir Oltean if (rc < 0) 821*8aa9ebccSVladimir Oltean return rc; 822*8aa9ebccSVladimir Oltean 823*8aa9ebccSVladimir Oltean sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID); 824*8aa9ebccSVladimir Oltean 825*8aa9ebccSVladimir Oltean if (part_no != priv->info->part_no) { 826*8aa9ebccSVladimir Oltean dev_err(dev, "Expected part number 0x%llx but read 0x%llx\n", 827*8aa9ebccSVladimir Oltean priv->info->part_no, part_no); 828*8aa9ebccSVladimir Oltean return -ENODEV; 829*8aa9ebccSVladimir Oltean } 830*8aa9ebccSVladimir Oltean 831*8aa9ebccSVladimir Oltean return 0; 832*8aa9ebccSVladimir Oltean } 833*8aa9ebccSVladimir Oltean 834*8aa9ebccSVladimir Oltean static int sja1105_probe(struct spi_device *spi) 835*8aa9ebccSVladimir Oltean { 836*8aa9ebccSVladimir Oltean struct device *dev = &spi->dev; 837*8aa9ebccSVladimir Oltean struct sja1105_private *priv; 838*8aa9ebccSVladimir Oltean struct dsa_switch *ds; 839*8aa9ebccSVladimir Oltean int rc; 840*8aa9ebccSVladimir Oltean 841*8aa9ebccSVladimir Oltean if (!dev->of_node) { 842*8aa9ebccSVladimir Oltean dev_err(dev, "No DTS bindings for SJA1105 driver\n"); 843*8aa9ebccSVladimir Oltean return -EINVAL; 844*8aa9ebccSVladimir Oltean } 845*8aa9ebccSVladimir Oltean 846*8aa9ebccSVladimir Oltean priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL); 847*8aa9ebccSVladimir Oltean if (!priv) 848*8aa9ebccSVladimir Oltean return -ENOMEM; 849*8aa9ebccSVladimir Oltean 850*8aa9ebccSVladimir Oltean /* Configure the optional reset pin and bring up switch */ 851*8aa9ebccSVladimir Oltean priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 852*8aa9ebccSVladimir Oltean if (IS_ERR(priv->reset_gpio)) 853*8aa9ebccSVladimir Oltean dev_dbg(dev, "reset-gpios not defined, ignoring\n"); 854*8aa9ebccSVladimir Oltean else 855*8aa9ebccSVladimir Oltean sja1105_hw_reset(priv->reset_gpio, 1, 1); 856*8aa9ebccSVladimir Oltean 857*8aa9ebccSVladimir Oltean /* Populate our driver private structure (priv) based on 858*8aa9ebccSVladimir Oltean * the device tree node that was probed (spi) 859*8aa9ebccSVladimir Oltean */ 860*8aa9ebccSVladimir Oltean priv->spidev = spi; 861*8aa9ebccSVladimir Oltean spi_set_drvdata(spi, priv); 862*8aa9ebccSVladimir Oltean 863*8aa9ebccSVladimir Oltean /* Configure the SPI bus */ 864*8aa9ebccSVladimir Oltean spi->bits_per_word = 8; 865*8aa9ebccSVladimir Oltean rc = spi_setup(spi); 866*8aa9ebccSVladimir Oltean if (rc < 0) { 867*8aa9ebccSVladimir Oltean dev_err(dev, "Could not init SPI\n"); 868*8aa9ebccSVladimir Oltean return rc; 869*8aa9ebccSVladimir Oltean } 870*8aa9ebccSVladimir Oltean 871*8aa9ebccSVladimir Oltean priv->info = of_device_get_match_data(dev); 872*8aa9ebccSVladimir Oltean 873*8aa9ebccSVladimir Oltean /* Detect hardware device */ 874*8aa9ebccSVladimir Oltean rc = sja1105_check_device_id(priv); 875*8aa9ebccSVladimir Oltean if (rc < 0) { 876*8aa9ebccSVladimir Oltean dev_err(dev, "Device ID check failed: %d\n", rc); 877*8aa9ebccSVladimir Oltean return rc; 878*8aa9ebccSVladimir Oltean } 879*8aa9ebccSVladimir Oltean 880*8aa9ebccSVladimir Oltean dev_info(dev, "Probed switch chip: %s\n", priv->info->name); 881*8aa9ebccSVladimir Oltean 882*8aa9ebccSVladimir Oltean ds = dsa_switch_alloc(dev, SJA1105_NUM_PORTS); 883*8aa9ebccSVladimir Oltean if (!ds) 884*8aa9ebccSVladimir Oltean return -ENOMEM; 885*8aa9ebccSVladimir Oltean 886*8aa9ebccSVladimir Oltean ds->ops = &sja1105_switch_ops; 887*8aa9ebccSVladimir Oltean ds->priv = priv; 888*8aa9ebccSVladimir Oltean priv->ds = ds; 889*8aa9ebccSVladimir Oltean 890*8aa9ebccSVladimir Oltean return dsa_register_switch(priv->ds); 891*8aa9ebccSVladimir Oltean } 892*8aa9ebccSVladimir Oltean 893*8aa9ebccSVladimir Oltean static int sja1105_remove(struct spi_device *spi) 894*8aa9ebccSVladimir Oltean { 895*8aa9ebccSVladimir Oltean struct sja1105_private *priv = spi_get_drvdata(spi); 896*8aa9ebccSVladimir Oltean 897*8aa9ebccSVladimir Oltean dsa_unregister_switch(priv->ds); 898*8aa9ebccSVladimir Oltean sja1105_static_config_free(&priv->static_config); 899*8aa9ebccSVladimir Oltean return 0; 900*8aa9ebccSVladimir Oltean } 901*8aa9ebccSVladimir Oltean 902*8aa9ebccSVladimir Oltean static const struct of_device_id sja1105_dt_ids[] = { 903*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, 904*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, 905*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105p", .data = &sja1105p_info }, 906*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105q", .data = &sja1105q_info }, 907*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105r", .data = &sja1105r_info }, 908*8aa9ebccSVladimir Oltean { .compatible = "nxp,sja1105s", .data = &sja1105s_info }, 909*8aa9ebccSVladimir Oltean { /* sentinel */ }, 910*8aa9ebccSVladimir Oltean }; 911*8aa9ebccSVladimir Oltean MODULE_DEVICE_TABLE(of, sja1105_dt_ids); 912*8aa9ebccSVladimir Oltean 913*8aa9ebccSVladimir Oltean static struct spi_driver sja1105_driver = { 914*8aa9ebccSVladimir Oltean .driver = { 915*8aa9ebccSVladimir Oltean .name = "sja1105", 916*8aa9ebccSVladimir Oltean .owner = THIS_MODULE, 917*8aa9ebccSVladimir Oltean .of_match_table = of_match_ptr(sja1105_dt_ids), 918*8aa9ebccSVladimir Oltean }, 919*8aa9ebccSVladimir Oltean .probe = sja1105_probe, 920*8aa9ebccSVladimir Oltean .remove = sja1105_remove, 921*8aa9ebccSVladimir Oltean }; 922*8aa9ebccSVladimir Oltean 923*8aa9ebccSVladimir Oltean module_spi_driver(sja1105_driver); 924*8aa9ebccSVladimir Oltean 925*8aa9ebccSVladimir Oltean MODULE_AUTHOR("Vladimir Oltean <olteanv@gmail.com>"); 926*8aa9ebccSVladimir Oltean MODULE_AUTHOR("Georg Waibel <georg.waibel@sensor-technik.de>"); 927*8aa9ebccSVladimir Oltean MODULE_DESCRIPTION("SJA1105 Driver"); 928*8aa9ebccSVladimir Oltean MODULE_LICENSE("GPL v2"); 929