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, ®))
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, ®16);
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