+ /* enable cpu port to receive multicast and broadcast frames */
+ priv->write(priv, AR8216_REG_FLOOD_MASK, 0x003f003f);
+
+ /* enable jumbo frames */
+ ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL,
+ AR8316_GCTRL_MTU, 9018 + 8 + 2);
+}
+
+static const struct ar8xxx_chip ar8316_chip = {
+ .caps = AR8XXX_CAP_GIGE,
+ .hw_init = ar8316_hw_init,
+ .init_globals = ar8316_init_globals,
+ .init_port = ar8216_init_port,
+ .setup_port = ar8216_setup_port,
+ .read_port_status = ar8216_read_port_status,
+ .atu_flush = ar8216_atu_flush,
+ .vtu_flush = ar8216_vtu_flush,
+ .vtu_load_vlan = ar8216_vtu_load_vlan,
+};
+
+static u32
+ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
+{
+ u32 t;
+
+ if (!cfg)
+ return 0;
+
+ t = 0;
+ switch (cfg->mode) {
+ case AR8327_PAD_NC:
+ break;
+
+ case AR8327_PAD_MAC2MAC_MII:
+ t = AR8327_PAD_MAC_MII_EN;
+ if (cfg->rxclk_sel)
+ t |= AR8327_PAD_MAC_MII_RXCLK_SEL;
+ if (cfg->txclk_sel)
+ t |= AR8327_PAD_MAC_MII_TXCLK_SEL;
+ break;
+
+ case AR8327_PAD_MAC2MAC_GMII:
+ t = AR8327_PAD_MAC_GMII_EN;
+ if (cfg->rxclk_sel)
+ t |= AR8327_PAD_MAC_GMII_RXCLK_SEL;
+ if (cfg->txclk_sel)
+ t |= AR8327_PAD_MAC_GMII_TXCLK_SEL;
+ break;
+
+ case AR8327_PAD_MAC_SGMII:
+ t = AR8327_PAD_SGMII_EN;
+ break;
+
+ case AR8327_PAD_MAC2PHY_MII:
+ t = AR8327_PAD_PHY_MII_EN;
+ if (cfg->rxclk_sel)
+ t |= AR8327_PAD_PHY_MII_RXCLK_SEL;
+ if (cfg->txclk_sel)
+ t |= AR8327_PAD_PHY_MII_TXCLK_SEL;
+ break;
+
+ case AR8327_PAD_MAC2PHY_GMII:
+ t = AR8327_PAD_PHY_GMII_EN;
+ if (cfg->pipe_rxclk_sel)
+ t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL;
+ if (cfg->rxclk_sel)
+ t |= AR8327_PAD_PHY_GMII_RXCLK_SEL;
+ if (cfg->txclk_sel)
+ t |= AR8327_PAD_PHY_GMII_TXCLK_SEL;
+ break;
+
+ case AR8327_PAD_MAC_RGMII:
+ t = AR8327_PAD_RGMII_EN;
+ t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
+ t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
+ if (cfg->rxclk_delay_en)
+ t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
+ if (cfg->txclk_delay_en)
+ t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
+ break;
+
+ case AR8327_PAD_PHY_GMII:
+ t = AR8327_PAD_PHYX_GMII_EN;
+ break;
+
+ case AR8327_PAD_PHY_RGMII:
+ t = AR8327_PAD_PHYX_RGMII_EN;
+ break;
+
+ case AR8327_PAD_PHY_MII:
+ t = AR8327_PAD_PHYX_MII_EN;
+ break;
+ }
+
+ return t;
+}
+
+static int
+ar8327_hw_init(struct ar8216_priv *priv)
+{
+ struct ar8327_platform_data *pdata;
+ u32 t;
+ int i;
+
+ pdata = priv->phy->dev.platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ t = ar8327_get_pad_cfg(pdata->pad0_cfg);
+ priv->write(priv, AR8327_REG_PAD0_MODE, t);
+ t = ar8327_get_pad_cfg(pdata->pad5_cfg);
+ priv->write(priv, AR8327_REG_PAD5_MODE, t);
+ t = ar8327_get_pad_cfg(pdata->pad6_cfg);
+ priv->write(priv, AR8327_REG_PAD6_MODE, t);
+
+ priv->write(priv, AR8327_REG_POWER_ON_STRIP, 0x40000000);
+
+ /* fixup PHYs */
+ for (i = 0; i < AR8327_NUM_PHYS; i++) {
+ /* For 100M waveform */
+ ar8216_phy_dbg_write(priv, i, 0, 0x02ea);
+
+ /* Turn on Gigabit clock */
+ ar8216_phy_dbg_write(priv, i, 0x3d, 0x68a0);
+ }
+
+ return 0;
+}
+
+static void
+ar8327_init_globals(struct ar8216_priv *priv)
+{
+ u32 t;
+
+ /* enable CPU port and disable mirror port */
+ t = AR8327_FWD_CTRL0_CPU_PORT_EN |
+ AR8327_FWD_CTRL0_MIRROR_PORT;
+ priv->write(priv, AR8327_REG_FWD_CTRL0, t);
+
+ /* forward multicast and broadcast frames to CPU */
+ t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
+ (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
+ priv->write(priv, AR8327_REG_FWD_CTRL1, t);
+
+ /* setup MTU */
+ ar8216_rmw(priv, AR8327_REG_MAX_FRAME_SIZE,
+ AR8327_MAX_FRAME_SIZE_MTU, 1518 + 8 + 2);
+}
+
+static void
+ar8327_init_cpuport(struct ar8216_priv *priv)
+{
+ struct ar8327_platform_data *pdata;
+ struct ar8327_port_cfg *cfg;
+ u32 t;
+
+ pdata = priv->phy->dev.platform_data;
+ if (!pdata)
+ return;
+
+ cfg = &pdata->cpuport_cfg;
+ if (!cfg->force_link) {
+ priv->write(priv, AR8327_REG_PORT_STATUS(AR8216_PORT_CPU),
+ AR8216_PORT_STATUS_LINK_AUTO);
+ return;
+ }
+
+ t = AR8216_PORT_STATUS_TXMAC | AR8216_PORT_STATUS_RXMAC;
+ t |= cfg->duplex ? AR8216_PORT_STATUS_DUPLEX : 0;
+ t |= cfg->rxpause ? AR8216_PORT_STATUS_RXFLOW : 0;
+ t |= cfg->txpause ? AR8216_PORT_STATUS_TXFLOW : 0;
+ switch (cfg->speed) {
+ case AR8327_PORT_SPEED_10:
+ t |= AR8216_PORT_SPEED_10M;
+ break;
+ case AR8327_PORT_SPEED_100:
+ t |= AR8216_PORT_SPEED_100M;
+ break;
+ case AR8327_PORT_SPEED_1000:
+ t |= AR8216_PORT_SPEED_1000M;
+ break;
+ }
+
+ priv->write(priv, AR8327_REG_PORT_STATUS(AR8216_PORT_CPU), t);
+}
+
+static void
+ar8327_init_port(struct ar8216_priv *priv, int port)
+{
+ u32 t;