drivers: pci_ep: Introduce UCLASS_PCI_EP uclass
Introduce new UCLASS_PCI_EP class for handling PCI endpoint devices, allowing to set various attributes of the PCI endpoint device, such as: * configuration space header * BAR definitions * outband memory mapping * start/stop PCI link Signed-off-by: Ramon Fried <ramon.fried@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									ef8b7e045e
								
							
						
					
					
						commit
						914026d258
					
				|  | @ -633,6 +633,12 @@ M:	Simon Glass <sjg@chromium.org> | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	tools/patman/ | F:	tools/patman/ | ||||||
| 
 | 
 | ||||||
|  | PCI Endpoint | ||||||
|  | M:	Ramon Fried <rfried.dev@gmail.com> | ||||||
|  | S:	Maintained | ||||||
|  | F:	drivers/pci_endpoint/ | ||||||
|  | F:  include/pci_ep.h | ||||||
|  | 
 | ||||||
| POWER | POWER | ||||||
| M:	Jaehoon Chung <jh80.chung@samsung.com> | M:	Jaehoon Chung <jh80.chung@samsung.com> | ||||||
| S:	Maintained | S:	Maintained | ||||||
|  |  | ||||||
|  | @ -66,6 +66,8 @@ source "drivers/nvme/Kconfig" | ||||||
| 
 | 
 | ||||||
| source "drivers/pci/Kconfig" | source "drivers/pci/Kconfig" | ||||||
| 
 | 
 | ||||||
|  | source "drivers/pci_endpoint/Kconfig" | ||||||
|  | 
 | ||||||
| source "drivers/pch/Kconfig" | source "drivers/pch/Kconfig" | ||||||
| 
 | 
 | ||||||
| source "drivers/pcmcia/Kconfig" | source "drivers/pcmcia/Kconfig" | ||||||
|  |  | ||||||
|  | @ -86,6 +86,7 @@ obj-$(CONFIG_FPGA) += fpga/ | ||||||
| obj-y += misc/ | obj-y += misc/ | ||||||
| obj-$(CONFIG_MMC) += mmc/ | obj-$(CONFIG_MMC) += mmc/ | ||||||
| obj-$(CONFIG_NVME) += nvme/ | obj-$(CONFIG_NVME) += nvme/ | ||||||
|  | obj-$(CONFIG_PCI_ENDPOINT) += pci_endpoint/ | ||||||
| obj-y += pcmcia/ | obj-y += pcmcia/ | ||||||
| obj-y += dfu/ | obj-y += dfu/ | ||||||
| obj-$(CONFIG_PCH) += pch/ | obj-$(CONFIG_PCH) += pch/ | ||||||
|  |  | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | # SPDX-License-Identifier: GPL-2.0 | ||||||
|  | # | ||||||
|  | # PCI Endpoint Support | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | menu "PCI Endpoint" | ||||||
|  | 
 | ||||||
|  | config PCI_ENDPOINT | ||||||
|  | 	bool "PCI Endpoint Support" | ||||||
|  | 	depends on DM | ||||||
|  | 	help | ||||||
|  | 	   Enable this configuration option to support configurable PCI | ||||||
|  | 	   endpoints. This should be enabled if the platform has a PCI | ||||||
|  | 	   controllers that can operate in endpoint mode (as a device | ||||||
|  | 	   connected to PCI host or bridge). | ||||||
|  | 
 | ||||||
|  | endmenu | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | # SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | #
 | ||||||
|  | # (C) Copyright 2019
 | ||||||
|  | # Ramon Fried <ramon.fried@gmail.com>
 | ||||||
|  | 
 | ||||||
|  | obj-y += pci_ep-uclass.o | ||||||
|  | @ -0,0 +1,211 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | /*
 | ||||||
|  |  * PCI Endpoint uclass | ||||||
|  |  * | ||||||
|  |  * Based on Linux PCI-EP driver written by | ||||||
|  |  * Kishon Vijay Abraham I <kishon@ti.com> | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2019 | ||||||
|  |  * Written by Ramon Fried <ramon.fried@gmail.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <dm.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <linux/log2.h> | ||||||
|  | #include <pci_ep.h> | ||||||
|  | 
 | ||||||
|  | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | 
 | ||||||
|  | int pci_ep_write_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->write_header) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->write_header(dev, fn, hdr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_read_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->read_header) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->read_header(dev, fn, hdr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_set_bar(struct udevice *dev, uint func_no, struct pci_bar *ep_bar) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 	int flags = ep_bar->flags; | ||||||
|  | 
 | ||||||
|  | 	/* Some basic bar validity checks */ | ||||||
|  | 	if (ep_bar->barno > BAR_5 || ep_bar < BAR_0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if ((ep_bar->barno == BAR_5 && | ||||||
|  | 	     (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) || | ||||||
|  | 	    ((flags & PCI_BASE_ADDRESS_SPACE_IO) && | ||||||
|  | 	     (flags & PCI_BASE_ADDRESS_IO_MASK)) || | ||||||
|  | 	    (upper_32_bits(ep_bar->size) && | ||||||
|  | 	     !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64))) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->set_bar) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->set_bar(dev, func_no, ep_bar); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_read_bar(struct udevice *dev, uint func_no, struct pci_bar *ep_bar, | ||||||
|  | 		    enum pci_barno barno) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	/* Some basic bar validity checks */ | ||||||
|  | 	if (barno > BAR_5 || barno < BAR_0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->read_bar) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->read_bar(dev, func_no, ep_bar, barno); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_clear_bar(struct udevice *dev, uint func_num, enum pci_barno bar) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->clear_bar) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->clear_bar(dev, func_num, bar); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_map_addr(struct udevice *dev, uint func_no, phys_addr_t addr, | ||||||
|  | 		    u64 pci_addr, size_t size) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->map_addr) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->map_addr(dev, func_no, addr, pci_addr, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_unmap_addr(struct udevice *dev, uint func_no, phys_addr_t addr) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->unmap_addr) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->unmap_addr(dev, func_no, addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_set_msi(struct udevice *dev, uint func_no, uint interrupts) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 	uint encode_int; | ||||||
|  | 
 | ||||||
|  | 	if (interrupts > 32) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->set_msi) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	/* MSI spec permits allocation of
 | ||||||
|  | 	 * only 1, 2, 4, 8, 16, 32 interrupts | ||||||
|  | 	 */ | ||||||
|  | 	encode_int = order_base_2(interrupts); | ||||||
|  | 
 | ||||||
|  | 	return ops->set_msi(dev, func_no, encode_int); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_get_msi(struct udevice *dev, uint func_no) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 	int interrupt; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->get_msi) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	interrupt = ops->get_msi(dev, func_no); | ||||||
|  | 
 | ||||||
|  | 	if (interrupt < 0) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	/* Translate back from order base 2*/ | ||||||
|  | 	interrupt = 1 << interrupt; | ||||||
|  | 
 | ||||||
|  | 	return interrupt; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_set_msix(struct udevice *dev, uint func_no, uint interrupts) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (interrupts < 1 || interrupts > 2048) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->set_msix) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->set_msix(dev, func_no, interrupts - 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_get_msix(struct udevice *dev, uint func_no) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 	int interrupt; | ||||||
|  | 
 | ||||||
|  | 	if (!ops->get_msix) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	interrupt = ops->get_msix(dev, func_no); | ||||||
|  | 
 | ||||||
|  | 	if (interrupt < 0) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	return interrupt + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_raise_irq(struct udevice *dev, uint func_no, | ||||||
|  | 		     enum pci_ep_irq_type type, uint interrupt_num) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->raise_irq) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->raise_irq(dev, func_no, type, interrupt_num); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_start(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->start) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->start(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int pci_ep_stop(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct pci_ep_ops *ops = pci_ep_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->stop) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->stop(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | UCLASS_DRIVER(pci_ep) = { | ||||||
|  | 	.id		= UCLASS_PCI_EP, | ||||||
|  | 	.name		= "pci_ep", | ||||||
|  | 	.flags		= DM_UC_FLAG_SEQ_ALIAS, | ||||||
|  | }; | ||||||
|  | @ -69,6 +69,7 @@ enum uclass_id { | ||||||
| 	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */ | 	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */ | ||||||
| 	UCLASS_PCH,		/* x86 platform controller hub */ | 	UCLASS_PCH,		/* x86 platform controller hub */ | ||||||
| 	UCLASS_PCI,		/* PCI bus */ | 	UCLASS_PCI,		/* PCI bus */ | ||||||
|  | 	UCLASS_PCI_EP,		/* PCI endpoint device */ | ||||||
| 	UCLASS_PCI_GENERIC,	/* Generic PCI bus device */ | 	UCLASS_PCI_GENERIC,	/* Generic PCI bus device */ | ||||||
| 	UCLASS_PHY,		/* Physical Layer (PHY) device */ | 	UCLASS_PHY,		/* Physical Layer (PHY) device */ | ||||||
| 	UCLASS_PINCONFIG,	/* Pin configuration node device */ | 	UCLASS_PINCONFIG,	/* Pin configuration node device */ | ||||||
|  |  | ||||||
|  | @ -0,0 +1,414 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ */ | ||||||
|  | /*
 | ||||||
|  |  * Adapted from Linux kernel driver | ||||||
|  |  * Copyright (C) 2017 Texas Instruments | ||||||
|  |  * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||||||
|  |  * | ||||||
|  |  * (C) Copyright 2019 | ||||||
|  |  * Ramon Fried <ramon.fried@gmail.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _PCI_EP_H | ||||||
|  | #define _PCI_EP_H | ||||||
|  | 
 | ||||||
|  | #include <pci.h> | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * enum pci_interrupt_pin - PCI INTx interrupt values | ||||||
|  |  * @PCI_INTERRUPT_UNKNOWN: Unknown or unassigned interrupt | ||||||
|  |  * @PCI_INTERRUPT_INTA: PCI INTA pin | ||||||
|  |  * @PCI_INTERRUPT_INTB: PCI INTB pin | ||||||
|  |  * @PCI_INTERRUPT_INTC: PCI INTC pin | ||||||
|  |  * @PCI_INTERRUPT_INTD: PCI INTD pin | ||||||
|  |  * | ||||||
|  |  * Corresponds to values for legacy PCI INTx interrupts, as can be found in the | ||||||
|  |  * PCI_INTERRUPT_PIN register. | ||||||
|  |  */ | ||||||
|  | enum pci_interrupt_pin { | ||||||
|  | 	PCI_INTERRUPT_UNKNOWN, | ||||||
|  | 	PCI_INTERRUPT_INTA, | ||||||
|  | 	PCI_INTERRUPT_INTB, | ||||||
|  | 	PCI_INTERRUPT_INTC, | ||||||
|  | 	PCI_INTERRUPT_INTD, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum pci_barno { | ||||||
|  | 	BAR_0, | ||||||
|  | 	BAR_1, | ||||||
|  | 	BAR_2, | ||||||
|  | 	BAR_3, | ||||||
|  | 	BAR_4, | ||||||
|  | 	BAR_5, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum pci_ep_irq_type { | ||||||
|  | 	PCI_EP_IRQ_UNKNOWN, | ||||||
|  | 	PCI_EP_IRQ_LEGACY, | ||||||
|  | 	PCI_EP_IRQ_MSI, | ||||||
|  | 	PCI_EP_IRQ_MSIX, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct pci_bar - represents the BAR (Base Address Register) of EP device | ||||||
|  |  * @phys_addr: physical address that should be mapped to the BAR | ||||||
|  |  * @size: the size of the address space present in BAR | ||||||
|  |  * pci_barno: number of pci BAR to set (0..5) | ||||||
|  |  * @flags: BAR access flags | ||||||
|  |  */ | ||||||
|  | struct pci_bar { | ||||||
|  | 	dma_addr_t	phys_addr; | ||||||
|  | 	size_t		size; | ||||||
|  | 	enum pci_barno	barno; | ||||||
|  | 	int		flags; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct pci_ep_header - represents standard configuration header | ||||||
|  |  * @vendorid: identifies device manufacturer | ||||||
|  |  * @deviceid: identifies a particular device | ||||||
|  |  * @revid: specifies a device-specific revision identifier | ||||||
|  |  * @progif_code: identifies a specific register-level programming interface | ||||||
|  |  * @subclass_code: identifies more specifically the function of the device | ||||||
|  |  * @baseclass_code: broadly classifies the type of function the device performs | ||||||
|  |  * @cache_line_size: specifies the system cacheline size in units of DWORDs | ||||||
|  |  * @subsys_vendor_id: vendor of the add-in card or subsystem | ||||||
|  |  * @subsys_id: id specific to vendor | ||||||
|  |  * @interrupt_pin: interrupt pin the device (or device function) uses | ||||||
|  |  */ | ||||||
|  | struct pci_ep_header { | ||||||
|  | 	u16	vendorid; | ||||||
|  | 	u16	deviceid; | ||||||
|  | 	u8	revid; | ||||||
|  | 	u8	progif_code; | ||||||
|  | 	u8	subclass_code; | ||||||
|  | 	u8	baseclass_code; | ||||||
|  | 	u8	cache_line_size; | ||||||
|  | 	u16	subsys_vendor_id; | ||||||
|  | 	u16	subsys_id; | ||||||
|  | 	enum pci_interrupt_pin interrupt_pin; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* PCI endpoint operations */ | ||||||
|  | struct pci_ep_ops { | ||||||
|  | 	/**
 | ||||||
|  | 	 * write_header() - Write a PCI configuration space header | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to write to | ||||||
|  | 	 * @func_num:	EP function to fill | ||||||
|  | 	 * @hdr:	header to write | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*write_header)(struct udevice *dev, uint func_num, | ||||||
|  | 				struct pci_ep_header *hdr); | ||||||
|  | 	/**
 | ||||||
|  | 	 * read_header() - Read a PCI configuration space header | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to write to | ||||||
|  | 	 * @func_num:	EP function to fill | ||||||
|  | 	 * @hdr:	header to read to | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*read_header)(struct udevice *dev, uint func_num, | ||||||
|  | 			       struct pci_ep_header *hdr); | ||||||
|  | 	/**
 | ||||||
|  | 	 * set_bar() - Set BAR (Base Address Register) properties | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @bar:	bar data | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*set_bar)(struct udevice *dev, uint func_num, | ||||||
|  | 			   struct pci_bar *bar); | ||||||
|  | 	/**
 | ||||||
|  | 	 * read_bar() - Read BAR (Base Address Register) properties | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to read | ||||||
|  | 	 * @func_num:	EP function to read | ||||||
|  | 	 * @bar:	struct to copy data to | ||||||
|  | 	 * @barno:	bar number to read | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*read_bar)(struct udevice *dev, uint func_num, | ||||||
|  | 			    struct pci_bar *bar, enum pci_barno barno); | ||||||
|  | 	/**
 | ||||||
|  | 	 * clear_bar() - clear BAR (Base Address Register) | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to clear | ||||||
|  | 	 * @func_num:	EP function to clear | ||||||
|  | 	 * @bar:	bar number | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*clear_bar)(struct udevice *dev, uint func_num, | ||||||
|  | 			     enum pci_barno bar); | ||||||
|  | 	/**
 | ||||||
|  | 	 * map_addr() - map CPU address to PCI address | ||||||
|  | 	 * | ||||||
|  | 	 * outband region is used in order to generate PCI read/write | ||||||
|  | 	 * transaction from local memory/write. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @addr:	local physical address base | ||||||
|  | 	 * @pci_addr:	pci address to translate to | ||||||
|  | 	 * @size:	region size | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*map_addr)(struct udevice *dev, uint func_num, | ||||||
|  | 			    phys_addr_t addr, u64 pci_addr, size_t size); | ||||||
|  | 	/**
 | ||||||
|  | 	 * unmap_addr() - unmap CPU address to PCI address | ||||||
|  | 	 * | ||||||
|  | 	 * unmap previously mapped region. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @addr:	local physical address base | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*unmap_addr)(struct udevice *dev, uint func_num, | ||||||
|  | 			      phys_addr_t addr); | ||||||
|  | 	/**
 | ||||||
|  | 	 * set_msi() - set msi capability property | ||||||
|  | 	 * | ||||||
|  | 	 * set the number of required MSI vectors the device | ||||||
|  | 	 * needs for operation. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @interrupts:	required interrupts count | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*set_msi)(struct udevice *dev, uint func_num, uint interrupts); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * get_msi() - get the number of MSI interrupts allocated by the host. | ||||||
|  | 	 * | ||||||
|  | 	 * Read the Multiple Message Enable bitfield from | ||||||
|  | 	 * Message control register. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to use | ||||||
|  | 	 * @func_num:	EP function to use | ||||||
|  | 	 * @return msi count if OK, -EINVAL if msi were not enabled at host. | ||||||
|  | 	 */ | ||||||
|  | 	int	(*get_msi)(struct udevice *dev, uint func_num); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * set_msix() - set msix capability property | ||||||
|  | 	 * | ||||||
|  | 	 * set the number of required MSIx vectors the device | ||||||
|  | 	 * needs for operation. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @interrupts:	required interrupts count | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*set_msix)(struct udevice *dev, uint func_num, | ||||||
|  | 			    uint interrupts); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * get_msix() - get the number of MSIx interrupts allocated by the host. | ||||||
|  | 	 * | ||||||
|  | 	 * Read the Multiple Message Enable bitfield from | ||||||
|  | 	 * Message control register. | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to use | ||||||
|  | 	 * @func_num:	EP function to use | ||||||
|  | 	 * @return msi count if OK, -EINVAL if msi were not enabled at host. | ||||||
|  | 	 */ | ||||||
|  | 	int	(*get_msix)(struct udevice *dev, uint func_num); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * raise_irq() - raise a legacy, MSI or MSI-X interrupt | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @func_num:	EP function to set | ||||||
|  | 	 * @type:	type of irq to send | ||||||
|  | 	 * @interrupt_num: interrupt vector to use | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*raise_irq)(struct udevice *dev, uint func_num, | ||||||
|  | 			     enum pci_ep_irq_type type, uint interrupt_num); | ||||||
|  | 	/**
 | ||||||
|  | 	 * start() - start the PCI link | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*start)(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * stop() - stop the PCI link | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	device to set | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int	(*stop)(struct udevice *dev); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define pci_ep_get_ops(dev)	((struct pci_ep_ops *)(dev)->driver->ops) | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_write_header() - Write a PCI configuration space header | ||||||
|  |  * | ||||||
|  |  * @dev:	device to write to | ||||||
|  |  * @func_num:	EP function to fill | ||||||
|  |  * @hdr:	header to write | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_write_header(struct udevice *dev, uint func_num, | ||||||
|  | 			struct pci_ep_header *hdr); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * dm_pci_ep_read_header() - Read a PCI configuration space header | ||||||
|  |  * | ||||||
|  |  * @dev:	device to write to | ||||||
|  |  * @func_num:	EP function to fill | ||||||
|  |  * @hdr:	header to read to | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_read_header(struct udevice *dev, uint func_num, | ||||||
|  | 		       struct pci_ep_header *hdr); | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_set_bar() - Set BAR (Base Address Register) properties | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @bar:	bar data | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_set_bar(struct udevice *dev, uint func_num, struct pci_bar *bar); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_read_bar() - Read BAR (Base Address Register) properties | ||||||
|  |  * | ||||||
|  |  * @dev:	device to read | ||||||
|  |  * @func_num:	EP function to read | ||||||
|  |  * @bar:	struct to copy data to | ||||||
|  |  * @barno:	bar number to read | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_read_bar(struct udevice *dev, uint func_no, struct pci_bar *ep_bar, | ||||||
|  | 		    enum pci_barno barno); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_clear_bar() - Clear BAR (Base Address Register) | ||||||
|  |  *			mark the BAR as empty so host won't map it. | ||||||
|  |  * @dev:	device to clear | ||||||
|  |  * @func_num:	EP function to clear | ||||||
|  |  * @bar:	bar number | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_clear_bar(struct udevice *dev, uint func_num, enum pci_barno bar); | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_map_addr() - map CPU address to PCI address | ||||||
|  |  * | ||||||
|  |  * outband region is used in order to generate PCI read/write | ||||||
|  |  * transaction from local memory/write. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @addr:	local physical address base | ||||||
|  |  * @pci_addr:	pci address to translate to | ||||||
|  |  * @size:	region size | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_map_addr(struct udevice *dev, uint func_num, phys_addr_t addr, | ||||||
|  | 		    u64 pci_addr, size_t size); | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_unmap_addr() - unmap CPU address to PCI address | ||||||
|  |  * | ||||||
|  |  * unmap previously mapped region. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @addr:	local physical address base | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_unmap_addr(struct udevice *dev, uint func_num, phys_addr_t addr); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_set_msi() - set msi capability property | ||||||
|  |  * | ||||||
|  |  * set the number of required MSI vectors the device | ||||||
|  |  * needs for operation. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @interrupts:	required interrupts count | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_set_msi(struct udevice *dev, uint func_num, uint interrupts); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_get_msi() - get the number of MSI interrupts allocated by the host. | ||||||
|  |  * | ||||||
|  |  * Read the Multiple Message Enable bitfield from | ||||||
|  |  * Message control register. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to use | ||||||
|  |  * @func_num:	EP function to use | ||||||
|  |  * @return msi count if OK, -EINVAL if msi were not enabled at host. | ||||||
|  |  */ | ||||||
|  | int pci_ep_get_msi(struct udevice *dev, uint func_num); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_set_msix() - set msi capability property | ||||||
|  |  * | ||||||
|  |  * set the number of required MSIx vectors the device | ||||||
|  |  * needs for operation. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @interrupts:	required interrupts count | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_set_msix(struct udevice *dev, uint func_num, uint interrupts); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_get_msix() - get the number of MSIx interrupts allocated by the host. | ||||||
|  |  * | ||||||
|  |  * Read the Multiple Message Enable bitfield from | ||||||
|  |  * Message control register. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to use | ||||||
|  |  * @func_num:	EP function to use | ||||||
|  |  * @return msi count if OK, -EINVAL if msi were not enabled at host. | ||||||
|  |  */ | ||||||
|  | int pci_ep_get_msix(struct udevice *dev, uint func_num); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_raise_irq() - raise a legacy, MSI or MSI-X interrupt | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @func_num:	EP function to set | ||||||
|  |  * @type:	type of irq to send | ||||||
|  |  * @interrupt_num: interrupt vector to use | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_raise_irq(struct udevice *dev, uint func_num, | ||||||
|  | 		     enum pci_ep_irq_type type, uint interrupt_num); | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_start() - start the PCI link | ||||||
|  |  * | ||||||
|  |  * Enable PCI endpoint device and start link | ||||||
|  |  * process. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_start(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * pci_ep_stop() - stop the PCI link | ||||||
|  |  * | ||||||
|  |  * Disable PCI endpoint device and stop | ||||||
|  |  * link. | ||||||
|  |  * | ||||||
|  |  * @dev:	device to set | ||||||
|  |  * @return 0 if OK, -ve on error | ||||||
|  |  */ | ||||||
|  | int pci_ep_stop(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
		Loading…
	
		Reference in New Issue