mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-06 17:12:01 +08:00
[DM/Feature] Basic PCI/PCIe (Peripheral Component Interconnect Express) bus
PCI/PCIe have better performance and more devices support, such as NVMe, GPU, Powerful NIC (Like RDMA). PCI/PCIe can access control by IOMMU that the virtualiztion and userspace driver will more safety. PCI/PCIe device could hot plugging, no design modifications SoC required, PCI/PCIe on Embedded SoC is popular now. We make a simple framework to support them. Feature Lists: 1.PCI INTx: the INT[A-D] pin IRQ for legacy PCI, work with platform PIC. 2.MSI/MSI-X: the message write IRQ for PCIe, work with platform's PIC. 3.PME: we only support the D0, D1, D2, D3HOT, D3COLD init by framework. 4.Endpoint: a simple EP framework for PCI FPGA or NTB function. 5.OFW: we only support work on OFW SoC, ACPI support in the future maybe. Host controller: 1. Common PCI host controller on ECAM. 2. Generic PCI host controller on ECAM. Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
@@ -23,6 +23,7 @@ rsource "hwcrypto/Kconfig"
|
||||
rsource "wlan/Kconfig"
|
||||
rsource "virtio/Kconfig"
|
||||
rsource "ofw/Kconfig"
|
||||
rsource "pci/Kconfig"
|
||||
rsource "pic/Kconfig"
|
||||
rsource "pin/Kconfig"
|
||||
rsource "pinctrl/Kconfig"
|
||||
|
||||
604
components/drivers/include/drivers/pci.h
Normal file
604
components/drivers/include/drivers/pci.h
Normal file
File diff suppressed because it is too large
Load Diff
179
components/drivers/include/drivers/pci_endpoint.h
Normal file
179
components/drivers/include/drivers/pci_endpoint.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-08-25 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __PCI_ENDPOINT_H__
|
||||
#define __PCI_ENDPOINT_H__
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
enum rt_pci_ep_pin
|
||||
{
|
||||
RT_PCI_EP_PIN_UNKNOWN,
|
||||
RT_PCI_EP_PIN_INTA,
|
||||
RT_PCI_EP_PIN_INTB,
|
||||
RT_PCI_EP_PIN_INTC,
|
||||
RT_PCI_EP_PIN_INTD,
|
||||
};
|
||||
|
||||
enum rt_pci_ep_irq
|
||||
{
|
||||
RT_PCI_EP_IRQ_UNKNOWN,
|
||||
RT_PCI_EP_IRQ_LEGACY,
|
||||
RT_PCI_EP_IRQ_MSI,
|
||||
RT_PCI_EP_IRQ_MSIX,
|
||||
};
|
||||
|
||||
struct rt_pci_ep_header
|
||||
{
|
||||
rt_uint16_t vendor;
|
||||
rt_uint16_t device;
|
||||
rt_uint8_t revision;
|
||||
rt_uint8_t progif;
|
||||
rt_uint8_t subclass;
|
||||
rt_uint8_t class_code;
|
||||
rt_uint8_t cache_line_size;
|
||||
rt_uint16_t subsystem_vendor;
|
||||
rt_uint16_t subsystem_device;
|
||||
|
||||
enum rt_pci_ep_pin intx;
|
||||
};
|
||||
|
||||
struct rt_pci_ep_bar
|
||||
{
|
||||
/* To PCI Bus */
|
||||
struct rt_pci_bus_resource bus;
|
||||
/* To CPU */
|
||||
rt_ubase_t cpu_addr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Type of MSI-X table, For more format detail,
|
||||
* please read `components/drivers/include/drivers/pci_msi.h`
|
||||
*/
|
||||
struct rt_pci_ep_msix_tbl
|
||||
{
|
||||
union
|
||||
{
|
||||
rt_uint64_t msg_addr;
|
||||
struct
|
||||
{
|
||||
rt_uint32_t msg_addr_upper;
|
||||
rt_uint32_t msg_addr_lower;
|
||||
};
|
||||
};
|
||||
rt_uint32_t msg_data;
|
||||
rt_uint32_t vector_ctrl;
|
||||
};
|
||||
|
||||
struct rt_pci_ep_ops;
|
||||
|
||||
struct rt_pci_ep
|
||||
{
|
||||
rt_list_t list;
|
||||
const char *name;
|
||||
|
||||
struct rt_ref ref;
|
||||
|
||||
const struct rt_device *rc_dev;
|
||||
const struct rt_pci_ep_ops *ops;
|
||||
|
||||
rt_uint8_t max_functions;
|
||||
RT_BITMAP_DECLARE(functions_map, 8);
|
||||
rt_list_t epf_nodes;
|
||||
struct rt_mutex lock;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct rt_pci_epf
|
||||
{
|
||||
rt_list_t list;
|
||||
const char *name;
|
||||
|
||||
struct rt_pci_ep_header *header;
|
||||
struct rt_pci_ep_bar bar[PCI_STD_NUM_BARS];
|
||||
|
||||
rt_uint8_t msi_interrupts;
|
||||
rt_uint16_t msix_interrupts;
|
||||
rt_uint8_t func_no;
|
||||
|
||||
struct rt_pci_ep *ep;
|
||||
};
|
||||
|
||||
struct rt_pci_ep_ops
|
||||
{
|
||||
rt_err_t (*write_header)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_header *hdr);
|
||||
|
||||
rt_err_t (*set_bar)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_bar *bar, int bar_idx);
|
||||
rt_err_t (*clear_bar)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_bar *bar, int bar_idx);
|
||||
|
||||
rt_err_t (*map_addr)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
rt_ubase_t addr, rt_uint64_t pci_addr, rt_size_t size);
|
||||
rt_err_t (*unmap_addr)(struct rt_pci_ep *ep, rt_uint8_t func_no, rt_ubase_t addr);
|
||||
|
||||
rt_err_t (*set_msi)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned irq_nr);
|
||||
rt_err_t (*get_msi)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned *out_irq_nr);
|
||||
|
||||
rt_err_t (*set_msix)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned irq_nr, int bar_idx, rt_off_t offset);
|
||||
rt_err_t (*get_msix)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned *out_irq_nr);
|
||||
|
||||
rt_err_t (*raise_irq)(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
enum rt_pci_ep_irq type, unsigned irq);
|
||||
|
||||
rt_err_t (*start)(struct rt_pci_ep *ep);
|
||||
rt_err_t (*stop)(struct rt_pci_ep *ep);
|
||||
};
|
||||
|
||||
rt_err_t rt_pci_ep_write_header(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_header *hdr);
|
||||
|
||||
rt_err_t rt_pci_ep_set_bar(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_bar *bar, int bar_idx);
|
||||
rt_err_t rt_pci_ep_clear_bar(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
struct rt_pci_ep_bar *bar, int bar_idx);
|
||||
|
||||
rt_err_t rt_pci_ep_map_addr(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
rt_ubase_t addr, rt_uint64_t pci_addr, rt_size_t size);
|
||||
rt_err_t rt_pci_ep_unmap_addr(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
rt_ubase_t addr);
|
||||
|
||||
rt_err_t rt_pci_ep_set_msi(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned irq_nr);
|
||||
rt_err_t rt_pci_ep_get_msi(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned *out_irq_nr);
|
||||
|
||||
rt_err_t rt_pci_ep_set_msix(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned irq_nr, int bar_idx, rt_off_t offset);
|
||||
rt_err_t rt_pci_ep_get_msix(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
unsigned *out_irq_nr);
|
||||
|
||||
rt_err_t rt_pci_ep_raise_irq(struct rt_pci_ep *ep, rt_uint8_t func_no,
|
||||
enum rt_pci_ep_irq type, unsigned irq);
|
||||
|
||||
rt_err_t rt_pci_ep_start(struct rt_pci_ep *ep);
|
||||
rt_err_t rt_pci_ep_stop(struct rt_pci_ep *ep);
|
||||
|
||||
rt_err_t rt_pci_ep_register(struct rt_pci_ep *ep);
|
||||
rt_err_t rt_pci_ep_unregister(struct rt_pci_ep *ep);
|
||||
|
||||
rt_err_t rt_pci_ep_add_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);
|
||||
rt_err_t rt_pci_ep_remove_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);
|
||||
|
||||
struct rt_pci_ep *rt_pci_ep_get(const char *name);
|
||||
void rt_pci_ep_put(struct rt_pci_ep *ep);
|
||||
|
||||
#endif /* __PCI_ENDPOINT_H__ */
|
||||
189
components/drivers/include/drivers/pci_msi.h
Normal file
189
components/drivers/include/drivers/pci_msi.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-08-25 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __PCI_MSI_H__
|
||||
#define __PCI_MSI_H__
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
/*
|
||||
* MSI Format:
|
||||
* T0: 32-bit Address
|
||||
* T1: 64-bit Address
|
||||
* T2: 32-bit Address with Per-Vector Masking
|
||||
* T3: 64-bit Address with Per-Vector Masking
|
||||
*
|
||||
* 31 16 15 8 7 0
|
||||
* +---------------------------+-----------------+---------------+
|
||||
* | Message Control | Next Capability | Capability ID | DW0
|
||||
* | | Pointer | (05h) |
|
||||
* +---------------------------+-----------------+---------------+
|
||||
* | Message Address [31:0] | DW1
|
||||
* +-------------------------------------------------------------+
|
||||
* | Message Address [63:32] | DW2 (T1: only 64-bit)
|
||||
* +---------------------------+---------------------------------+
|
||||
* | Reserved | Message Data | DW3
|
||||
* +---------------------------+---------------------------------+
|
||||
* | Mask Bits | DW4 (T2/T3: only with Per-Vector Masking)
|
||||
* +-------------------------------------------------------------+
|
||||
* | Pending Bits | DW5 (T2/T3: only with Per-Vector Masking)
|
||||
* +-------------------------------------------------------------+
|
||||
*
|
||||
* MSI Message Control:
|
||||
*
|
||||
* 15 9 8 7 6 4 3 1 0
|
||||
* +----------------------+---+---+---------------+----------+---+
|
||||
* | Reserved | | | | | |
|
||||
* +----------------------+---+---+---------------+----------+---+
|
||||
* ^ ^ ^ ^ ^
|
||||
* | | | | |
|
||||
* | | | | +---- MSI Enable (RW)
|
||||
* | | | +----------- Multiple Message Capable (RO, log2n, [n <= 5])
|
||||
* | | +------------------------- Multiple Message Enable (RW, log2n, [n <= 5])
|
||||
* | +----------------------------------- 64-bit Address Capable
|
||||
* +--------------------------------------- Per-Vector Masking Capable
|
||||
*/
|
||||
|
||||
struct rt_pci_msi_conf
|
||||
{
|
||||
rt_uint32_t mask;
|
||||
rt_uint8_t mask_pos;
|
||||
int default_irq;
|
||||
|
||||
struct
|
||||
{
|
||||
rt_uint8_t is_masking:1;
|
||||
rt_uint8_t is_64bit:1;
|
||||
rt_uint8_t multi_msg_max:3; /* log2 num of messages allocated */
|
||||
rt_uint8_t multi_msg_use:3; /* log2 num of messages supported */
|
||||
} cap;
|
||||
};
|
||||
|
||||
/*
|
||||
* MSI-X Format:
|
||||
*
|
||||
* 31 16 15 8 7 0
|
||||
* +---------------------------+-----------------+---------------+
|
||||
* | Message Control | Next Capability | Capability ID | DW0
|
||||
* | | Pointer | (11h) |
|
||||
* +---------------------------+-----------------+---+-----------+
|
||||
* | MSI-X Table Offset | Table BIR | DW1 (BIR: BAR Index Register)
|
||||
* +-------------------------------------------------+-----------+ |
|
||||
* | Pending Bit Array (PBA) Offset | PBA BIR | DW2 --------+ |
|
||||
* +-------------------------------------------------+-----------+ | |
|
||||
* | |
|
||||
* MSI-X Message Control: | |
|
||||
* | |
|
||||
* 15 14 13 11 10 0 | |
|
||||
* +---+---+----------+------------------------------------------+ | |
|
||||
* | | | Reserved | Table Size in N-1 (RO) | | |
|
||||
* +---+---+----------+------------------------------------------+ | |
|
||||
* ^ ^ | |
|
||||
* | | | |
|
||||
* | +---- Function Mask (RW) | |
|
||||
* +-------- MSI-X Enable (RW) | |
|
||||
* | |
|
||||
* MSI-X Table (BAR[Table BIR] + MSI-X Table Offset): | |
|
||||
* | |
|
||||
* DW3 DW2 DW1 DW0 | |
|
||||
* +----------------+--------------+---------------+---------------+ <---------|-+
|
||||
* | Vector Control | Message Data | Upper Address | Lower Address | Entry 0 |
|
||||
* +----------------+--------------+---------------+---------------+ |
|
||||
* | Vector Control | Message Data | Upper Address | Lower Address | Entry 1 |
|
||||
* +----------------+--------------+---------------+---------------+ |
|
||||
* | ...... | ...... | ...... | ...... | |
|
||||
* +----------------+--------------+---------------+---------------+ |
|
||||
* | Vector Control | Message Data | Upper Address | Lower Address | Entry N-1 |
|
||||
* +----------------+--------------+---------------+---------------+ |
|
||||
* ^ |
|
||||
* | |
|
||||
* +---- Bit 0 is vector Mask Bit (R/W) |
|
||||
* |
|
||||
* MSI-X Pending Bit Array (BAR[PBA BIR] + Pending Bit Array Offset): |
|
||||
* |
|
||||
* DW1 DW0 |
|
||||
* +-------------------------------+ <-----------------------------------------+
|
||||
* | Pending Bits 0 - 63 | QW 0
|
||||
* +-------------------------------+
|
||||
* | Pending Bits 64 - 127 | QW 1
|
||||
* +-------------------------------+
|
||||
* | ...... |
|
||||
* +-------------------------------+
|
||||
* | Pending Bits | QW (N-1)/64
|
||||
* +-------------------------------+
|
||||
*/
|
||||
|
||||
struct rt_pci_msix_conf
|
||||
{
|
||||
int index;
|
||||
|
||||
rt_uint32_t msg_ctrl;
|
||||
void *table_base;
|
||||
};
|
||||
|
||||
struct rt_pci_msi_msg
|
||||
{
|
||||
rt_uint32_t address_lo;
|
||||
rt_uint32_t address_hi;
|
||||
rt_uint32_t data;
|
||||
};
|
||||
|
||||
struct rt_pci_msi_desc
|
||||
{
|
||||
rt_list_t list;
|
||||
|
||||
int irq;
|
||||
rt_size_t vector_used;
|
||||
rt_size_t vector_count;
|
||||
|
||||
union
|
||||
{
|
||||
/* For MSI-X */
|
||||
rt_bitmap_t *affinity;
|
||||
/* For MSI */
|
||||
rt_bitmap_t **affinities;
|
||||
};
|
||||
|
||||
struct rt_pci_device *pdev;
|
||||
struct rt_pci_msi_msg msg;
|
||||
|
||||
void *write_msi_msg_data;
|
||||
void (*write_msi_msg)(struct rt_pci_msi_desc *, void *);
|
||||
|
||||
rt_bool_t is_msix;
|
||||
union
|
||||
{
|
||||
struct rt_pci_msi_conf msi;
|
||||
struct rt_pci_msix_conf msix;
|
||||
};
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define rt_pci_msi_first_desc(pdev) \
|
||||
(rt_list_isempty(&(pdev)->msi_desc_nodes) ? RT_NULL : \
|
||||
rt_list_first_entry(&(pdev)->msi_desc_nodes, struct rt_pci_msi_desc, list))
|
||||
|
||||
#define rt_pci_msi_for_each_desc(pdev, desc) \
|
||||
rt_list_for_each_entry(desc, &(pdev)->msi_desc_nodes, list)
|
||||
|
||||
#define rt_pci_msix_table_size(flags) ((flags & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
|
||||
|
||||
rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type);
|
||||
|
||||
void rt_pci_msi_shutdown(struct rt_pci_device *pdev);
|
||||
void rt_pci_msix_shutdown(struct rt_pci_device *pdev);
|
||||
void rt_pci_msi_free_irqs(struct rt_pci_device *pdev);
|
||||
void rt_pci_msi_write_msg(struct rt_pci_msi_desc *desc, struct rt_pci_msi_msg *msg);
|
||||
|
||||
void rt_pci_msi_mask_irq(struct rt_pic_irq *pirq);
|
||||
void rt_pci_msi_unmask_irq(struct rt_pic_irq *pirq);
|
||||
|
||||
#endif /* __PCI_MSI_H__ */
|
||||
49
components/drivers/pci/Kconfig
Normal file
49
components/drivers/pci/Kconfig
Normal file
@@ -0,0 +1,49 @@
|
||||
menuconfig RT_USING_PCI
|
||||
bool "Using Peripheral Component Interconnect Express (PCIe/PCI)"
|
||||
depends on RT_USING_DM
|
||||
depends on RT_USING_PIC
|
||||
select RT_USING_ADT
|
||||
select RT_USING_ADT_BITMAP
|
||||
default n
|
||||
|
||||
config RT_PCI_MSI
|
||||
bool "PCI MSI/MSI-X"
|
||||
depends on RT_USING_PCI
|
||||
default y
|
||||
|
||||
config RT_PCI_ENDPOINT
|
||||
bool "PCI Endpoint"
|
||||
depends on RT_USING_PCI
|
||||
select RT_USING_ADT_REF
|
||||
default n
|
||||
|
||||
config RT_PCI_SYS_64BIT
|
||||
bool "PCI System 64bit"
|
||||
depends on RT_USING_PCI
|
||||
depends on ARCH_CPU_64BIT
|
||||
default y
|
||||
|
||||
config RT_PCI_CACHE_LINE_SIZE
|
||||
int "PCI Cache line size"
|
||||
depends on RT_USING_PCI
|
||||
default 8 if ARCH_CPU_64BIT
|
||||
default 4
|
||||
|
||||
config RT_PCI_LOCKLESS
|
||||
bool "PCI Lock less in options"
|
||||
depends on RT_USING_PCI
|
||||
default n
|
||||
|
||||
if RT_USING_PCI
|
||||
|
||||
comment "PCI Device Drivers"
|
||||
|
||||
config RT_PCI_ECAM
|
||||
bool "PCIe ECAM"
|
||||
depends on RT_USING_PCI
|
||||
default y
|
||||
help
|
||||
PCIe Express Enhanced Configuration Access Mechanism
|
||||
|
||||
rsource "host/Kconfig"
|
||||
endif
|
||||
28
components/drivers/pci/SConscript
Normal file
28
components/drivers/pci/SConscript
Normal file
@@ -0,0 +1,28 @@
|
||||
from building import *
|
||||
|
||||
objs = []
|
||||
|
||||
if not GetDepend(['RT_USING_PCI']):
|
||||
Return('objs')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
list = os.listdir(cwd)
|
||||
CPPPATH = [cwd + '/../include']
|
||||
|
||||
src = ['access.c', 'host-bridge.c', 'irq.c', 'pci.c', 'pme.c', 'probe.c']
|
||||
|
||||
if GetDepend(['RT_USING_OFW']):
|
||||
src += ['ofw.c']
|
||||
|
||||
if GetDepend(['RT_PCI_ECAM']):
|
||||
src += ['ecam.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
objs = objs + group
|
||||
|
||||
Return('objs')
|
||||
159
components/drivers/pci/access.c
Executable file
159
components/drivers/pci/access.c
Executable file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
struct rt_spinlock rt_pci_lock = { 0 };
|
||||
|
||||
#ifdef RT_PCI_LOCKLESS
|
||||
#define pci_lock_config(l) do { (void)(l); } while (0)
|
||||
#define pci_unlock_config(l) do { (void)(l); } while (0)
|
||||
#else
|
||||
#define pci_lock_config(l) l = rt_spin_lock_irqsave(&rt_pci_lock)
|
||||
#define pci_unlock_config(l) rt_spin_unlock_irqrestore(&rt_pci_lock, l)
|
||||
#endif
|
||||
|
||||
#define PCI_OPS_READ(name, type) \
|
||||
rt_err_t rt_pci_bus_read_config_##name(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg, type *value) \
|
||||
{ \
|
||||
rt_err_t err; \
|
||||
rt_ubase_t level; \
|
||||
rt_uint32_t data = 0; \
|
||||
pci_lock_config(level); \
|
||||
err = bus->ops->read(bus, devfn, reg, sizeof(type), &data); \
|
||||
*value = err ? (type)(~0) : (type)data; \
|
||||
pci_unlock_config(level); \
|
||||
return err; \
|
||||
}
|
||||
|
||||
#define PCI_OPS_WRITE(name, type) \
|
||||
rt_err_t rt_pci_bus_write_config_##name(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg, type value) \
|
||||
{ \
|
||||
rt_err_t err; \
|
||||
rt_ubase_t level; \
|
||||
pci_lock_config(level); \
|
||||
err = bus->ops->write(bus, devfn, reg, sizeof(type), value); \
|
||||
pci_unlock_config(level); \
|
||||
return err; \
|
||||
}
|
||||
|
||||
#define PCI_OPS(name, type) \
|
||||
PCI_OPS_READ(name, type) \
|
||||
PCI_OPS_WRITE(name, type)
|
||||
|
||||
PCI_OPS(u8, rt_uint8_t)
|
||||
PCI_OPS(u16, rt_uint16_t)
|
||||
PCI_OPS(u32, rt_uint32_t)
|
||||
|
||||
#undef PCI_OP_WRITE
|
||||
#undef PCI_OP_READ
|
||||
#undef PCI_OPS
|
||||
|
||||
rt_err_t rt_pci_bus_read_config_uxx(struct rt_pci_bus *bus,
|
||||
rt_uint32_t devfn, int reg, int width, rt_uint32_t *value)
|
||||
{
|
||||
void *base;
|
||||
|
||||
if ((base = bus->ops->map(bus, devfn, reg)))
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
*value = HWREG8(base);
|
||||
}
|
||||
else if (width == 2)
|
||||
{
|
||||
*value = HWREG16(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = HWREG32(base);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_err_t rt_pci_bus_write_config_uxx(struct rt_pci_bus *bus,
|
||||
rt_uint32_t devfn, int reg, int width, rt_uint32_t value)
|
||||
{
|
||||
void *base;
|
||||
|
||||
if ((base = bus->ops->map(bus, devfn, reg)))
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
HWREG8(base) = value;
|
||||
}
|
||||
else if (width == 2)
|
||||
{
|
||||
HWREG16(base) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
HWREG32(base) = value;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_err_t rt_pci_bus_read_config_generic_u32(struct rt_pci_bus *bus,
|
||||
rt_uint32_t devfn, int reg, int width, rt_uint32_t *value)
|
||||
{
|
||||
void *base;
|
||||
|
||||
if ((base = bus->ops->map(bus, devfn, reg)))
|
||||
{
|
||||
*value = HWREG32(base);
|
||||
|
||||
if (width <= 2)
|
||||
{
|
||||
*value = (*value >> (8 * (reg & 3))) & ((1 << (width * 8)) - 1);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rt_err_t rt_pci_bus_write_config_generic_u32(struct rt_pci_bus *bus,
|
||||
rt_uint32_t devfn, int reg, int width, rt_uint32_t value)
|
||||
{
|
||||
void *base;
|
||||
|
||||
if ((base = bus->ops->map(bus, devfn, reg & ~0x3)))
|
||||
{
|
||||
if (width == 4)
|
||||
{
|
||||
HWREG32(base) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_uint32_t mask, tmp;
|
||||
|
||||
mask = ~(((1 << (width * 8)) - 1) << ((reg & 0x3) * 8));
|
||||
tmp = HWREG32(base) & mask;
|
||||
tmp |= value << ((reg & 0x3) * 8);
|
||||
HWREG32(base) = tmp;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
72
components/drivers/pci/ecam.c
Normal file
72
components/drivers/pci/ecam.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#define DBG_TAG "pci.ecam"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include "ecam.h"
|
||||
|
||||
struct pci_ecam_config_window *pci_ecam_create(struct rt_pci_host_bridge *host_bridge,
|
||||
const struct pci_ecam_ops *ops)
|
||||
{
|
||||
struct pci_ecam_config_window *conf_win = rt_calloc(1, sizeof(*conf_win));
|
||||
|
||||
if (!conf_win)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
conf_win->bus_range = host_bridge->bus_range;
|
||||
conf_win->bus_shift = ops->bus_shift;
|
||||
conf_win->ops = ops;
|
||||
|
||||
host_bridge->ops = (const struct rt_pci_ops *)&ops->pci_ops;
|
||||
|
||||
return conf_win;
|
||||
}
|
||||
|
||||
void *pci_ecam_map(struct rt_pci_bus *bus, rt_uint32_t devfn, int where)
|
||||
{
|
||||
struct pci_ecam_config_window *conf_win = bus->sysdata;
|
||||
const struct pci_ecam_ops *eops = conf_win->ops;
|
||||
void *win = conf_win->win, *map;
|
||||
rt_uint32_t busn = bus->number, bus_shift = eops->bus_shift, devfn_shift = bus_shift - 8;
|
||||
|
||||
busn -= conf_win->bus_range[0];
|
||||
|
||||
if (bus_shift)
|
||||
{
|
||||
rt_uint32_t bus_offset = (busn & PCIE_ECAM_BUS_MASK) << bus_shift;
|
||||
rt_uint32_t devfn_offset = (devfn & PCIE_ECAM_DEVFN_MASK) << devfn_shift;
|
||||
|
||||
where &= PCIE_ECAM_REG_MASK;
|
||||
map = win + (bus_offset | devfn_offset | where);
|
||||
}
|
||||
else
|
||||
{
|
||||
map = win + PCIE_ECAM_OFFSET(busn, devfn, where);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
const struct pci_ecam_ops pci_generic_ecam_ops =
|
||||
{
|
||||
.pci_ops =
|
||||
{
|
||||
.map = pci_ecam_map,
|
||||
.read = rt_pci_bus_read_config_uxx,
|
||||
.write = rt_pci_bus_write_config_uxx,
|
||||
}
|
||||
};
|
||||
69
components/drivers/pci/ecam.h
Normal file
69
components/drivers/pci/ecam.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __RT_PCI_ECAM_H__
|
||||
#define __RT_PCI_ECAM_H__
|
||||
|
||||
#include <drivers/pci.h>
|
||||
#include <drivers/ofw.h>
|
||||
#include <drivers/ofw_io.h>
|
||||
#include <drivers/platform.h>
|
||||
|
||||
/*
|
||||
* Memory address shift values for the byte-level address that
|
||||
* can be used when accessing the PCI Express Configuration Space.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Enhanced Configuration Access Mechanism (ECAM)
|
||||
*
|
||||
* See PCI Express Base Specification, Revision 5.0, Version 1.0,
|
||||
* Section 7.2.2, Table 7-1, p. 677.
|
||||
*/
|
||||
#define PCIE_ECAM_BUS_SHIFT 20 /* Bus number */
|
||||
#define PCIE_ECAM_DEVFN_SHIFT 12 /* Device and Function number */
|
||||
|
||||
#define PCIE_ECAM_BUS_MASK 0xff
|
||||
#define PCIE_ECAM_DEVFN_MASK 0xff
|
||||
#define PCIE_ECAM_REG_MASK 0xfff /* Limit offset to a maximum of 4K */
|
||||
|
||||
#define PCIE_ECAM_BUS(x) (((x) & PCIE_ECAM_BUS_MASK) << PCIE_ECAM_BUS_SHIFT)
|
||||
#define PCIE_ECAM_DEVFN(x) (((x) & PCIE_ECAM_DEVFN_MASK) << PCIE_ECAM_DEVFN_SHIFT)
|
||||
#define PCIE_ECAM_REG(x) ((x) & PCIE_ECAM_REG_MASK)
|
||||
|
||||
#define PCIE_ECAM_OFFSET(bus, devfn, where) \
|
||||
(PCIE_ECAM_BUS(bus) | PCIE_ECAM_DEVFN(devfn) | PCIE_ECAM_REG(where))
|
||||
|
||||
struct pci_ecam_ops
|
||||
{
|
||||
rt_uint32_t bus_shift;
|
||||
const struct rt_pci_ops pci_ops;
|
||||
};
|
||||
|
||||
struct pci_ecam_config_window
|
||||
{
|
||||
rt_uint32_t *bus_range;
|
||||
rt_uint32_t bus_shift;
|
||||
|
||||
void *win;
|
||||
void *priv;
|
||||
const struct pci_ecam_ops *ops;
|
||||
};
|
||||
|
||||
/* Default ECAM ops */
|
||||
extern const struct pci_ecam_ops pci_generic_ecam_ops;
|
||||
|
||||
void *pci_ecam_map(struct rt_pci_bus *bus, rt_uint32_t devfn, int where);
|
||||
struct pci_ecam_config_window *pci_ecam_create(struct rt_pci_host_bridge *host_bridge,
|
||||
const struct pci_ecam_ops *ops);
|
||||
rt_err_t pci_host_common_probe(struct rt_platform_device *pdev);
|
||||
rt_err_t pci_host_common_remove(struct rt_platform_device *pdev);
|
||||
|
||||
#endif /* __RT_PCI_ECAM_H__ */
|
||||
15
components/drivers/pci/endpoint/SConscript
Normal file
15
components/drivers/pci/endpoint/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_PCI_ENDPOINT']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = ['endpoint.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
504
components/drivers/pci/endpoint/endpoint.c
Normal file
504
components/drivers/pci/endpoint/endpoint.c
Normal file
File diff suppressed because it is too large
Load Diff
129
components/drivers/pci/host-bridge.c
Normal file
129
components/drivers/pci/host-bridge.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <drivers/pm.h>
|
||||
#include <drivers/pci.h>
|
||||
|
||||
#ifdef RT_USING_PM
|
||||
struct host_bridge_pm_status
|
||||
{
|
||||
rt_uint8_t mode;
|
||||
rt_bool_t enable;
|
||||
};
|
||||
|
||||
static const enum rt_pci_power system_pci_pm_mode[] =
|
||||
{
|
||||
[PM_SLEEP_MODE_NONE] = RT_PCI_D0,
|
||||
[PM_SLEEP_MODE_IDLE] = RT_PCI_D3HOT,
|
||||
[PM_SLEEP_MODE_LIGHT] = RT_PCI_D1,
|
||||
[PM_SLEEP_MODE_DEEP] = RT_PCI_D1,
|
||||
[PM_SLEEP_MODE_STANDBY] = RT_PCI_D2,
|
||||
[PM_SLEEP_MODE_SHUTDOWN] = RT_PCI_D3COLD,
|
||||
};
|
||||
|
||||
static rt_bool_t pci_device_pm_ops(struct rt_pci_device *pdev, void *data)
|
||||
{
|
||||
struct host_bridge_pm_status *status = data;
|
||||
|
||||
rt_pci_enable_wake(pdev, system_pci_pm_mode[status->mode], status->enable);
|
||||
|
||||
/* To find all devices, always return false */
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
static rt_err_t host_bridge_pm_suspend(const struct rt_device *device, rt_uint8_t mode)
|
||||
{
|
||||
struct host_bridge_pm_status status;
|
||||
struct rt_pci_device *pdev = rt_container_of(device, struct rt_pci_device, parent);
|
||||
|
||||
status.mode = mode;
|
||||
status.enable = RT_FALSE;
|
||||
rt_pci_enum_device(pdev->bus, pci_device_pm_ops, &status);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void host_bridge_pm_resume(const struct rt_device *device, rt_uint8_t mode)
|
||||
{
|
||||
struct host_bridge_pm_status status;
|
||||
struct rt_pci_device *pdev = rt_container_of(device, struct rt_pci_device, parent);
|
||||
|
||||
status.mode = mode;
|
||||
status.enable = RT_TRUE;
|
||||
rt_pci_enum_device(pdev->bus, pci_device_pm_ops, &status);
|
||||
}
|
||||
|
||||
static const struct rt_device_pm_ops host_bridge_pm_ops =
|
||||
{
|
||||
.suspend = host_bridge_pm_suspend,
|
||||
.resume = host_bridge_pm_resume,
|
||||
};
|
||||
#endif /* RT_USING_PM */
|
||||
|
||||
static void host_bridge_free(struct rt_pci_device *pdev)
|
||||
{
|
||||
#ifdef RT_USING_PM
|
||||
rt_pm_device_unregister(&pdev->parent);
|
||||
#endif
|
||||
}
|
||||
|
||||
static rt_err_t host_bridge_probe(struct rt_pci_device *pdev)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
|
||||
rt_pci_set_master(pdev);
|
||||
|
||||
#ifdef RT_USING_PM
|
||||
rt_pm_device_register(&pdev->parent, &host_bridge_pm_ops);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t host_bridge_remove(struct rt_pci_device *pdev)
|
||||
{
|
||||
host_bridge_free(pdev);
|
||||
rt_pci_clear_master(pdev);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t host_bridge_shutdown(struct rt_pci_device *pdev)
|
||||
{
|
||||
host_bridge_free(pdev);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_pci_device_id host_bridge_pci_ids[] =
|
||||
{
|
||||
/* PCI host bridges */
|
||||
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_REDHAT, 0x0008) },
|
||||
/* Any PCI-Express port */
|
||||
{ RT_PCI_DEVICE_CLASS(PCIS_BRIDGE_PCI_NORMAL, ~0) },
|
||||
/* PCI-to-PCI bridge */
|
||||
{ RT_PCI_DEVICE_CLASS(PCIS_BRIDGE_PCI_SUBTRACTIVE, ~0) },
|
||||
/* Any Root Complex Event Collector */
|
||||
{ RT_PCI_DEVICE_CLASS(((PCIS_SYSTEM_RCEC << 8) | 0x00), ~0) },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_pci_driver host_bridge_driver =
|
||||
{
|
||||
.name = "host-bridge",
|
||||
|
||||
.ids = host_bridge_pci_ids,
|
||||
.probe = host_bridge_probe,
|
||||
.remove = host_bridge_remove,
|
||||
.shutdown = host_bridge_shutdown,
|
||||
};
|
||||
RT_PCI_DRIVER_EXPORT(host_bridge_driver);
|
||||
10
components/drivers/pci/host/Kconfig
Normal file
10
components/drivers/pci/host/Kconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
config RT_PCI_HOST_COMMON
|
||||
bool "Common PCI host controller"
|
||||
depends on RT_PCI_ECAM
|
||||
default y
|
||||
|
||||
config RT_PCI_HOST_GENERIC
|
||||
bool "Generic PCI host controller"
|
||||
depends on RT_PCI_ECAM
|
||||
select RT_PCI_HOST_COMMON
|
||||
default y
|
||||
25
components/drivers/pci/host/SConscript
Normal file
25
components/drivers/pci/host/SConscript
Normal file
@@ -0,0 +1,25 @@
|
||||
from building import *
|
||||
|
||||
objs = []
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
list = os.listdir(cwd)
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = []
|
||||
|
||||
if GetDepend(['RT_PCI_HOST_COMMON']):
|
||||
src += ['pci-host-common.c']
|
||||
|
||||
if GetDepend(['RT_PCI_HOST_GENERIC']):
|
||||
src += ['pci-host-generic.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
objs = objs + group
|
||||
|
||||
Return('objs')
|
||||
85
components/drivers/pci/host/pci-host-common.c
Normal file
85
components/drivers/pci/host/pci-host-common.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "../ecam.h"
|
||||
|
||||
rt_err_t pci_host_common_probe(struct rt_platform_device *pdev)
|
||||
{
|
||||
void *base;
|
||||
rt_err_t err;
|
||||
struct rt_device *dev = &pdev->parent;
|
||||
struct pci_ecam_config_window *conf_win;
|
||||
struct rt_pci_host_bridge *host_bridge = rt_pci_host_bridge_alloc(0);
|
||||
|
||||
if (!host_bridge)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
if (!(base = rt_dm_dev_iomap(dev, 0)))
|
||||
{
|
||||
err = -RT_EIO;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
host_bridge->parent.ofw_node = dev->ofw_node;
|
||||
|
||||
if ((err = rt_pci_host_bridge_init(host_bridge)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
host_bridge->sysdata = conf_win = pci_ecam_create(host_bridge,
|
||||
(const struct pci_ecam_ops *)pdev->id->data);
|
||||
|
||||
if (!conf_win)
|
||||
{
|
||||
err = -RT_ENOMEM;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
conf_win->win = base;
|
||||
conf_win->priv = host_bridge;
|
||||
|
||||
if ((err = rt_pci_host_bridge_probe(host_bridge)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
dev->user_data = host_bridge;
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail:
|
||||
if (base)
|
||||
{
|
||||
rt_iounmap(base);
|
||||
}
|
||||
rt_pci_host_bridge_free(host_bridge);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
rt_err_t pci_host_common_remove(struct rt_platform_device *pdev)
|
||||
{
|
||||
struct pci_ecam_config_window *conf_win;
|
||||
struct rt_pci_host_bridge *host_bridge = pdev->parent.user_data;
|
||||
|
||||
rt_pci_host_bridge_remove(host_bridge);
|
||||
|
||||
conf_win = host_bridge->sysdata;
|
||||
|
||||
rt_iounmap(conf_win->win);
|
||||
rt_pci_host_bridge_free(host_bridge);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
66
components/drivers/pci/host/pci-host-generic.c
Normal file
66
components/drivers/pci/host/pci-host-generic.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "../ecam.h"
|
||||
|
||||
static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops =
|
||||
{
|
||||
.bus_shift = 16,
|
||||
.pci_ops =
|
||||
{
|
||||
.map = pci_ecam_map,
|
||||
.read = rt_pci_bus_read_config_uxx,
|
||||
.write = rt_pci_bus_write_config_uxx,
|
||||
}
|
||||
};
|
||||
|
||||
static void *pci_dw_ecam_map_bus(struct rt_pci_bus *bus, rt_uint32_t devfn, int where)
|
||||
{
|
||||
struct pci_ecam_config_window *conf_win = bus->sysdata;
|
||||
|
||||
if (bus->number == conf_win->bus_range[0] && RT_PCI_SLOT(devfn) > 0)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
return pci_ecam_map(bus, devfn, where);
|
||||
}
|
||||
|
||||
static const struct pci_ecam_ops pci_dw_ecam_bus_ops =
|
||||
{
|
||||
.pci_ops =
|
||||
{
|
||||
.map = pci_dw_ecam_map_bus,
|
||||
.read = rt_pci_bus_read_config_uxx,
|
||||
.write = rt_pci_bus_write_config_uxx,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct rt_ofw_node_id gen_pci_ofw_ids[] =
|
||||
{
|
||||
{ .compatible = "pci-host-cam-generic", .data = &gen_pci_cfg_cam_bus_ops },
|
||||
{ .compatible = "pci-host-ecam-generic", .data = &pci_generic_ecam_ops },
|
||||
{ .compatible = "marvell,armada8k-pcie-ecam", .data = &pci_dw_ecam_bus_ops },
|
||||
{ .compatible = "socionext,synquacer-pcie-ecam", .data = &pci_dw_ecam_bus_ops },
|
||||
{ .compatible = "snps,dw-pcie-ecam", .data = &pci_dw_ecam_bus_ops },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_platform_driver gen_pci_driver =
|
||||
{
|
||||
.name = "pci-host-generic",
|
||||
.ids = gen_pci_ofw_ids,
|
||||
|
||||
.probe = pci_host_common_probe,
|
||||
.remove = pci_host_common_remove,
|
||||
};
|
||||
RT_PLATFORM_DRIVER_EXPORT(gen_pci_driver);
|
||||
60
components/drivers/pci/irq.c
Normal file
60
components/drivers/pci/irq.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-07 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define DBG_TAG "pci.irq"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
void rt_pci_assign_irq(struct rt_pci_device *pdev)
|
||||
{
|
||||
int irq = 0;
|
||||
rt_uint8_t pin, slot = -1;
|
||||
struct rt_pci_host_bridge *host_bridge = rt_pci_find_host_bridge(pdev->bus);
|
||||
|
||||
if (!host_bridge->irq_map)
|
||||
{
|
||||
LOG_D("PCI-Device<%s> runtime IRQ mapping not provided by platform",
|
||||
rt_dm_dev_get_name(&pdev->parent));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must try the swizzle when interrupt line passes through a P2P bridge */
|
||||
rt_pci_read_config_u8(pdev, PCIR_INTPIN, &pin);
|
||||
|
||||
if (pin > RT_PCI_INTX_PIN_MAX)
|
||||
{
|
||||
pin = 1;
|
||||
}
|
||||
|
||||
if (pin)
|
||||
{
|
||||
if (host_bridge->irq_slot)
|
||||
{
|
||||
slot = host_bridge->irq_slot(pdev, &pin);
|
||||
}
|
||||
|
||||
/* Map IRQ */
|
||||
if ((irq = host_bridge->irq_map(pdev, slot, pin)) == -1)
|
||||
{
|
||||
irq = 0;
|
||||
}
|
||||
}
|
||||
pdev->irq = irq;
|
||||
|
||||
LOG_D("PCI-Device<%s> assign IRQ: got %d", rt_dm_dev_get_name(&pdev->parent), pdev->irq);
|
||||
|
||||
/* Save IRQ */
|
||||
rt_pci_write_config_u8(pdev, PCIR_INTLINE, irq);
|
||||
}
|
||||
15
components/drivers/pci/msi/SConscript
Normal file
15
components/drivers/pci/msi/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
|
||||
if not GetDepend(['RT_PCI_MSI']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/../../include']
|
||||
|
||||
src = ['device.c', 'irq.c', 'msi.c']
|
||||
|
||||
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
46
components/drivers/pci/msi/device.c
Normal file
46
components/drivers/pci/msi/device.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
void rt_pci_msi_init(struct rt_pci_device *pdev)
|
||||
{
|
||||
if (pdev && (pdev->msi_cap = rt_pci_find_capability(pdev, PCIY_MSI)))
|
||||
{
|
||||
rt_uint16_t ctrl;
|
||||
|
||||
rt_pci_read_config_u16(pdev, pdev->msi_cap + PCIR_MSI_CTRL, &ctrl);
|
||||
|
||||
if (ctrl & PCIM_MSICTRL_MSI_ENABLE)
|
||||
{
|
||||
rt_pci_write_config_u16(pdev, pdev->msi_cap + PCIR_MSI_CTRL, ctrl & ~PCIM_MSICTRL_MSI_ENABLE);
|
||||
}
|
||||
|
||||
if (!(ctrl & PCIM_MSICTRL_64BIT))
|
||||
{
|
||||
pdev->no_64bit_msi = RT_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rt_pci_msix_init(struct rt_pci_device *pdev)
|
||||
{
|
||||
if (pdev && (pdev->msix_cap = rt_pci_find_capability(pdev, PCIY_MSIX)))
|
||||
{
|
||||
rt_uint16_t ctrl;
|
||||
|
||||
rt_pci_read_config_u16(pdev, pdev->msix_cap + PCIR_MSIX_CTRL, &ctrl);
|
||||
|
||||
if (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE)
|
||||
{
|
||||
rt_pci_write_config_u16(pdev, pdev->msix_cap + PCIR_MSIX_CTRL, ctrl & ~PCIM_MSIXCTRL_MSIX_ENABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
146
components/drivers/pci/msi/irq.c
Normal file
146
components/drivers/pci/msi/irq.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <drivers/pci_msi.h>
|
||||
|
||||
#define DBG_TAG "pci.msi.irq"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
static struct rt_spinlock msi_irq_map_lock = {};
|
||||
static RT_BITMAP_DECLARE(msi_irq_map, MAX_HANDLERS) = {};
|
||||
|
||||
rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type)
|
||||
{
|
||||
int irq, index = 0, irq_nr = 0;
|
||||
rt_err_t err = RT_EOK;
|
||||
struct rt_pic_irq *pirq;
|
||||
struct rt_pic *msi_pic;
|
||||
struct rt_pci_msi_desc *desc;
|
||||
|
||||
if (!pdev)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
msi_pic = pdev->msi_pic;
|
||||
|
||||
if (type == PCIY_MSI)
|
||||
{
|
||||
int last_irq = -1;
|
||||
rt_size_t irq_nr;
|
||||
|
||||
desc = rt_pci_msi_first_desc(pdev);
|
||||
irq_nr = 1 << desc->msi.cap.multi_msg_use;
|
||||
|
||||
rt_hw_spin_lock(&msi_irq_map_lock.lock);
|
||||
|
||||
_retry:
|
||||
for (int i = 0; i < irq_nr; ++i)
|
||||
{
|
||||
if ((irq = msi_pic->ops->irq_alloc_msi(msi_pic, desc)) < 0)
|
||||
{
|
||||
err = irq;
|
||||
|
||||
LOG_E("Setup %s[%d] IRQ error = %s", "MSI", i, rt_strerror(err));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (last_irq >= 0 && last_irq + 1 != irq)
|
||||
{
|
||||
for (int idx = 0; idx < i; ++i, --last_irq)
|
||||
{
|
||||
rt_bitmap_set_bit(msi_irq_map, last_irq);
|
||||
}
|
||||
|
||||
last_irq = irq;
|
||||
goto _retry;
|
||||
}
|
||||
|
||||
last_irq = irq;
|
||||
}
|
||||
|
||||
if (!err)
|
||||
{
|
||||
/* Get the first irq */
|
||||
desc->irq = irq - irq_nr;
|
||||
}
|
||||
|
||||
rt_bitmap_for_each_set_bit(msi_irq_map, irq, MAX_HANDLERS)
|
||||
{
|
||||
msi_pic->ops->irq_free_msi(msi_pic, irq);
|
||||
|
||||
/* Free bit so the next user doesn't need to bzero */
|
||||
rt_bitmap_clear_bit(msi_irq_map, irq);
|
||||
}
|
||||
|
||||
rt_hw_spin_unlock(&msi_irq_map_lock.lock);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
for (int idx = 0; idx < nvec; ++idx)
|
||||
{
|
||||
pirq = rt_pic_find_pirq(msi_pic, irq + idx);
|
||||
pirq->msi_desc = desc;
|
||||
|
||||
msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg);
|
||||
|
||||
rt_pci_msi_write_msg(desc, &desc->msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == PCIY_MSIX)
|
||||
{
|
||||
rt_pci_msi_for_each_desc(pdev, desc)
|
||||
{
|
||||
if ((irq = msi_pic->ops->irq_alloc_msi(msi_pic, desc)) < 0)
|
||||
{
|
||||
err = irq;
|
||||
|
||||
LOG_E("Setup %s[%d] IRQ error = %s", "MSI-X",
|
||||
desc->msix.index, rt_strerror(err));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
desc->irq = irq;
|
||||
pirq = rt_pic_find_pirq(msi_pic, irq);
|
||||
pirq->msi_desc = desc;
|
||||
|
||||
msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg);
|
||||
|
||||
rt_pci_msi_write_msg(desc, &desc->msg);
|
||||
|
||||
++irq_nr;
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
rt_pci_msi_for_each_desc(pdev, desc)
|
||||
{
|
||||
if (index >= irq_nr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
msi_pic->ops->irq_free_msi(msi_pic, desc->irq);
|
||||
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = -RT_EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
949
components/drivers/pci/msi/msi.c
Normal file
949
components/drivers/pci/msi/msi.c
Normal file
File diff suppressed because it is too large
Load Diff
621
components/drivers/pci/ofw.c
Normal file
621
components/drivers/pci/ofw.c
Normal file
File diff suppressed because it is too large
Load Diff
1004
components/drivers/pci/pci.c
Normal file
1004
components/drivers/pci/pci.c
Normal file
File diff suppressed because it is too large
Load Diff
272
components/drivers/pci/pci_ids.h
Normal file
272
components/drivers/pci/pci_ids.h
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __PCI_IDS_H__
|
||||
#define __PCI_IDS_H__
|
||||
|
||||
#define PCI_VENDOR_ID_LOONGSON 0x0014
|
||||
#define PCI_VENDOR_ID_TTTECH 0x0357
|
||||
#define PCI_VENDOR_ID_DYNALINK 0x0675
|
||||
#define PCI_VENDOR_ID_UBIQUITI 0x0777
|
||||
#define PCI_VENDOR_ID_BERKOM 0x0871
|
||||
#define PCI_VENDOR_ID_COMPAQ 0x0e11
|
||||
#define PCI_VENDOR_ID_NCR 0x1000
|
||||
#define PCI_VENDOR_ID_ATI 0x1002
|
||||
#define PCI_VENDOR_ID_VLSI 0x1004
|
||||
#define PCI_VENDOR_ID_ADL 0x1005
|
||||
#define PCI_VENDOR_ID_NS 0x100b
|
||||
#define PCI_VENDOR_ID_TSENG 0x100c
|
||||
#define PCI_VENDOR_ID_WEITEK 0x100e
|
||||
#define PCI_VENDOR_ID_DEC 0x1011
|
||||
#define PCI_VENDOR_ID_CIRRUS 0x1013
|
||||
#define PCI_VENDOR_ID_IBM 0x1014
|
||||
#define PCI_VENDOR_ID_UNISYS 0x1018
|
||||
#define PCI_VENDOR_ID_COMPEX2 0x101a
|
||||
#define PCI_VENDOR_ID_WD 0x101c
|
||||
#define PCI_VENDOR_ID_AMI 0x101e
|
||||
#define PCI_VENDOR_ID_AMD 0x1022
|
||||
#define PCI_VENDOR_ID_TRIDENT 0x1023
|
||||
#define PCI_VENDOR_ID_AI 0x1025
|
||||
#define PCI_VENDOR_ID_DELL 0x1028
|
||||
#define PCI_VENDOR_ID_MATROX 0x102b
|
||||
#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS 0x14f2
|
||||
#define PCI_VENDOR_ID_CT 0x102c
|
||||
#define PCI_VENDOR_ID_MIRO 0x1031
|
||||
#define PCI_VENDOR_ID_NEC 0x1033
|
||||
#define PCI_VENDOR_ID_FD 0x1036
|
||||
#define PCI_VENDOR_ID_SI 0x1039
|
||||
#define PCI_VENDOR_ID_HP 0x103c
|
||||
#define PCI_VENDOR_ID_PCTECH 0x1042
|
||||
#define PCI_VENDOR_ID_ASUSTEK 0x1043
|
||||
#define PCI_VENDOR_ID_DPT 0x1044
|
||||
#define PCI_VENDOR_ID_OPTI 0x1045
|
||||
#define PCI_VENDOR_ID_ELSA 0x1048
|
||||
#define PCI_VENDOR_ID_STMICRO 0x104a
|
||||
#define PCI_VENDOR_ID_BUSLOGIC 0x104b
|
||||
#define PCI_VENDOR_ID_TI 0x104c
|
||||
#define PCI_VENDOR_ID_SONY 0x104d
|
||||
#define PCI_VENDOR_ID_ANIGMA 0x1051
|
||||
#define PCI_VENDOR_ID_EFAR 0x1055
|
||||
#define PCI_VENDOR_ID_MOTOROLA 0x1057
|
||||
#define PCI_VENDOR_ID_PROMISE 0x105a
|
||||
#define PCI_VENDOR_ID_FOXCONN 0x105b
|
||||
#define PCI_VENDOR_ID_UMC 0x1060
|
||||
#define PCI_VENDOR_ID_PICOPOWER 0x1066
|
||||
#define PCI_VENDOR_ID_MYLEX 0x1069
|
||||
#define PCI_VENDOR_ID_APPLE 0x106b
|
||||
#define PCI_VENDOR_ID_YAMAHA 0x1073
|
||||
#define PCI_VENDOR_ID_QLOGIC 0x1077
|
||||
#define PCI_VENDOR_ID_CYRIX 0x1078
|
||||
#define PCI_VENDOR_ID_CONTAQ 0x1080
|
||||
#define PCI_VENDOR_ID_OLICOM 0x108d
|
||||
#define PCI_VENDOR_ID_SUN 0x108e
|
||||
#define PCI_VENDOR_ID_NI 0x1093
|
||||
#define PCI_VENDOR_ID_CMD 0x1095
|
||||
#define PCI_VENDOR_ID_BROOKTREE 0x109e
|
||||
#define PCI_VENDOR_ID_SGI 0x10a9
|
||||
#define PCI_VENDOR_ID_WINBOND 0x10ad
|
||||
#define PCI_VENDOR_ID_PLX 0x10b5
|
||||
#define PCI_VENDOR_ID_MADGE 0x10b6
|
||||
#define PCI_VENDOR_ID_3COM 0x10b7
|
||||
#define PCI_VENDOR_ID_AL 0x10b9
|
||||
#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
|
||||
#define PCI_VENDOR_ID_TCONRAD 0x10da
|
||||
#define PCI_VENDOR_ID_ROHM 0x10db
|
||||
#define PCI_VENDOR_ID_NVIDIA 0x10de
|
||||
#define PCI_VENDOR_ID_IMS 0x10e0
|
||||
#define PCI_VENDOR_ID_AMCC 0x10e8
|
||||
#define PCI_VENDOR_ID_INTERG 0x10ea
|
||||
#define PCI_VENDOR_ID_REALTEK 0x10ec
|
||||
#define PCI_VENDOR_ID_XILINX 0x10ee
|
||||
#define PCI_VENDOR_ID_INIT 0x1101
|
||||
#define PCI_VENDOR_ID_CREATIVE 0x1102
|
||||
#define PCI_VENDOR_ID_ECTIVA PCI_VENDOR_ID_CREATIVE
|
||||
#define PCI_VENDOR_ID_TTI 0x1103
|
||||
#define PCI_VENDOR_ID_SIGMA 0x1105
|
||||
#define PCI_VENDOR_ID_VIA 0x1106
|
||||
#define PCI_VENDOR_ID_SIEMENS 0x110a
|
||||
#define PCI_VENDOR_ID_VORTEX 0x1119
|
||||
#define PCI_VENDOR_ID_EF 0x111a
|
||||
#define PCI_VENDOR_ID_IDT 0x111d
|
||||
#define PCI_VENDOR_ID_FORE 0x1127
|
||||
#define PCI_VENDOR_ID_PHILIPS 0x1131
|
||||
#define PCI_VENDOR_ID_EICON 0x1133
|
||||
#define PCI_VENDOR_ID_CISCO 0x1137
|
||||
#define PCI_VENDOR_ID_ZIATECH 0x1138
|
||||
#define PCI_VENDOR_ID_SYSKONNECT 0x1148
|
||||
#define PCI_VENDOR_ID_DIGI 0x114f
|
||||
#define PCI_VENDOR_ID_XIRCOM 0x115d
|
||||
#define PCI_VENDOR_ID_SERVERWORKS 0x1166
|
||||
#define PCI_VENDOR_ID_ALTERA 0x1172
|
||||
#define PCI_VENDOR_ID_SBE 0x1176
|
||||
#define PCI_VENDOR_ID_TOSHIBA 0x1179
|
||||
#define PCI_VENDOR_ID_TOSHIBA_2 0x102f
|
||||
#define PCI_VENDOR_ID_ATTO 0x117c
|
||||
#define PCI_VENDOR_ID_RICOH 0x1180
|
||||
#define PCI_VENDOR_ID_DLINK 0x1186
|
||||
#define PCI_VENDOR_ID_ARTOP 0x1191
|
||||
#define PCI_VENDOR_ID_ZEITNET 0x1193
|
||||
#define PCI_VENDOR_ID_FUJITSU_ME 0x119e
|
||||
#define PCI_VENDOR_ID_MARVELL 0x11ab
|
||||
#define PCI_VENDOR_ID_V3 0x11b0
|
||||
#define PCI_VENDOR_ID_ATT 0x11c1
|
||||
#define PCI_VENDOR_ID_SPECIALIX 0x11cb
|
||||
#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4
|
||||
#define PCI_VENDOR_ID_ZORAN 0x11de
|
||||
#define PCI_VENDOR_ID_COMPEX 0x11f6
|
||||
#define PCI_VENDOR_ID_PMC_Sierra 0x11f8
|
||||
#define PCI_VENDOR_ID_RP 0x11fe
|
||||
#define PCI_VENDOR_ID_CYCLADES 0x120e
|
||||
#define PCI_VENDOR_ID_ESSENTIAL 0x120f
|
||||
#define PCI_VENDOR_ID_O2 0x1217
|
||||
#define PCI_VENDOR_ID_3DFX 0x121a
|
||||
#define PCI_VENDOR_ID_QEMU 0x1234
|
||||
#define PCI_VENDOR_ID_AVM 0x1244
|
||||
#define PCI_VENDOR_ID_STALLION 0x124d
|
||||
#define PCI_VENDOR_ID_ESS 0x125d
|
||||
#define PCI_VENDOR_ID_SATSAGEM 0x1267
|
||||
#define PCI_VENDOR_ID_ENSONIQ 0x1274
|
||||
#define PCI_VENDOR_ID_TRANSMETA 0x1279
|
||||
#define PCI_VENDOR_ID_ROCKWELL 0x127a
|
||||
#define PCI_VENDOR_ID_ITE 0x1283
|
||||
#define PCI_VENDOR_ID_ALTEON 0x12ae
|
||||
#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
|
||||
#define PCI_VENDOR_ID_PERICOM 0x12d8
|
||||
#define PCI_VENDOR_ID_AUREAL 0x12eb
|
||||
#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
|
||||
#define PCI_VENDOR_ID_ESDGMBH 0x12fe
|
||||
#define PCI_VENDOR_ID_CB 0x1307
|
||||
#define PCI_VENDOR_ID_SIIG 0x131f
|
||||
#define PCI_VENDOR_ID_RADISYS 0x1331
|
||||
#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332
|
||||
#define PCI_VENDOR_ID_DOMEX 0x134a
|
||||
#define PCI_VENDOR_ID_INTASHIELD 0x135a
|
||||
#define PCI_VENDOR_ID_QUATECH 0x135c
|
||||
#define PCI_VENDOR_ID_SEALEVEL 0x135e
|
||||
#define PCI_VENDOR_ID_HYPERCOPE 0x1365
|
||||
#define PCI_VENDOR_ID_DIGIGRAM 0x1369
|
||||
#define PCI_VENDOR_ID_KAWASAKI 0x136b
|
||||
#define PCI_VENDOR_ID_CNET 0x1371
|
||||
#define PCI_VENDOR_ID_LMC 0x1376
|
||||
#define PCI_VENDOR_ID_NETGEAR 0x1385
|
||||
#define PCI_VENDOR_ID_APPLICOM 0x1389
|
||||
#define PCI_VENDOR_ID_MOXA 0x1393
|
||||
#define PCI_VENDOR_ID_CCD 0x1397
|
||||
#define PCI_VENDOR_ID_EXAR 0x13a8
|
||||
#define PCI_VENDOR_ID_MICROGATE 0x13c0
|
||||
#define PCI_VENDOR_ID_3WARE 0x13c1
|
||||
#define PCI_VENDOR_ID_IOMEGA 0x13ca
|
||||
#define PCI_VENDOR_ID_ABOCOM 0x13d1
|
||||
#define PCI_VENDOR_ID_SUNDANCE 0x13f0
|
||||
#define PCI_VENDOR_ID_CMEDIA 0x13f6
|
||||
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
|
||||
#define PCI_VENDOR_ID_MEILHAUS 0x1402
|
||||
#define PCI_VENDOR_ID_LAVA 0x1407
|
||||
#define PCI_VENDOR_ID_TIMEDIA 0x1409
|
||||
#define PCI_VENDOR_ID_ICE 0x1412
|
||||
#define PCI_VENDOR_ID_MICROSOFT 0x1414
|
||||
#define PCI_VENDOR_ID_OXSEMI 0x1415
|
||||
#define PCI_VENDOR_ID_CHELSIO 0x1425
|
||||
#define PCI_VENDOR_ID_ADLINK 0x144a
|
||||
#define PCI_VENDOR_ID_SAMSUNG 0x144d
|
||||
#define PCI_VENDOR_ID_GIGABYTE 0x1458
|
||||
#define PCI_VENDOR_ID_AMBIT 0x1468
|
||||
#define PCI_VENDOR_ID_MYRICOM 0x14c1
|
||||
#define PCI_VENDOR_ID_MEDIATEK 0x14c3
|
||||
#define PCI_VENDOR_ID_TITAN 0x14d2
|
||||
#define PCI_VENDOR_ID_PANACOM 0x14d4
|
||||
#define PCI_VENDOR_ID_SIPACKETS 0x14d9
|
||||
#define PCI_VENDOR_ID_AFAVLAB 0x14db
|
||||
#define PCI_VENDOR_ID_AMPLICON 0x14dc
|
||||
#define PCI_VENDOR_ID_BCM_GVC 0x14a4
|
||||
#define PCI_VENDOR_ID_TOPIC 0x151f
|
||||
#define PCI_VENDOR_ID_MAINPINE 0x1522
|
||||
#define PCI_VENDOR_ID_SYBA 0x1592
|
||||
#define PCI_VENDOR_ID_MORETON 0x15aa
|
||||
#define PCI_VENDOR_ID_VMWARE 0x15ad
|
||||
#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
|
||||
#define PCI_VENDOR_ID_MELLANOX 0x15b3
|
||||
#define PCI_VENDOR_ID_DFI 0x15bd
|
||||
#define PCI_VENDOR_ID_QUICKNET 0x15e2
|
||||
#define PCI_VENDOR_ID_PDC 0x15e9
|
||||
#define PCI_VENDOR_ID_FARSITE 0x1619
|
||||
#define PCI_VENDOR_ID_ARIMA 0x161f
|
||||
#define PCI_VENDOR_ID_BROCADE 0x1657
|
||||
#define PCI_VENDOR_ID_SIBYTE 0x166d
|
||||
#define PCI_VENDOR_ID_ATHEROS 0x168c
|
||||
#define PCI_VENDOR_ID_NETCELL 0x169c
|
||||
#define PCI_VENDOR_ID_CENATEK 0x16ca
|
||||
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
|
||||
#define PCI_VENDOR_ID_USR 0x16ec
|
||||
#define PCI_VENDOR_ID_VITESSE 0x1725
|
||||
#define PCI_VENDOR_ID_LINKSYS 0x1737
|
||||
#define PCI_VENDOR_ID_ALTIMA 0x173b
|
||||
#define PCI_VENDOR_ID_CAVIUM 0x177d
|
||||
#define PCI_VENDOR_ID_TECHWELL 0x1797
|
||||
#define PCI_VENDOR_ID_BELKIN 0x1799
|
||||
#define PCI_VENDOR_ID_RDC 0x17f3
|
||||
#define PCI_VENDOR_ID_GLI 0x17a0
|
||||
#define PCI_VENDOR_ID_LENOVO 0x17aa
|
||||
#define PCI_VENDOR_ID_QCOM 0x17cb
|
||||
#define PCI_VENDOR_ID_CDNS 0x17cd
|
||||
#define PCI_VENDOR_ID_ARECA 0x17d3
|
||||
#define PCI_VENDOR_ID_S2IO 0x17d5
|
||||
#define PCI_VENDOR_ID_SITECOM 0x182d
|
||||
#define PCI_VENDOR_ID_TOPSPIN 0x1867
|
||||
#define PCI_VENDOR_ID_COMMTECH 0x18f7
|
||||
#define PCI_VENDOR_ID_SILAN 0x1904
|
||||
#define PCI_VENDOR_ID_RENESAS 0x1912
|
||||
#define PCI_VENDOR_ID_SOLARFLARE 0x1924
|
||||
#define PCI_VENDOR_ID_TDI 0x192e
|
||||
#define PCI_VENDOR_ID_FREESCALE 0x1957
|
||||
#define PCI_VENDOR_ID_NXP PCI_VENDOR_ID_FREESCALE
|
||||
#define PCI_VENDOR_ID_PASEMI 0x1959
|
||||
#define PCI_VENDOR_ID_ATTANSIC 0x1969
|
||||
#define PCI_VENDOR_ID_JMICRON 0x197b
|
||||
#define PCI_VENDOR_ID_KORENIX 0x1982
|
||||
#define PCI_VENDOR_ID_HUAWEI 0x19e5
|
||||
#define PCI_VENDOR_ID_NETRONOME 0x19ee
|
||||
#define PCI_VENDOR_ID_QMI 0x1a32
|
||||
#define PCI_VENDOR_ID_AZWAVE 0x1a3b
|
||||
#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4
|
||||
#define PCI_VENDOR_ID_ASMEDIA 0x1b21
|
||||
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
||||
#define PCI_VENDOR_ID_SILICOM_DENMARK 0x1c2c
|
||||
#define PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS 0x1c36
|
||||
#define PCI_VENDOR_ID_CIRCUITCO 0x1cc8
|
||||
#define PCI_VENDOR_ID_AMAZON 0x1d0f
|
||||
#define PCI_VENDOR_ID_ZHAOXIN 0x1d17
|
||||
#define PCI_VENDOR_ID_HYGON 0x1d94
|
||||
#define PCI_VENDOR_ID_FUNGIBLE 0x1dad
|
||||
#define PCI_VENDOR_ID_HXT 0x1dbf
|
||||
#define PCI_VENDOR_ID_TEKRAM 0x1de1
|
||||
#define PCI_VENDOR_ID_TEHUTI 0x1fc9
|
||||
#define PCI_VENDOR_ID_SUNIX 0x1fd4
|
||||
#define PCI_VENDOR_ID_HINT 0x3388
|
||||
#define PCI_VENDOR_ID_3DLABS 0x3d3d
|
||||
#define PCI_VENDOR_ID_NETXEN 0x4040
|
||||
#define PCI_VENDOR_ID_AKS 0x416c
|
||||
#define PCI_VENDOR_ID_ACCESSIO 0x494f
|
||||
#define PCI_VENDOR_ID_S3 0x5333
|
||||
#define PCI_VENDOR_ID_DUNORD 0x5544
|
||||
#define PCI_VENDOR_ID_DCI 0x6666
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
#define PCI_VENDOR_ID_SCALEMP 0x8686
|
||||
#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
|
||||
#define PCI_VENDOR_ID_KTI 0x8e2e
|
||||
#define PCI_VENDOR_ID_ADAPTEC 0x9004
|
||||
#define PCI_VENDOR_ID_ADAPTEC2 0x9005
|
||||
#define PCI_VENDOR_ID_HOLTEK 0x9412
|
||||
#define PCI_VENDOR_ID_NETMOS 0x9710
|
||||
#define PCI_VENDOR_ID_3COM_2 0xa727
|
||||
#define PCI_VENDOR_ID_DIGIUM 0xd161
|
||||
#define PCI_VENDOR_ID_TIGERJET 0xe159
|
||||
#define PCI_VENDOR_ID_XILINX_RME 0xea60
|
||||
#define PCI_VENDOR_ID_XEN 0x5853
|
||||
#define PCI_VENDOR_ID_OCZ 0x1b85
|
||||
#define PCI_VENDOR_ID_NCUBE 0x10ff
|
||||
|
||||
#endif /* __PCI_IDS_H__ */
|
||||
1090
components/drivers/pci/pci_regs.h
Normal file
1090
components/drivers/pci/pci_regs.h
Normal file
File diff suppressed because it is too large
Load Diff
121
components/drivers/pci/pme.c
Normal file
121
components/drivers/pci/pme.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-10-24 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <drivers/pci.h>
|
||||
#include <drivers/core/power_domain.h>
|
||||
|
||||
#define DBG_TAG "pci.pme"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
/*
|
||||
* Power Management Capability Register:
|
||||
*
|
||||
* 31 27 26 25 24 22 21 20 19 18 16 15 8 7 0
|
||||
* +---------+---+---+--------+---+---+---+------+-----------+----------------+
|
||||
* | | | | | | | | | | Capabilitiy ID |
|
||||
* +---------+---+---+--------+---+---+---+------+-----------+----------------+
|
||||
* ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||
* | | | | | | | | |
|
||||
* | | | | | | | | +---- Next Capabilitiy Pointer
|
||||
* | | | | | | | +------------- Version
|
||||
* | | | | | | +------------------- PME Clock
|
||||
* | | | | | +----------------------- Immediate Readiness on Return to D0
|
||||
* | | | | +--------------------------- Device Specifiic Initializtion
|
||||
* | | | +--------------------------------- Aux Current
|
||||
* | | +---------------------------------------- D1 Support
|
||||
* | +-------------------------------------------- D2 Support
|
||||
* +--------------------------------------------------- PME Support
|
||||
*/
|
||||
|
||||
void rt_pci_pme_init(struct rt_pci_device *pdev)
|
||||
{
|
||||
rt_uint16_t pmc;
|
||||
|
||||
if (!pdev || !(pdev->pme_cap = rt_pci_find_capability(pdev, PCIY_PMG)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_pci_read_config_u16(pdev, pdev->pme_cap + PCIR_POWER_CAP, &pmc);
|
||||
|
||||
if ((pmc & PCIM_PCAP_SPEC) > 3)
|
||||
{
|
||||
LOG_E("%s: Unsupported PME CAP regs spec %u",
|
||||
rt_dm_dev_get_name(&pdev->parent), pmc & PCIM_PCAP_SPEC);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pmc &= PCIM_PCAP_PMEMASK;
|
||||
|
||||
if (pmc)
|
||||
{
|
||||
pdev->pme_support = RT_FIELD_GET(PCIM_PCAP_PMEMASK, pmc);
|
||||
|
||||
rt_pci_pme_active(pdev, RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
rt_err_t rt_pci_enable_wake(struct rt_pci_device *pdev,
|
||||
enum rt_pci_power state, rt_bool_t enable)
|
||||
{
|
||||
if (!pdev || state >= RT_PCI_PME_MAX)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (rt_pci_pme_capable(pdev, state) ||
|
||||
rt_pci_pme_capable(pdev, RT_PCI_D3COLD))
|
||||
{
|
||||
rt_pci_pme_active(pdev, RT_EOK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_pci_pme_active(pdev, RT_FALSE);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable)
|
||||
{
|
||||
rt_uint16_t pmcsr;
|
||||
|
||||
if (!pdev->pme_support)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_pci_read_config_u16(pdev, pdev->pme_cap + PCIR_POWER_STATUS, &pmcsr);
|
||||
/* Clear PME_Status by writing 1 to it and enable PME# */
|
||||
pmcsr |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
pmcsr &= ~PCIM_PSTAT_PMEENABLE;
|
||||
}
|
||||
|
||||
rt_pci_write_config_u16(pdev, pdev->pme_cap + PCIR_POWER_STATUS, pmcsr);
|
||||
}
|
||||
|
||||
void rt_pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable)
|
||||
{
|
||||
if (!pdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pci_pme_active(pdev, enable);
|
||||
rt_dm_power_domain_attach(&pdev->parent, enable);
|
||||
}
|
||||
922
components/drivers/pci/probe.c
Normal file
922
components/drivers/pci/probe.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user