linux/drivers/net/dsa/bcm_sf2.h
<<
>>
Prefs
   1/*
   2 * Broadcom Starfighter2 private context
   3 *
   4 * Copyright (C) 2014, Broadcom Corporation
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#ifndef __BCM_SF2_H
  13#define __BCM_SF2_H
  14
  15#include <linux/platform_device.h>
  16#include <linux/kernel.h>
  17#include <linux/io.h>
  18#include <linux/spinlock.h>
  19#include <linux/mutex.h>
  20#include <linux/mii.h>
  21#include <linux/ethtool.h>
  22#include <linux/types.h>
  23#include <linux/bitops.h>
  24
  25#include <net/dsa.h>
  26
  27#include "bcm_sf2_regs.h"
  28
  29struct bcm_sf2_hw_params {
  30        u16     top_rev;
  31        u16     core_rev;
  32        u16     gphy_rev;
  33        u32     num_gphy;
  34        u8      num_acb_queue;
  35        u8      num_rgmii;
  36        u8      num_ports;
  37        u8      fcb_pause_override:1;
  38        u8      acb_packets_inflight:1;
  39};
  40
  41#define BCM_SF2_REGS_NAME {\
  42        "core", "reg", "intrl2_0", "intrl2_1", "fcb", "acb" \
  43}
  44
  45#define BCM_SF2_REGS_NUM        6
  46
  47struct bcm_sf2_port_status {
  48        unsigned int link;
  49
  50        struct ethtool_eee eee;
  51
  52        u32 vlan_ctl_mask;
  53
  54        struct net_device *bridge_dev;
  55};
  56
  57struct bcm_sf2_arl_entry {
  58        u8 port;
  59        u8 mac[ETH_ALEN];
  60        u16 vid;
  61        u8 is_valid:1;
  62        u8 is_age:1;
  63        u8 is_static:1;
  64};
  65
  66static inline void bcm_sf2_mac_from_u64(u64 src, u8 *dst)
  67{
  68        unsigned int i;
  69
  70        for (i = 0; i < ETH_ALEN; i++)
  71                dst[ETH_ALEN - 1 - i] = (src >> (8 * i)) & 0xff;
  72}
  73
  74static inline u64 bcm_sf2_mac_to_u64(const u8 *src)
  75{
  76        unsigned int i;
  77        u64 dst = 0;
  78
  79        for (i = 0; i < ETH_ALEN; i++)
  80                dst |= (u64)src[ETH_ALEN - 1 - i] << (8 * i);
  81
  82        return dst;
  83}
  84
  85static inline void bcm_sf2_arl_to_entry(struct bcm_sf2_arl_entry *ent,
  86                                        u64 mac_vid, u32 fwd_entry)
  87{
  88        memset(ent, 0, sizeof(*ent));
  89        ent->port = fwd_entry & PORTID_MASK;
  90        ent->is_valid = !!(fwd_entry & ARL_VALID);
  91        ent->is_age = !!(fwd_entry & ARL_AGE);
  92        ent->is_static = !!(fwd_entry & ARL_STATIC);
  93        bcm_sf2_mac_from_u64(mac_vid, ent->mac);
  94        ent->vid = mac_vid >> VID_SHIFT;
  95}
  96
  97static inline void bcm_sf2_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
  98                                          const struct bcm_sf2_arl_entry *ent)
  99{
 100        *mac_vid = bcm_sf2_mac_to_u64(ent->mac);
 101        *mac_vid |= (u64)(ent->vid & VID_MASK) << VID_SHIFT;
 102        *fwd_entry = ent->port & PORTID_MASK;
 103        if (ent->is_valid)
 104                *fwd_entry |= ARL_VALID;
 105        if (ent->is_static)
 106                *fwd_entry |= ARL_STATIC;
 107        if (ent->is_age)
 108                *fwd_entry |= ARL_AGE;
 109}
 110
 111struct bcm_sf2_priv {
 112        /* Base registers, keep those in order with BCM_SF2_REGS_NAME */
 113        void __iomem                    *core;
 114        void __iomem                    *reg;
 115        void __iomem                    *intrl2_0;
 116        void __iomem                    *intrl2_1;
 117        void __iomem                    *fcb;
 118        void __iomem                    *acb;
 119
 120        /* spinlock protecting access to the indirect registers */
 121        spinlock_t                      indir_lock;
 122
 123        int                             irq0;
 124        int                             irq1;
 125        u32                             irq0_stat;
 126        u32                             irq0_mask;
 127        u32                             irq1_stat;
 128        u32                             irq1_mask;
 129
 130        /* Mutex protecting access to the MIB counters */
 131        struct mutex                    stats_mutex;
 132
 133        struct bcm_sf2_hw_params        hw_params;
 134
 135        struct bcm_sf2_port_status      port_sts[DSA_MAX_PORTS];
 136
 137        /* Mask of ports enabled for Wake-on-LAN */
 138        u32                             wol_ports_mask;
 139
 140        /* MoCA port location */
 141        int                             moca_port;
 142
 143        /* Bitmask of ports having an integrated PHY */
 144        unsigned int                    int_phy_mask;
 145};
 146
 147struct bcm_sf2_hw_stats {
 148        const char      *string;
 149        u16             reg;
 150        u8              sizeof_stat;
 151};
 152
 153#define SF2_IO_MACRO(name) \
 154static inline u32 name##_readl(struct bcm_sf2_priv *priv, u32 off)      \
 155{                                                                       \
 156        return __raw_readl(priv->name + off);                           \
 157}                                                                       \
 158static inline void name##_writel(struct bcm_sf2_priv *priv,             \
 159                                  u32 val, u32 off)                     \
 160{                                                                       \
 161        __raw_writel(val, priv->name + off);                            \
 162}                                                                       \
 163
 164/* Accesses to 64-bits register requires us to latch the hi/lo pairs
 165 * using the REG_DIR_DATA_{READ,WRITE} ancillary registers. The 'indir_lock'
 166 * spinlock is automatically grabbed and released to provide relative
 167 * atomiticy with latched reads/writes.
 168 */
 169#define SF2_IO64_MACRO(name) \
 170static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off)      \
 171{                                                                       \
 172        u32 indir, dir;                                                 \
 173        spin_lock(&priv->indir_lock);                                   \
 174        dir = __raw_readl(priv->name + off);                            \
 175        indir = reg_readl(priv, REG_DIR_DATA_READ);                     \
 176        spin_unlock(&priv->indir_lock);                                 \
 177        return (u64)indir << 32 | dir;                                  \
 178}                                                                       \
 179static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val,    \
 180                                                        u32 off)        \
 181{                                                                       \
 182        spin_lock(&priv->indir_lock);                                   \
 183        reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE);       \
 184        __raw_writel(lower_32_bits(val), priv->name + off);             \
 185        spin_unlock(&priv->indir_lock);                                 \
 186}
 187
 188#define SWITCH_INTR_L2(which)                                           \
 189static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \
 190                                                u32 mask)               \
 191{                                                                       \
 192        intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR);     \
 193        priv->irq##which##_mask &= ~(mask);                             \
 194}                                                                       \
 195static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \
 196                                                u32 mask)               \
 197{                                                                       \
 198        intrl2_## which##_writel(priv, mask, INTRL2_CPU_MASK_SET);      \
 199        priv->irq##which##_mask |= (mask);                              \
 200}                                                                       \
 201
 202SF2_IO_MACRO(core);
 203SF2_IO_MACRO(reg);
 204SF2_IO64_MACRO(core);
 205SF2_IO_MACRO(intrl2_0);
 206SF2_IO_MACRO(intrl2_1);
 207SF2_IO_MACRO(fcb);
 208SF2_IO_MACRO(acb);
 209
 210SWITCH_INTR_L2(0);
 211SWITCH_INTR_L2(1);
 212
 213#endif /* __BCM_SF2_H */
 214