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
  55struct bcm_sf2_arl_entry {
  56        u8 port;
  57        u8 mac[ETH_ALEN];
  58        u16 vid;
  59        u8 is_valid:1;
  60        u8 is_age:1;
  61        u8 is_static:1;
  62};
  63
  64static inline void bcm_sf2_mac_from_u64(u64 src, u8 *dst)
  65{
  66        unsigned int i;
  67
  68        for (i = 0; i < ETH_ALEN; i++)
  69                dst[ETH_ALEN - 1 - i] = (src >> (8 * i)) & 0xff;
  70}
  71
  72static inline u64 bcm_sf2_mac_to_u64(const u8 *src)
  73{
  74        unsigned int i;
  75        u64 dst = 0;
  76
  77        for (i = 0; i < ETH_ALEN; i++)
  78                dst |= (u64)src[ETH_ALEN - 1 - i] << (8 * i);
  79
  80        return dst;
  81}
  82
  83static inline void bcm_sf2_arl_to_entry(struct bcm_sf2_arl_entry *ent,
  84                                        u64 mac_vid, u32 fwd_entry)
  85{
  86        memset(ent, 0, sizeof(*ent));
  87        ent->port = fwd_entry & PORTID_MASK;
  88        ent->is_valid = !!(fwd_entry & ARL_VALID);
  89        ent->is_age = !!(fwd_entry & ARL_AGE);
  90        ent->is_static = !!(fwd_entry & ARL_STATIC);
  91        bcm_sf2_mac_from_u64(mac_vid, ent->mac);
  92        ent->vid = mac_vid >> VID_SHIFT;
  93}
  94
  95static inline void bcm_sf2_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
  96                                          const struct bcm_sf2_arl_entry *ent)
  97{
  98        *mac_vid = bcm_sf2_mac_to_u64(ent->mac);
  99        *mac_vid |= (u64)(ent->vid & VID_MASK) << VID_SHIFT;
 100        *fwd_entry = ent->port & PORTID_MASK;
 101        if (ent->is_valid)
 102                *fwd_entry |= ARL_VALID;
 103        if (ent->is_static)
 104                *fwd_entry |= ARL_STATIC;
 105        if (ent->is_age)
 106                *fwd_entry |= ARL_AGE;
 107}
 108
 109struct bcm_sf2_priv {
 110        /* Base registers, keep those in order with BCM_SF2_REGS_NAME */
 111        void __iomem                    *core;
 112        void __iomem                    *reg;
 113        void __iomem                    *intrl2_0;
 114        void __iomem                    *intrl2_1;
 115        void __iomem                    *fcb;
 116        void __iomem                    *acb;
 117
 118        /* spinlock protecting access to the indirect registers */
 119        spinlock_t                      indir_lock;
 120
 121        int                             irq0;
 122        int                             irq1;
 123        u32                             irq0_stat;
 124        u32                             irq0_mask;
 125        u32                             irq1_stat;
 126        u32                             irq1_mask;
 127
 128        /* Mutex protecting access to the MIB counters */
 129        struct mutex                    stats_mutex;
 130
 131        struct bcm_sf2_hw_params        hw_params;
 132
 133        struct bcm_sf2_port_status      port_sts[DSA_MAX_PORTS];
 134
 135        /* Mask of ports enabled for Wake-on-LAN */
 136        u32                             wol_ports_mask;
 137
 138        /* MoCA port location */
 139        int                             moca_port;
 140
 141        /* Bitmask of ports having an integrated PHY */
 142        unsigned int                    int_phy_mask;
 143};
 144
 145struct bcm_sf2_hw_stats {
 146        const char      *string;
 147        u16             reg;
 148        u8              sizeof_stat;
 149};
 150
 151#define SF2_IO_MACRO(name) \
 152static inline u32 name##_readl(struct bcm_sf2_priv *priv, u32 off)      \
 153{                                                                       \
 154        return __raw_readl(priv->name + off);                           \
 155}                                                                       \
 156static inline void name##_writel(struct bcm_sf2_priv *priv,             \
 157                                  u32 val, u32 off)                     \
 158{                                                                       \
 159        __raw_writel(val, priv->name + off);                            \
 160}                                                                       \
 161
 162/* Accesses to 64-bits register requires us to latch the hi/lo pairs
 163 * using the REG_DIR_DATA_{READ,WRITE} ancillary registers. The 'indir_lock'
 164 * spinlock is automatically grabbed and released to provide relative
 165 * atomiticy with latched reads/writes.
 166 */
 167#define SF2_IO64_MACRO(name) \
 168static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off)      \
 169{                                                                       \
 170        u32 indir, dir;                                                 \
 171        spin_lock(&priv->indir_lock);                                   \
 172        dir = __raw_readl(priv->name + off);                            \
 173        indir = reg_readl(priv, REG_DIR_DATA_READ);                     \
 174        spin_unlock(&priv->indir_lock);                                 \
 175        return (u64)indir << 32 | dir;                                  \
 176}                                                                       \
 177static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val,    \
 178                                                        u32 off)        \
 179{                                                                       \
 180        spin_lock(&priv->indir_lock);                                   \
 181        reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE);       \
 182        __raw_writel(lower_32_bits(val), priv->name + off);             \
 183        spin_unlock(&priv->indir_lock);                                 \
 184}
 185
 186#define SWITCH_INTR_L2(which)                                           \
 187static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \
 188                                                u32 mask)               \
 189{                                                                       \
 190        intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR);     \
 191        priv->irq##which##_mask &= ~(mask);                             \
 192}                                                                       \
 193static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \
 194                                                u32 mask)               \
 195{                                                                       \
 196        intrl2_## which##_writel(priv, mask, INTRL2_CPU_MASK_SET);      \
 197        priv->irq##which##_mask |= (mask);                              \
 198}                                                                       \
 199
 200SF2_IO_MACRO(core);
 201SF2_IO_MACRO(reg);
 202SF2_IO64_MACRO(core);
 203SF2_IO_MACRO(intrl2_0);
 204SF2_IO_MACRO(intrl2_1);
 205SF2_IO_MACRO(fcb);
 206SF2_IO_MACRO(acb);
 207
 208SWITCH_INTR_L2(0);
 209SWITCH_INTR_L2(1);
 210
 211#endif /* __BCM_SF2_H */
 212