xref: /dflybsd-src/sys/dev/drm/include/linux/pci.h (revision 789731325bde747251c28a37e0a00ed4efb88c46)
15af3f531SFrançois Tigeot /*
2a85cb24fSFrançois Tigeot  * Copyright (c) 2014-2020 François Tigeot <ftigeot@wolfpond.org>
35af3f531SFrançois Tigeot  * All rights reserved.
45af3f531SFrançois Tigeot  *
55af3f531SFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
65af3f531SFrançois Tigeot  * modification, are permitted provided that the following conditions
75af3f531SFrançois Tigeot  * are met:
85af3f531SFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
95af3f531SFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
105af3f531SFrançois Tigeot  *    disclaimer.
115af3f531SFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
125af3f531SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
135af3f531SFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
145af3f531SFrançois Tigeot  *
155af3f531SFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
165af3f531SFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
175af3f531SFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
185af3f531SFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
195af3f531SFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
205af3f531SFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
215af3f531SFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
225af3f531SFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235af3f531SFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
245af3f531SFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255af3f531SFrançois Tigeot  */
265af3f531SFrançois Tigeot 
275af3f531SFrançois Tigeot #ifndef LINUX_PCI_H
285af3f531SFrançois Tigeot #define LINUX_PCI_H
295af3f531SFrançois Tigeot 
307857f1b8SFrançois Tigeot #include <linux/mod_devicetable.h>
319ca0d65eSFrançois Tigeot 
3247ad44e8SFrançois Tigeot #include <linux/types.h>
337857f1b8SFrançois Tigeot #include <linux/init.h>
34a85cb24fSFrançois Tigeot #include <linux/ioport.h>
3519c468b4SFrançois Tigeot #include <linux/list.h>
3619c468b4SFrançois Tigeot #include <linux/compiler.h>
3719c468b4SFrançois Tigeot #include <linux/errno.h>
38c30871e1SFrançois Tigeot #include <linux/kobject.h>
3919c468b4SFrançois Tigeot #include <linux/atomic.h>
409ca0d65eSFrançois Tigeot #include <linux/device.h>
419ca0d65eSFrançois Tigeot #include <linux/io.h>
428a697a22SFrançois Tigeot #include <uapi/linux/pci.h>
439ca0d65eSFrançois Tigeot 
445af3f531SFrançois Tigeot #include <linux/pci_ids.h>
45*78973132SSergey Zigachev #include <linux/pci_regs.h>
465af3f531SFrançois Tigeot 
477857f1b8SFrançois Tigeot #include <sys/pciio.h>
487857f1b8SFrançois Tigeot #include <sys/rman.h>
497857f1b8SFrançois Tigeot #include <bus/pci/pcivar.h>
507857f1b8SFrançois Tigeot #include <bus/pci/pcireg.h>
517857f1b8SFrançois Tigeot 
527857f1b8SFrançois Tigeot #define PCI_ANY_ID	(~0u)
537857f1b8SFrançois Tigeot 
546f06a24cSzrj struct pci_bus;
551dedbd3bSFrançois Tigeot struct device_node;
566f06a24cSzrj 
5716507489SFrançois Tigeot struct pci_device_id {
5816507489SFrançois Tigeot 	uint32_t vendor;
5916507489SFrançois Tigeot 	uint32_t device;
6016507489SFrançois Tigeot 	uint32_t subvendor;
6116507489SFrançois Tigeot 	uint32_t subdevice;
626812b25aSFrançois Tigeot 	uint32_t class;
636812b25aSFrançois Tigeot 	uint32_t class_mask;
6416507489SFrançois Tigeot 	unsigned long driver_data;
6516507489SFrançois Tigeot };
6616507489SFrançois Tigeot 
67a85cb24fSFrançois Tigeot typedef unsigned short pci_dev_flags_t;
68a85cb24fSFrançois Tigeot 
69a85cb24fSFrançois Tigeot #define PCI_DEV_FLAGS_NEEDS_RESUME	(1 << 11)
70a85cb24fSFrançois Tigeot 
719ca0d65eSFrançois Tigeot struct pci_dev {
726f06a24cSzrj 	struct pci_bus *bus;		/* bus device is nailed to */
73fb572d17SFrançois Tigeot 	struct device dev;
743e7afdc3Szrj 
751c45d30aSFrançois Tigeot 	uint32_t devfn;
76fc53575bSzrj 	uint16_t vendor;		/* vendor ID */
77fc53575bSzrj 	uint16_t device;		/* device ID */
78fc53575bSzrj 	uint16_t subsystem_vendor;
79fc53575bSzrj 	uint16_t subsystem_device;
802c9916cdSFrançois Tigeot 
81fc53575bSzrj 	uint8_t revision;		/* revision ID */
826812b25aSFrançois Tigeot 
83fc53575bSzrj 	unsigned int irq;		/* handle with care */
8459e561f5SFrançois Tigeot 	void *pci_dev_data;
85183e2373SFrançois Tigeot 
86f792f2bdSFrançois Tigeot 	unsigned int	no_64bit_msi:1;
87a85cb24fSFrançois Tigeot 	pci_dev_flags_t dev_flags;
88f792f2bdSFrançois Tigeot 
89183e2373SFrançois Tigeot 	/* DragonFly-specific data */
90183e2373SFrançois Tigeot 	int		_irq_type;
91183e2373SFrançois Tigeot 	struct resource	*_irqr;
92183e2373SFrançois Tigeot 	int		_irqrid;
939ca0d65eSFrançois Tigeot };
949ca0d65eSFrançois Tigeot 
956f06a24cSzrj struct pci_bus {
966f06a24cSzrj 	struct pci_dev *self;		/* handle to pdev self */
976f06a24cSzrj 	struct device *dev;		/* handle to dev */
986f06a24cSzrj 
996f06a24cSzrj 	unsigned char number;		/* bus addr number */
1003f2dd94aSFrançois Tigeot 
1013f2dd94aSFrançois Tigeot 	unsigned char max_bus_speed;
1026f06a24cSzrj };
1036f06a24cSzrj 
10459e561f5SFrançois Tigeot struct pci_driver {
1051dedbd3bSFrançois Tigeot 	const char *name;
1061dedbd3bSFrançois Tigeot 	const struct pci_device_id *id_table;
1071dedbd3bSFrançois Tigeot 	int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
1081dedbd3bSFrançois Tigeot 	void (*remove)(struct pci_dev *dev);
10959e561f5SFrançois Tigeot };
11059e561f5SFrançois Tigeot 
11134b686b2SFrançois Tigeot #define PCI_DMA_BIDIRECTIONAL	0
11234b686b2SFrançois Tigeot 
113c6f73aabSFrançois Tigeot /* extracted from radeon/si.c radeon/cik.c */
114c6f73aabSFrançois Tigeot #define PCI_EXP_LNKCTL PCIER_LINKCTRL /* 16 */
115c6f73aabSFrançois Tigeot #define PCI_EXP_LNKCTL2 48
116c6f73aabSFrançois Tigeot #define PCI_EXP_LNKCTL_HAWD PCIEM_LNKCTL_HAWD /* 0x0200 */
117c6f73aabSFrançois Tigeot #define PCI_EXP_DEVSTA PCIER_DEVSTS /* 10 */
118c6f73aabSFrançois Tigeot #define PCI_EXP_DEVSTA_TRPND 0x0020
119c6f73aabSFrançois Tigeot #define PCI_EXP_LNKCAP_CLKPM 0x00040000
120c6f73aabSFrançois Tigeot 
1219ca0d65eSFrançois Tigeot static inline int
pci_read_config_byte(struct pci_dev * pdev,int where,u8 * val)1229ca0d65eSFrançois Tigeot pci_read_config_byte(struct pci_dev *pdev, int where, u8 *val)
1239ca0d65eSFrançois Tigeot {
124fb572d17SFrançois Tigeot 	*val = (u8)pci_read_config(pdev->dev.bsddev, where, 1);
1259ca0d65eSFrançois Tigeot 	return 0;
1269ca0d65eSFrançois Tigeot }
1279ca0d65eSFrançois Tigeot 
1289ca0d65eSFrançois Tigeot static inline int
pci_read_config_word(struct pci_dev * pdev,int where,u16 * val)1299ca0d65eSFrançois Tigeot pci_read_config_word(struct pci_dev *pdev, int where, u16 *val)
1309ca0d65eSFrançois Tigeot {
131fb572d17SFrançois Tigeot 	*val = (u16)pci_read_config(pdev->dev.bsddev, where, 2);
1329ca0d65eSFrançois Tigeot 	return 0;
1339ca0d65eSFrançois Tigeot }
1349ca0d65eSFrançois Tigeot 
1359ca0d65eSFrançois Tigeot static inline int
pci_read_config_dword(struct pci_dev * pdev,int where,u32 * val)1369ca0d65eSFrançois Tigeot pci_read_config_dword(struct pci_dev *pdev, int where, u32 *val)
1379ca0d65eSFrançois Tigeot {
138fb572d17SFrançois Tigeot 	*val = (u32)pci_read_config(pdev->dev.bsddev, where, 4);
1399ca0d65eSFrançois Tigeot 	return 0;
1409ca0d65eSFrançois Tigeot }
1419ca0d65eSFrançois Tigeot 
1429ca0d65eSFrançois Tigeot static inline int
pci_write_config_byte(struct pci_dev * pdev,int where,u8 val)1439ca0d65eSFrançois Tigeot pci_write_config_byte(struct pci_dev *pdev, int where, u8 val)
1449ca0d65eSFrançois Tigeot {
145fb572d17SFrançois Tigeot 	pci_write_config(pdev->dev.bsddev, where, val, 1);
1469ca0d65eSFrançois Tigeot 	return 0;
1479ca0d65eSFrançois Tigeot }
1489ca0d65eSFrançois Tigeot 
1499ca0d65eSFrançois Tigeot static inline int
pci_write_config_word(struct pci_dev * pdev,int where,u16 val)1509ca0d65eSFrançois Tigeot pci_write_config_word(struct pci_dev *pdev, int where, u16 val)
1519ca0d65eSFrançois Tigeot {
152fb572d17SFrançois Tigeot 	pci_write_config(pdev->dev.bsddev, where, val, 2);
1539ca0d65eSFrançois Tigeot 	return 0;
1549ca0d65eSFrançois Tigeot }
1559ca0d65eSFrançois Tigeot 
1569ca0d65eSFrançois Tigeot static inline int
pci_write_config_dword(struct pci_dev * pdev,int where,u32 val)1579ca0d65eSFrançois Tigeot pci_write_config_dword(struct pci_dev *pdev, int where, u32 val)
1589ca0d65eSFrançois Tigeot {
159fb572d17SFrançois Tigeot 	pci_write_config(pdev->dev.bsddev, where, val, 4);
1609ca0d65eSFrançois Tigeot 	return 0;
1619ca0d65eSFrançois Tigeot }
1629ca0d65eSFrançois Tigeot 
1638374c58bSzrj /* extracted from drm/radeon/evergreen.c */
1648374c58bSzrj static inline int
pcie_get_readrq(struct pci_dev * pdev)1658374c58bSzrj pcie_get_readrq(struct pci_dev *pdev)
1668374c58bSzrj {
1678374c58bSzrj 	u16 ctl;
1688374c58bSzrj 	int err, cap;
1698374c58bSzrj 
170fb572d17SFrançois Tigeot 	err = pci_find_extcap(pdev->dev.bsddev, PCIY_EXPRESS, &cap);
1718374c58bSzrj 
1728374c58bSzrj 	cap += PCIER_DEVCTRL;
1738374c58bSzrj 
174fb572d17SFrançois Tigeot 	ctl = pci_read_config(pdev->dev.bsddev, cap, 2);
1758374c58bSzrj 
1768374c58bSzrj 	return 128 << ((ctl & PCIEM_DEVCTL_MAX_READRQ_MASK) >> 12);
1778374c58bSzrj }
1788374c58bSzrj 
1798374c58bSzrj /* valid rq sizes: 128, 256, 512, 1024, 2048, 4096 (^2N) */
1808374c58bSzrj static inline int
pcie_set_readrq(struct pci_dev * pdev,int rq)1818374c58bSzrj pcie_set_readrq(struct pci_dev *pdev, int rq)
1828374c58bSzrj {
1838374c58bSzrj 	u16 ctl;
1848374c58bSzrj 	int err, cap;
1858374c58bSzrj 
1868374c58bSzrj 	if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
1878374c58bSzrj 		return -EINVAL;
1888374c58bSzrj 
189fb572d17SFrançois Tigeot 	err = pci_find_extcap(pdev->dev.bsddev, PCIY_EXPRESS, &cap);
1908374c58bSzrj 	if (err)
1918374c58bSzrj 		return (-1);
1928374c58bSzrj 
1938374c58bSzrj 	cap += PCIER_DEVCTRL;
1948374c58bSzrj 
195fb572d17SFrançois Tigeot 	ctl = pci_read_config(pdev->dev.bsddev, cap, 2);
1968374c58bSzrj 	ctl &= ~PCIEM_DEVCTL_MAX_READRQ_MASK;
1978374c58bSzrj 	ctl |= ((ffs(rq) - 8) << 12);
198fb572d17SFrançois Tigeot 	pci_write_config(pdev->dev.bsddev, cap, ctl, 2);
1998374c58bSzrj 	return 0;
2008374c58bSzrj }
2019ca0d65eSFrançois Tigeot 
2029ca0d65eSFrançois Tigeot static inline struct pci_dev *
pci_dev_get(struct pci_dev * dev)2039ca0d65eSFrançois Tigeot pci_dev_get(struct pci_dev *dev)
2049ca0d65eSFrançois Tigeot {
2059ca0d65eSFrançois Tigeot 	/* Linux increments a reference count here */
2069ca0d65eSFrançois Tigeot 	return dev;
2079ca0d65eSFrançois Tigeot }
2089ca0d65eSFrançois Tigeot 
2099ca0d65eSFrançois Tigeot static inline struct pci_dev *
pci_dev_put(struct pci_dev * dev)2109ca0d65eSFrançois Tigeot pci_dev_put(struct pci_dev *dev)
2119ca0d65eSFrançois Tigeot {
2129ca0d65eSFrançois Tigeot 	/* Linux decrements a reference count here */
2139ca0d65eSFrançois Tigeot 	return dev;
2149ca0d65eSFrançois Tigeot }
2159ca0d65eSFrançois Tigeot 
2169ca0d65eSFrançois Tigeot 
2179ca0d65eSFrançois Tigeot static inline int
pci_set_dma_mask(struct pci_dev * dev,u64 mask)2189ca0d65eSFrançois Tigeot pci_set_dma_mask(struct pci_dev *dev, u64 mask)
2199ca0d65eSFrançois Tigeot {
2209ca0d65eSFrançois Tigeot 	return -EIO;
2219ca0d65eSFrançois Tigeot }
2229ca0d65eSFrançois Tigeot 
2239ca0d65eSFrançois Tigeot static inline int
pci_set_consistent_dma_mask(struct pci_dev * dev,u64 mask)2249ca0d65eSFrançois Tigeot pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
2259ca0d65eSFrançois Tigeot {
2269ca0d65eSFrançois Tigeot 	return -EIO;
2279ca0d65eSFrançois Tigeot }
2289ca0d65eSFrançois Tigeot 
2294eae5ca7SFrançois Tigeot typedef int pci_power_t;
2304eae5ca7SFrançois Tigeot 
2314eae5ca7SFrançois Tigeot #define PCI_D0		0
2324eae5ca7SFrançois Tigeot #define PCI_D1		1
2334eae5ca7SFrançois Tigeot #define PCI_D2		2
2344eae5ca7SFrançois Tigeot #define PCI_D3hot	3
2354eae5ca7SFrançois Tigeot #define PCI_D3cold	4
2364eae5ca7SFrançois Tigeot 
23734b686b2SFrançois Tigeot #include <asm/pci.h>
23834b686b2SFrançois Tigeot 
239160e34d7SFrançois Tigeot static inline struct resource_list_entry*
_pci_get_rle(struct pci_dev * pdev,int bar)240160e34d7SFrançois Tigeot _pci_get_rle(struct pci_dev *pdev, int bar)
241160e34d7SFrançois Tigeot {
242160e34d7SFrançois Tigeot 	struct pci_devinfo *dinfo;
243fb572d17SFrançois Tigeot 	device_t dev = pdev->dev.bsddev;
244160e34d7SFrançois Tigeot 	struct resource_list_entry *rle;
245160e34d7SFrançois Tigeot 
246160e34d7SFrançois Tigeot 	dinfo = device_get_ivars(dev);
247160e34d7SFrançois Tigeot 
248160e34d7SFrançois Tigeot 	/* Some child devices don't have registered resources, they
249160e34d7SFrançois Tigeot 	 * are only present in the parent */
2504a55b913SFrançois Tigeot 	if (dinfo == NULL)
251160e34d7SFrançois Tigeot 		dev = device_get_parent(dev);
252160e34d7SFrançois Tigeot 	dinfo = device_get_ivars(dev);
253160e34d7SFrançois Tigeot 	if (dinfo == NULL)
254160e34d7SFrançois Tigeot 		return NULL;
255160e34d7SFrançois Tigeot 
256160e34d7SFrançois Tigeot 	rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, PCIR_BAR(bar));
257160e34d7SFrançois Tigeot 	if (rle == NULL) {
258160e34d7SFrançois Tigeot 		rle = resource_list_find(&dinfo->resources,
259160e34d7SFrançois Tigeot 					 SYS_RES_IOPORT, PCIR_BAR(bar));
260160e34d7SFrançois Tigeot 	}
261160e34d7SFrançois Tigeot 
262160e34d7SFrançois Tigeot 	return rle;
263160e34d7SFrançois Tigeot }
264160e34d7SFrançois Tigeot 
265160e34d7SFrançois Tigeot /*
266160e34d7SFrançois Tigeot  * Returns the first address (memory address or I/O port number)
267160e34d7SFrançois Tigeot  * associated with one of the PCI I/O regions.The region is selected by
268160e34d7SFrançois Tigeot  * the integer bar (the base address register), ranging from 0–5 (inclusive).
269160e34d7SFrançois Tigeot  * The return value can be used by ioremap()
270160e34d7SFrançois Tigeot  */
271160e34d7SFrançois Tigeot static inline phys_addr_t
pci_resource_start(struct pci_dev * pdev,int bar)272160e34d7SFrançois Tigeot pci_resource_start(struct pci_dev *pdev, int bar)
273160e34d7SFrançois Tigeot {
27489bbdcc9SFrançois Tigeot 	struct resource *res;
27589bbdcc9SFrançois Tigeot 	int rid;
276160e34d7SFrançois Tigeot 
27789bbdcc9SFrançois Tigeot 	rid = PCIR_BAR(bar);
278fb572d17SFrançois Tigeot 	res = bus_alloc_resource_any(pdev->dev.bsddev, SYS_RES_MEMORY, &rid, RF_SHAREABLE);
27989bbdcc9SFrançois Tigeot 	if (res == NULL) {
280fb572d17SFrançois Tigeot 		kprintf("pci_resource_start(0x%p, 0x%x) failed\n", pdev, PCIR_BAR(bar));
281160e34d7SFrançois Tigeot 		return -1;
28289bbdcc9SFrançois Tigeot 	}
283160e34d7SFrançois Tigeot 
28489bbdcc9SFrançois Tigeot 	return rman_get_start(res);
285160e34d7SFrançois Tigeot }
286160e34d7SFrançois Tigeot 
287160e34d7SFrançois Tigeot static inline phys_addr_t
pci_resource_len(struct pci_dev * pdev,int bar)288160e34d7SFrançois Tigeot pci_resource_len(struct pci_dev *pdev, int bar)
289160e34d7SFrançois Tigeot {
290160e34d7SFrançois Tigeot 	struct resource_list_entry *rle;
291160e34d7SFrançois Tigeot 
292160e34d7SFrançois Tigeot 	rle = _pci_get_rle(pdev, bar);
293160e34d7SFrançois Tigeot 	if (rle == NULL)
294160e34d7SFrançois Tigeot 		return -1;
295160e34d7SFrançois Tigeot 
296160e34d7SFrançois Tigeot 	return  rman_get_size(rle->res);
297160e34d7SFrançois Tigeot }
298160e34d7SFrançois Tigeot 
pci_iomap(struct pci_dev * dev,int bar,unsigned long maxlen)29928596060SFrançois Tigeot static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
30028596060SFrançois Tigeot {
30128596060SFrançois Tigeot 	resource_size_t base, size;
30228596060SFrançois Tigeot 
30328596060SFrançois Tigeot 	base = pci_resource_start(dev, bar);
30428596060SFrançois Tigeot 	size = pci_resource_len(dev, bar);
30528596060SFrançois Tigeot 
30628596060SFrançois Tigeot 	if (base == 0)
30728596060SFrançois Tigeot 		return NULL;
30828596060SFrançois Tigeot 
30928596060SFrançois Tigeot 	if (maxlen && size > maxlen)
31028596060SFrançois Tigeot 		size = maxlen;
31128596060SFrançois Tigeot 
31228596060SFrançois Tigeot 	return ioremap(base, size);
31328596060SFrançois Tigeot }
31428596060SFrançois Tigeot 
315abdc2210SFrançois Tigeot static inline int
pci_bus_read_config_byte(struct pci_bus * bus,unsigned int devfn,int where,u8 * val)316abdc2210SFrançois Tigeot pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val)
317abdc2210SFrançois Tigeot {
318abdc2210SFrançois Tigeot 	const struct pci_dev *pdev = container_of(&bus, struct pci_dev, bus);
319abdc2210SFrançois Tigeot 
320abdc2210SFrançois Tigeot 	*val = (u8)pci_read_config(pdev->dev.bsddev, where, 1);
321abdc2210SFrançois Tigeot 	return 0;
322abdc2210SFrançois Tigeot }
323abdc2210SFrançois Tigeot 
324abdc2210SFrançois Tigeot static inline int
pci_bus_read_config_word(struct pci_bus * bus,unsigned int devfn,int where,u16 * val)325abdc2210SFrançois Tigeot pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val)
326abdc2210SFrançois Tigeot {
327abdc2210SFrançois Tigeot 	const struct pci_dev *pdev = container_of(&bus, struct pci_dev, bus);
328abdc2210SFrançois Tigeot 
329abdc2210SFrançois Tigeot 	*val = (u16)pci_read_config(pdev->dev.bsddev, where, 2);
330abdc2210SFrançois Tigeot 	return 0;
331abdc2210SFrançois Tigeot }
332abdc2210SFrançois Tigeot 
333ae96415fSFrançois Tigeot static inline const char *
pci_name(struct pci_dev * pdev)334ae96415fSFrançois Tigeot pci_name(struct pci_dev *pdev)
335ae96415fSFrançois Tigeot {
336ae96415fSFrançois Tigeot 	return device_get_desc(pdev->dev.bsddev);
337ae96415fSFrançois Tigeot }
338ae96415fSFrançois Tigeot 
33959e561f5SFrançois Tigeot static inline void *
pci_get_drvdata(struct pci_dev * pdev)34059e561f5SFrançois Tigeot pci_get_drvdata(struct pci_dev *pdev)
34159e561f5SFrançois Tigeot {
34259e561f5SFrançois Tigeot 	return pdev->pci_dev_data;
34359e561f5SFrançois Tigeot }
34459e561f5SFrançois Tigeot 
34559e561f5SFrançois Tigeot static inline void
pci_set_drvdata(struct pci_dev * pdev,void * data)34659e561f5SFrançois Tigeot pci_set_drvdata(struct pci_dev *pdev, void *data)
34759e561f5SFrançois Tigeot {
34859e561f5SFrançois Tigeot 	pdev->pci_dev_data = data;
34959e561f5SFrançois Tigeot }
35059e561f5SFrançois Tigeot 
35159e561f5SFrançois Tigeot static inline int
pci_register_driver(struct pci_driver * drv)35259e561f5SFrançois Tigeot pci_register_driver(struct pci_driver *drv)
35359e561f5SFrançois Tigeot {
3541dedbd3bSFrançois Tigeot 	/* pci_register_driver not implemented */
35559e561f5SFrançois Tigeot 	return 0;
35659e561f5SFrançois Tigeot }
35759e561f5SFrançois Tigeot 
3587857f1b8SFrançois Tigeot static inline void
pci_unregister_driver(struct pci_driver * dev)3591dedbd3bSFrançois Tigeot pci_unregister_driver(struct pci_driver *dev)
3601dedbd3bSFrançois Tigeot {
3611dedbd3bSFrançois Tigeot 	/* pci_unregister_driver not implemented */
3621dedbd3bSFrançois Tigeot }
3631dedbd3bSFrançois Tigeot 
3641dedbd3bSFrançois Tigeot static inline void
pci_clear_master(struct pci_dev * pdev)3657857f1b8SFrançois Tigeot pci_clear_master(struct pci_dev *pdev)
3667857f1b8SFrançois Tigeot {
3677857f1b8SFrançois Tigeot 	pci_disable_busmaster(pdev->dev.bsddev);
3687857f1b8SFrançois Tigeot }
3697857f1b8SFrançois Tigeot 
3707857f1b8SFrançois Tigeot static inline void
pci_set_master(struct pci_dev * pdev)3717857f1b8SFrançois Tigeot pci_set_master(struct pci_dev *pdev)
3727857f1b8SFrançois Tigeot {
3737857f1b8SFrançois Tigeot 	pci_enable_busmaster(pdev->dev.bsddev);
3747857f1b8SFrançois Tigeot }
3757857f1b8SFrançois Tigeot 
3767857f1b8SFrançois Tigeot static inline int
pci_pcie_cap(struct pci_dev * pdev)3777857f1b8SFrançois Tigeot pci_pcie_cap(struct pci_dev *pdev)
3787857f1b8SFrançois Tigeot {
3797857f1b8SFrançois Tigeot 	return pci_get_pciecap_ptr(pdev->dev.bsddev);
3807857f1b8SFrançois Tigeot }
3817857f1b8SFrançois Tigeot 
382f792f2bdSFrançois Tigeot /* DRM_MAX_PCI_RESOURCE */
383f792f2bdSFrançois Tigeot #define DEVICE_COUNT_RESOURCE	6
384f792f2bdSFrançois Tigeot 
385465fa37bSFrançois Tigeot #include <uapi/linux/pci_regs.h>
386465fa37bSFrançois Tigeot 
387465fa37bSFrançois Tigeot /* From FreeBSD */
388*78973132SSergey Zigachev 
389*78973132SSergey Zigachev static inline int
pci_enable_device(struct pci_dev * pdev)390*78973132SSergey Zigachev pci_enable_device(struct pci_dev *pdev)
391*78973132SSergey Zigachev {
392*78973132SSergey Zigachev 
393*78973132SSergey Zigachev 	pci_enable_io(pdev->dev.bsddev, SYS_RES_IOPORT);
394*78973132SSergey Zigachev 	pci_enable_io(pdev->dev.bsddev, SYS_RES_MEMORY);
395*78973132SSergey Zigachev 	return (0);
396*78973132SSergey Zigachev }
397*78973132SSergey Zigachev 
398*78973132SSergey Zigachev static inline void
pci_disable_device(struct pci_dev * pdev)399*78973132SSergey Zigachev pci_disable_device(struct pci_dev *pdev)
400*78973132SSergey Zigachev {
401*78973132SSergey Zigachev 
402*78973132SSergey Zigachev 	pci_disable_busmaster(pdev->dev.bsddev);
403*78973132SSergey Zigachev }
404*78973132SSergey Zigachev 
pcie_cap_has_devctl(const struct pci_dev * dev)405465fa37bSFrançois Tigeot static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
406465fa37bSFrançois Tigeot {
407465fa37bSFrançois Tigeot 		return true;
408465fa37bSFrançois Tigeot }
409465fa37bSFrançois Tigeot 
410465fa37bSFrançois Tigeot static inline int
pci_find_capability(struct pci_dev * pdev,int capid)411465fa37bSFrançois Tigeot pci_find_capability(struct pci_dev *pdev, int capid)
412465fa37bSFrançois Tigeot {
413465fa37bSFrançois Tigeot 	int reg;
414465fa37bSFrançois Tigeot 
415465fa37bSFrançois Tigeot 	if (pci_find_extcap(pdev->dev.bsddev, capid, &reg))
416465fa37bSFrançois Tigeot 		return (0);
417465fa37bSFrançois Tigeot 	return (reg);
418465fa37bSFrançois Tigeot }
419465fa37bSFrançois Tigeot 
pcie_flags_reg(struct pci_dev * dev)420465fa37bSFrançois Tigeot static inline u16 pcie_flags_reg(struct pci_dev *dev)
421465fa37bSFrançois Tigeot {
422465fa37bSFrançois Tigeot 	int pos;
423465fa37bSFrançois Tigeot 	u16 reg16;
424465fa37bSFrançois Tigeot 
425465fa37bSFrançois Tigeot 	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
426465fa37bSFrançois Tigeot 	if (!pos)
427465fa37bSFrançois Tigeot 		return 0;
428465fa37bSFrançois Tigeot 
429465fa37bSFrançois Tigeot 	pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
430465fa37bSFrançois Tigeot 
431465fa37bSFrançois Tigeot 	return reg16;
432465fa37bSFrançois Tigeot }
433465fa37bSFrançois Tigeot 
pci_pcie_type(struct pci_dev * dev)434465fa37bSFrançois Tigeot static inline int pci_pcie_type(struct pci_dev *dev)
435465fa37bSFrançois Tigeot {
436465fa37bSFrançois Tigeot 	return (pcie_flags_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4;
437465fa37bSFrançois Tigeot }
438465fa37bSFrançois Tigeot 
439465fa37bSFrançois Tigeot 
pcie_cap_version(struct pci_dev * dev)440465fa37bSFrançois Tigeot static inline int pcie_cap_version(struct pci_dev *dev)
441465fa37bSFrançois Tigeot {
442465fa37bSFrançois Tigeot 	return pcie_flags_reg(dev) & PCI_EXP_FLAGS_VERS;
443465fa37bSFrançois Tigeot }
444465fa37bSFrançois Tigeot 
pcie_cap_has_lnkctl(struct pci_dev * dev)445465fa37bSFrançois Tigeot static inline bool pcie_cap_has_lnkctl(struct pci_dev *dev)
446465fa37bSFrançois Tigeot {
447465fa37bSFrançois Tigeot 	int type = pci_pcie_type(dev);
448465fa37bSFrançois Tigeot 
449465fa37bSFrançois Tigeot 	return pcie_cap_version(dev) > 1 ||
450465fa37bSFrançois Tigeot 	       type == PCI_EXP_TYPE_ROOT_PORT ||
451465fa37bSFrançois Tigeot 	       type == PCI_EXP_TYPE_ENDPOINT ||
452465fa37bSFrançois Tigeot 	       type == PCI_EXP_TYPE_LEG_END;
453465fa37bSFrançois Tigeot }
454465fa37bSFrançois Tigeot 
pcie_cap_has_sltctl(struct pci_dev * dev)455465fa37bSFrançois Tigeot static inline bool pcie_cap_has_sltctl(struct pci_dev *dev)
456465fa37bSFrançois Tigeot {
457465fa37bSFrançois Tigeot 	int type = pci_pcie_type(dev);
458465fa37bSFrançois Tigeot 
459465fa37bSFrançois Tigeot 	return pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT ||
460465fa37bSFrançois Tigeot 	    (type == PCI_EXP_TYPE_DOWNSTREAM &&
461465fa37bSFrançois Tigeot 	    pcie_flags_reg(dev) & PCI_EXP_FLAGS_SLOT);
462465fa37bSFrançois Tigeot }
463465fa37bSFrançois Tigeot 
pcie_cap_has_rtctl(struct pci_dev * dev)464465fa37bSFrançois Tigeot static inline bool pcie_cap_has_rtctl(struct pci_dev *dev)
465465fa37bSFrançois Tigeot {
466465fa37bSFrançois Tigeot 	int type = pci_pcie_type(dev);
467465fa37bSFrançois Tigeot 
468465fa37bSFrançois Tigeot 	return pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT ||
469465fa37bSFrançois Tigeot 	    type == PCI_EXP_TYPE_RC_EC;
470465fa37bSFrançois Tigeot }
471465fa37bSFrançois Tigeot 
472465fa37bSFrançois Tigeot static inline bool
pcie_capability_reg_implemented(struct pci_dev * dev,int pos)473465fa37bSFrançois Tigeot pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
474465fa37bSFrançois Tigeot {
475465fa37bSFrançois Tigeot 	if (!pci_is_pcie(dev->dev.bsddev))
476465fa37bSFrançois Tigeot 		return false;
477465fa37bSFrançois Tigeot 
478465fa37bSFrançois Tigeot 	switch (pos) {
479465fa37bSFrançois Tigeot 	case PCI_EXP_FLAGS_TYPE:
480465fa37bSFrançois Tigeot 		return true;
481465fa37bSFrançois Tigeot 	case PCI_EXP_DEVCAP:
482465fa37bSFrançois Tigeot 	case PCI_EXP_DEVCTL:
483465fa37bSFrançois Tigeot 	case PCI_EXP_DEVSTA:
484465fa37bSFrançois Tigeot 		return pcie_cap_has_devctl(dev);
485465fa37bSFrançois Tigeot 	case PCI_EXP_LNKCAP:
486465fa37bSFrançois Tigeot 	case PCI_EXP_LNKCTL:
487465fa37bSFrançois Tigeot 	case PCI_EXP_LNKSTA:
488465fa37bSFrançois Tigeot 		return pcie_cap_has_lnkctl(dev);
489465fa37bSFrançois Tigeot 	case PCI_EXP_SLTCAP:
490465fa37bSFrançois Tigeot 	case PCI_EXP_SLTCTL:
491465fa37bSFrançois Tigeot 	case PCI_EXP_SLTSTA:
492465fa37bSFrançois Tigeot 		return pcie_cap_has_sltctl(dev);
493465fa37bSFrançois Tigeot 	case PCI_EXP_RTCTL:
494465fa37bSFrançois Tigeot 	case PCI_EXP_RTCAP:
495465fa37bSFrançois Tigeot 	case PCI_EXP_RTSTA:
496465fa37bSFrançois Tigeot 		return pcie_cap_has_rtctl(dev);
497465fa37bSFrançois Tigeot 	case PCI_EXP_DEVCAP2:
498465fa37bSFrançois Tigeot 	case PCI_EXP_DEVCTL2:
499465fa37bSFrançois Tigeot 	case PCI_EXP_LNKCAP2:
500465fa37bSFrançois Tigeot 	case PCI_EXP_LNKCTL2:
501465fa37bSFrançois Tigeot 	case PCI_EXP_LNKSTA2:
502465fa37bSFrançois Tigeot 		return pcie_cap_version(dev) > 1;
503465fa37bSFrançois Tigeot 	default:
504465fa37bSFrançois Tigeot 		return false;
505465fa37bSFrançois Tigeot 	}
506465fa37bSFrançois Tigeot }
507465fa37bSFrançois Tigeot 
5086bdbad30SFrançois Tigeot static inline void __iomem __must_check *
pci_map_rom(struct pci_dev * pdev,size_t * size)5096bdbad30SFrançois Tigeot pci_map_rom(struct pci_dev *pdev, size_t *size)
5106bdbad30SFrançois Tigeot {
5116bdbad30SFrançois Tigeot 	return vga_pci_map_bios(device_get_parent(pdev->dev.bsddev), size);
5126bdbad30SFrançois Tigeot }
5136bdbad30SFrançois Tigeot 
5146bdbad30SFrançois Tigeot static inline void
pci_unmap_rom(struct pci_dev * pdev,void __iomem * rom)5156bdbad30SFrançois Tigeot pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
5166bdbad30SFrançois Tigeot {
5176bdbad30SFrançois Tigeot 	vga_pci_unmap_bios(device_get_parent(pdev->dev.bsddev), rom);
5186bdbad30SFrançois Tigeot }
5196bdbad30SFrançois Tigeot 
520a85cb24fSFrançois Tigeot static inline int
pci_resource_flags(struct pci_dev * pdev,int bar)521a85cb24fSFrançois Tigeot pci_resource_flags(struct pci_dev *pdev, int bar)
522a85cb24fSFrançois Tigeot {
523a85cb24fSFrançois Tigeot 	/* Hardcoded to return only the type */
524a85cb24fSFrançois Tigeot 	if ((bar & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) {
525a85cb24fSFrançois Tigeot 		kprintf("pci_resource_flags: pdev=%p bar=%d type=IO\n", pdev, bar);
526a85cb24fSFrançois Tigeot 		return IORESOURCE_IO;
527a85cb24fSFrançois Tigeot 	} else {
528a85cb24fSFrançois Tigeot 		kprintf("pci_resource_flags: pdev=%p bar=%d type=MEM\n", pdev, bar);
529a85cb24fSFrançois Tigeot 		return IORESOURCE_MEM;
530a85cb24fSFrançois Tigeot 	}
531a85cb24fSFrançois Tigeot }
532a85cb24fSFrançois Tigeot 
5333f2dd94aSFrançois Tigeot enum pci_bus_speed {
5343f2dd94aSFrançois Tigeot 	PCIE_SPEED_2_5GT		= 0x14,
5353f2dd94aSFrançois Tigeot 	PCIE_SPEED_5_0GT		= 0x15,
5363f2dd94aSFrançois Tigeot 	PCIE_SPEED_8_0GT		= 0x16,
537*78973132SSergey Zigachev 	PCIE_SPEED_16_0GT		= 0x17,
5383f2dd94aSFrançois Tigeot 	PCI_SPEED_UNKNOWN		= 0xff,
5393f2dd94aSFrançois Tigeot };
5403f2dd94aSFrançois Tigeot 
541*78973132SSergey Zigachev /* Values from Link Status register, PCIe r3.1, sec 7.8.8 */
542*78973132SSergey Zigachev enum pcie_link_width {
543*78973132SSergey Zigachev 	PCIE_LNK_WIDTH_RESRV	= 0x00,
544*78973132SSergey Zigachev 	PCIE_LNK_X1		= 0x01,
545*78973132SSergey Zigachev 	PCIE_LNK_X2		= 0x02,
546*78973132SSergey Zigachev 	PCIE_LNK_X4		= 0x04,
547*78973132SSergey Zigachev 	PCIE_LNK_X8		= 0x08,
548*78973132SSergey Zigachev 	PCIE_LNK_X12		= 0x0c,
549*78973132SSergey Zigachev 	PCIE_LNK_X16		= 0x10,
550*78973132SSergey Zigachev 	PCIE_LNK_X32		= 0x20,
551*78973132SSergey Zigachev 	PCIE_LNK_WIDTH_UNKNOWN	= 0xff,
552*78973132SSergey Zigachev };
553*78973132SSergey Zigachev 
5543f2dd94aSFrançois Tigeot int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val);
5553f2dd94aSFrançois Tigeot 
556*78973132SSergey Zigachev #define	PCIER_LINK_CAP		0xc
557*78973132SSergey Zigachev 
558*78973132SSergey Zigachev static inline enum pci_bus_speed
pcie_get_speed_cap(struct pci_dev * dev)559*78973132SSergey Zigachev pcie_get_speed_cap(struct pci_dev *dev)
560*78973132SSergey Zigachev {
561*78973132SSergey Zigachev 	device_t root;
562*78973132SSergey Zigachev 	uint32_t lnkcap, lnkcap2;
563*78973132SSergey Zigachev 	int error, pos;
564*78973132SSergey Zigachev 
565*78973132SSergey Zigachev 	root = device_get_parent(dev->dev.bsddev);
566*78973132SSergey Zigachev 	if (root == NULL)
567*78973132SSergey Zigachev 		return (PCI_SPEED_UNKNOWN);
568*78973132SSergey Zigachev 	root = device_get_parent(root);
569*78973132SSergey Zigachev 	if (root == NULL)
570*78973132SSergey Zigachev 		return (PCI_SPEED_UNKNOWN);
571*78973132SSergey Zigachev 	root = device_get_parent(root);
572*78973132SSergey Zigachev 	if (root == NULL)
573*78973132SSergey Zigachev 		return (PCI_SPEED_UNKNOWN);
574*78973132SSergey Zigachev 
575*78973132SSergey Zigachev 	if (pci_get_vendor(root) == PCI_VENDOR_ID_VIA ||
576*78973132SSergey Zigachev 	    pci_get_vendor(root) == PCI_VENDOR_ID_SERVERWORKS)
577*78973132SSergey Zigachev 		return (PCI_SPEED_UNKNOWN);
578*78973132SSergey Zigachev 
579*78973132SSergey Zigachev 	if ((error = pci_find_extcap(root, PCIY_EXPRESS, &pos)) != 0)
580*78973132SSergey Zigachev 		return (PCI_SPEED_UNKNOWN);
581*78973132SSergey Zigachev 
582*78973132SSergey Zigachev 	lnkcap2 = pci_read_config(root, pos + PCIER_LINK_CAP2, 4);
583*78973132SSergey Zigachev 
584*78973132SSergey Zigachev 	if (lnkcap2) {	/* PCIe r3.0-compliant */
585*78973132SSergey Zigachev 		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
586*78973132SSergey Zigachev 			return (PCIE_SPEED_2_5GT);
587*78973132SSergey Zigachev 		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
588*78973132SSergey Zigachev 			return (PCIE_SPEED_5_0GT);
589*78973132SSergey Zigachev 		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
590*78973132SSergey Zigachev 			return (PCIE_SPEED_8_0GT);
591*78973132SSergey Zigachev 		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
592*78973132SSergey Zigachev 			return (PCIE_SPEED_16_0GT);
593*78973132SSergey Zigachev 	} else {	/* pre-r3.0 */
594*78973132SSergey Zigachev 		lnkcap = pci_read_config(root, pos + PCIER_LINK_CAP, 4);
595*78973132SSergey Zigachev 		if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
596*78973132SSergey Zigachev 			return (PCIE_SPEED_2_5GT);
597*78973132SSergey Zigachev 		if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
598*78973132SSergey Zigachev 			return (PCIE_SPEED_5_0GT);
599*78973132SSergey Zigachev 		if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
600*78973132SSergey Zigachev 			return (PCIE_SPEED_8_0GT);
601*78973132SSergey Zigachev 		if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
602*78973132SSergey Zigachev 			return (PCIE_SPEED_16_0GT);
603*78973132SSergey Zigachev 	}
604*78973132SSergey Zigachev 	return (PCI_SPEED_UNKNOWN);
605*78973132SSergey Zigachev }
606*78973132SSergey Zigachev 
607*78973132SSergey Zigachev static inline enum pcie_link_width
pcie_get_width_cap(struct pci_dev * dev)608*78973132SSergey Zigachev pcie_get_width_cap(struct pci_dev *dev)
609*78973132SSergey Zigachev {
610*78973132SSergey Zigachev 	uint32_t lnkcap;
611*78973132SSergey Zigachev 
612*78973132SSergey Zigachev 	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
613*78973132SSergey Zigachev 	if (lnkcap)
614*78973132SSergey Zigachev 		return ((lnkcap & PCI_EXP_LNKCAP_MLW) >> 4);
615*78973132SSergey Zigachev 
616*78973132SSergey Zigachev 	return (PCIE_LNK_WIDTH_UNKNOWN);
617*78973132SSergey Zigachev }
618*78973132SSergey Zigachev 
6191f0f7e1cSFrançois Tigeot #include <linux/pci-dma-compat.h>
6201f0f7e1cSFrançois Tigeot 
6215af3f531SFrançois Tigeot #endif /* LINUX_PCI_H */
622