18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
28c2ecf20Sopenharmony_ci/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifndef _PRESTERA_H_
58c2ecf20Sopenharmony_ci#define _PRESTERA_H_
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/notifier.h>
88c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
98c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
108c2ecf20Sopenharmony_ci#include <net/devlink.h>
118c2ecf20Sopenharmony_ci#include <uapi/linux/if_ether.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define PRESTERA_DRV_NAME	"prestera"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define PRESTERA_DEFAULT_VID    1
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct prestera_fw_rev {
188c2ecf20Sopenharmony_ci	u16 maj;
198c2ecf20Sopenharmony_ci	u16 min;
208c2ecf20Sopenharmony_ci	u16 sub;
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistruct prestera_port_stats {
248c2ecf20Sopenharmony_ci	u64 good_octets_received;
258c2ecf20Sopenharmony_ci	u64 bad_octets_received;
268c2ecf20Sopenharmony_ci	u64 mac_trans_error;
278c2ecf20Sopenharmony_ci	u64 broadcast_frames_received;
288c2ecf20Sopenharmony_ci	u64 multicast_frames_received;
298c2ecf20Sopenharmony_ci	u64 frames_64_octets;
308c2ecf20Sopenharmony_ci	u64 frames_65_to_127_octets;
318c2ecf20Sopenharmony_ci	u64 frames_128_to_255_octets;
328c2ecf20Sopenharmony_ci	u64 frames_256_to_511_octets;
338c2ecf20Sopenharmony_ci	u64 frames_512_to_1023_octets;
348c2ecf20Sopenharmony_ci	u64 frames_1024_to_max_octets;
358c2ecf20Sopenharmony_ci	u64 excessive_collision;
368c2ecf20Sopenharmony_ci	u64 multicast_frames_sent;
378c2ecf20Sopenharmony_ci	u64 broadcast_frames_sent;
388c2ecf20Sopenharmony_ci	u64 fc_sent;
398c2ecf20Sopenharmony_ci	u64 fc_received;
408c2ecf20Sopenharmony_ci	u64 buffer_overrun;
418c2ecf20Sopenharmony_ci	u64 undersize;
428c2ecf20Sopenharmony_ci	u64 fragments;
438c2ecf20Sopenharmony_ci	u64 oversize;
448c2ecf20Sopenharmony_ci	u64 jabber;
458c2ecf20Sopenharmony_ci	u64 rx_error_frame_received;
468c2ecf20Sopenharmony_ci	u64 bad_crc;
478c2ecf20Sopenharmony_ci	u64 collisions;
488c2ecf20Sopenharmony_ci	u64 late_collision;
498c2ecf20Sopenharmony_ci	u64 unicast_frames_received;
508c2ecf20Sopenharmony_ci	u64 unicast_frames_sent;
518c2ecf20Sopenharmony_ci	u64 sent_multiple;
528c2ecf20Sopenharmony_ci	u64 sent_deferred;
538c2ecf20Sopenharmony_ci	u64 good_octets_sent;
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistruct prestera_port_caps {
578c2ecf20Sopenharmony_ci	u64 supp_link_modes;
588c2ecf20Sopenharmony_ci	u8 supp_fec;
598c2ecf20Sopenharmony_ci	u8 type;
608c2ecf20Sopenharmony_ci	u8 transceiver;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct prestera_port {
648c2ecf20Sopenharmony_ci	struct net_device *dev;
658c2ecf20Sopenharmony_ci	struct prestera_switch *sw;
668c2ecf20Sopenharmony_ci	struct devlink_port dl_port;
678c2ecf20Sopenharmony_ci	u32 id;
688c2ecf20Sopenharmony_ci	u32 hw_id;
698c2ecf20Sopenharmony_ci	u32 dev_id;
708c2ecf20Sopenharmony_ci	u16 fp_id;
718c2ecf20Sopenharmony_ci	u16 pvid;
728c2ecf20Sopenharmony_ci	bool autoneg;
738c2ecf20Sopenharmony_ci	u64 adver_link_modes;
748c2ecf20Sopenharmony_ci	u8 adver_fec;
758c2ecf20Sopenharmony_ci	struct prestera_port_caps caps;
768c2ecf20Sopenharmony_ci	struct list_head list;
778c2ecf20Sopenharmony_ci	struct list_head vlans_list;
788c2ecf20Sopenharmony_ci	struct {
798c2ecf20Sopenharmony_ci		struct prestera_port_stats stats;
808c2ecf20Sopenharmony_ci		struct delayed_work caching_dw;
818c2ecf20Sopenharmony_ci	} cached_hw_stats;
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistruct prestera_device {
858c2ecf20Sopenharmony_ci	struct device *dev;
868c2ecf20Sopenharmony_ci	u8 __iomem *ctl_regs;
878c2ecf20Sopenharmony_ci	u8 __iomem *pp_regs;
888c2ecf20Sopenharmony_ci	struct prestera_fw_rev fw_rev;
898c2ecf20Sopenharmony_ci	void *priv;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* called by device driver to handle received packets */
928c2ecf20Sopenharmony_ci	void (*recv_pkt)(struct prestera_device *dev);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	/* called by device driver to pass event up to the higher layer */
958c2ecf20Sopenharmony_ci	int (*recv_msg)(struct prestera_device *dev, void *msg, size_t size);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* called by higher layer to send request to the firmware */
988c2ecf20Sopenharmony_ci	int (*send_req)(struct prestera_device *dev, void *in_msg,
998c2ecf20Sopenharmony_ci			size_t in_size, void *out_msg, size_t out_size,
1008c2ecf20Sopenharmony_ci			unsigned int wait);
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cienum prestera_event_type {
1048c2ecf20Sopenharmony_ci	PRESTERA_EVENT_TYPE_UNSPEC,
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	PRESTERA_EVENT_TYPE_PORT,
1078c2ecf20Sopenharmony_ci	PRESTERA_EVENT_TYPE_FDB,
1088c2ecf20Sopenharmony_ci	PRESTERA_EVENT_TYPE_RXTX,
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	PRESTERA_EVENT_TYPE_MAX
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cienum prestera_rxtx_event_id {
1148c2ecf20Sopenharmony_ci	PRESTERA_RXTX_EVENT_UNSPEC,
1158c2ecf20Sopenharmony_ci	PRESTERA_RXTX_EVENT_RCV_PKT,
1168c2ecf20Sopenharmony_ci};
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cienum prestera_port_event_id {
1198c2ecf20Sopenharmony_ci	PRESTERA_PORT_EVENT_UNSPEC,
1208c2ecf20Sopenharmony_ci	PRESTERA_PORT_EVENT_STATE_CHANGED,
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistruct prestera_port_event {
1248c2ecf20Sopenharmony_ci	u32 port_id;
1258c2ecf20Sopenharmony_ci	union {
1268c2ecf20Sopenharmony_ci		u32 oper_state;
1278c2ecf20Sopenharmony_ci	} data;
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cienum prestera_fdb_event_id {
1318c2ecf20Sopenharmony_ci	PRESTERA_FDB_EVENT_UNSPEC,
1328c2ecf20Sopenharmony_ci	PRESTERA_FDB_EVENT_LEARNED,
1338c2ecf20Sopenharmony_ci	PRESTERA_FDB_EVENT_AGED,
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistruct prestera_fdb_event {
1378c2ecf20Sopenharmony_ci	u32 port_id;
1388c2ecf20Sopenharmony_ci	u32 vid;
1398c2ecf20Sopenharmony_ci	union {
1408c2ecf20Sopenharmony_ci		u8 mac[ETH_ALEN];
1418c2ecf20Sopenharmony_ci	} data;
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistruct prestera_event {
1458c2ecf20Sopenharmony_ci	u16 id;
1468c2ecf20Sopenharmony_ci	union {
1478c2ecf20Sopenharmony_ci		struct prestera_port_event port_evt;
1488c2ecf20Sopenharmony_ci		struct prestera_fdb_event fdb_evt;
1498c2ecf20Sopenharmony_ci	};
1508c2ecf20Sopenharmony_ci};
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistruct prestera_switchdev;
1538c2ecf20Sopenharmony_cistruct prestera_rxtx;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistruct prestera_switch {
1568c2ecf20Sopenharmony_ci	struct prestera_device *dev;
1578c2ecf20Sopenharmony_ci	struct prestera_switchdev *swdev;
1588c2ecf20Sopenharmony_ci	struct prestera_rxtx *rxtx;
1598c2ecf20Sopenharmony_ci	struct list_head event_handlers;
1608c2ecf20Sopenharmony_ci	struct notifier_block netdev_nb;
1618c2ecf20Sopenharmony_ci	char base_mac[ETH_ALEN];
1628c2ecf20Sopenharmony_ci	struct list_head port_list;
1638c2ecf20Sopenharmony_ci	rwlock_t port_list_lock;
1648c2ecf20Sopenharmony_ci	u32 port_count;
1658c2ecf20Sopenharmony_ci	u32 mtu_min;
1668c2ecf20Sopenharmony_ci	u32 mtu_max;
1678c2ecf20Sopenharmony_ci	u8 id;
1688c2ecf20Sopenharmony_ci};
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistruct prestera_rxtx_params {
1718c2ecf20Sopenharmony_ci	bool use_sdma;
1728c2ecf20Sopenharmony_ci	u32 map_addr;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci#define prestera_dev(sw)		((sw)->dev->dev)
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic inline void prestera_write(const struct prestera_switch *sw,
1788c2ecf20Sopenharmony_ci				  unsigned int reg, u32 val)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	writel(val, sw->dev->pp_regs + reg);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic inline u32 prestera_read(const struct prestera_switch *sw,
1848c2ecf20Sopenharmony_ci				unsigned int reg)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	return readl(sw->dev->pp_regs + reg);
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciint prestera_device_register(struct prestera_device *dev);
1908c2ecf20Sopenharmony_civoid prestera_device_unregister(struct prestera_device *dev);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistruct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
1938c2ecf20Sopenharmony_ci						 u32 dev_id, u32 hw_id);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ciint prestera_port_autoneg_set(struct prestera_port *port, bool enable,
1968c2ecf20Sopenharmony_ci			      u64 adver_link_modes, u8 adver_fec);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistruct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistruct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciint prestera_port_pvid_set(struct prestera_port *port, u16 vid);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cibool prestera_netdev_check(const struct net_device *dev);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci#endif /* _PRESTERA_H_ */
207