+enum {
+ AR8XXX_VER_AR8216 = 0x01,
+ AR8XXX_VER_AR8236 = 0x03,
+ AR8XXX_VER_AR8316 = 0x10,
+ AR8XXX_VER_AR8327 = 0x12,
+ AR8XXX_VER_AR8337 = 0x13,
+};
+
+#define AR8XXX_NUM_ARL_RECORDS 100
+
+enum arl_op {
+ AR8XXX_ARL_INITIALIZE,
+ AR8XXX_ARL_GET_NEXT
+};
+
+struct arl_entry {
+ u16 portmap;
+ u8 mac[6];
+};
+
+struct ar8xxx_priv;
+
+struct ar8xxx_mib_desc {
+ unsigned int size;
+ unsigned int offset;
+ const char *name;
+};
+
+struct ar8xxx_chip {
+ unsigned long caps;
+ bool config_at_probe;
+ bool mii_lo_first;
+
+ /* parameters to calculate REG_PORT_STATS_BASE */
+ unsigned reg_port_stats_start;
+ unsigned reg_port_stats_length;
+
+ unsigned reg_arl_ctrl;
+
+ int (*hw_init)(struct ar8xxx_priv *priv);
+ void (*cleanup)(struct ar8xxx_priv *priv);
+
+ const char *name;
+ int vlans;
+ int ports;
+ const struct switch_dev_ops *swops;
+
+ void (*init_globals)(struct ar8xxx_priv *priv);
+ void (*init_port)(struct ar8xxx_priv *priv, int port);
+ void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 members);
+ u32 (*read_port_status)(struct ar8xxx_priv *priv, int port);
+ u32 (*read_port_eee_status)(struct ar8xxx_priv *priv, int port);
+ int (*atu_flush)(struct ar8xxx_priv *priv);
+ int (*atu_flush_port)(struct ar8xxx_priv *priv, int port);
+ void (*vtu_flush)(struct ar8xxx_priv *priv);
+ void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vid, u32 port_mask);
+ void (*phy_fixup)(struct ar8xxx_priv *priv, int phy);
+ void (*set_mirror_regs)(struct ar8xxx_priv *priv);
+ void (*get_arl_entry)(struct ar8xxx_priv *priv, struct arl_entry *a,
+ u32 *status, enum arl_op op);
+ int (*sw_hw_apply)(struct switch_dev *dev);
+ void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev);
+ int (*phy_read)(struct ar8xxx_priv *priv, int addr, int regnum);
+ int (*phy_write)(struct ar8xxx_priv *priv, int addr, int regnum, u16 val);
+
+ const struct ar8xxx_mib_desc *mib_decs;
+ unsigned num_mibs;
+ unsigned mib_func;
+};
+
+struct ar8xxx_priv {
+ struct switch_dev dev;
+ struct mii_bus *mii_bus;
+ struct mii_bus *sw_mii_bus;
+ struct phy_device *phy;
+ struct device *pdev;
+
+ int (*get_port_link)(unsigned port);
+
+ const struct net_device_ops *ndo_old;
+ struct net_device_ops ndo;
+ struct mutex reg_mutex;
+ u8 chip_ver;
+ u8 chip_rev;
+ const struct ar8xxx_chip *chip;
+ void *chip_data;
+ bool initialized;
+ bool port4_phy;
+ char buf[2048];
+ struct arl_entry arl_table[AR8XXX_NUM_ARL_RECORDS];
+ char arl_buf[AR8XXX_NUM_ARL_RECORDS * 32 + 256];
+ bool link_up[AR8X16_MAX_PORTS];
+
+ bool init;
+
+ struct mutex mib_lock;
+ struct delayed_work mib_work;
+ int mib_next_port;
+ u64 *mib_stats;
+
+ struct list_head list;
+ unsigned int use_count;
+
+ /* all fields below are cleared on reset */
+ bool vlan;
+ u16 vlan_id[AR8X16_MAX_VLANS];
+ u8 vlan_table[AR8X16_MAX_VLANS];
+ u8 vlan_tagged;
+ u16 pvid[AR8X16_MAX_PORTS];
+ int arl_age_time;
+
+ /* mirroring */
+ bool mirror_rx;
+ bool mirror_tx;
+ int source_port;
+ int monitor_port;
+ u8 port_vlan_prio[AR8X16_MAX_PORTS];
+};
+
+u32
+ar8xxx_mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum);
+void
+ar8xxx_mii_write32(struct ar8xxx_priv *priv, int phy_id, int regnum, u32 val);
+u32
+ar8xxx_read(struct ar8xxx_priv *priv, int reg);
+void
+ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val);
+u32
+ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
+
+void
+ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr,
+ u16 dbg_addr, u16 *dbg_data);
+void
+ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
+ u16 dbg_addr, u16 dbg_data);
+void
+ar8xxx_phy_mmd_write(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg, u16 data);
+u16
+ar8xxx_phy_mmd_read(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg);
+void
+ar8xxx_phy_init(struct ar8xxx_priv *priv);
+int
+ar8xxx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_reset_mibs(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_mirror_rx_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_mirror_rx_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_mirror_tx_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_mirror_tx_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_mirror_monitor_port(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_mirror_monitor_port(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_mirror_source_port(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_mirror_source_port(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan);
+int
+ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan);
+int
+ar8xxx_sw_hw_apply(struct switch_dev *dev);
+int
+ar8xxx_sw_reset_switch(struct switch_dev *dev);
+int
+ar8xxx_sw_get_port_link(struct switch_dev *dev, int port,
+ struct switch_port_link *link);
+int
+ar8xxx_sw_set_port_reset_mib(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_port_mib(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_arl_age_time(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_arl_age_time(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_get_arl_table(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_flush_arl_table(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val);
+int
+ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
+
+static inline struct ar8xxx_priv *
+swdev_to_ar8xxx(struct switch_dev *swdev)
+{
+ return container_of(swdev, struct ar8xxx_priv, dev);
+}
+
+static inline bool ar8xxx_has_gige(struct ar8xxx_priv *priv)
+{
+ return priv->chip->caps & AR8XXX_CAP_GIGE;
+}
+
+static inline bool ar8xxx_has_mib_counters(struct ar8xxx_priv *priv)
+{
+ return priv->chip->caps & AR8XXX_CAP_MIB_COUNTERS;
+}
+
+static inline bool chip_is_ar8216(struct ar8xxx_priv *priv)
+{
+ return priv->chip_ver == AR8XXX_VER_AR8216;
+}
+
+static inline bool chip_is_ar8236(struct ar8xxx_priv *priv)
+{
+ return priv->chip_ver == AR8XXX_VER_AR8236;
+}
+
+static inline bool chip_is_ar8316(struct ar8xxx_priv *priv)
+{
+ return priv->chip_ver == AR8XXX_VER_AR8316;
+}
+
+static inline bool chip_is_ar8327(struct ar8xxx_priv *priv)
+{
+ return priv->chip_ver == AR8XXX_VER_AR8327;
+}
+
+static inline bool chip_is_ar8337(struct ar8xxx_priv *priv)
+{
+ return priv->chip_ver == AR8XXX_VER_AR8337;
+}
+
+static inline void
+ar8xxx_reg_set(struct ar8xxx_priv *priv, int reg, u32 val)
+{
+ ar8xxx_rmw(priv, reg, 0, val);
+}
+
+static inline void
+ar8xxx_reg_clear(struct ar8xxx_priv *priv, int reg, u32 val)
+{
+ ar8xxx_rmw(priv, reg, val, 0);
+}
+
+static inline void
+split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
+{
+ regaddr >>= 1;
+ *r1 = regaddr & 0x1e;
+
+ regaddr >>= 5;
+ *r2 = regaddr & 0x7;
+
+ regaddr >>= 3;
+ *page = regaddr & 0x1ff;
+}
+
+static inline void
+wait_for_page_switch(void)
+{
+ udelay(5);
+}
+