diff options
Diffstat (limited to 'drivers/net/dsa/microchip/ksz_common.h')
| -rw-r--r-- | drivers/net/dsa/microchip/ksz_common.h | 177 | 
1 files changed, 175 insertions, 2 deletions
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 72ec250b9540..dd60d0837fc6 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -7,9 +7,152 @@  #ifndef __KSZ_COMMON_H  #define __KSZ_COMMON_H +#include <linux/etherdevice.h> +#include <linux/kernel.h> +#include <linux/mutex.h> +#include <linux/phy.h>  #include <linux/regmap.h> +#include <net/dsa.h> + +struct vlan_table { +	u32 table[3]; +}; + +struct ksz_port_mib { +	struct mutex cnt_mutex;		/* structure access */ +	u8 cnt_ptr; +	u64 *counters; +}; + +struct ksz_port { +	u16 member; +	u16 vid_member; +	int stp_state; +	struct phy_device phydev; + +	u32 on:1;			/* port is not disabled by hardware */ +	u32 phy:1;			/* port has a PHY */ +	u32 fiber:1;			/* port is fiber */ +	u32 sgmii:1;			/* port is SGMII */ +	u32 force:1; +	u32 read:1;			/* read MIB counters in background */ +	u32 freeze:1;			/* MIB counter freeze is enabled */ + +	struct ksz_port_mib mib; +}; + +struct ksz_device { +	struct dsa_switch *ds; +	struct ksz_platform_data *pdata; +	const char *name; + +	struct mutex dev_mutex;		/* device access */ +	struct mutex stats_mutex;	/* status access */ +	struct mutex alu_mutex;		/* ALU access */ +	struct mutex vlan_mutex;	/* vlan access */ +	const struct ksz_dev_ops *dev_ops; + +	struct device *dev; +	struct regmap *regmap[3]; + +	void *priv; + +	struct gpio_desc *reset_gpio;	/* Optional reset GPIO */ + +	/* chip specific data */ +	u32 chip_id; +	int num_vlans; +	int num_alus; +	int num_statics; +	int cpu_port;			/* port connected to CPU */ +	int cpu_ports;			/* port bitmap can be cpu port */ +	int phy_port_cnt; +	int port_cnt; +	int reg_mib_cnt; +	int mib_cnt; +	int mib_port_cnt; +	int last_port;			/* ports after that not used */ +	phy_interface_t interface; +	u32 regs_size; +	bool phy_errata_9477; +	bool synclko_125; + +	struct vlan_table *vlan_cache; + +	struct ksz_port *ports; +	struct timer_list mib_read_timer; +	struct work_struct mib_read; +	unsigned long mib_read_interval; +	u16 br_member; +	u16 member; +	u16 live_ports; +	u16 on_ports;			/* ports enabled by DSA */ +	u16 rx_ports; +	u16 tx_ports; +	u16 mirror_rx; +	u16 mirror_tx; +	u32 features;			/* chip specific features */ +	u32 overrides;			/* chip functions set by user */ +	u16 host_mask; +	u16 port_mask; +}; + +struct alu_struct { +	/* entry 1 */ +	u8	is_static:1; +	u8	is_src_filter:1; +	u8	is_dst_filter:1; +	u8	prio_age:3; +	u32	_reserv_0_1:23; +	u8	mstp:3; +	/* entry 2 */ +	u8	is_override:1; +	u8	is_use_fid:1; +	u32	_reserv_1_1:23; +	u8	port_forward:7; +	/* entry 3 & 4*/ +	u32	_reserv_2_1:9; +	u8	fid:7; +	u8	mac[ETH_ALEN]; +}; + +struct ksz_dev_ops { +	u32 (*get_port_addr)(int port, int offset); +	void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); +	void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); +	void (*phy_setup)(struct ksz_device *dev, int port, +			  struct phy_device *phy); +	void (*port_cleanup)(struct ksz_device *dev, int port); +	void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); +	void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); +	void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); +	int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr, +			       u8 *fid, u8 *src_port, u8 *timestamp, +			       u16 *entries); +	int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr, +			       struct alu_struct *alu); +	void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr, +				struct alu_struct *alu); +	void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr, +			  u64 *cnt); +	void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, +			  u64 *dropped, u64 *cnt); +	void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); +	void (*port_init_cnt)(struct ksz_device *dev, int port); +	int (*shutdown)(struct ksz_device *dev); +	int (*detect)(struct ksz_device *dev); +	int (*init)(struct ksz_device *dev); +	void (*exit)(struct ksz_device *dev); +}; + +struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); +int ksz_switch_register(struct ksz_device *dev, +			const struct ksz_dev_ops *ops); +void ksz_switch_remove(struct ksz_device *dev); + +int ksz8795_switch_register(struct ksz_device *dev); +int ksz9477_switch_register(struct ksz_device *dev); -void ksz_port_cleanup(struct ksz_device *dev, int port);  void ksz_update_port_member(struct ksz_device *dev, int port);  void ksz_init_mib_timer(struct ksz_device *dev); @@ -68,6 +211,22 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)  	return ret;  } +static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) +{ +	u32 value[2]; +	int ret; + +	ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); +	if (!ret) { +		/* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ +		value[0] = swab32(value[0]); +		value[1] = swab32(value[1]); +		*val = swab64((u64)*value); +	} + +	return ret; +} +  static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)  {  	return regmap_write(dev->regmap[0], reg, value); @@ -83,6 +242,18 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)  	return regmap_write(dev->regmap[2], reg, value);  } +static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) +{ +	u32 val[2]; + +	/* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ +	value = swab64(value); +	val[0] = swab32(value & 0xffffffffULL); +	val[1] = swab32(value >> 32ULL); + +	return regmap_bulk_write(dev->regmap[2], reg, val, 2); +} +  static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,  			      u8 *data)  { @@ -123,6 +294,8 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,  #define KSZ_SPI_OP_RD		3  #define KSZ_SPI_OP_WR		2 +#define swabnot_used(x)		0 +  #define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad)		\  	swab##swp((opcode) << ((regbits) + (regpad))) @@ -130,7 +303,7 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,  	{								\  		.name = #width,						\  		.val_bits = (width),					\ -		.reg_stride = (width) / 8,				\ +		.reg_stride = 1,					\  		.reg_bits = (regbits) + (regalign),			\  		.pad_bits = (regpad),					\  		.max_register = BIT(regbits) - 1,			\  |