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
23#include <net/dsa.h>
24
25#include "bcm_sf2_regs.h"
26
27struct bcm_sf2_hw_params {
28	u16	top_rev;
29	u16	core_rev;
30	u16	gphy_rev;
31	u32	num_gphy;
32	u8	num_acb_queue;
33	u8	num_rgmii;
34	u8	num_ports;
35	u8	fcb_pause_override:1;
36	u8	acb_packets_inflight:1;
37};
38
39#define BCM_SF2_REGS_NAME {\
40	"core", "reg", "intrl2_0", "intrl2_1", "fcb", "acb" \
41}
42
43#define BCM_SF2_REGS_NUM	6
44
45struct bcm_sf2_port_status {
46	unsigned int link;
47
48	struct ethtool_eee eee;
49
50	u32 vlan_ctl_mask;
51};
52
53struct bcm_sf2_priv {
54	/* Base registers, keep those in order with BCM_SF2_REGS_NAME */
55	void __iomem			*core;
56	void __iomem			*reg;
57	void __iomem			*intrl2_0;
58	void __iomem			*intrl2_1;
59	void __iomem			*fcb;
60	void __iomem			*acb;
61
62	/* spinlock protecting access to the indirect registers */
63	spinlock_t			indir_lock;
64
65	int				irq0;
66	int				irq1;
67	u32				irq0_stat;
68	u32				irq0_mask;
69	u32				irq1_stat;
70	u32				irq1_mask;
71
72	/* Mutex protecting access to the MIB counters */
73	struct mutex			stats_mutex;
74
75	struct bcm_sf2_hw_params	hw_params;
76
77	struct bcm_sf2_port_status	port_sts[DSA_MAX_PORTS];
78
79	/* Mask of ports enabled for Wake-on-LAN */
80	u32				wol_ports_mask;
81};
82
83struct bcm_sf2_hw_stats {
84	const char	*string;
85	u16		reg;
86	u8		sizeof_stat;
87};
88
89#define SF2_IO_MACRO(name) \
90static inline u32 name##_readl(struct bcm_sf2_priv *priv, u32 off)	\
91{									\
92	return __raw_readl(priv->name + off);				\
93}									\
94static inline void name##_writel(struct bcm_sf2_priv *priv,		\
95				  u32 val, u32 off)			\
96{									\
97	__raw_writel(val, priv->name + off);				\
98}									\
99
100/* Accesses to 64-bits register requires us to latch the hi/lo pairs
101 * using the REG_DIR_DATA_{READ,WRITE} ancillary registers. The 'indir_lock'
102 * spinlock is automatically grabbed and released to provide relative
103 * atomiticy with latched reads/writes.
104 */
105#define SF2_IO64_MACRO(name) \
106static inline u64 name##_readq(struct bcm_sf2_priv *priv, u32 off)	\
107{									\
108	u32 indir, dir;							\
109	spin_lock(&priv->indir_lock);					\
110	dir = __raw_readl(priv->name + off);				\
111	indir = reg_readl(priv, REG_DIR_DATA_READ);			\
112	spin_unlock(&priv->indir_lock);					\
113	return (u64)indir << 32 | dir;					\
114}									\
115static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val,	\
116							u32 off)	\
117{									\
118	spin_lock(&priv->indir_lock);					\
119	reg_writel(priv, upper_32_bits(val), REG_DIR_DATA_WRITE);	\
120	__raw_writel(lower_32_bits(val), priv->name + off);		\
121	spin_unlock(&priv->indir_lock);					\
122}
123
124#define SWITCH_INTR_L2(which)						\
125static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \
126						u32 mask)		\
127{									\
128	intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR);	\
129	priv->irq##which##_mask &= ~(mask);				\
130}									\
131static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \
132						u32 mask)		\
133{									\
134	intrl2_## which##_writel(priv, mask, INTRL2_CPU_MASK_SET);	\
135	priv->irq##which##_mask |= (mask);				\
136}									\
137
138SF2_IO_MACRO(core);
139SF2_IO_MACRO(reg);
140SF2_IO64_MACRO(core);
141SF2_IO_MACRO(intrl2_0);
142SF2_IO_MACRO(intrl2_1);
143SF2_IO_MACRO(fcb);
144SF2_IO_MACRO(acb);
145
146SWITCH_INTR_L2(0);
147SWITCH_INTR_L2(1);
148
149#endif /* __BCM_SF2_H */
150