18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _SPARC64_VIO_H
38c2ecf20Sopenharmony_ci#define _SPARC64_VIO_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/kernel.h>
68c2ecf20Sopenharmony_ci#include <linux/device.h>
78c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
88c2ecf20Sopenharmony_ci#include <linux/timer.h>
98c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
108c2ecf20Sopenharmony_ci#include <linux/completion.h>
118c2ecf20Sopenharmony_ci#include <linux/list.h>
128c2ecf20Sopenharmony_ci#include <linux/log2.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <asm/ldc.h>
158c2ecf20Sopenharmony_ci#include <asm/mdesc.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct vio_msg_tag {
188c2ecf20Sopenharmony_ci	u8			type;
198c2ecf20Sopenharmony_ci#define VIO_TYPE_CTRL		0x01
208c2ecf20Sopenharmony_ci#define VIO_TYPE_DATA		0x02
218c2ecf20Sopenharmony_ci#define VIO_TYPE_ERR		0x04
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	u8			stype;
248c2ecf20Sopenharmony_ci#define VIO_SUBTYPE_INFO	0x01
258c2ecf20Sopenharmony_ci#define VIO_SUBTYPE_ACK		0x02
268c2ecf20Sopenharmony_ci#define VIO_SUBTYPE_NACK	0x04
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	u16			stype_env;
298c2ecf20Sopenharmony_ci#define VIO_VER_INFO		0x0001
308c2ecf20Sopenharmony_ci#define VIO_ATTR_INFO		0x0002
318c2ecf20Sopenharmony_ci#define VIO_DRING_REG		0x0003
328c2ecf20Sopenharmony_ci#define VIO_DRING_UNREG		0x0004
338c2ecf20Sopenharmony_ci#define VIO_RDX			0x0005
348c2ecf20Sopenharmony_ci#define VIO_PKT_DATA		0x0040
358c2ecf20Sopenharmony_ci#define VIO_DESC_DATA		0x0041
368c2ecf20Sopenharmony_ci#define VIO_DRING_DATA		0x0042
378c2ecf20Sopenharmony_ci#define VNET_MCAST_INFO		0x0101
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	u32		sid;
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistruct vio_rdx {
438c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
448c2ecf20Sopenharmony_ci	u64			resv[6];
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistruct vio_ver_info {
488c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
498c2ecf20Sopenharmony_ci	u16			major;
508c2ecf20Sopenharmony_ci	u16			minor;
518c2ecf20Sopenharmony_ci	u8			dev_class;
528c2ecf20Sopenharmony_ci#define VDEV_NETWORK		0x01
538c2ecf20Sopenharmony_ci#define VDEV_NETWORK_SWITCH	0x02
548c2ecf20Sopenharmony_ci#define VDEV_DISK		0x03
558c2ecf20Sopenharmony_ci#define VDEV_DISK_SERVER	0x04
568c2ecf20Sopenharmony_ci#define VDEV_CONSOLE_CON	0x05
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	u8			resv1[3];
598c2ecf20Sopenharmony_ci	u64			resv2[5];
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistruct vio_dring_register {
638c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
648c2ecf20Sopenharmony_ci	u64			dring_ident;
658c2ecf20Sopenharmony_ci	u32			num_descr;
668c2ecf20Sopenharmony_ci	u32			descr_size;
678c2ecf20Sopenharmony_ci	u16			options;
688c2ecf20Sopenharmony_ci#define VIO_TX_DRING		0x0001
698c2ecf20Sopenharmony_ci#define VIO_RX_DRING		0x0002
708c2ecf20Sopenharmony_ci#define VIO_RX_DRING_DATA	0x0004
718c2ecf20Sopenharmony_ci	u16			resv;
728c2ecf20Sopenharmony_ci	u32			num_cookies;
738c2ecf20Sopenharmony_ci	struct ldc_trans_cookie	cookies[0];
748c2ecf20Sopenharmony_ci};
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistruct vio_dring_unregister {
778c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
788c2ecf20Sopenharmony_ci	u64			dring_ident;
798c2ecf20Sopenharmony_ci	u64			resv[5];
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/* Data transfer modes */
838c2ecf20Sopenharmony_ci#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
848c2ecf20Sopenharmony_ci#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
858c2ecf20Sopenharmony_ci#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
868c2ecf20Sopenharmony_ci/* in vers >= 1.2, VIO_DRING_MODE is 0x04 and transfer mode is a bitmask */
878c2ecf20Sopenharmony_ci#define VIO_NEW_DRING_MODE	0x04
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistruct vio_dring_data {
908c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
918c2ecf20Sopenharmony_ci	u64			seq;
928c2ecf20Sopenharmony_ci	u64			dring_ident;
938c2ecf20Sopenharmony_ci	u32			start_idx;
948c2ecf20Sopenharmony_ci	u32			end_idx;
958c2ecf20Sopenharmony_ci	u8			state;
968c2ecf20Sopenharmony_ci#define VIO_DRING_ACTIVE	0x01
978c2ecf20Sopenharmony_ci#define VIO_DRING_STOPPED	0x02
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	u8			__pad1;
1008c2ecf20Sopenharmony_ci	u16			__pad2;
1018c2ecf20Sopenharmony_ci	u32			__pad3;
1028c2ecf20Sopenharmony_ci	u64			__par4[2];
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct vio_dring_hdr {
1068c2ecf20Sopenharmony_ci	u8			state;
1078c2ecf20Sopenharmony_ci#define VIO_DESC_FREE		0x01
1088c2ecf20Sopenharmony_ci#define VIO_DESC_READY		0x02
1098c2ecf20Sopenharmony_ci#define VIO_DESC_ACCEPTED	0x03
1108c2ecf20Sopenharmony_ci#define VIO_DESC_DONE		0x04
1118c2ecf20Sopenharmony_ci	u8			ack;
1128c2ecf20Sopenharmony_ci#define VIO_ACK_ENABLE		0x01
1138c2ecf20Sopenharmony_ci#define VIO_ACK_DISABLE		0x00
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	u16			__pad1;
1168c2ecf20Sopenharmony_ci	u32			__pad2;
1178c2ecf20Sopenharmony_ci};
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/* VIO disk specific structures and defines */
1208c2ecf20Sopenharmony_cistruct vio_disk_attr_info {
1218c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
1228c2ecf20Sopenharmony_ci	u8			xfer_mode;
1238c2ecf20Sopenharmony_ci	u8			vdisk_type;
1248c2ecf20Sopenharmony_ci#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
1258c2ecf20Sopenharmony_ci#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
1268c2ecf20Sopenharmony_ci	u8			vdisk_mtype;		/* v1.1 */
1278c2ecf20Sopenharmony_ci#define VD_MEDIA_TYPE_FIXED	0x01 /* Fixed device */
1288c2ecf20Sopenharmony_ci#define VD_MEDIA_TYPE_CD	0x02 /* CD Device    */
1298c2ecf20Sopenharmony_ci#define VD_MEDIA_TYPE_DVD	0x03 /* DVD Device   */
1308c2ecf20Sopenharmony_ci	u8			resv1;
1318c2ecf20Sopenharmony_ci	u32			vdisk_block_size;
1328c2ecf20Sopenharmony_ci	u64			operations;
1338c2ecf20Sopenharmony_ci	u64			vdisk_size;		/* v1.1 */
1348c2ecf20Sopenharmony_ci	u64			max_xfer_size;
1358c2ecf20Sopenharmony_ci	u32			phys_block_size;	/* v1.2 */
1368c2ecf20Sopenharmony_ci	u32			resv2;
1378c2ecf20Sopenharmony_ci	u64			resv3[1];
1388c2ecf20Sopenharmony_ci};
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistruct vio_disk_desc {
1418c2ecf20Sopenharmony_ci	struct vio_dring_hdr	hdr;
1428c2ecf20Sopenharmony_ci	u64			req_id;
1438c2ecf20Sopenharmony_ci	u8			operation;
1448c2ecf20Sopenharmony_ci#define VD_OP_BREAD		0x01 /* Block read			*/
1458c2ecf20Sopenharmony_ci#define VD_OP_BWRITE		0x02 /* Block write			*/
1468c2ecf20Sopenharmony_ci#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
1478c2ecf20Sopenharmony_ci#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
1488c2ecf20Sopenharmony_ci#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
1498c2ecf20Sopenharmony_ci#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
1508c2ecf20Sopenharmony_ci#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
1518c2ecf20Sopenharmony_ci#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
1528c2ecf20Sopenharmony_ci#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
1538c2ecf20Sopenharmony_ci#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
1548c2ecf20Sopenharmony_ci#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
1558c2ecf20Sopenharmony_ci#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
1568c2ecf20Sopenharmony_ci#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
1578c2ecf20Sopenharmony_ci	u8			slice;
1588c2ecf20Sopenharmony_ci	u16			resv1;
1598c2ecf20Sopenharmony_ci	u32			status;
1608c2ecf20Sopenharmony_ci	u64			offset;
1618c2ecf20Sopenharmony_ci	u64			size;
1628c2ecf20Sopenharmony_ci	u32			ncookies;
1638c2ecf20Sopenharmony_ci	u32			resv2;
1648c2ecf20Sopenharmony_ci	struct ldc_trans_cookie	cookies[0];
1658c2ecf20Sopenharmony_ci};
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#define VIO_DISK_VNAME_LEN	8
1688c2ecf20Sopenharmony_ci#define VIO_DISK_ALABEL_LEN	128
1698c2ecf20Sopenharmony_ci#define VIO_DISK_NUM_PART	8
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistruct vio_disk_vtoc {
1728c2ecf20Sopenharmony_ci	u8			volume_name[VIO_DISK_VNAME_LEN];
1738c2ecf20Sopenharmony_ci	u16			sector_size;
1748c2ecf20Sopenharmony_ci	u16			num_partitions;
1758c2ecf20Sopenharmony_ci	u8			ascii_label[VIO_DISK_ALABEL_LEN];
1768c2ecf20Sopenharmony_ci	struct {
1778c2ecf20Sopenharmony_ci		u16		id;
1788c2ecf20Sopenharmony_ci		u16		perm_flags;
1798c2ecf20Sopenharmony_ci		u32		resv;
1808c2ecf20Sopenharmony_ci		u64		start_block;
1818c2ecf20Sopenharmony_ci		u64		num_blocks;
1828c2ecf20Sopenharmony_ci	} partitions[VIO_DISK_NUM_PART];
1838c2ecf20Sopenharmony_ci};
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistruct vio_disk_geom {
1868c2ecf20Sopenharmony_ci	u16			num_cyl; /* Num data cylinders		*/
1878c2ecf20Sopenharmony_ci	u16			alt_cyl; /* Num alternate cylinders	*/
1888c2ecf20Sopenharmony_ci	u16			beg_cyl; /* Cyl off of fixed head area	*/
1898c2ecf20Sopenharmony_ci	u16			num_hd;  /* Num heads			*/
1908c2ecf20Sopenharmony_ci	u16			num_sec; /* Num sectors			*/
1918c2ecf20Sopenharmony_ci	u16			ifact;   /* Interleave factor		*/
1928c2ecf20Sopenharmony_ci	u16			apc;     /* Alts per cylinder (SCSI)	*/
1938c2ecf20Sopenharmony_ci	u16			rpm;	 /* Revolutions per minute	*/
1948c2ecf20Sopenharmony_ci	u16			phy_cyl; /* Num physical cylinders	*/
1958c2ecf20Sopenharmony_ci	u16			wr_skip; /* Num sects to skip, writes	*/
1968c2ecf20Sopenharmony_ci	u16			rd_skip; /* Num sects to skip, writes	*/
1978c2ecf20Sopenharmony_ci};
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistruct vio_disk_devid {
2008c2ecf20Sopenharmony_ci	u16			resv;
2018c2ecf20Sopenharmony_ci	u16			type;
2028c2ecf20Sopenharmony_ci	u32			len;
2038c2ecf20Sopenharmony_ci	char			id[0];
2048c2ecf20Sopenharmony_ci};
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistruct vio_disk_efi {
2078c2ecf20Sopenharmony_ci	u64			lba;
2088c2ecf20Sopenharmony_ci	u64			len;
2098c2ecf20Sopenharmony_ci	char			data[0];
2108c2ecf20Sopenharmony_ci};
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci/* VIO net specific structures and defines */
2138c2ecf20Sopenharmony_cistruct vio_net_attr_info {
2148c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
2158c2ecf20Sopenharmony_ci	u8			xfer_mode;
2168c2ecf20Sopenharmony_ci	u8			addr_type;
2178c2ecf20Sopenharmony_ci#define VNET_ADDR_ETHERMAC	0x01
2188c2ecf20Sopenharmony_ci	u16			ack_freq;
2198c2ecf20Sopenharmony_ci	u8			plnk_updt;
2208c2ecf20Sopenharmony_ci#define PHYSLINK_UPDATE_NONE		0x00
2218c2ecf20Sopenharmony_ci#define PHYSLINK_UPDATE_STATE		0x01
2228c2ecf20Sopenharmony_ci#define PHYSLINK_UPDATE_STATE_ACK	0x02
2238c2ecf20Sopenharmony_ci#define PHYSLINK_UPDATE_STATE_NACK	0x03
2248c2ecf20Sopenharmony_ci	u8			options;
2258c2ecf20Sopenharmony_ci	u16			resv1;
2268c2ecf20Sopenharmony_ci	u64			addr;
2278c2ecf20Sopenharmony_ci	u64			mtu;
2288c2ecf20Sopenharmony_ci	u16			cflags;
2298c2ecf20Sopenharmony_ci#define VNET_LSO_IPV4_CAPAB		0x0001
2308c2ecf20Sopenharmony_ci	u16			ipv4_lso_maxlen;
2318c2ecf20Sopenharmony_ci	u32			resv2;
2328c2ecf20Sopenharmony_ci	u64			resv3[2];
2338c2ecf20Sopenharmony_ci};
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci#define VNET_NUM_MCAST		7
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistruct vio_net_mcast_info {
2388c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
2398c2ecf20Sopenharmony_ci	u8			set;
2408c2ecf20Sopenharmony_ci	u8			count;
2418c2ecf20Sopenharmony_ci	u8			mcast_addr[VNET_NUM_MCAST * 6];
2428c2ecf20Sopenharmony_ci	u32			resv;
2438c2ecf20Sopenharmony_ci};
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistruct vio_net_desc {
2468c2ecf20Sopenharmony_ci	struct vio_dring_hdr	hdr;
2478c2ecf20Sopenharmony_ci	u32			size;
2488c2ecf20Sopenharmony_ci	u32			ncookies;
2498c2ecf20Sopenharmony_ci	struct ldc_trans_cookie	cookies[0];
2508c2ecf20Sopenharmony_ci};
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistruct vio_net_dext {
2538c2ecf20Sopenharmony_ci	u8		flags;
2548c2ecf20Sopenharmony_ci#define VNET_PKT_HASH			0x01
2558c2ecf20Sopenharmony_ci#define	VNET_PKT_HCK_IPV4_HDRCKSUM	0x02
2568c2ecf20Sopenharmony_ci#define	VNET_PKT_HCK_FULLCKSUM		0x04
2578c2ecf20Sopenharmony_ci#define	VNET_PKT_IPV4_LSO		0x08
2588c2ecf20Sopenharmony_ci#define	VNET_PKT_HCK_IPV4_HDRCKSUM_OK	0x10
2598c2ecf20Sopenharmony_ci#define	VNET_PKT_HCK_FULLCKSUM_OK	0x20
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	u8		vnet_hashval;
2628c2ecf20Sopenharmony_ci	u16		ipv4_lso_mss;
2638c2ecf20Sopenharmony_ci	u32		resv3;
2648c2ecf20Sopenharmony_ci};
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic inline struct vio_net_dext *vio_net_ext(struct vio_net_desc *desc)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	return (struct vio_net_dext *)&desc->cookies[2];
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci#define VIO_MAX_RING_COOKIES	24
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistruct vio_dring_state {
2748c2ecf20Sopenharmony_ci	u64			ident;
2758c2ecf20Sopenharmony_ci	void			*base;
2768c2ecf20Sopenharmony_ci	u64			snd_nxt;
2778c2ecf20Sopenharmony_ci	u64			rcv_nxt;
2788c2ecf20Sopenharmony_ci	u32			entry_size;
2798c2ecf20Sopenharmony_ci	u32			num_entries;
2808c2ecf20Sopenharmony_ci	u32			prod;
2818c2ecf20Sopenharmony_ci	u32			cons;
2828c2ecf20Sopenharmony_ci	u32			pending;
2838c2ecf20Sopenharmony_ci	int			ncookies;
2848c2ecf20Sopenharmony_ci	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
2858c2ecf20Sopenharmony_ci};
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci#define VIO_TAG_SIZE		((int)sizeof(struct vio_msg_tag))
2888c2ecf20Sopenharmony_ci#define VIO_VCC_MTU_SIZE	(LDC_PACKET_SIZE - VIO_TAG_SIZE)
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistruct vio_vcc {
2918c2ecf20Sopenharmony_ci	struct vio_msg_tag	tag;
2928c2ecf20Sopenharmony_ci	char			data[VIO_VCC_MTU_SIZE];
2938c2ecf20Sopenharmony_ci};
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic inline void *vio_dring_cur(struct vio_dring_state *dr)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	return dr->base + (dr->entry_size * dr->prod);
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic inline void *vio_dring_entry(struct vio_dring_state *dr,
3018c2ecf20Sopenharmony_ci				    unsigned int index)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	return dr->base + (dr->entry_size * index);
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic inline u32 vio_dring_avail(struct vio_dring_state *dr,
3078c2ecf20Sopenharmony_ci				  unsigned int ring_size)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	return (dr->pending -
3108c2ecf20Sopenharmony_ci		((dr->prod - dr->cons) & (ring_size - 1)) - 1);
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic inline u32 vio_dring_next(struct vio_dring_state *dr, u32 index)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	if (++index == dr->num_entries)
3168c2ecf20Sopenharmony_ci		index = 0;
3178c2ecf20Sopenharmony_ci	return index;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic inline u32 vio_dring_prev(struct vio_dring_state *dr, u32 index)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	if (index == 0)
3238c2ecf20Sopenharmony_ci		return dr->num_entries - 1;
3248c2ecf20Sopenharmony_ci	else
3258c2ecf20Sopenharmony_ci		return index - 1;
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci#define VIO_MAX_TYPE_LEN	32
3298c2ecf20Sopenharmony_ci#define VIO_MAX_NAME_LEN	32
3308c2ecf20Sopenharmony_ci#define VIO_MAX_COMPAT_LEN	64
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistruct vio_dev {
3338c2ecf20Sopenharmony_ci	u64			mp;
3348c2ecf20Sopenharmony_ci	struct device_node	*dp;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	char			node_name[VIO_MAX_NAME_LEN];
3378c2ecf20Sopenharmony_ci	char			type[VIO_MAX_TYPE_LEN];
3388c2ecf20Sopenharmony_ci	char			compat[VIO_MAX_COMPAT_LEN];
3398c2ecf20Sopenharmony_ci	int			compat_len;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	u64			dev_no;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	unsigned long		port_id;
3448c2ecf20Sopenharmony_ci	unsigned long		channel_id;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	unsigned int		tx_irq;
3478c2ecf20Sopenharmony_ci	unsigned int		rx_irq;
3488c2ecf20Sopenharmony_ci	u64			rx_ino;
3498c2ecf20Sopenharmony_ci	u64			tx_ino;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* Handle to the root of "channel-devices" sub-tree in MDESC */
3528c2ecf20Sopenharmony_ci	u64			cdev_handle;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	/* MD specific data used to identify the vdev in MD */
3558c2ecf20Sopenharmony_ci	union md_node_info	md_node_info;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	struct device		dev;
3588c2ecf20Sopenharmony_ci};
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistruct vio_driver {
3618c2ecf20Sopenharmony_ci	const char			*name;
3628c2ecf20Sopenharmony_ci	struct list_head		node;
3638c2ecf20Sopenharmony_ci	const struct vio_device_id	*id_table;
3648c2ecf20Sopenharmony_ci	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
3658c2ecf20Sopenharmony_ci	int (*remove)(struct vio_dev *dev);
3668c2ecf20Sopenharmony_ci	void (*shutdown)(struct vio_dev *dev);
3678c2ecf20Sopenharmony_ci	unsigned long			driver_data;
3688c2ecf20Sopenharmony_ci	struct device_driver		driver;
3698c2ecf20Sopenharmony_ci	bool				no_irq;
3708c2ecf20Sopenharmony_ci};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistruct vio_version {
3738c2ecf20Sopenharmony_ci	u16		major;
3748c2ecf20Sopenharmony_ci	u16		minor;
3758c2ecf20Sopenharmony_ci};
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_cistruct vio_driver_state;
3788c2ecf20Sopenharmony_cistruct vio_driver_ops {
3798c2ecf20Sopenharmony_ci	int	(*send_attr)(struct vio_driver_state *vio);
3808c2ecf20Sopenharmony_ci	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
3818c2ecf20Sopenharmony_ci	void	(*handshake_complete)(struct vio_driver_state *vio);
3828c2ecf20Sopenharmony_ci};
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistruct vio_completion {
3858c2ecf20Sopenharmony_ci	struct completion	com;
3868c2ecf20Sopenharmony_ci	int			err;
3878c2ecf20Sopenharmony_ci	int			waiting_for;
3888c2ecf20Sopenharmony_ci};
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistruct vio_driver_state {
3918c2ecf20Sopenharmony_ci	/* Protects VIO handshake and, optionally, driver private state.  */
3928c2ecf20Sopenharmony_ci	spinlock_t		lock;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	struct ldc_channel	*lp;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	u32			_peer_sid;
3978c2ecf20Sopenharmony_ci	u32			_local_sid;
3988c2ecf20Sopenharmony_ci	struct vio_dring_state	drings[2];
3998c2ecf20Sopenharmony_ci#define VIO_DRIVER_TX_RING	0
4008c2ecf20Sopenharmony_ci#define VIO_DRIVER_RX_RING	1
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	u8			hs_state;
4038c2ecf20Sopenharmony_ci#define VIO_HS_INVALID		0x00
4048c2ecf20Sopenharmony_ci#define VIO_HS_GOTVERS		0x01
4058c2ecf20Sopenharmony_ci#define VIO_HS_GOT_ATTR		0x04
4068c2ecf20Sopenharmony_ci#define VIO_HS_SENT_DREG	0x08
4078c2ecf20Sopenharmony_ci#define VIO_HS_SENT_RDX		0x10
4088c2ecf20Sopenharmony_ci#define VIO_HS_GOT_RDX_ACK	0x20
4098c2ecf20Sopenharmony_ci#define VIO_HS_GOT_RDX		0x40
4108c2ecf20Sopenharmony_ci#define VIO_HS_SENT_RDX_ACK	0x80
4118c2ecf20Sopenharmony_ci#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	u8			dev_class;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	u8			dr_state;
4168c2ecf20Sopenharmony_ci#define VIO_DR_STATE_TXREG	0x01
4178c2ecf20Sopenharmony_ci#define VIO_DR_STATE_RXREG	0x02
4188c2ecf20Sopenharmony_ci#define VIO_DR_STATE_TXREQ	0x10
4198c2ecf20Sopenharmony_ci#define VIO_DR_STATE_RXREQ	0x20
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	u8			debug;
4228c2ecf20Sopenharmony_ci#define VIO_DEBUG_HS		0x01
4238c2ecf20Sopenharmony_ci#define VIO_DEBUG_DATA		0x02
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	void			*desc_buf;
4268c2ecf20Sopenharmony_ci	unsigned int		desc_buf_len;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	struct vio_completion	*cmp;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	struct vio_dev		*vdev;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	struct timer_list	timer;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	struct vio_version	ver;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	struct vio_version	*ver_table;
4378c2ecf20Sopenharmony_ci	int			ver_table_entries;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	char			*name;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	struct vio_driver_ops	*ops;
4428c2ecf20Sopenharmony_ci};
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic inline bool vio_version_before(struct vio_driver_state *vio,
4458c2ecf20Sopenharmony_ci				      u16 major, u16 minor)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
4488c2ecf20Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	return have < want;
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistatic inline bool vio_version_after(struct vio_driver_state *vio,
4548c2ecf20Sopenharmony_ci				      u16 major, u16 minor)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
4578c2ecf20Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	return have > want;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic inline bool vio_version_after_eq(struct vio_driver_state *vio,
4638c2ecf20Sopenharmony_ci					u16 major, u16 minor)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
4668c2ecf20Sopenharmony_ci	u32 want = (u32)major << 16 | minor;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	return have >= want;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci#define viodbg(TYPE, f, a...) \
4728c2ecf20Sopenharmony_cido {	if (vio->debug & VIO_DEBUG_##TYPE) \
4738c2ecf20Sopenharmony_ci		printk(KERN_INFO "vio: ID[%lu] " f, \
4748c2ecf20Sopenharmony_ci		       vio->vdev->channel_id, ## a); \
4758c2ecf20Sopenharmony_ci} while (0)
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ciint __vio_register_driver(struct vio_driver *drv, struct module *owner,
4788c2ecf20Sopenharmony_ci				 const char *mod_name);
4798c2ecf20Sopenharmony_ci/*
4808c2ecf20Sopenharmony_ci * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
4818c2ecf20Sopenharmony_ci */
4828c2ecf20Sopenharmony_ci#define vio_register_driver(driver)		\
4838c2ecf20Sopenharmony_ci	__vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
4848c2ecf20Sopenharmony_civoid vio_unregister_driver(struct vio_driver *drv);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic inline struct vio_driver *to_vio_driver(struct device_driver *drv)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	return container_of(drv, struct vio_driver, driver);
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic inline struct vio_dev *to_vio_dev(struct device *dev)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	return container_of(dev, struct vio_dev, dev);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ciint vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
4978c2ecf20Sopenharmony_civoid vio_link_state_change(struct vio_driver_state *vio, int event);
4988c2ecf20Sopenharmony_civoid vio_conn_reset(struct vio_driver_state *vio);
4998c2ecf20Sopenharmony_ciint vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
5008c2ecf20Sopenharmony_ciint vio_validate_sid(struct vio_driver_state *vio,
5018c2ecf20Sopenharmony_ci		     struct vio_msg_tag *tp);
5028c2ecf20Sopenharmony_ciu32 vio_send_sid(struct vio_driver_state *vio);
5038c2ecf20Sopenharmony_ciint vio_ldc_alloc(struct vio_driver_state *vio,
5048c2ecf20Sopenharmony_ci		  struct ldc_channel_config *base_cfg, void *event_arg);
5058c2ecf20Sopenharmony_civoid vio_ldc_free(struct vio_driver_state *vio);
5068c2ecf20Sopenharmony_ciint vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
5078c2ecf20Sopenharmony_ci		    u8 dev_class, struct vio_version *ver_table,
5088c2ecf20Sopenharmony_ci		    int ver_table_size, struct vio_driver_ops *ops,
5098c2ecf20Sopenharmony_ci		    char *name);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_civoid vio_port_up(struct vio_driver_state *vio);
5128c2ecf20Sopenharmony_ciint vio_set_intr(unsigned long dev_ino, int state);
5138c2ecf20Sopenharmony_ciu64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci#endif /* _SPARC64_VIO_H */
516