xref: /kernel/linux/linux-5.10/drivers/fpga/dfl.h (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver Header File for FPGA Device Feature List (DFL) Support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017-2018 Intel Corporation, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Authors:
88c2ecf20Sopenharmony_ci *   Kang Luwei <luwei.kang@intel.com>
98c2ecf20Sopenharmony_ci *   Zhang Yi <yi.z.zhang@intel.com>
108c2ecf20Sopenharmony_ci *   Wu Hao <hao.wu@intel.com>
118c2ecf20Sopenharmony_ci *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#ifndef __FPGA_DFL_H
158c2ecf20Sopenharmony_ci#define __FPGA_DFL_H
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
188c2ecf20Sopenharmony_ci#include <linux/cdev.h>
198c2ecf20Sopenharmony_ci#include <linux/delay.h>
208c2ecf20Sopenharmony_ci#include <linux/eventfd.h>
218c2ecf20Sopenharmony_ci#include <linux/fs.h>
228c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
238c2ecf20Sopenharmony_ci#include <linux/iopoll.h>
248c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h>
258c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
268c2ecf20Sopenharmony_ci#include <linux/slab.h>
278c2ecf20Sopenharmony_ci#include <linux/uuid.h>
288c2ecf20Sopenharmony_ci#include <linux/fpga/fpga-region.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* maximum supported number of ports */
318c2ecf20Sopenharmony_ci#define MAX_DFL_FPGA_PORT_NUM 4
328c2ecf20Sopenharmony_ci/* plus one for fme device */
338c2ecf20Sopenharmony_ci#define MAX_DFL_FEATURE_DEV_NUM    (MAX_DFL_FPGA_PORT_NUM + 1)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* Reserved 0xfe for Header Group Register and 0xff for AFU */
368c2ecf20Sopenharmony_ci#define FEATURE_ID_FIU_HEADER		0xfe
378c2ecf20Sopenharmony_ci#define FEATURE_ID_AFU			0xff
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_HEADER		FEATURE_ID_FIU_HEADER
408c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_THERMAL_MGMT	0x1
418c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_POWER_MGMT	0x2
428c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_GLOBAL_IPERF	0x3
438c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_GLOBAL_ERR	0x4
448c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_PR_MGMT		0x5
458c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_HSSI		0x6
468c2ecf20Sopenharmony_ci#define FME_FEATURE_ID_GLOBAL_DPERF	0x7
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_HEADER		FEATURE_ID_FIU_HEADER
498c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_AFU		FEATURE_ID_AFU
508c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_ERROR		0x10
518c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_UMSG		0x11
528c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_UINT		0x12
538c2ecf20Sopenharmony_ci#define PORT_FEATURE_ID_STP		0x13
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/*
568c2ecf20Sopenharmony_ci * Device Feature Header Register Set
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * For FIUs, they all have DFH + GUID + NEXT_AFU as common header registers.
598c2ecf20Sopenharmony_ci * For AFUs, they have DFH + GUID as common header registers.
608c2ecf20Sopenharmony_ci * For private features, they only have DFH register as common header.
618c2ecf20Sopenharmony_ci */
628c2ecf20Sopenharmony_ci#define DFH			0x0
638c2ecf20Sopenharmony_ci#define GUID_L			0x8
648c2ecf20Sopenharmony_ci#define GUID_H			0x10
658c2ecf20Sopenharmony_ci#define NEXT_AFU		0x18
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define DFH_SIZE		0x8
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* Device Feature Header Register Bitfield */
708c2ecf20Sopenharmony_ci#define DFH_ID			GENMASK_ULL(11, 0)	/* Feature ID */
718c2ecf20Sopenharmony_ci#define DFH_ID_FIU_FME		0
728c2ecf20Sopenharmony_ci#define DFH_ID_FIU_PORT		1
738c2ecf20Sopenharmony_ci#define DFH_REVISION		GENMASK_ULL(15, 12)	/* Feature revision */
748c2ecf20Sopenharmony_ci#define DFH_NEXT_HDR_OFST	GENMASK_ULL(39, 16)	/* Offset to next DFH */
758c2ecf20Sopenharmony_ci#define DFH_EOL			BIT_ULL(40)		/* End of list */
768c2ecf20Sopenharmony_ci#define DFH_TYPE		GENMASK_ULL(63, 60)	/* Feature type */
778c2ecf20Sopenharmony_ci#define DFH_TYPE_AFU		1
788c2ecf20Sopenharmony_ci#define DFH_TYPE_PRIVATE	3
798c2ecf20Sopenharmony_ci#define DFH_TYPE_FIU		4
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* Next AFU Register Bitfield */
828c2ecf20Sopenharmony_ci#define NEXT_AFU_NEXT_DFH_OFST	GENMASK_ULL(23, 0)	/* Offset to next AFU */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/* FME Header Register Set */
858c2ecf20Sopenharmony_ci#define FME_HDR_DFH		DFH
868c2ecf20Sopenharmony_ci#define FME_HDR_GUID_L		GUID_L
878c2ecf20Sopenharmony_ci#define FME_HDR_GUID_H		GUID_H
888c2ecf20Sopenharmony_ci#define FME_HDR_NEXT_AFU	NEXT_AFU
898c2ecf20Sopenharmony_ci#define FME_HDR_CAP		0x30
908c2ecf20Sopenharmony_ci#define FME_HDR_PORT_OFST(n)	(0x38 + ((n) * 0x8))
918c2ecf20Sopenharmony_ci#define FME_HDR_BITSTREAM_ID	0x60
928c2ecf20Sopenharmony_ci#define FME_HDR_BITSTREAM_MD	0x68
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/* FME Fab Capability Register Bitfield */
958c2ecf20Sopenharmony_ci#define FME_CAP_FABRIC_VERID	GENMASK_ULL(7, 0)	/* Fabric version ID */
968c2ecf20Sopenharmony_ci#define FME_CAP_SOCKET_ID	BIT_ULL(8)		/* Socket ID */
978c2ecf20Sopenharmony_ci#define FME_CAP_PCIE0_LINK_AVL	BIT_ULL(12)		/* PCIE0 Link */
988c2ecf20Sopenharmony_ci#define FME_CAP_PCIE1_LINK_AVL	BIT_ULL(13)		/* PCIE1 Link */
998c2ecf20Sopenharmony_ci#define FME_CAP_COHR_LINK_AVL	BIT_ULL(14)		/* Coherent Link */
1008c2ecf20Sopenharmony_ci#define FME_CAP_IOMMU_AVL	BIT_ULL(16)		/* IOMMU available */
1018c2ecf20Sopenharmony_ci#define FME_CAP_NUM_PORTS	GENMASK_ULL(19, 17)	/* Number of ports */
1028c2ecf20Sopenharmony_ci#define FME_CAP_ADDR_WIDTH	GENMASK_ULL(29, 24)	/* Address bus width */
1038c2ecf20Sopenharmony_ci#define FME_CAP_CACHE_SIZE	GENMASK_ULL(43, 32)	/* cache size in KB */
1048c2ecf20Sopenharmony_ci#define FME_CAP_CACHE_ASSOC	GENMASK_ULL(47, 44)	/* Associativity */
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/* FME Port Offset Register Bitfield */
1078c2ecf20Sopenharmony_ci/* Offset to port device feature header */
1088c2ecf20Sopenharmony_ci#define FME_PORT_OFST_DFH_OFST	GENMASK_ULL(23, 0)
1098c2ecf20Sopenharmony_ci/* PCI Bar ID for this port */
1108c2ecf20Sopenharmony_ci#define FME_PORT_OFST_BAR_ID	GENMASK_ULL(34, 32)
1118c2ecf20Sopenharmony_ci/* AFU MMIO access permission. 1 - VF, 0 - PF. */
1128c2ecf20Sopenharmony_ci#define FME_PORT_OFST_ACC_CTRL	BIT_ULL(55)
1138c2ecf20Sopenharmony_ci#define FME_PORT_OFST_ACC_PF	0
1148c2ecf20Sopenharmony_ci#define FME_PORT_OFST_ACC_VF	1
1158c2ecf20Sopenharmony_ci#define FME_PORT_OFST_IMP	BIT_ULL(60)
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/* FME Error Capability Register */
1188c2ecf20Sopenharmony_ci#define FME_ERROR_CAP		0x70
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/* FME Error Capability Register Bitfield */
1218c2ecf20Sopenharmony_ci#define FME_ERROR_CAP_SUPP_INT	BIT_ULL(0)		/* Interrupt Support */
1228c2ecf20Sopenharmony_ci#define FME_ERROR_CAP_INT_VECT	GENMASK_ULL(12, 1)	/* Interrupt vector */
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci/* PORT Header Register Set */
1258c2ecf20Sopenharmony_ci#define PORT_HDR_DFH		DFH
1268c2ecf20Sopenharmony_ci#define PORT_HDR_GUID_L		GUID_L
1278c2ecf20Sopenharmony_ci#define PORT_HDR_GUID_H		GUID_H
1288c2ecf20Sopenharmony_ci#define PORT_HDR_NEXT_AFU	NEXT_AFU
1298c2ecf20Sopenharmony_ci#define PORT_HDR_CAP		0x30
1308c2ecf20Sopenharmony_ci#define PORT_HDR_CTRL		0x38
1318c2ecf20Sopenharmony_ci#define PORT_HDR_STS		0x40
1328c2ecf20Sopenharmony_ci#define PORT_HDR_USRCLK_CMD0	0x50
1338c2ecf20Sopenharmony_ci#define PORT_HDR_USRCLK_CMD1	0x58
1348c2ecf20Sopenharmony_ci#define PORT_HDR_USRCLK_STS0	0x60
1358c2ecf20Sopenharmony_ci#define PORT_HDR_USRCLK_STS1	0x68
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci/* Port Capability Register Bitfield */
1388c2ecf20Sopenharmony_ci#define PORT_CAP_PORT_NUM	GENMASK_ULL(1, 0)	/* ID of this port */
1398c2ecf20Sopenharmony_ci#define PORT_CAP_MMIO_SIZE	GENMASK_ULL(23, 8)	/* MMIO size in KB */
1408c2ecf20Sopenharmony_ci#define PORT_CAP_SUPP_INT_NUM	GENMASK_ULL(35, 32)	/* Interrupts num */
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/* Port Control Register Bitfield */
1438c2ecf20Sopenharmony_ci#define PORT_CTRL_SFTRST	BIT_ULL(0)		/* Port soft reset */
1448c2ecf20Sopenharmony_ci/* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/
1458c2ecf20Sopenharmony_ci#define PORT_CTRL_LATENCY	BIT_ULL(2)
1468c2ecf20Sopenharmony_ci#define PORT_CTRL_SFTRST_ACK	BIT_ULL(4)		/* HW ack for reset */
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/* Port Status Register Bitfield */
1498c2ecf20Sopenharmony_ci#define PORT_STS_AP2_EVT	BIT_ULL(13)		/* AP2 event detected */
1508c2ecf20Sopenharmony_ci#define PORT_STS_AP1_EVT	BIT_ULL(12)		/* AP1 event detected */
1518c2ecf20Sopenharmony_ci#define PORT_STS_PWR_STATE	GENMASK_ULL(11, 8)	/* AFU power states */
1528c2ecf20Sopenharmony_ci#define PORT_STS_PWR_STATE_NORM 0
1538c2ecf20Sopenharmony_ci#define PORT_STS_PWR_STATE_AP1	1			/* 50% throttling */
1548c2ecf20Sopenharmony_ci#define PORT_STS_PWR_STATE_AP2	2			/* 90% throttling */
1558c2ecf20Sopenharmony_ci#define PORT_STS_PWR_STATE_AP6	6			/* 100% throttling */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/* Port Error Capability Register */
1588c2ecf20Sopenharmony_ci#define PORT_ERROR_CAP		0x38
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* Port Error Capability Register Bitfield */
1618c2ecf20Sopenharmony_ci#define PORT_ERROR_CAP_SUPP_INT	BIT_ULL(0)		/* Interrupt Support */
1628c2ecf20Sopenharmony_ci#define PORT_ERROR_CAP_INT_VECT	GENMASK_ULL(12, 1)	/* Interrupt vector */
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/* Port Uint Capability Register */
1658c2ecf20Sopenharmony_ci#define PORT_UINT_CAP		0x8
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci/* Port Uint Capability Register Bitfield */
1688c2ecf20Sopenharmony_ci#define PORT_UINT_CAP_INT_NUM	GENMASK_ULL(11, 0)	/* Interrupts num */
1698c2ecf20Sopenharmony_ci#define PORT_UINT_CAP_FST_VECT	GENMASK_ULL(23, 12)	/* First Vector */
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci/**
1728c2ecf20Sopenharmony_ci * struct dfl_fpga_port_ops - port ops
1738c2ecf20Sopenharmony_ci *
1748c2ecf20Sopenharmony_ci * @name: name of this port ops, to match with port platform device.
1758c2ecf20Sopenharmony_ci * @owner: pointer to the module which owns this port ops.
1768c2ecf20Sopenharmony_ci * @node: node to link port ops to global list.
1778c2ecf20Sopenharmony_ci * @get_id: get port id from hardware.
1788c2ecf20Sopenharmony_ci * @enable_set: enable/disable the port.
1798c2ecf20Sopenharmony_ci */
1808c2ecf20Sopenharmony_cistruct dfl_fpga_port_ops {
1818c2ecf20Sopenharmony_ci	const char *name;
1828c2ecf20Sopenharmony_ci	struct module *owner;
1838c2ecf20Sopenharmony_ci	struct list_head node;
1848c2ecf20Sopenharmony_ci	int (*get_id)(struct platform_device *pdev);
1858c2ecf20Sopenharmony_ci	int (*enable_set)(struct platform_device *pdev, bool enable);
1868c2ecf20Sopenharmony_ci};
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_civoid dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops);
1898c2ecf20Sopenharmony_civoid dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops);
1908c2ecf20Sopenharmony_cistruct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev);
1918c2ecf20Sopenharmony_civoid dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops);
1928c2ecf20Sopenharmony_ciint dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/**
1958c2ecf20Sopenharmony_ci * struct dfl_feature_id - dfl private feature id
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * @id: unique dfl private feature id.
1988c2ecf20Sopenharmony_ci */
1998c2ecf20Sopenharmony_cistruct dfl_feature_id {
2008c2ecf20Sopenharmony_ci	u16 id;
2018c2ecf20Sopenharmony_ci};
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci/**
2048c2ecf20Sopenharmony_ci * struct dfl_feature_driver - dfl private feature driver
2058c2ecf20Sopenharmony_ci *
2068c2ecf20Sopenharmony_ci * @id_table: id_table for dfl private features supported by this driver.
2078c2ecf20Sopenharmony_ci * @ops: ops of this dfl private feature driver.
2088c2ecf20Sopenharmony_ci */
2098c2ecf20Sopenharmony_cistruct dfl_feature_driver {
2108c2ecf20Sopenharmony_ci	const struct dfl_feature_id *id_table;
2118c2ecf20Sopenharmony_ci	const struct dfl_feature_ops *ops;
2128c2ecf20Sopenharmony_ci};
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/**
2158c2ecf20Sopenharmony_ci * struct dfl_feature_irq_ctx - dfl private feature interrupt context
2168c2ecf20Sopenharmony_ci *
2178c2ecf20Sopenharmony_ci * @irq: Linux IRQ number of this interrupt.
2188c2ecf20Sopenharmony_ci * @trigger: eventfd context to signal when interrupt happens.
2198c2ecf20Sopenharmony_ci * @name: irq name needed when requesting irq.
2208c2ecf20Sopenharmony_ci */
2218c2ecf20Sopenharmony_cistruct dfl_feature_irq_ctx {
2228c2ecf20Sopenharmony_ci	int irq;
2238c2ecf20Sopenharmony_ci	struct eventfd_ctx *trigger;
2248c2ecf20Sopenharmony_ci	char *name;
2258c2ecf20Sopenharmony_ci};
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci/**
2288c2ecf20Sopenharmony_ci * struct dfl_feature - sub feature of the feature devices
2298c2ecf20Sopenharmony_ci *
2308c2ecf20Sopenharmony_ci * @dev: ptr to pdev of the feature device which has the sub feature.
2318c2ecf20Sopenharmony_ci * @id: sub feature id.
2328c2ecf20Sopenharmony_ci * @resource_index: each sub feature has one mmio resource for its registers.
2338c2ecf20Sopenharmony_ci *		    this index is used to find its mmio resource from the
2348c2ecf20Sopenharmony_ci *		    feature dev (platform device)'s reources.
2358c2ecf20Sopenharmony_ci * @ioaddr: mapped mmio resource address.
2368c2ecf20Sopenharmony_ci * @irq_ctx: interrupt context list.
2378c2ecf20Sopenharmony_ci * @nr_irqs: number of interrupt contexts.
2388c2ecf20Sopenharmony_ci * @ops: ops of this sub feature.
2398c2ecf20Sopenharmony_ci * @ddev: ptr to the dfl device of this sub feature.
2408c2ecf20Sopenharmony_ci * @priv: priv data of this feature.
2418c2ecf20Sopenharmony_ci */
2428c2ecf20Sopenharmony_cistruct dfl_feature {
2438c2ecf20Sopenharmony_ci	struct platform_device *dev;
2448c2ecf20Sopenharmony_ci	u16 id;
2458c2ecf20Sopenharmony_ci	int resource_index;
2468c2ecf20Sopenharmony_ci	void __iomem *ioaddr;
2478c2ecf20Sopenharmony_ci	struct dfl_feature_irq_ctx *irq_ctx;
2488c2ecf20Sopenharmony_ci	unsigned int nr_irqs;
2498c2ecf20Sopenharmony_ci	const struct dfl_feature_ops *ops;
2508c2ecf20Sopenharmony_ci	struct dfl_device *ddev;
2518c2ecf20Sopenharmony_ci	void *priv;
2528c2ecf20Sopenharmony_ci};
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci#define FEATURE_DEV_ID_UNUSED	(-1)
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci/**
2578c2ecf20Sopenharmony_ci * struct dfl_feature_platform_data - platform data for feature devices
2588c2ecf20Sopenharmony_ci *
2598c2ecf20Sopenharmony_ci * @node: node to link feature devs to container device's port_dev_list.
2608c2ecf20Sopenharmony_ci * @lock: mutex to protect platform data.
2618c2ecf20Sopenharmony_ci * @cdev: cdev of feature dev.
2628c2ecf20Sopenharmony_ci * @dev: ptr to platform device linked with this platform data.
2638c2ecf20Sopenharmony_ci * @dfl_cdev: ptr to container device.
2648c2ecf20Sopenharmony_ci * @id: id used for this feature device.
2658c2ecf20Sopenharmony_ci * @disable_count: count for port disable.
2668c2ecf20Sopenharmony_ci * @excl_open: set on feature device exclusive open.
2678c2ecf20Sopenharmony_ci * @open_count: count for feature device open.
2688c2ecf20Sopenharmony_ci * @num: number for sub features.
2698c2ecf20Sopenharmony_ci * @private: ptr to feature dev private data.
2708c2ecf20Sopenharmony_ci * @features: sub features of this feature dev.
2718c2ecf20Sopenharmony_ci */
2728c2ecf20Sopenharmony_cistruct dfl_feature_platform_data {
2738c2ecf20Sopenharmony_ci	struct list_head node;
2748c2ecf20Sopenharmony_ci	struct mutex lock;
2758c2ecf20Sopenharmony_ci	struct cdev cdev;
2768c2ecf20Sopenharmony_ci	struct platform_device *dev;
2778c2ecf20Sopenharmony_ci	struct dfl_fpga_cdev *dfl_cdev;
2788c2ecf20Sopenharmony_ci	int id;
2798c2ecf20Sopenharmony_ci	unsigned int disable_count;
2808c2ecf20Sopenharmony_ci	bool excl_open;
2818c2ecf20Sopenharmony_ci	int open_count;
2828c2ecf20Sopenharmony_ci	void *private;
2838c2ecf20Sopenharmony_ci	int num;
2848c2ecf20Sopenharmony_ci	struct dfl_feature features[];
2858c2ecf20Sopenharmony_ci};
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic inline
2888c2ecf20Sopenharmony_ciint dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata,
2898c2ecf20Sopenharmony_ci			      bool excl)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	if (pdata->excl_open)
2928c2ecf20Sopenharmony_ci		return -EBUSY;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (excl) {
2958c2ecf20Sopenharmony_ci		if (pdata->open_count)
2968c2ecf20Sopenharmony_ci			return -EBUSY;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		pdata->excl_open = true;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci	pdata->open_count++;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	return 0;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic inline
3068c2ecf20Sopenharmony_civoid dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	pdata->excl_open = false;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	if (WARN_ON(pdata->open_count <= 0))
3118c2ecf20Sopenharmony_ci		return;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	pdata->open_count--;
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic inline
3178c2ecf20Sopenharmony_ciint dfl_feature_dev_use_count(struct dfl_feature_platform_data *pdata)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	return pdata->open_count;
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic inline
3238c2ecf20Sopenharmony_civoid dfl_fpga_pdata_set_private(struct dfl_feature_platform_data *pdata,
3248c2ecf20Sopenharmony_ci				void *private)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	pdata->private = private;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic inline
3308c2ecf20Sopenharmony_civoid *dfl_fpga_pdata_get_private(struct dfl_feature_platform_data *pdata)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	return pdata->private;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistruct dfl_feature_ops {
3368c2ecf20Sopenharmony_ci	int (*init)(struct platform_device *pdev, struct dfl_feature *feature);
3378c2ecf20Sopenharmony_ci	void (*uinit)(struct platform_device *pdev,
3388c2ecf20Sopenharmony_ci		      struct dfl_feature *feature);
3398c2ecf20Sopenharmony_ci	long (*ioctl)(struct platform_device *pdev, struct dfl_feature *feature,
3408c2ecf20Sopenharmony_ci		      unsigned int cmd, unsigned long arg);
3418c2ecf20Sopenharmony_ci};
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci#define DFL_FPGA_FEATURE_DEV_FME		"dfl-fme"
3448c2ecf20Sopenharmony_ci#define DFL_FPGA_FEATURE_DEV_PORT		"dfl-port"
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_civoid dfl_fpga_dev_feature_uinit(struct platform_device *pdev);
3478c2ecf20Sopenharmony_ciint dfl_fpga_dev_feature_init(struct platform_device *pdev,
3488c2ecf20Sopenharmony_ci			      struct dfl_feature_driver *feature_drvs);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ciint dfl_fpga_dev_ops_register(struct platform_device *pdev,
3518c2ecf20Sopenharmony_ci			      const struct file_operations *fops,
3528c2ecf20Sopenharmony_ci			      struct module *owner);
3538c2ecf20Sopenharmony_civoid dfl_fpga_dev_ops_unregister(struct platform_device *pdev);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic inline
3568c2ecf20Sopenharmony_cistruct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct dfl_feature_platform_data *pdata;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	pdata = container_of(inode->i_cdev, struct dfl_feature_platform_data,
3618c2ecf20Sopenharmony_ci			     cdev);
3628c2ecf20Sopenharmony_ci	return pdata->dev;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci#define dfl_fpga_dev_for_each_feature(pdata, feature)			    \
3668c2ecf20Sopenharmony_ci	for ((feature) = (pdata)->features;				    \
3678c2ecf20Sopenharmony_ci	   (feature) < (pdata)->features + (pdata)->num; (feature)++)
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic inline
3708c2ecf20Sopenharmony_cistruct dfl_feature *dfl_get_feature_by_id(struct device *dev, u16 id)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
3738c2ecf20Sopenharmony_ci	struct dfl_feature *feature;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	dfl_fpga_dev_for_each_feature(pdata, feature)
3768c2ecf20Sopenharmony_ci		if (feature->id == id)
3778c2ecf20Sopenharmony_ci			return feature;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	return NULL;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic inline
3838c2ecf20Sopenharmony_civoid __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u16 id)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	struct dfl_feature *feature = dfl_get_feature_by_id(dev, id);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	if (feature && feature->ioaddr)
3888c2ecf20Sopenharmony_ci		return feature->ioaddr;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	WARN_ON(1);
3918c2ecf20Sopenharmony_ci	return NULL;
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic inline bool is_dfl_feature_present(struct device *dev, u16 id)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	return !!dfl_get_feature_ioaddr_by_id(dev, id);
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_cistatic inline
4008c2ecf20Sopenharmony_cistruct device *dfl_fpga_pdata_to_parent(struct dfl_feature_platform_data *pdata)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	return pdata->dev->dev.parent->parent;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic inline bool dfl_feature_is_fme(void __iomem *base)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	u64 v = readq(base + DFH);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	return (FIELD_GET(DFH_TYPE, v) == DFH_TYPE_FIU) &&
4108c2ecf20Sopenharmony_ci		(FIELD_GET(DFH_ID, v) == DFH_ID_FIU_FME);
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic inline bool dfl_feature_is_port(void __iomem *base)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	u64 v = readq(base + DFH);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	return (FIELD_GET(DFH_TYPE, v) == DFH_TYPE_FIU) &&
4188c2ecf20Sopenharmony_ci		(FIELD_GET(DFH_ID, v) == DFH_ID_FIU_PORT);
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic inline u8 dfl_feature_revision(void __iomem *base)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	return (u8)FIELD_GET(DFH_REVISION, readq(base + DFH));
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci/**
4278c2ecf20Sopenharmony_ci * struct dfl_fpga_enum_info - DFL FPGA enumeration information
4288c2ecf20Sopenharmony_ci *
4298c2ecf20Sopenharmony_ci * @dev: parent device.
4308c2ecf20Sopenharmony_ci * @dfls: list of device feature lists.
4318c2ecf20Sopenharmony_ci * @nr_irqs: number of irqs for all feature devices.
4328c2ecf20Sopenharmony_ci * @irq_table: Linux IRQ numbers for all irqs, indexed by hw irq numbers.
4338c2ecf20Sopenharmony_ci */
4348c2ecf20Sopenharmony_cistruct dfl_fpga_enum_info {
4358c2ecf20Sopenharmony_ci	struct device *dev;
4368c2ecf20Sopenharmony_ci	struct list_head dfls;
4378c2ecf20Sopenharmony_ci	unsigned int nr_irqs;
4388c2ecf20Sopenharmony_ci	int *irq_table;
4398c2ecf20Sopenharmony_ci};
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci/**
4428c2ecf20Sopenharmony_ci * struct dfl_fpga_enum_dfl - DFL FPGA enumeration device feature list info
4438c2ecf20Sopenharmony_ci *
4448c2ecf20Sopenharmony_ci * @start: base address of this device feature list.
4458c2ecf20Sopenharmony_ci * @len: size of this device feature list.
4468c2ecf20Sopenharmony_ci * @node: node in list of device feature lists.
4478c2ecf20Sopenharmony_ci */
4488c2ecf20Sopenharmony_cistruct dfl_fpga_enum_dfl {
4498c2ecf20Sopenharmony_ci	resource_size_t start;
4508c2ecf20Sopenharmony_ci	resource_size_t len;
4518c2ecf20Sopenharmony_ci	struct list_head node;
4528c2ecf20Sopenharmony_ci};
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_cistruct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev);
4558c2ecf20Sopenharmony_ciint dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
4568c2ecf20Sopenharmony_ci			       resource_size_t start, resource_size_t len);
4578c2ecf20Sopenharmony_ciint dfl_fpga_enum_info_add_irq(struct dfl_fpga_enum_info *info,
4588c2ecf20Sopenharmony_ci			       unsigned int nr_irqs, int *irq_table);
4598c2ecf20Sopenharmony_civoid dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci/**
4628c2ecf20Sopenharmony_ci * struct dfl_fpga_cdev - container device of DFL based FPGA
4638c2ecf20Sopenharmony_ci *
4648c2ecf20Sopenharmony_ci * @parent: parent device of this container device.
4658c2ecf20Sopenharmony_ci * @region: base fpga region.
4668c2ecf20Sopenharmony_ci * @fme_dev: FME feature device under this container device.
4678c2ecf20Sopenharmony_ci * @lock: mutex lock to protect the port device list.
4688c2ecf20Sopenharmony_ci * @port_dev_list: list of all port feature devices under this container device.
4698c2ecf20Sopenharmony_ci * @released_port_num: released port number under this container device.
4708c2ecf20Sopenharmony_ci */
4718c2ecf20Sopenharmony_cistruct dfl_fpga_cdev {
4728c2ecf20Sopenharmony_ci	struct device *parent;
4738c2ecf20Sopenharmony_ci	struct fpga_region *region;
4748c2ecf20Sopenharmony_ci	struct device *fme_dev;
4758c2ecf20Sopenharmony_ci	struct mutex lock;
4768c2ecf20Sopenharmony_ci	struct list_head port_dev_list;
4778c2ecf20Sopenharmony_ci	int released_port_num;
4788c2ecf20Sopenharmony_ci};
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistruct dfl_fpga_cdev *
4818c2ecf20Sopenharmony_cidfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info);
4828c2ecf20Sopenharmony_civoid dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev);
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci/*
4858c2ecf20Sopenharmony_ci * need to drop the device reference with put_device() after use port platform
4868c2ecf20Sopenharmony_ci * device returned by __dfl_fpga_cdev_find_port and dfl_fpga_cdev_find_port
4878c2ecf20Sopenharmony_ci * functions.
4888c2ecf20Sopenharmony_ci */
4898c2ecf20Sopenharmony_cistruct platform_device *
4908c2ecf20Sopenharmony_ci__dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
4918c2ecf20Sopenharmony_ci			  int (*match)(struct platform_device *, void *));
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_cistatic inline struct platform_device *
4948c2ecf20Sopenharmony_cidfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
4958c2ecf20Sopenharmony_ci			int (*match)(struct platform_device *, void *))
4968c2ecf20Sopenharmony_ci{
4978c2ecf20Sopenharmony_ci	struct platform_device *pdev;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	mutex_lock(&cdev->lock);
5008c2ecf20Sopenharmony_ci	pdev = __dfl_fpga_cdev_find_port(cdev, data, match);
5018c2ecf20Sopenharmony_ci	mutex_unlock(&cdev->lock);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	return pdev;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ciint dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id);
5078c2ecf20Sopenharmony_ciint dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id);
5088c2ecf20Sopenharmony_civoid dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev);
5098c2ecf20Sopenharmony_ciint dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf);
5108c2ecf20Sopenharmony_ciint dfl_fpga_set_irq_triggers(struct dfl_feature *feature, unsigned int start,
5118c2ecf20Sopenharmony_ci			      unsigned int count, int32_t *fds);
5128c2ecf20Sopenharmony_cilong dfl_feature_ioctl_get_num_irqs(struct platform_device *pdev,
5138c2ecf20Sopenharmony_ci				    struct dfl_feature *feature,
5148c2ecf20Sopenharmony_ci				    unsigned long arg);
5158c2ecf20Sopenharmony_cilong dfl_feature_ioctl_set_irq(struct platform_device *pdev,
5168c2ecf20Sopenharmony_ci			       struct dfl_feature *feature,
5178c2ecf20Sopenharmony_ci			       unsigned long arg);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci/**
5208c2ecf20Sopenharmony_ci * enum dfl_id_type - define the DFL FIU types
5218c2ecf20Sopenharmony_ci */
5228c2ecf20Sopenharmony_cienum dfl_id_type {
5238c2ecf20Sopenharmony_ci	FME_ID,
5248c2ecf20Sopenharmony_ci	PORT_ID,
5258c2ecf20Sopenharmony_ci	DFL_ID_MAX,
5268c2ecf20Sopenharmony_ci};
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci/**
5298c2ecf20Sopenharmony_ci * struct dfl_device_id -  dfl device identifier
5308c2ecf20Sopenharmony_ci * @type: contains 4 bits DFL FIU type of the device. See enum dfl_id_type.
5318c2ecf20Sopenharmony_ci * @feature_id: contains 12 bits feature identifier local to its DFL FIU type.
5328c2ecf20Sopenharmony_ci * @driver_data: driver specific data.
5338c2ecf20Sopenharmony_ci */
5348c2ecf20Sopenharmony_cistruct dfl_device_id {
5358c2ecf20Sopenharmony_ci	u8 type;
5368c2ecf20Sopenharmony_ci	u16 feature_id;
5378c2ecf20Sopenharmony_ci	unsigned long driver_data;
5388c2ecf20Sopenharmony_ci};
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci/**
5418c2ecf20Sopenharmony_ci * struct dfl_device - represent an dfl device on dfl bus
5428c2ecf20Sopenharmony_ci *
5438c2ecf20Sopenharmony_ci * @dev: generic device interface.
5448c2ecf20Sopenharmony_ci * @id: id of the dfl device.
5458c2ecf20Sopenharmony_ci * @type: type of DFL FIU of the device. See enum dfl_id_type.
5468c2ecf20Sopenharmony_ci * @feature_id: 16 bits feature identifier local to its DFL FIU type.
5478c2ecf20Sopenharmony_ci * @mmio_res: mmio resource of this dfl device.
5488c2ecf20Sopenharmony_ci * @irqs: list of Linux IRQ numbers of this dfl device.
5498c2ecf20Sopenharmony_ci * @num_irqs: number of IRQs supported by this dfl device.
5508c2ecf20Sopenharmony_ci * @cdev: pointer to DFL FPGA container device this dfl device belongs to.
5518c2ecf20Sopenharmony_ci * @id_entry: matched id entry in dfl driver's id table.
5528c2ecf20Sopenharmony_ci */
5538c2ecf20Sopenharmony_cistruct dfl_device {
5548c2ecf20Sopenharmony_ci	struct device dev;
5558c2ecf20Sopenharmony_ci	int id;
5568c2ecf20Sopenharmony_ci	u8 type;
5578c2ecf20Sopenharmony_ci	u16 feature_id;
5588c2ecf20Sopenharmony_ci	struct resource mmio_res;
5598c2ecf20Sopenharmony_ci	int *irqs;
5608c2ecf20Sopenharmony_ci	unsigned int num_irqs;
5618c2ecf20Sopenharmony_ci	struct dfl_fpga_cdev *cdev;
5628c2ecf20Sopenharmony_ci	const struct dfl_device_id *id_entry;
5638c2ecf20Sopenharmony_ci};
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci/**
5668c2ecf20Sopenharmony_ci * struct dfl_driver - represent an dfl device driver
5678c2ecf20Sopenharmony_ci *
5688c2ecf20Sopenharmony_ci * @drv: driver model structure.
5698c2ecf20Sopenharmony_ci * @id_table: pointer to table of device IDs the driver is interested in.
5708c2ecf20Sopenharmony_ci *	      { } member terminated.
5718c2ecf20Sopenharmony_ci * @probe: mandatory callback for device binding.
5728c2ecf20Sopenharmony_ci * @remove: callback for device unbinding.
5738c2ecf20Sopenharmony_ci */
5748c2ecf20Sopenharmony_cistruct dfl_driver {
5758c2ecf20Sopenharmony_ci	struct device_driver drv;
5768c2ecf20Sopenharmony_ci	const struct dfl_device_id *id_table;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	int (*probe)(struct dfl_device *dfl_dev);
5798c2ecf20Sopenharmony_ci	void (*remove)(struct dfl_device *dfl_dev);
5808c2ecf20Sopenharmony_ci};
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci#define to_dfl_dev(d) container_of(d, struct dfl_device, dev)
5838c2ecf20Sopenharmony_ci#define to_dfl_drv(d) container_of(d, struct dfl_driver, drv)
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci/*
5868c2ecf20Sopenharmony_ci * use a macro to avoid include chaining to get THIS_MODULE.
5878c2ecf20Sopenharmony_ci */
5888c2ecf20Sopenharmony_ci#define dfl_driver_register(drv) \
5898c2ecf20Sopenharmony_ci	__dfl_driver_register(drv, THIS_MODULE)
5908c2ecf20Sopenharmony_ciint __dfl_driver_register(struct dfl_driver *dfl_drv, struct module *owner);
5918c2ecf20Sopenharmony_civoid dfl_driver_unregister(struct dfl_driver *dfl_drv);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci/*
5948c2ecf20Sopenharmony_ci * module_dfl_driver() - Helper macro for drivers that don't do
5958c2ecf20Sopenharmony_ci * anything special in module init/exit.  This eliminates a lot of
5968c2ecf20Sopenharmony_ci * boilerplate.  Each module may only use this macro once, and
5978c2ecf20Sopenharmony_ci * calling it replaces module_init() and module_exit().
5988c2ecf20Sopenharmony_ci */
5998c2ecf20Sopenharmony_ci#define module_dfl_driver(__dfl_driver) \
6008c2ecf20Sopenharmony_ci	module_driver(__dfl_driver, dfl_driver_register, \
6018c2ecf20Sopenharmony_ci		      dfl_driver_unregister)
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci#endif /* __FPGA_DFL_H */
604