diff --git a/components/drivers/include/drivers/ofw_io.h b/components/drivers/include/drivers/ofw_io.h index f458435d09..e6014585ac 100755 --- a/components/drivers/include/drivers/ofw_io.h +++ b/components/drivers/include/drivers/ofw_io.h @@ -22,7 +22,7 @@ int rt_ofw_io_size_cells(struct rt_ofw_node *np); int rt_ofw_get_address_count(struct rt_ofw_node *np); rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_address, rt_uint64_t *out_size); rt_err_t rt_ofw_get_address_by_name(struct rt_ofw_node *np, const char *name, - rt_uint64_t *out_address, rt_uint64_t *out_size); + rt_uint64_t *out_address, rt_uint64_t *out_size); int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_regs); rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address); @@ -32,20 +32,46 @@ rt_inline rt_uint64_t rt_ofw_translate_dma2cpu(struct rt_ofw_node *np, rt_uint64 { rt_uint64_t bus_addr, cpu_addr; - bus_addr = rt_ofw_reverse_address(np, "dma-ranges", address); - cpu_addr = rt_ofw_translate_address(np, "ranges", bus_addr); + cpu_addr = rt_ofw_translate_address(np, "dma-ranges", address); + if (cpu_addr != ~0ULL && cpu_addr != address) + { + return cpu_addr; + } - return cpu_addr != ~0ULL ? cpu_addr : address; + bus_addr = rt_ofw_translate_address(np, "dma-ranges", address); + if (bus_addr != ~0ULL && bus_addr != address) + { + cpu_addr = rt_ofw_translate_address(np, "ranges", bus_addr); + if (cpu_addr != ~0ULL && cpu_addr != address) + { + return cpu_addr; + } + } + + return address; } rt_inline rt_uint64_t rt_ofw_translate_cpu2dma(struct rt_ofw_node *np, rt_uint64_t address) { rt_uint64_t bus_addr, dma_addr; - bus_addr = rt_ofw_reverse_address(np, "ranges", address); - dma_addr = rt_ofw_translate_address(np, "dma-ranges", bus_addr); + dma_addr = rt_ofw_reverse_address(np, "dma-ranges", address); + if (dma_addr != ~0ULL && dma_addr != address) + { + return dma_addr; + } - return dma_addr != ~0ULL ? dma_addr : address; + bus_addr = rt_ofw_reverse_address(np, "ranges", address); + if (bus_addr != ~0ULL && bus_addr != address) + { + dma_addr = rt_ofw_reverse_address(np, "dma-ranges", bus_addr); + if (dma_addr != ~0ULL && dma_addr != address) + { + return dma_addr; + } + } + + return address; } void *rt_ofw_iomap(struct rt_ofw_node *np, int index); diff --git a/components/drivers/include/drivers/pci.h b/components/drivers/include/drivers/pci.h index 414a0abf1a..8bdf7afca2 100644 --- a/components/drivers/include/drivers/pci.h +++ b/components/drivers/include/drivers/pci.h @@ -22,12 +22,12 @@ #include "../../pci/pci_ids.h" #include "../../pci/pci_regs.h" -#define RT_PCI_INTX_PIN_MAX 4 -#define RT_PCI_BAR_NR_MAX 6 -#define RT_PCI_DEVICE_MAX 32 -#define RT_PCI_FUNCTION_MAX 8 +#define RT_PCI_INTX_PIN_MAX 4 +#define RT_PCI_BAR_NR_MAX 6 +#define RT_PCI_DEVICE_MAX 32 +#define RT_PCI_FUNCTION_MAX 8 -#define RT_PCI_FIND_CAP_TTL 48 +#define RT_PCI_FIND_CAP_TTL 48 /* * The PCI interface treats multi-function devices as independent @@ -37,25 +37,24 @@ * 7:3 = slot * 2:0 = function */ -#define RT_PCI_DEVID(bus, devfn) ((((rt_uint16_t)(bus)) << 8) | (devfn)) -#define RT_PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -#define RT_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) -#define RT_PCI_FUNC(devfn) ((devfn) & 0x07) +#define RT_PCI_DEVID(bus, devfn) ((((rt_uint16_t)(bus)) << 8) | (devfn)) +#define RT_PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define RT_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define RT_PCI_FUNC(devfn) ((devfn) & 0x07) -#define PCIE_LINK_STATE_L0S RT_BIT(0) -#define PCIE_LINK_STATE_L1 RT_BIT(1) -#define PCIE_LINK_STATE_CLKPM RT_BIT(2) -#define PCIE_LINK_STATE_L1_1 RT_BIT(3) -#define PCIE_LINK_STATE_L1_2 RT_BIT(4) -#define PCIE_LINK_STATE_L1_1_PCIPM RT_BIT(5) -#define PCIE_LINK_STATE_L1_2_PCIPM RT_BIT(6) -#define PCIE_LINK_STATE_ALL \ -( \ - PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | \ - PCIE_LINK_STATE_CLKPM | \ - PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2 | \ - PCIE_LINK_STATE_L1_1_PCIPM | PCIE_LINK_STATE_L1_2_PCIPM \ -) +#define PCIE_LINK_STATE_L0S RT_BIT(0) +#define PCIE_LINK_STATE_L1 RT_BIT(1) +#define PCIE_LINK_STATE_CLKPM RT_BIT(2) +#define PCIE_LINK_STATE_L1_1 RT_BIT(3) +#define PCIE_LINK_STATE_L1_2 RT_BIT(4) +#define PCIE_LINK_STATE_L1_1_PCIPM RT_BIT(5) +#define PCIE_LINK_STATE_L1_2_PCIPM RT_BIT(6) +#define PCIE_LINK_STATE_ALL \ + ( \ + PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | \ + PCIE_LINK_STATE_CLKPM | \ + PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2 | \ + PCIE_LINK_STATE_L1_1_PCIPM | PCIE_LINK_STATE_L1_2_PCIPM) struct rt_pci_bus_region { @@ -65,17 +64,17 @@ struct rt_pci_bus_region rt_uint64_t bus_start; -#define PCI_BUS_REGION_F_NONE 0xffffffff /* PCI no memory */ -#define PCI_BUS_REGION_F_MEM 0x00000000 /* PCI memory space */ -#define PCI_BUS_REGION_F_IO 0x00000001 /* PCI IO space */ -#define PCI_BUS_REGION_F_PREFETCH 0x00000008 /* Prefetchable PCI memory */ +#define PCI_BUS_REGION_F_NONE 0xffffffff /* PCI no memory */ +#define PCI_BUS_REGION_F_MEM 0x00000000 /* PCI memory space */ +#define PCI_BUS_REGION_F_IO 0x00000001 /* PCI IO space */ +#define PCI_BUS_REGION_F_PREFETCH 0x00000008 /* Prefetchable PCI memory */ rt_ubase_t flags; }; struct rt_pci_bus_resource { rt_ubase_t base; - rt_size_t size; + rt_size_t size; rt_ubase_t flags; }; @@ -104,17 +103,17 @@ struct rt_pci_bus; struct rt_pci_device_id { -#define PCI_ANY_ID (~0) +#define PCI_ANY_ID (~0) #define RT_PCI_DEVICE_ID(vend, dev) \ - .vendor = (vend), \ - .device = (dev), \ + .vendor = (vend), \ + .device = (dev), \ .subsystem_vendor = PCI_ANY_ID, \ .subsystem_device = PCI_ANY_ID -#define RT_PCI_DEVICE_CLASS(dev_class, dev_class_mask) \ - .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ - .subsystem_vendor = PCI_ANY_ID, \ - .subsystem_device = PCI_ANY_ID, \ +#define RT_PCI_DEVICE_CLASS(dev_class, dev_class_mask) \ + .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ + .subsystem_vendor = PCI_ANY_ID, \ + .subsystem_device = PCI_ANY_ID, \ .class = (dev_class), .class_mask = (dev_class_mask), rt_uint32_t vendor, device; /* Vendor and device ID or PCI_ANY_ID */ @@ -128,9 +127,9 @@ struct rt_pci_device_id struct rt_pci_device { struct rt_device parent; - const char *name; + const char *name; - rt_list_t list; + rt_list_t list; struct rt_pci_bus *bus; struct rt_pci_bus *subbus; /* In PCI-to-PCI bridge, 'End Point' or 'Port' is NULL */ @@ -142,19 +141,19 @@ struct rt_pci_device rt_uint16_t subsystem_vendor; rt_uint16_t subsystem_device; rt_uint32_t class; /* 3 bytes: (base, sub, prog-if) */ - rt_uint8_t revision; - rt_uint8_t hdr_type; - rt_uint8_t max_latency; - rt_uint8_t min_grantl; - rt_uint8_t int_pin; - rt_uint8_t int_line; + rt_uint8_t revision; + rt_uint8_t hdr_type; + rt_uint8_t max_latency; + rt_uint8_t min_grantl; + rt_uint8_t int_pin; + rt_uint8_t int_line; rt_uint16_t exp_flags; rt_uint32_t cfg_size; void *sysdata; - int irq; - rt_uint8_t pin; + int irq; + rt_uint8_t pin; struct rt_pic *intx_pic; rt_bool_t pm_enabled; @@ -167,20 +166,20 @@ struct rt_pci_device rt_uint8_t msix_cap; rt_uint8_t pcie_cap; - rt_uint8_t busmaster:1; /* Is the bus master */ - rt_uint8_t multi_function:1; /* Multi-function device */ - rt_uint8_t ari_enabled:1; /* Alternative Routing-ID Interpretation */ - rt_uint8_t no_msi:1; /* May not use MSI */ - rt_uint8_t no_64bit_msi:1; /* May only use 32-bit MSIs */ - rt_uint8_t msi_enabled:1; /* MSI enable */ - rt_uint8_t msix_enabled:1; /* MSIx enable */ - rt_uint8_t broken_intx_masking:1; /* INTx masking can't be used */ - rt_uint8_t pme_support:5; /* Bitmask of states from which PME# can be generated */ + rt_uint8_t busmaster : 1; /* Is the bus master */ + rt_uint8_t multi_function : 1; /* Multi-function device */ + rt_uint8_t ari_enabled : 1; /* Alternative Routing-ID Interpretation */ + rt_uint8_t no_msi : 1; /* May not use MSI */ + rt_uint8_t no_64bit_msi : 1; /* May only use 32-bit MSIs */ + rt_uint8_t msi_enabled : 1; /* MSI enable */ + rt_uint8_t msix_enabled : 1; /* MSIx enable */ + rt_uint8_t broken_intx_masking : 1; /* INTx masking can't be used */ + rt_uint8_t pme_support : 5; /* Bitmask of states from which PME# can be generated */ #ifdef RT_PCI_MSI - void *msix_base; - struct rt_pic *msi_pic; - rt_list_t msi_desc_nodes; + void *msix_base; + struct rt_pic *msi_pic; + rt_list_t msi_desc_nodes; struct rt_spinlock msi_lock; #endif }; @@ -191,20 +190,20 @@ struct rt_pci_host_bridge rt_uint32_t domain; - struct rt_pci_bus *root_bus; + struct rt_pci_bus *root_bus; const struct rt_pci_ops *ops; const struct rt_pci_ops *child_ops; - rt_uint32_t bus_range[2]; - rt_size_t bus_regions_nr; + rt_uint32_t bus_range[2]; + rt_size_t bus_regions_nr; struct rt_pci_bus_region *bus_regions; - rt_size_t dma_regions_nr; + rt_size_t dma_regions_nr; struct rt_pci_bus_region *dma_regions; rt_uint8_t (*irq_slot)(struct rt_pci_device *pdev, rt_uint8_t *pinp); - int (*irq_map)(struct rt_pci_device *pdev, rt_uint8_t slot, rt_uint8_t pin); + int (*irq_map)(struct rt_pci_device *pdev, rt_uint8_t slot, rt_uint8_t pin); - void *sysdata; + void *sysdata; rt_uint8_t priv[0]; }; #define rt_device_to_pci_host_bridge(dev) rt_container_of(dev, struct rt_pci_host_bridge, parent) @@ -217,16 +216,16 @@ struct rt_pci_ops void *(*map)(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg); rt_err_t (*read)(struct rt_pci_bus *bus, - rt_uint32_t devfn, int reg, int width, rt_uint32_t *value); + rt_uint32_t devfn, int reg, int width, rt_uint32_t *value); rt_err_t (*write)(struct rt_pci_bus *bus, - rt_uint32_t devfn, int reg, int width, rt_uint32_t value); + rt_uint32_t devfn, int reg, int width, rt_uint32_t value); }; struct rt_pci_bus { - rt_list_t list; - rt_list_t children_nodes; - rt_list_t devices_nodes; + rt_list_t list; + rt_list_t children_nodes; + rt_list_t devices_nodes; struct rt_pci_bus *parent; union @@ -239,8 +238,8 @@ struct rt_pci_bus const struct rt_pci_ops *ops; - char name[48]; - char number; + char name[48]; + char number; struct rt_spinlock lock; void *sysdata; @@ -250,7 +249,7 @@ struct rt_pci_driver { struct rt_driver parent; - const char *name; + const char *name; const struct rt_pci_device_id *ids; rt_err_t (*probe)(struct rt_pci_device *pdev); @@ -278,9 +277,9 @@ enum rt_pci_power void rt_pci_pme_init(struct rt_pci_device *pdev); void rt_pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable); rt_err_t rt_pci_enable_wake(struct rt_pci_device *pci_dev, - enum rt_pci_power state, rt_bool_t enable); + enum rt_pci_power state, rt_bool_t enable); rt_inline rt_bool_t rt_pci_pme_capable(struct rt_pci_device *pdev, - enum rt_pci_power state) + enum rt_pci_power state) { if (!pdev->pme_cap) { @@ -295,6 +294,8 @@ void rt_pci_msix_init(struct rt_pci_device *pdev); void rt_pci_set_master(struct rt_pci_device *pdev); void rt_pci_clear_master(struct rt_pci_device *pdev); +rt_err_t rt_pci_enable_device(struct rt_pci_device *pdev); +rt_err_t rt_pci_disable_device(struct rt_pci_device *pdev); struct rt_pci_host_bridge *rt_pci_host_bridge_alloc(rt_size_t priv_size); rt_err_t rt_pci_host_bridge_free(struct rt_pci_host_bridge *); @@ -340,7 +341,7 @@ rt_inline rt_bool_t rt_pci_is_root_bus(struct rt_pci_bus *bus) rt_inline rt_bool_t rt_pci_is_bridge(struct rt_pci_device *pdev) { return pdev->hdr_type == PCIM_HDRTYPE_BRIDGE || - pdev->hdr_type == PCIM_HDRTYPE_CARDBUS; + pdev->hdr_type == PCIM_HDRTYPE_CARDBUS; } rt_inline rt_bool_t rt_pci_is_pcie(struct rt_pci_device *pdev) @@ -349,86 +350,85 @@ rt_inline rt_bool_t rt_pci_is_pcie(struct rt_pci_device *pdev) } #define rt_pci_foreach_bridge(pdev, bus) \ - rt_list_for_each_entry(pdev, &bus->devices_nodes, list) \ - if (rt_pci_is_bridge(pdev)) + rt_list_for_each_entry(pdev, &bus->devices_nodes, list) if (rt_pci_is_bridge(pdev)) rt_err_t rt_pci_bus_read_config_u8(struct rt_pci_bus *bus, - rt_uint32_t devfn, int pos, rt_uint8_t *value); + rt_uint32_t devfn, int pos, rt_uint8_t *value); rt_err_t rt_pci_bus_read_config_u16(struct rt_pci_bus *bus, - rt_uint32_t devfn, int pos, rt_uint16_t *value); + rt_uint32_t devfn, int pos, rt_uint16_t *value); rt_err_t rt_pci_bus_read_config_u32(struct rt_pci_bus *bus, - rt_uint32_t devfn, int pos, rt_uint32_t *value); + rt_uint32_t devfn, int pos, rt_uint32_t *value); rt_err_t rt_pci_bus_write_config_u8(struct rt_pci_bus *bus, - rt_uint32_t devfn, int reg, rt_uint8_t value); + rt_uint32_t devfn, int reg, rt_uint8_t value); rt_err_t rt_pci_bus_write_config_u16(struct rt_pci_bus *bus, - rt_uint32_t devfn, int reg, rt_uint16_t value); + rt_uint32_t devfn, int reg, rt_uint16_t value); rt_err_t rt_pci_bus_write_config_u32(struct rt_pci_bus *bus, - rt_uint32_t devfn, int reg, rt_uint32_t value); + rt_uint32_t devfn, int reg, rt_uint32_t value); 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); + rt_uint32_t devfn, int reg, int width, rt_uint32_t *value); 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); + rt_uint32_t devfn, int reg, int width, rt_uint32_t value); 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); + rt_uint32_t devfn, int reg, int width, rt_uint32_t *value); 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); + rt_uint32_t devfn, int reg, int width, rt_uint32_t value); rt_inline rt_err_t rt_pci_read_config_u8(const struct rt_pci_device *pdev, - int reg, rt_uint8_t *value) + int reg, rt_uint8_t *value) { return rt_pci_bus_read_config_u8(pdev->bus, pdev->devfn, reg, value); } rt_inline rt_err_t rt_pci_read_config_u16(const struct rt_pci_device *pdev, - int reg, rt_uint16_t *value) + int reg, rt_uint16_t *value) { return rt_pci_bus_read_config_u16(pdev->bus, pdev->devfn, reg, value); } rt_inline rt_err_t rt_pci_read_config_u32(const struct rt_pci_device *pdev, - int reg, rt_uint32_t *value) + int reg, rt_uint32_t *value) { return rt_pci_bus_read_config_u32(pdev->bus, pdev->devfn, reg, value); } rt_inline rt_err_t rt_pci_write_config_u8(const struct rt_pci_device *pdev, - int reg, rt_uint8_t value) + int reg, rt_uint8_t value) { return rt_pci_bus_write_config_u8(pdev->bus, pdev->devfn, reg, value); } rt_inline rt_err_t rt_pci_write_config_u16(const struct rt_pci_device *pdev, - int reg, rt_uint16_t value) + int reg, rt_uint16_t value) { return rt_pci_bus_write_config_u16(pdev->bus, pdev->devfn, reg, value); } rt_inline rt_err_t rt_pci_write_config_u32(const struct rt_pci_device *pdev, - int reg, rt_uint32_t value) + int reg, rt_uint32_t value) { return rt_pci_bus_write_config_u32(pdev->bus, pdev->devfn, reg, value); } #ifdef RT_USING_OFW int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev, - rt_uint8_t slot, rt_uint8_t pin); + rt_uint8_t slot, rt_uint8_t pin); -rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge); +rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge); -rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge); +rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge); rt_err_t rt_pci_ofw_bus_init(struct rt_pci_bus *bus); rt_err_t rt_pci_ofw_bus_free(struct rt_pci_bus *bus); rt_err_t rt_pci_ofw_device_init(struct rt_pci_device *pdev); rt_err_t rt_pci_ofw_device_free(struct rt_pci_device *pdev); #else -rt_inline rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) +rt_inline rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge) { return RT_EOK; } @@ -449,12 +449,12 @@ rt_inline rt_err_t rt_pci_ofw_device_free(struct rt_pci_device *pdev) return RT_EOK; } rt_inline int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev, - rt_uint8_t slot, rt_uint8_t pin) + rt_uint8_t slot, rt_uint8_t pin) { return -1; } -rt_inline rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) +rt_inline rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge) { return -RT_ENOSYS; } @@ -481,30 +481,30 @@ rt_bool_t rt_pci_check_and_unmask_intx(struct rt_pci_device *pdev); void rt_pci_irq_mask(struct rt_pci_device *pdev); void rt_pci_irq_unmask(struct rt_pci_device *pdev); -#define RT_PCI_IRQ_F_LEGACY RT_BIT(0) /* Allow legacy interrupts */ -#define RT_PCI_IRQ_F_MSI RT_BIT(1) /* Allow MSI interrupts */ -#define RT_PCI_IRQ_F_MSIX RT_BIT(2) /* Allow MSI-X interrupts */ -#define RT_PCI_IRQ_F_AFFINITY RT_BIT(3) /* Auto-assign affinity */ -#define RT_PCI_IRQ_F_ALL_TYPES (RT_PCI_IRQ_F_LEGACY | RT_PCI_IRQ_F_MSI | RT_PCI_IRQ_F_MSIX) +#define RT_PCI_IRQ_F_LEGACY RT_BIT(0) /* Allow legacy interrupts */ +#define RT_PCI_IRQ_F_MSI RT_BIT(1) /* Allow MSI interrupts */ +#define RT_PCI_IRQ_F_MSIX RT_BIT(2) /* Allow MSI-X interrupts */ +#define RT_PCI_IRQ_F_AFFINITY RT_BIT(3) /* Auto-assign affinity */ +#define RT_PCI_IRQ_F_ALL_TYPES (RT_PCI_IRQ_F_LEGACY | RT_PCI_IRQ_F_MSI | RT_PCI_IRQ_F_MSIX) #ifdef RT_PCI_MSI rt_ssize_t rt_pci_alloc_vector(struct rt_pci_device *pdev, int min, int max, - rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))); + rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))); void rt_pci_free_vector(struct rt_pci_device *pdev); rt_ssize_t rt_pci_msi_vector_count(struct rt_pci_device *pdev); rt_err_t rt_pci_msi_disable(struct rt_pci_device *pdev); rt_ssize_t rt_pci_msi_enable_range_affinity(struct rt_pci_device *pdev, - int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))); + int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))); rt_ssize_t rt_pci_msix_vector_count(struct rt_pci_device *pdev); rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev); -rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int min, int max, - RT_IRQ_AFFINITY_DECLARE((*affinities))); +rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int min, int max, + RT_IRQ_AFFINITY_DECLARE((*affinities))); #else rt_inline rt_ssize_t rt_pci_alloc_vector(struct rt_pci_device *pdev, int min, int max, - rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))) + rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))) { return -RT_ENOSYS; } @@ -525,7 +525,7 @@ rt_inline rt_err_t rt_pci_msi_disable(struct rt_pci_device *pdev) } rt_inline rt_ssize_t rt_pci_msi_enable_range_affinity(struct rt_pci_device *pdev, - int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))) + int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))) { return -RT_ENOSYS; } @@ -540,16 +540,16 @@ rt_inline rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev) return RT_EOK; } -rt_inline rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int min, int max, - RT_IRQ_AFFINITY_DECLARE((*affinities))) +rt_inline rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int min, int max, + RT_IRQ_AFFINITY_DECLARE((*affinities))) { return -RT_ENOSYS; } #endif /* RT_PCI_MSI */ rt_inline void rt_pci_msix_entry_index_linear(struct rt_pci_msix_entry *entries, - rt_size_t nvectors) + rt_size_t nvectors) { for (int i = 0; i < nvectors; ++i) { @@ -558,7 +558,7 @@ rt_inline void rt_pci_msix_entry_index_linear(struct rt_pci_msix_entry *entries, } rt_inline rt_ssize_t rt_pci_msi_enable_range(struct rt_pci_device *pdev, - int min, int max) + int min, int max) { return rt_pci_msi_enable_range_affinity(pdev, min, max, RT_NULL); } @@ -569,38 +569,38 @@ rt_inline rt_err_t rt_pci_msi_enable(struct rt_pci_device *pdev) return res == 1 ? res : RT_EOK; } -rt_inline rt_ssize_t rt_pci_msix_enable_range(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int min, int max) +rt_inline rt_ssize_t rt_pci_msix_enable_range(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int min, int max) { return rt_pci_msix_enable_range_affinity(pdev, entries, min, max, RT_NULL); } -rt_inline rt_ssize_t rt_pci_msix_enable(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int count) +rt_inline rt_ssize_t rt_pci_msix_enable(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int count) { return rt_pci_msix_enable_range(pdev, entries, count, count); } rt_err_t rt_pci_region_setup(struct rt_pci_host_bridge *host_bridge); struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_bridge, - void **out_addr, rt_size_t size, rt_ubase_t flags, rt_bool_t mem64); + void **out_addr, rt_size_t size, rt_ubase_t flags, rt_bool_t mem64); rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, - struct rt_pci_device *pdev); + struct rt_pci_device *pdev); void rt_pci_enum_device(struct rt_pci_bus *bus, - rt_bool_t (callback(struct rt_pci_device *, void *)), void *data); + rt_bool_t(callback(struct rt_pci_device *, void *)), void *data); -const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, - const struct rt_pci_device_id *id); +const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, + const struct rt_pci_device_id *id); -const struct rt_pci_device_id *rt_pci_match_ids(struct rt_pci_device *pdev, - const struct rt_pci_device_id *ids); +const struct rt_pci_device_id *rt_pci_match_ids(struct rt_pci_device *pdev, + const struct rt_pci_device_id *ids); rt_err_t rt_pci_driver_register(struct rt_pci_driver *pdrv); rt_err_t rt_pci_device_register(struct rt_pci_device *pdev); -struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device* pdev,rt_ubase_t flags,int index); -#define RT_PCI_DRIVER_EXPORT(driver) RT_DRIVER_EXPORT(driver, pci, BUILIN) +struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device *pdev, rt_ubase_t flags, int index); +#define RT_PCI_DRIVER_EXPORT(driver) RT_DRIVER_EXPORT(driver, pci, BUILIN) extern struct rt_spinlock rt_pci_lock; diff --git a/components/drivers/ofw/io.c b/components/drivers/ofw/io.c index a84df210a6..2b0352f253 100755 --- a/components/drivers/ofw/io.c +++ b/components/drivers/ofw/io.c @@ -21,8 +21,8 @@ #include "ofw_internal.h" -static volatile rt_atomic_t _bus_ranges_idx = 0; -static struct bus_ranges *_bus_ranges[RT_USING_OFW_BUS_RANGES_NUMBER] = {}; +static volatile rt_atomic_t _bus_ranges_idx = 0; +static struct bus_ranges *_bus_ranges[RT_USING_OFW_BUS_RANGES_NUMBER] = {}; static int ofw_bus_addr_cells(struct rt_ofw_node *np) { @@ -101,19 +101,19 @@ int rt_ofw_get_address_count(struct rt_ofw_node *np) static rt_err_t ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_address, rt_uint64_t *out_size) { - rt_ssize_t len; - rt_err_t err = RT_EOK; - int addr_cells = rt_ofw_io_addr_cells(np); - int size_cells = rt_ofw_io_size_cells(np); - int skip_cells = (addr_cells + size_cells) * index; - const fdt32_t *cell = rt_ofw_prop_read_raw(np, "reg", &len); + rt_ssize_t len; + rt_err_t err = RT_EOK; + int addr_cells = rt_ofw_io_addr_cells(np); + int size_cells = rt_ofw_io_size_cells(np); + int skip_cells = (addr_cells + size_cells) * index; + const fdt32_t *cell = rt_ofw_prop_read_raw(np, "reg", &len); if (cell && skip_cells < (len / sizeof(*cell))) { - cell += skip_cells; - *out_address = rt_fdt_next_cell(&cell, addr_cells); - *out_address = rt_ofw_translate_address(np, RT_NULL, *out_address); - *out_size = rt_fdt_read_number(cell, size_cells); + cell += skip_cells; + *out_address = rt_fdt_next_cell(&cell, addr_cells); + *out_address = rt_ofw_translate_address(np, RT_NULL, *out_address); + *out_size = rt_fdt_read_number(cell, size_cells); } else { @@ -154,11 +154,11 @@ rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_ } static rt_err_t ofw_get_address_by_name(struct rt_ofw_node *np, const char *name, - rt_uint64_t *out_address, rt_uint64_t *out_size) + rt_uint64_t *out_address, rt_uint64_t *out_size) { - int index = 0; - rt_err_t err = -RT_EEMPTY; - const char *reg_name; + int index = 0; + rt_err_t err = -RT_EEMPTY; + const char *reg_name; struct rt_ofw_prop *prop; rt_ofw_foreach_prop_string(np, "reg-names", prop, reg_name) @@ -177,7 +177,7 @@ static rt_err_t ofw_get_address_by_name(struct rt_ofw_node *np, const char *name } rt_err_t rt_ofw_get_address_by_name(struct rt_ofw_node *np, const char *name, - rt_uint64_t *out_address, rt_uint64_t *out_size) + rt_uint64_t *out_address, rt_uint64_t *out_size) { rt_err_t err; @@ -213,11 +213,11 @@ int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_re if (np && nr > 0 && out_regs) { - rt_ssize_t len; - int max_nr; - int addr_cells = rt_ofw_io_addr_cells(np); - int size_cells = rt_ofw_io_size_cells(np); - const fdt32_t *cell = rt_ofw_prop_read_raw(np, "reg", &len); + rt_ssize_t len; + int max_nr; + int addr_cells = rt_ofw_io_addr_cells(np); + int size_cells = rt_ofw_io_size_cells(np); + const fdt32_t *cell = rt_ofw_prop_read_raw(np, "reg", &len); max_nr = len / (sizeof(*cell) * (addr_cells + size_cells)); @@ -228,7 +228,7 @@ int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_re count = nr; - while (nr --> 0) + while (nr-- > 0) { *out_regs = rt_fdt_next_cell(&cell, addr_cells); *out_regs = rt_ofw_translate_address(np, RT_NULL, *out_regs); @@ -246,13 +246,44 @@ int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_re return count; } +static rt_bool_t ofw_bus_is_pci(struct rt_ofw_node *bus) +{ + rt_ssize_t len; + struct rt_ofw_prop *prop; + + if (!bus) + { + return RT_FALSE; + } + + prop = rt_ofw_get_prop(bus, "device_type", &len); + + return prop && prop->value && len >= 3 && + !rt_strncmp(prop->value, "pci", 3); +} + +static rt_uint64_t ofw_read_bus_address(const fdt32_t **cell, int addr_cells, + struct rt_ofw_node *bus) +{ + if (addr_cells == 3 && ofw_bus_is_pci(bus)) + { + const fdt32_t *c = *cell; + + *cell += 3; + + return ((rt_uint64_t)fdt32_to_cpu(c[1]) << 32) | fdt32_to_cpu(c[2]); + } + + return rt_fdt_next_cell(cell, addr_cells); +} + static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_prop *prop) { - int id; - const fdt32_t *cell; + int id; + const fdt32_t *cell; struct bus_ranges *ranges = RT_NULL; - int child_address_cells, child_size_cells, parent_address_cells, groups; - rt_uint64_t *child_addr, *parent_addr, *child_size; + int child_address_cells, child_size_cells, parent_address_cells, groups; + rt_uint64_t *child_addr, *parent_addr, *child_size; /* * Address Translation Example: @@ -285,20 +316,21 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p * bus-address = parent-bus-address + (reg-address - child-bus-address) */ - do { - child_address_cells = rt_ofw_bus_addr_cells(np); - child_size_cells = rt_ofw_bus_size_cells(np); + do + { + child_address_cells = rt_ofw_bus_addr_cells(np); + child_size_cells = rt_ofw_bus_size_cells(np); parent_address_cells = rt_ofw_io_addr_cells(np); if (child_address_cells < 0 || child_size_cells < 0 || parent_address_cells < 0) { LOG_D("%s read address/size cells fail: child[%d, %d] parent[%d]", - np->full_name, child_address_cells, child_size_cells, parent_address_cells); + np->full_name, child_address_cells, child_size_cells, parent_address_cells); break; } - groups = prop->length / sizeof(*cell); + groups = prop->length / sizeof(*cell); groups /= child_address_cells + child_size_cells + parent_address_cells; ranges = rt_malloc(sizeof(*ranges) + sizeof(rt_uint64_t) * 3 * groups); @@ -308,25 +340,26 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p break; } - ranges->nr = groups; - ranges->child_addr = (void *)ranges + sizeof(*ranges); + ranges->nr = groups; + ranges->child_addr = (void *)ranges + sizeof(*ranges); ranges->parent_addr = &ranges->child_addr[groups]; - ranges->child_size = &ranges->parent_addr[groups]; + ranges->child_size = &ranges->parent_addr[groups]; cell = prop->value; - child_addr = ranges->child_addr; + child_addr = ranges->child_addr; parent_addr = ranges->parent_addr; - child_size = ranges->child_size; + child_size = ranges->child_size; - while (groups --> 0) + while (groups-- > 0) { - *child_addr++ = rt_fdt_next_cell(&cell, child_address_cells); - *parent_addr++ = rt_fdt_next_cell(&cell, parent_address_cells); - *child_size++ = rt_fdt_next_cell(&cell, child_size_cells); + *child_addr++ = ofw_read_bus_address(&cell, child_address_cells, np); + *parent_addr++ = ofw_read_bus_address(&cell, parent_address_cells, np->parent); + *child_size++ = rt_fdt_next_cell(&cell, child_size_cells); } - ranges->np = np; + ranges->np = np; + ranges->range_type = prop->name; id = (int)rt_atomic_add(&_bus_ranges_idx, 1); RT_ASSERT(id < RT_ARRAY_SIZE(_bus_ranges)); @@ -337,158 +370,176 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p return ranges; } +static struct bus_ranges *ofw_get_bus_ranges(struct rt_ofw_node *bus, const char *range_type) +{ + rt_ssize_t len; + struct rt_ofw_prop *prop; + struct bus_ranges *ranges = RT_NULL; + + prop = rt_ofw_get_prop(bus, range_type, &len); + + if (!prop || !len) + { + return RT_NULL; + } + + for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) + { + if (!_bus_ranges[i]) + { + break; + } + + if (_bus_ranges[i]->np == bus && + !rt_strcmp(_bus_ranges[i]->range_type, range_type)) + { + ranges = _bus_ranges[i]; + break; + } + } + + if (!ranges) + { + ranges = ofw_bus_ranges(bus, prop); + } + + return ranges; +} + +static rt_uint64_t ofw_translate_at_bus(struct rt_ofw_node *bus, const char *range_type, + rt_uint64_t address) +{ + struct bus_ranges *ranges = ofw_get_bus_ranges(bus, range_type); + + if (!ranges) + { + return ~0ULL; + } + + for (int i = 0; i < ranges->nr; ++i) + { + rt_uint64_t child_addr = ranges->child_addr[i]; + rt_uint64_t child_size = ranges->child_size[i]; + + if (address >= child_addr && address < child_addr + child_size) + { + return address + (ranges->parent_addr[i] - child_addr); + } + } + + return address; +} + +static rt_uint64_t ofw_reverse_at_bus(struct rt_ofw_node *bus, const char *range_type, + rt_uint64_t address) +{ + struct bus_ranges *ranges = ofw_get_bus_ranges(bus, range_type); + + if (!ranges) + { + return ~0ULL; + } + + for (int i = 0; i < ranges->nr; ++i) + { + rt_uint64_t parent_addr = ranges->parent_addr[i]; + rt_uint64_t child_size = ranges->child_size[i]; + + if (address >= parent_addr && address < parent_addr + child_size) + { + return ranges->child_addr[i] + (address - parent_addr); + } + } + + return address; +} + rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) { - rt_uint64_t cpu_addr = address; + struct rt_ofw_node *bus; if (!range_type) { range_type = "ranges"; } - rt_ofw_foreach_parent_node(np) + for (bus = np ? np->parent : RT_NULL; bus; bus = bus->parent) { - rt_ssize_t len; - struct rt_ofw_prop *prop; - struct bus_ranges *ranges = RT_NULL; + rt_ssize_t len; + rt_uint64_t translated; - prop = rt_ofw_get_prop(np, range_type, &len); - - if (!prop || !len) + if (!rt_ofw_get_prop(bus, range_type, &len) || !len) { continue; } - for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) + translated = ofw_translate_at_bus(bus, range_type, address); + if (translated == ~0ULL) { - if (!_bus_ranges[i]) - { - break; - } - - if (_bus_ranges[i]->np == np) - { - ranges = _bus_ranges[i]; - break; - } + return ~0ULL; } - if (!ranges) - { - ranges = ofw_bus_ranges(np, prop); - } - - if (ranges) - { - for (int i = 0; i < ranges->nr; ++i) - { - rt_uint64_t child_addr = ranges->child_addr[i]; - rt_uint64_t child_size = ranges->child_size[i]; - - if (address >= child_addr && address < child_addr + child_size) - { - cpu_addr = address + (ranges->parent_addr[i] - child_addr); - - break; - } - } - } - else - { - cpu_addr = ~0ULL; - } - - rt_ofw_node_put(np); - - break; + address = translated; } - return cpu_addr; + return address; } rt_uint64_t rt_ofw_reverse_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) { - rt_uint64_t bus_addr = address; + struct rt_ofw_node *bus; + struct rt_ofw_node *parents[16]; + int count = 0; if (!range_type) { range_type = "ranges"; } - rt_ofw_foreach_parent_node(np) + for (bus = np ? np->parent : RT_NULL; bus; bus = bus->parent) { rt_ssize_t len; - struct rt_ofw_prop *prop; - struct bus_ranges *ranges = RT_NULL; - prop = rt_ofw_get_prop(np, range_type, &len); - - if (!prop || !len) + if (!rt_ofw_get_prop(bus, range_type, &len) || !len) { continue; } - for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) + if (count < (int)RT_ARRAY_SIZE(parents)) { - if (!_bus_ranges[i]) - { - break; - } - - if (_bus_ranges[i]->np == np) - { - ranges = _bus_ranges[i]; - break; - } + parents[count++] = bus; } - - if (!ranges) - { - ranges = ofw_bus_ranges(np, prop); - } - - if (ranges) - { - for (int i = 0; i < ranges->nr; ++i) - { - rt_uint64_t parent_addr = ranges->parent_addr[i]; - rt_uint64_t child_size = ranges->child_size[i]; - - if (address >= parent_addr && address < parent_addr + child_size) - { - bus_addr = ranges->child_addr[i] + (address - parent_addr); - - break; - } - } - } - else - { - bus_addr = ~0ULL; - } - - rt_ofw_node_put(np); - - break; } - return bus_addr; + while (count-- > 0) + { + rt_uint64_t reversed = ofw_reverse_at_bus(parents[count], range_type, address); + + if (reversed == ~0ULL) + { + return ~0ULL; + } + + address = reversed; + } + + return address; } #ifdef ARCH_CPU_64BIT #define ofw_address_cpu_cast(np, address) (void *)(address) #else #define ofw_address_cpu_cast(np, address) \ -({ \ - if (((address) >> 32)) \ - { \ - LOG_W("%s find 64 bits address = %x%x", \ - rt_ofw_node_full_name(np), \ - ofw_static_cast(rt_ubase_t, (address) >> 32), \ - ofw_static_cast(rt_ubase_t, (address))); \ - } \ - (void *)ofw_static_cast(rt_ubase_t, (address)); \ -}) + ({ \ + if (((address) >> 32)) \ + { \ + LOG_W("%s find 64 bits address = %x%x", \ + rt_ofw_node_full_name(np), \ + ofw_static_cast(rt_ubase_t, (address) >> 32), \ + ofw_static_cast(rt_ubase_t, (address))); \ + } \ + (void *)ofw_static_cast(rt_ubase_t, (address)); \ + }) #endif void *rt_ofw_iomap(struct rt_ofw_node *np, int index) diff --git a/components/drivers/ofw/ofw_internal.h b/components/drivers/ofw/ofw_internal.h index 0a8c7c8b23..2d4990d0fe 100755 --- a/components/drivers/ofw/ofw_internal.h +++ b/components/drivers/ofw/ofw_internal.h @@ -15,14 +15,14 @@ #include #include -#define OFW_PHANDLE_MIN 1 -#define OFW_PHANDLE_MAX FDT_MAX_PHANDLE +#define OFW_PHANDLE_MIN 1 +#define OFW_PHANDLE_MAX FDT_MAX_PHANDLE -#define OFW_NODE_MAX_DEPTH 64 -#define OFW_NODE_MIN_HASH 128 +#define OFW_NODE_MAX_DEPTH 64 +#define OFW_NODE_MIN_HASH 128 -#define OFW_ROOT_NODE_ADDR_CELLS_DEFAULT 1 -#define OFW_ROOT_NODE_SIZE_CELLS_DEFAULT 1 +#define OFW_ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define OFW_ROOT_NODE_SIZE_CELLS_DEFAULT 1 struct fdt_info { /* Always "/", because we save "ofw" information in root node. */ @@ -33,24 +33,25 @@ struct fdt_info /* Only root can use */ struct fdt_reserve_entry *rsvmap; - rt_size_t rsvmap_nr; + rt_size_t rsvmap_nr; }; struct alias_info { rt_list_t list; - int id; + int id; const char *tag; - rt_size_t tag_len; + rt_size_t tag_len; struct rt_ofw_node *np; }; struct bus_ranges { - rt_size_t nr; + rt_size_t nr; struct rt_ofw_node *np; + const char *range_type; rt_uint64_t *child_addr; rt_uint64_t *parent_addr; diff --git a/components/drivers/pci/msi/irq.c b/components/drivers/pci/msi/irq.c index 8e3b7333e0..b8acfc53c0 100644 --- a/components/drivers/pci/msi/irq.c +++ b/components/drivers/pci/msi/irq.c @@ -19,10 +19,10 @@ 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; + 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) @@ -34,10 +34,10 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) if (type == PCIY_MSI) { - int last_irq = -1, irq_idx; + int last_irq = -1, irq_idx; rt_size_t irq_nr; - desc = rt_pci_msi_first_desc(pdev); + 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); @@ -49,14 +49,14 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) { err = irq; - LOG_E("Setup %s[%d] IRQ error = %s", "MSI", i, rt_strerror(err)); + LOG_E("Setup %s[%d] IRQ in %s error = %s", "MSI", i, msi_pic->ops->name, rt_strerror(err)); break; } if (last_irq >= 0 && last_irq + 1 != irq) { - for (int idx = 0; idx < i; ++i, --last_irq) + for (int idx = 0; idx < i; ++idx, --last_irq) { rt_bitmap_set_bit(msi_irq_map, last_irq); } @@ -88,7 +88,7 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) { for (int idx = 0; idx < nvec; ++idx) { - pirq = rt_pic_find_pirq(msi_pic, irq + idx); + pirq = rt_pic_find_pirq(msi_pic, desc->irq + idx); pirq->msi_desc = desc; msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg); @@ -105,14 +105,14 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) { err = irq; - LOG_E("Setup %s[%d] IRQ error = %s", "MSI-X", - desc->msix.index, rt_strerror(err)); + LOG_E("Setup %s[%d] IRQ in %s error = %s", "MSI-X", + desc->msix.index, msi_pic->ops->name, rt_strerror(err)); break; } - desc->irq = irq; - pirq = rt_pic_find_pirq(msi_pic, irq); + 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); @@ -147,8 +147,8 @@ rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type) rt_err_t rt_pci_msi_cleanup_irqs(struct rt_pci_device *pdev) { - int type; - struct rt_pic *msi_pic; + int type; + struct rt_pic *msi_pic; struct rt_pci_msi_desc *desc; if (!pdev) diff --git a/components/drivers/pci/msi/msi.c b/components/drivers/pci/msi/msi.c index 11ccdcb10c..8b0647cecf 100644 --- a/components/drivers/pci/msi/msi.c +++ b/components/drivers/pci/msi/msi.c @@ -39,7 +39,7 @@ rt_inline void *msix_vector_ctrl_base(struct rt_pci_msix_conf *msix) } rt_inline void msix_write_vector_ctrl(struct rt_pci_msix_conf *msix, - rt_uint32_t ctrl) + rt_uint32_t ctrl) { void *vc_addr = msix_vector_ctrl_base(msix); @@ -56,7 +56,7 @@ rt_inline void msix_mask(struct rt_pci_msix_conf *msix) } static void msix_update_ctrl(struct rt_pci_device *pdev, - rt_uint16_t clear, rt_uint16_t set) + rt_uint16_t clear, rt_uint16_t set) { rt_uint16_t msgctl; @@ -83,7 +83,7 @@ rt_inline rt_uint32_t msi_multi_mask(struct rt_pci_msi_conf *msi) } static void msi_write_mask(struct rt_pci_msi_conf *msi, - rt_uint32_t clear, rt_uint32_t set, struct rt_pci_device *pdev) + rt_uint32_t clear, rt_uint32_t set, struct rt_pci_device *pdev) { if (msi->cap.is_masking) { @@ -98,13 +98,13 @@ static void msi_write_mask(struct rt_pci_msi_conf *msi, } rt_inline void msi_mask(struct rt_pci_msi_conf *msi, - rt_uint32_t mask, struct rt_pci_device *pdev) + rt_uint32_t mask, struct rt_pci_device *pdev) { msi_write_mask(msi, 0, mask, pdev); } rt_inline void msi_unmask(struct rt_pci_msi_conf *msi, - rt_uint32_t mask, struct rt_pci_device *pdev) + rt_uint32_t mask, struct rt_pci_device *pdev) { msi_write_mask(msi, mask, 0, pdev); } @@ -126,14 +126,14 @@ static void msi_write_enable(struct rt_pci_device *pdev, rt_bool_t enable) } static void msi_affinity_init(struct rt_pci_msi_desc *desc, int msi_index, - rt_bitmap_t *cpumasks) + rt_bitmap_t *cpumasks) { - int irq; - struct rt_pic_irq *pirq; - struct rt_pci_device *pdev = desc->pdev; - struct rt_pic *msi_pic = pdev->msi_pic; + int irq; + struct rt_pic_irq *pirq; + struct rt_pci_device *pdev = desc->pdev; + struct rt_pic *msi_pic = pdev->msi_pic; - irq = desc->irq + desc->is_msix ? 0 : msi_index; + irq = desc->is_msix ? desc->irq : desc->irq + msi_index; pirq = rt_pic_find_pirq(msi_pic, irq); /* Save affinity */ @@ -152,9 +152,9 @@ static void msi_affinity_init(struct rt_pci_msi_desc *desc, int msi_index, rt_uint64_t data_address; /* Get MSI/MSI-X write data adddress */ - data_address = desc->msg.address_hi; + data_address = desc->msg.address_hi; data_address <<= 32; - data_address |= desc->msg.address_lo; + data_address |= desc->msg.address_lo; /* Prepare affinity */ cpumasks = pirq->affinity; @@ -194,7 +194,7 @@ void rt_pci_msi_shutdown(struct rt_pci_device *pdev) } /* Restore pdev->irq to its default pin-assertion IRQ */ - pdev->irq = desc->msi.default_irq; + pdev->irq = desc->msi.default_irq; pdev->msi_enabled = RT_FALSE; } @@ -260,13 +260,13 @@ void rt_pci_msi_write_msg(struct rt_pci_msi_desc *desc, struct rt_pci_msi_msg *m if (desc->is_msix) { - void *msix_entry; - rt_bool_t unmasked; - rt_uint32_t msgctl; + void *msix_entry; + rt_bool_t unmasked; + rt_uint32_t msgctl; struct rt_pci_msix_conf *msix = &desc->msix; - msgctl = msix->msg_ctrl; - unmasked = !(msgctl & PCIM_MSIX_ENTRYVECTOR_CTRL_MASK); + msgctl = msix->msg_ctrl; + unmasked = !(msgctl & PCIM_MSIX_ENTRYVECTOR_CTRL_MASK); msix_entry = msix_table_base(msix); if (unmasked) @@ -276,7 +276,7 @@ void rt_pci_msi_write_msg(struct rt_pci_msi_desc *desc, struct rt_pci_msi_msg *m HWREG32(msix_entry + PCIM_MSIX_ENTRY_LOWER_ADDR) = msg->address_lo; HWREG32(msix_entry + PCIM_MSIX_ENTRY_UPPER_ADDR) = msg->address_hi; - HWREG32(msix_entry + PCIM_MSIX_ENTRY_DATA) = msg->data; + HWREG32(msix_entry + PCIM_MSIX_ENTRY_DATA) = msg->data; if (unmasked) { @@ -288,8 +288,8 @@ void rt_pci_msi_write_msg(struct rt_pci_msi_desc *desc, struct rt_pci_msi_msg *m } else { - rt_uint16_t msgctl; - int pos = pdev->msi_cap; + rt_uint16_t msgctl; + int pos = pdev->msi_cap; struct rt_pci_msi_conf *msi = &desc->msi; rt_pci_read_config_u16(pdev, pos + PCIR_MSI_CTRL, &msgctl); @@ -365,7 +365,7 @@ void rt_pci_msi_unmask_irq(struct rt_pic_irq *pirq) } rt_ssize_t rt_pci_alloc_vector(struct rt_pci_device *pdev, int min, int max, - rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))) + rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities))) { rt_ssize_t res = -RT_ENOSYS; @@ -458,9 +458,9 @@ static rt_err_t msi_verify_entries(struct rt_pci_device *pdev) if (desc->msg.address_hi) { LOG_D("%s: Arch assigned 64-bit MSI address %08x%08x" - "but device only supports 32 bits", - rt_dm_dev_get_name(&pdev->parent), - desc->msg.address_hi, desc->msg.address_lo); + "but device only supports 32 bits", + rt_dm_dev_get_name(&pdev->parent), + desc->msg.address_hi, desc->msg.address_lo); return -RT_EIO; } @@ -470,10 +470,10 @@ static rt_err_t msi_verify_entries(struct rt_pci_device *pdev) return RT_EOK; } -static rt_err_t msi_insert_desc(struct rt_pci_device *pdev, - struct rt_pci_msi_desc *init_desc) +static rt_err_t msi_insert_desc(struct rt_pci_device *pdev, + struct rt_pci_msi_desc *init_desc) { - rt_size_t msi_affinity_ptr_size = 0; + rt_size_t msi_affinity_ptr_size = 0; struct rt_pci_msi_desc *msi_desc; if (!init_desc->is_msix) @@ -545,19 +545,19 @@ rt_err_t rt_pci_msi_disable(struct rt_pci_device *pdev) static rt_err_t msi_setup_msi_desc(struct rt_pci_device *pdev, int nvec) { - rt_uint16_t msgctl; + rt_uint16_t msgctl; struct rt_pci_msi_desc desc; rt_memset(&desc, 0, sizeof(desc)); - desc.vector_used = nvec; + desc.vector_used = nvec; desc.vector_count = rt_pci_msi_vector_count(pdev); - desc.is_msix = RT_FALSE; + desc.is_msix = RT_FALSE; rt_pci_read_config_u16(pdev, pdev->msi_cap + PCIR_MSI_CTRL, &msgctl); - desc.msi.cap.is_64bit = !!(msgctl & PCIM_MSICTRL_64BIT); - desc.msi.cap.is_masking = !!(msgctl & PCIM_MSICTRL_VECTOR); + desc.msi.cap.is_64bit = !!(msgctl & PCIM_MSICTRL_64BIT); + desc.msi.cap.is_masking = !!(msgctl & PCIM_MSICTRL_VECTOR); desc.msi.cap.multi_msg_max = (msgctl & PCIM_MSICTRL_MMC_MASK) >> 1; for (int log2 = 0; log2 < 5; ++log2) @@ -591,9 +591,9 @@ static rt_err_t msi_setup_msi_desc(struct rt_pci_device *pdev, int nvec) } static rt_ssize_t msi_capability_init(struct rt_pci_device *pdev, - int nvec, RT_IRQ_AFFINITY_DECLARE((*affinities))) + int nvec, RT_IRQ_AFFINITY_DECLARE((*affinities))) { - rt_err_t err; + rt_err_t err; struct rt_pci_msi_desc *desc; msi_write_enable(pdev, RT_FALSE); @@ -624,7 +624,7 @@ static rt_ssize_t msi_capability_init(struct rt_pci_device *pdev, rt_pci_msi_free_irqs(pdev); LOG_E("%s: Setup %s interrupts(%d) error = %s", - rt_dm_dev_get_name(&pdev->parent), "MSI", nvec, rt_strerror(err)); + rt_dm_dev_get_name(&pdev->parent), "MSI", nvec, rt_strerror(err)); return err; } @@ -651,9 +651,9 @@ static rt_ssize_t msi_capability_init(struct rt_pci_device *pdev, } rt_ssize_t rt_pci_msi_enable_range_affinity(struct rt_pci_device *pdev, - int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))) + int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities))) { - int nvec = max; + int nvec = max; rt_size_t entries_nr; if (!pdev || min > max) @@ -736,9 +736,9 @@ rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev) static void *msix_table_remap(struct rt_pci_device *pdev, rt_size_t entries_nr) { - rt_uint8_t bir; + rt_uint8_t bir; rt_uint32_t table_offset; - rt_ubase_t table_base_phys; + rt_ubase_t table_base_phys; rt_pci_read_config_u32(pdev, pdev->msix_cap + PCIR_MSIX_TABLE, &table_offset); bir = (rt_uint8_t)(table_offset & PCIM_MSIX_BIR_MASK); @@ -756,26 +756,26 @@ static void *msix_table_remap(struct rt_pci_device *pdev, rt_size_t entries_nr) } static rt_err_t msix_setup_msi_descs(struct rt_pci_device *pdev, - void *table_base, struct rt_pci_msix_entry *entries, int nvec) + void *table_base, struct rt_pci_msix_entry *entries, int nvec) { - rt_err_t err; + rt_err_t err; struct rt_pci_msi_desc desc; rt_memset(&desc, 0, sizeof(desc)); - desc.vector_used = 1; + desc.vector_used = 1; desc.vector_count = rt_pci_msix_vector_count(pdev); - desc.is_msix = RT_TRUE; + desc.is_msix = RT_TRUE; desc.msix.table_base = table_base; for (int i = 0; i < nvec; ++i) { void *table_entry; - int index = entries ? entries[i].index : i; + int index = entries ? entries[i].index : i; desc.msix.index = index; - table_entry = msix_table_base(&desc.msix); + table_entry = msix_table_base(&desc.msix); desc.msix.msg_ctrl = HWREG32(table_entry + PCIM_MSIX_ENTRY_VECTOR_CTRL); @@ -788,15 +788,15 @@ static rt_err_t msix_setup_msi_descs(struct rt_pci_device *pdev, return err; } -static rt_ssize_t msix_capability_init(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int nvec, - RT_IRQ_AFFINITY_DECLARE((*affinities))) +static rt_ssize_t msix_capability_init(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int nvec, + RT_IRQ_AFFINITY_DECLARE((*affinities))) { - rt_err_t err; - rt_uint16_t msgctl; - rt_size_t table_size; - void *table_base, *table_entry; - struct rt_pci_msi_desc *desc; + rt_err_t err; + rt_uint16_t msgctl; + rt_size_t table_size; + void *table_base, *table_entry; + struct rt_pci_msi_desc *desc; struct rt_pci_msix_entry *entry; /* @@ -840,7 +840,7 @@ static rt_ssize_t msix_capability_init(struct rt_pci_device *pdev, rt_pci_msi_free_irqs(pdev); LOG_E("%s: Setup %s interrupts(%d) error = %s", - rt_dm_dev_get_name(&pdev->parent), "MSI-X", nvec, rt_strerror(err)); + rt_dm_dev_get_name(&pdev->parent), "MSI-X", nvec, rt_strerror(err)); goto _out_disbale_msix; } @@ -878,11 +878,11 @@ _out_disbale_msix: return err; } -rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, - struct rt_pci_msix_entry *entries, int min, int max, - RT_IRQ_AFFINITY_DECLARE((*affinities))) +rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, + struct rt_pci_msix_entry *entries, int min, int max, + RT_IRQ_AFFINITY_DECLARE((*affinities))) { - int nvec = max; + int nvec = max; rt_size_t entries_nr; if (!pdev || min > max) @@ -940,7 +940,7 @@ rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev, if (target->index == entries[j].index) { LOG_E("%s: msix entry[%d].index = entry[%d].index", - rt_dm_dev_get_name(&pdev->parent), i, j); + rt_dm_dev_get_name(&pdev->parent), i, j); return -RT_EINVAL; } diff --git a/components/drivers/pci/ofw.c b/components/drivers/pci/ofw.c index 450402d6bd..7398051881 100644 --- a/components/drivers/pci/ofw.c +++ b/components/drivers/pci/ofw.c @@ -23,11 +23,11 @@ static rt_err_t pci_ofw_irq_parse(struct rt_pci_device *pdev, struct rt_ofw_cell_args *out_irq) { - rt_err_t err = RT_EOK; - rt_uint8_t pin; - fdt32_t map_addr[4]; + rt_err_t err = RT_EOK; + rt_uint8_t pin; + fdt32_t map_addr[4]; struct rt_pci_device *p2pdev; - struct rt_ofw_node *dev_np, *p2pnode = RT_NULL; + struct rt_ofw_node *dev_np, *p2pnode = RT_NULL; /* Parse device tree if dev have a device node */ dev_np = pdev->parent.ofw_node; @@ -57,7 +57,7 @@ static rt_err_t pci_ofw_irq_parse(struct rt_pci_device *pdev, struct rt_ofw_cell /* Try local interrupt-map in the device node */ if (rt_ofw_prop_read_raw(dev_np, "interrupt-map", RT_NULL)) { - pin = rt_pci_irq_intx(pdev, pin); + pin = rt_pci_irq_intx(pdev, pin); p2pnode = dev_np; } @@ -92,15 +92,15 @@ static rt_err_t pci_ofw_irq_parse(struct rt_pci_device *pdev, struct rt_ofw_cell } /* Try get INTx in P2P */ - pin = rt_pci_irq_intx(pdev, pin); + pin = rt_pci_irq_intx(pdev, pin); pdev = p2pdev; } /* For more format detail, please read `components/drivers/ofw/irq.c:ofw_parse_irq_map` */ - out_irq->data = map_addr; + out_irq->data = map_addr; out_irq->args_count = 2; - out_irq->args[0] = 3; - out_irq->args[1] = 1; + out_irq->args[0] = 3; + out_irq->args[1] = 1; /* In addr cells */ map_addr[0] = cpu_to_fdt32((pdev->bus->number << 16) | (pdev->devfn << 8)); @@ -115,24 +115,24 @@ _err: if (err == -RT_EEMPTY) { LOG_W("PCI-Device<%s> no interrupt-map found, INTx interrupts not available", - rt_dm_dev_get_name(&pdev->parent)); + rt_dm_dev_get_name(&pdev->parent)); LOG_W("PCI-Device<%s> possibly some PCI slots don't have level triggered interrupts capability", - rt_dm_dev_get_name(&pdev->parent)); + rt_dm_dev_get_name(&pdev->parent)); } else if (err && err != -RT_ENOSYS) { LOG_E("PCI-Device<%s> irq parse failed with err = %s", - rt_dm_dev_get_name(&pdev->parent), rt_strerror(err)); + rt_dm_dev_get_name(&pdev->parent), rt_strerror(err)); } return err; } int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev, - rt_uint8_t slot, rt_uint8_t pin) + rt_uint8_t slot, rt_uint8_t pin) { - int irq = -1; - rt_err_t status; + int irq = -1; + rt_err_t status; struct rt_ofw_cell_args irq_args; if (!pdev) @@ -159,25 +159,25 @@ _end: } static rt_err_t pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, const char *propname, - int phy_addr_cells, int phy_size_cells, int cpu_addr_cells, - struct rt_pci_bus_region **out_regions, rt_size_t *out_regions_nr) + int phy_addr_cells, int phy_size_cells, int cpu_addr_cells, + struct rt_pci_bus_region **out_regions, rt_size_t *out_regions_nr) { const fdt32_t *cell; - rt_ssize_t total_cells; - int groups, space_code; - rt_uint32_t phy_addr[3]; - rt_uint64_t cpu_addr, phy_addr_size; + rt_ssize_t total_cells; + int groups, space_code; + rt_uint32_t phy_addr[3]; + rt_uint64_t cpu_addr, phy_addr_size; - *out_regions = RT_NULL; + *out_regions = RT_NULL; *out_regions_nr = 0; - cell = rt_ofw_prop_read_raw(dev_np, propname, &total_cells); + cell = rt_ofw_prop_read_raw(dev_np, propname, &total_cells); if (!cell) { return -RT_EEMPTY; } - groups = total_cells / sizeof(*cell) / (phy_addr_cells + phy_size_cells + cpu_addr_cells); + groups = total_cells / sizeof(*cell) / (phy_addr_cells + phy_size_cells + cpu_addr_cells); *out_regions = rt_malloc(groups * sizeof(struct rt_pci_bus_region)); if (!*out_regions) @@ -214,21 +214,20 @@ static rt_err_t pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, const char *pro space_code = (phy_addr[0] >> 24) & 0x3; - cpu_addr = rt_fdt_read_number(cell, cpu_addr_cells); - cell += cpu_addr_cells; - phy_addr_size = rt_fdt_read_number(cell, phy_size_cells); - cell += phy_size_cells; + cpu_addr = rt_fdt_read_number(cell, cpu_addr_cells); + cell += cpu_addr_cells; + phy_addr_size = rt_fdt_read_number(cell, phy_size_cells); + cell += phy_size_cells; (*out_regions)[i].phy_addr = ((rt_uint64_t)phy_addr[1] << 32) | phy_addr[2]; (*out_regions)[i].cpu_addr = cpu_addr; - (*out_regions)[i].size = phy_addr_size; + (*out_regions)[i].size = phy_addr_size; (*out_regions)[i].bus_start = (*out_regions)[i].phy_addr; if (space_code & 2) { - (*out_regions)[i].flags = phy_addr[0] & (1U << 30) ? - PCI_BUS_REGION_F_PREFETCH : PCI_BUS_REGION_F_MEM; + (*out_regions)[i].flags = phy_addr[0] & (1U << 30) ? PCI_BUS_REGION_F_PREFETCH : PCI_BUS_REGION_F_MEM; } else if (space_code & 1) { @@ -245,11 +244,11 @@ static rt_err_t pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, const char *pro return RT_EOK; } -rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) +rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge) { rt_err_t err; - int phy_addr_cells = -1, phy_size_cells = -1, cpu_addr_cells; + int phy_addr_cells = -1, phy_size_cells = -1, cpu_addr_cells; if (!dev_np || !host_bridge) { @@ -266,8 +265,8 @@ rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, } if (pci_ofw_parse_ranges(dev_np, "ranges", - phy_addr_cells, phy_size_cells, cpu_addr_cells, - &host_bridge->bus_regions, &host_bridge->bus_regions_nr)) + phy_addr_cells, phy_size_cells, cpu_addr_cells, + &host_bridge->bus_regions, &host_bridge->bus_regions_nr)) { return -RT_EINVAL; } @@ -281,8 +280,8 @@ rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, } err = pci_ofw_parse_ranges(dev_np, "dma-ranges", - phy_addr_cells, phy_size_cells, cpu_addr_cells, - &host_bridge->dma_regions, &host_bridge->dma_regions_nr); + phy_addr_cells, phy_size_cells, cpu_addr_cells, + &host_bridge->dma_regions, &host_bridge->dma_regions_nr); if (err && err != -RT_EEMPTY) { @@ -290,7 +289,7 @@ rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, host_bridge->bus_regions_nr = 0; LOG_E("%s: Read dma-ranges error = %s", rt_ofw_node_full_name(dev_np), - rt_strerror(err)); + rt_strerror(err)); return err; } @@ -298,10 +297,10 @@ rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, return RT_EOK; } -rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) +rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, + struct rt_pci_host_bridge *host_bridge) { - rt_err_t err; + rt_err_t err; const char *propname; if (!dev_np || !host_bridge) @@ -310,18 +309,26 @@ rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, } host_bridge->irq_slot = rt_pci_irq_slot; - host_bridge->irq_map = rt_pci_ofw_irq_parse_and_map; + host_bridge->irq_map = rt_pci_ofw_irq_parse_and_map; if (rt_ofw_prop_read_u32_array_index(dev_np, "bus-range", 0, 2, host_bridge->bus_range) < 0) { host_bridge->bus_range[0] = 0x00; host_bridge->bus_range[1] = 0xff; LOG_I("%s: No \"%s\" found, using [%#02x, %#02x]", rt_ofw_node_full_name(dev_np), "bus-range", - host_bridge->bus_range[0], host_bridge->bus_range[1]); + host_bridge->bus_range[0], host_bridge->bus_range[1]); } propname = rt_ofw_get_prop_fuzzy_name(dev_np, ",pci-domain$"); - rt_ofw_prop_read_u32(dev_np, propname, &host_bridge->domain); + + if (propname) + { + rt_ofw_prop_read_u32(dev_np, propname, &host_bridge->domain); + } + else + { + host_bridge->domain = RT_UINT32_MAX; + } err = rt_pci_ofw_parse_ranges(dev_np, host_bridge); @@ -463,9 +470,9 @@ rt_err_t rt_pci_ofw_bus_free(struct rt_pci_bus *bus) static void ofw_msi_pic_init(struct rt_pci_device *pdev) { #ifdef RT_PCI_MSI - rt_uint32_t rid; + rt_uint32_t rid; struct rt_pci_host_bridge *bridge; - struct rt_ofw_node *np, *msi_ic_np = RT_NULL; + struct rt_ofw_node *np, *msi_ic_np = RT_NULL; /* * NOTE: Typically, a device's RID is equal to the PCI device's ID. @@ -505,21 +512,21 @@ static void ofw_msi_pic_init(struct rt_pci_device *pdev) if (!pdev->msi_pic->ops->irq_compose_msi_msg) { LOG_E("%s: MSI pic MUST implemented %s", - rt_ofw_node_full_name(msi_ic_np), "irq_compose_msi_msg"); + rt_ofw_node_full_name(msi_ic_np), "irq_compose_msi_msg"); RT_ASSERT(0); } if (!pdev->msi_pic->ops->irq_alloc_msi) { LOG_E("%s: MSI pic MUST implemented %s", - rt_ofw_node_full_name(msi_ic_np), "irq_alloc_msi"); + rt_ofw_node_full_name(msi_ic_np), "irq_alloc_msi"); RT_ASSERT(0); } if (!pdev->msi_pic->ops->irq_free_msi) { LOG_E("%s: MSI pic MUST implemented %s", - rt_ofw_node_full_name(msi_ic_np), "irq_free_msi"); + rt_ofw_node_full_name(msi_ic_np), "irq_free_msi"); RT_ASSERT(0); } @@ -530,7 +537,7 @@ _out_put_msi_parent_node: static rt_int32_t ofw_pci_devfn(struct rt_ofw_node *np) { - rt_int32_t res; + rt_int32_t res; rt_uint32_t reg[5]; res = rt_ofw_prop_read_u32_array_index(np, "reg", 0, RT_ARRAY_SIZE(reg), reg); diff --git a/components/drivers/pci/pci.c b/components/drivers/pci/pci.c index 3ba3967e7d..ca34082d4b 100644 --- a/components/drivers/pci/pci.c +++ b/components/drivers/pci/pci.c @@ -47,9 +47,9 @@ rt_uint32_t rt_pci_domain(struct rt_pci_device *pdev) } static rt_uint8_t pci_find_next_cap_ttl(struct rt_pci_bus *bus, - rt_uint32_t devfn, rt_uint8_t pos, int cap, int *ttl) + rt_uint32_t devfn, rt_uint8_t pos, int cap, int *ttl) { - rt_uint8_t ret = 0, id; + rt_uint8_t ret = 0, id; rt_uint16_t ent; rt_pci_bus_read_config_u8(bus, devfn, pos, &pos); @@ -81,7 +81,7 @@ static rt_uint8_t pci_find_next_cap_ttl(struct rt_pci_bus *bus, } static rt_uint8_t pci_find_next_cap(struct rt_pci_bus *bus, - rt_uint32_t devfn, rt_uint8_t pos, int cap) + rt_uint32_t devfn, rt_uint8_t pos, int cap) { int ttl = RT_PCI_FIND_CAP_TTL; @@ -89,9 +89,9 @@ static rt_uint8_t pci_find_next_cap(struct rt_pci_bus *bus, } static rt_uint8_t pci_bus_find_cap_start(struct rt_pci_bus *bus, - rt_uint32_t devfn, rt_uint8_t hdr_type) + rt_uint32_t devfn, rt_uint8_t hdr_type) { - rt_uint8_t res = 0; + rt_uint8_t res = 0; rt_uint16_t status; rt_pci_bus_read_config_u16(bus, devfn, PCIR_STATUS, &status); @@ -169,7 +169,7 @@ rt_uint16_t rt_pci_find_ext_capability(struct rt_pci_device *pdev, int cap) rt_uint16_t rt_pci_find_ext_next_capability(struct rt_pci_device *pdev, rt_uint16_t pos, int cap) { - int ttl; + int ttl; rt_uint32_t header; rt_uint16_t start = pos; @@ -262,6 +262,83 @@ void rt_pci_clear_master(struct rt_pci_device *pdev) } } +static rt_err_t pci_enable_resources(struct rt_pci_device *pdev) +{ + rt_uint16_t cmd, old_cmd, subclass; + + rt_pci_read_config_u16(pdev, PCIR_COMMAND, &cmd); + old_cmd = cmd; + + for (int i = 0; i < RT_PCI_BAR_NR_MAX; ++i) + { + struct rt_pci_bus_resource *res = &pdev->resource[i]; + + if (res->flags == PCI_BUS_REGION_F_NONE || res->size == 0) + { + continue; + } + + if (res->flags & PCI_BUS_REGION_F_IO) + { + cmd |= PCIM_CMD_PORTEN; + } + else + { + cmd |= PCIM_CMD_MEMEN; + } + } + + if (pdev->rom.size) + { + cmd |= PCIM_CMD_MEMEN; + } + + rt_pci_read_config_u16(pdev, PCIR_SUBCLASS, &subclass); + + if (subclass == PCIS_DISPLAY_VGA) + { + cmd |= PCIM_CMD_PORTEN; + } + + if (cmd != old_cmd) + { + LOG_D("%s enabling device (%04x -> %04x)", rt_dm_dev_get_name(&pdev->parent), old_cmd, cmd); + rt_pci_write_config_u16(pdev, PCIR_COMMAND, cmd); + } + + return RT_EOK; +} + +rt_err_t rt_pci_enable_device(struct rt_pci_device *pdev) +{ + if (!pdev) + { + return -RT_EINVAL; + } + + pci_enable_resources(pdev); + rt_pci_set_master(pdev); + + return RT_EOK; +} + +rt_err_t rt_pci_disable_device(struct rt_pci_device *pdev) +{ + rt_uint16_t cmd; + + if (!pdev) + { + return -RT_EINVAL; + } + + rt_pci_read_config_u16(pdev, PCIR_COMMAND, &cmd); + cmd &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + rt_pci_write_config_u16(pdev, PCIR_COMMAND, cmd); + pdev->busmaster = RT_FALSE; + + return RT_EOK; +} + void rt_pci_intx(struct rt_pci_device *pdev, rt_bool_t enable) { rt_uint16_t pci_command, new; @@ -290,11 +367,11 @@ void rt_pci_intx(struct rt_pci_device *pdev, rt_bool_t enable) static rt_bool_t pci_check_and_set_intx_mask(struct rt_pci_device *pdev, rt_bool_t mask) { - rt_ubase_t level; - rt_bool_t irq_pending; - rt_bool_t res = RT_TRUE; - rt_uint16_t origcmd, newcmd; - rt_uint32_t cmd_status_dword; + rt_ubase_t level; + rt_bool_t irq_pending; + rt_bool_t res = RT_TRUE; + rt_uint16_t origcmd, newcmd; + rt_uint32_t cmd_status_dword; struct rt_pci_bus *bus = pdev->bus; level = rt_spin_lock_irqsave(&rt_pci_lock); @@ -315,7 +392,7 @@ static rt_bool_t pci_check_and_set_intx_mask(struct rt_pci_device *pdev, rt_bool else { origcmd = cmd_status_dword; - newcmd = origcmd & ~PCIM_CMD_INTxDIS; + newcmd = origcmd & ~PCIM_CMD_INTxDIS; if (mask) { @@ -360,7 +437,7 @@ void rt_pci_irq_mask(struct rt_pci_device *pdev) { if (pdev) { - rt_bool_t unused; + rt_bool_t unused; struct rt_pic_irq *pirq; rt_pci_intx(pdev, RT_FALSE); @@ -436,7 +513,7 @@ rt_uint8_t rt_pci_irq_slot(struct rt_pci_device *pdev, rt_uint8_t *pinp) while (!rt_pci_is_root_bus(pdev->bus)) { - pin = rt_pci_irq_intx(pdev, pin); + pin = rt_pci_irq_intx(pdev, pin); pdev = pdev->bus->self; } @@ -460,9 +537,7 @@ rt_err_t rt_pci_region_setup(struct rt_pci_host_bridge *host_bridge) region->bus_start = rt_max_t(rt_size_t, 0x1000, region->phy_addr); LOG_I("Bus %s region(%d):", - region->flags == PCI_BUS_REGION_F_MEM ? "Memory" : - (region->flags == PCI_BUS_REGION_F_PREFETCH ? "Prefetchable Mem" : - (region->flags == PCI_BUS_REGION_F_IO ? "I/O" : "Unknown")), i); + region->flags == PCI_BUS_REGION_F_MEM ? "Memory" : (region->flags == PCI_BUS_REGION_F_PREFETCH ? "Prefetchable Mem" : (region->flags == PCI_BUS_REGION_F_IO ? "I/O" : "Unknown")), i); LOG_I(" cpu: [%p, %p]", region->cpu_addr, (region->cpu_addr + region->size - 1)); LOG_I(" physical: [%p, %p]", region->phy_addr, (region->phy_addr + region->size - 1)); } @@ -471,7 +546,7 @@ rt_err_t rt_pci_region_setup(struct rt_pci_host_bridge *host_bridge) } struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_bridge, - void **out_addr, rt_size_t size, rt_ubase_t flags, rt_bool_t mem64) + void **out_addr, rt_size_t size, rt_ubase_t flags, rt_bool_t mem64) { struct rt_pci_bus_region *bus_region, *region = RT_NULL; @@ -484,7 +559,7 @@ struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_br void *addr; region = bus_region; - addr = (void *)(((region->bus_start - 1) | (size - 1)) + 1); + addr = (void *)(((region->bus_start - 1) | (size - 1)) + 1); if ((rt_uint64_t)addr - region->phy_addr + size <= region->size) { @@ -500,8 +575,9 @@ struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_br continue; } } - else if (addr64) + else if (addr64 && flags == PCI_BUS_REGION_F_MEM) { + /* 32-bit MEM BAR needs a CPU address below 4G. */ region = RT_NULL; /* Try again */ @@ -509,7 +585,7 @@ struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_br } region->bus_start = ((rt_uint64_t)addr + size); - *out_addr = addr; + *out_addr = addr; } break; @@ -526,16 +602,16 @@ struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_br } rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, - struct rt_pci_device *pdev) + struct rt_pci_device *pdev) { - rt_err_t err = RT_EOK; - rt_size_t size; - rt_ubase_t addr = 0; + rt_err_t err = RT_EOK; + rt_size_t size; + rt_ubase_t addr = 0; rt_uint32_t cfg; - rt_size_t bars_nr; - rt_uint8_t hdr_type; - rt_bool_t prefetch = RT_FALSE; - rt_uint16_t class, command = 0; + rt_size_t bars_nr; + rt_uint8_t hdr_type; + rt_bool_t prefetch = RT_FALSE; + rt_uint16_t orig_cmd, command = 0; for (int i = 0; i < host_bridge->bus_regions_nr; ++i) { @@ -546,8 +622,13 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, } } - rt_pci_read_config_u16(pdev, PCIR_COMMAND, &command); - command = (command & ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) | PCIM_CMD_BUSMASTEREN; + rt_pci_read_config_u16(pdev, PCIR_COMMAND, &orig_cmd); + if (orig_cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) + { + rt_pci_write_config_u16(pdev, PCIR_COMMAND, + orig_cmd & ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)); + } + rt_pci_read_config_u8(pdev, PCIR_HDRTYPE, &hdr_type); if (pdev->hdr_type != hdr_type) @@ -576,12 +657,14 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, for (int i = 0; i < bars_nr; ++i) { - rt_ubase_t flags; - rt_ubase_t bar_base; - rt_bool_t mem64 = RT_FALSE; + rt_ubase_t flags; + rt_ubase_t bar_base; + rt_bool_t mem64 = RT_FALSE; + rt_bool_t bar_is_64 = RT_FALSE; + rt_uint32_t bar_lo_mask = 0; struct rt_pci_bus_region *region; - cfg = 0; + cfg = 0; bar_base = PCIR_BAR(i); rt_pci_write_config_u32(pdev, bar_base, RT_UINT32_MAX); @@ -596,25 +679,28 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, rt_pci_write_config_u32(pdev, bar_base, 0UL); continue; } - - if (cfg & PCIM_BAR_SPACE) + else if (cfg & PCIM_BAR_SPACE) { - mem64 = RT_FALSE; - flags = PCI_BUS_REGION_F_IO; + mem64 = RT_FALSE; + flags = PCI_BUS_REGION_F_IO; + bar_lo_mask = cfg & ~PCIM_BAR_IO_MASK; - size = cfg & PCIM_BAR_IO_MASK; + size = cfg & PCIM_BAR_IO_MASK; size &= ~(size - 1); } else { /* memory */ + bar_lo_mask = cfg & ~PCIM_BAR_MEM_MASK; + if ((cfg & PCIM_BAR_MEM_TYPE_MASK) == PCIM_BAR_MEM_TYPE_64) { /* 64bits */ rt_uint32_t cfg64; rt_uint64_t bar64; - mem64 = RT_TRUE; + mem64 = RT_TRUE; + bar_is_64 = RT_TRUE; rt_pci_write_config_u32(pdev, bar_base + sizeof(rt_uint32_t), RT_UINT32_MAX); rt_pci_read_config_u32(pdev, bar_base + sizeof(rt_uint32_t), &cfg64); @@ -627,7 +713,7 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, { /* 32bits */ mem64 = RT_FALSE; - size = (rt_uint32_t)(~(cfg & PCIM_BAR_MEM_MASK) + 1); + size = (rt_uint32_t)(~(cfg & PCIM_BAR_MEM_MASK) + 1); } if (prefetch && (cfg & PCIM_BAR_MEM_PREFETCH)) @@ -644,27 +730,39 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, if (region) { - rt_pci_write_config_u32(pdev, bar_base, addr); + rt_uint32_t bar_val; - if (mem64) + if (flags == PCI_BUS_REGION_F_IO) { - bar_base += sizeof(rt_uint32_t); - #ifdef RT_PCI_SYS_64BIT - rt_pci_write_config_u32(pdev, bar_base, (rt_uint32_t)(addr >> 32)); - #else - /* - * If we are a 64-bit decoder then increment to the upper 32 bits - * of the bar and force it to locate in the lower 4GB of memory. - */ - rt_pci_write_config_u32(pdev, bar_base, 0UL); - #endif + bar_val = rt_lower_32_bits(addr) | bar_lo_mask; + rt_pci_write_config_u32(pdev, bar_base, bar_val); + } + else + { + rt_pci_write_config_u32(pdev, bar_base, 0); + if (bar_is_64) + { + rt_pci_write_config_u32(pdev, bar_base + sizeof(rt_uint32_t), 0); + } + + bar_val = rt_lower_32_bits((rt_ubase_t)addr) | bar_lo_mask; + rt_pci_write_config_u32(pdev, bar_base, bar_val); + + if (bar_is_64) + { +#ifdef RT_PCI_SYS_64BIT + rt_pci_write_config_u32(pdev, bar_base + sizeof(rt_uint32_t), rt_upper_32_bits(addr)); +#else + rt_pci_write_config_u32(pdev, bar_base + sizeof(rt_uint32_t), 0UL); +#endif + } } - pdev->resource[i].size = size; - pdev->resource[i].base = region->cpu_addr + (addr - region->phy_addr); + pdev->resource[i].size = size; + pdev->resource[i].base = region->cpu_addr + (addr - region->phy_addr); pdev->resource[i].flags = flags; - if (mem64) + if (bar_is_64) { ++i; pdev->resource[i].flags = PCI_BUS_REGION_F_NONE; @@ -675,8 +773,6 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, err = -RT_ERROR; LOG_W("%s alloc bar(%d) address fail", rt_dm_dev_get_name(&pdev->parent), i); } - - command |= (cfg & PCIM_BAR_SPACE) ? PCIM_CMD_PORTEN : PCIM_CMD_MEMEN; } if (hdr_type == PCIM_HDRTYPE_NORMAL || hdr_type == PCIM_HDRTYPE_BRIDGE) @@ -694,29 +790,24 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, { rt_pci_write_config_u32(pdev, rom_addr, addr); } - command |= PCIM_CMD_MEMEN; - pdev->rom.base = addr; - pdev->rom.size = size; + pdev->rom.base = addr; + pdev->rom.size = size; pdev->rom.flags = PCI_BUS_REGION_F_MEM; } } - rt_pci_read_config_u16(pdev, PCIR_SUBCLASS, &class); - - if (class == PCIS_DISPLAY_VGA) - { - command |= PCIM_CMD_PORTEN; - } - + rt_pci_read_config_u16(pdev, PCIR_COMMAND, &command); + command &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); rt_pci_write_config_u16(pdev, PCIR_COMMAND, command); + pdev->busmaster = RT_FALSE; rt_pci_write_config_u8(pdev, PCIR_CACHELNSZ, RT_PCI_CACHE_LINE_SIZE); rt_pci_write_config_u8(pdev, PCIR_LATTIMER, 0x80); return err; } -struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device* pdev,rt_ubase_t flags,int index) +struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device *pdev, rt_ubase_t flags, int index) { for (int i = 0; i < RT_PCI_BAR_NR_MAX; i++) { @@ -731,11 +822,11 @@ struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device* pdev,rt_ubase_ } void rt_pci_enum_device(struct rt_pci_bus *bus, - rt_bool_t (callback(struct rt_pci_device *, void *)), void *data) + rt_bool_t(callback(struct rt_pci_device *, void *)), void *data) { - rt_bool_t is_end = RT_FALSE; - struct rt_spinlock *lock; - struct rt_pci_bus *parent; + rt_bool_t is_end = RT_FALSE; + struct rt_spinlock *lock; + struct rt_pci_bus *parent; struct rt_pci_device *pdev, *last_pdev = RT_NULL; /* Walk tree */ @@ -851,15 +942,15 @@ void rt_pci_enum_device(struct rt_pci_bus *bus, } last_pdev = RT_NULL; - bus = parent; + bus = parent; parent = parent->parent; spin_unlock(lock); } } } -const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, - const struct rt_pci_device_id *id) +const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, + const struct rt_pci_device_id *id) { if ((id->vendor == PCI_ANY_ID || id->vendor == pdev->vendor) && (id->device == PCI_ANY_ID || id->device == pdev->device) && @@ -873,8 +964,8 @@ const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, return RT_NULL; } -const struct rt_pci_device_id *rt_pci_match_ids(struct rt_pci_device *pdev, - const struct rt_pci_device_id *ids) +const struct rt_pci_device_id *rt_pci_match_ids(struct rt_pci_device *pdev, + const struct rt_pci_device_id *ids) { while (ids->vendor || ids->subsystem_vendor || ids->class_mask) { @@ -920,9 +1011,9 @@ rt_err_t rt_pci_device_register(struct rt_pci_device *pdev) static rt_bool_t pci_match(rt_driver_t drv, rt_device_t dev) { - rt_bool_t match = RT_FALSE; - struct rt_pci_driver *pdrv = rt_container_of(drv, struct rt_pci_driver, parent); - struct rt_pci_device *pdev = rt_container_of(dev, struct rt_pci_device, parent); + rt_bool_t match = RT_FALSE; + struct rt_pci_driver *pdrv = rt_container_of(drv, struct rt_pci_driver, parent); + struct rt_pci_device *pdev = rt_container_of(dev, struct rt_pci_device, parent); if (pdrv->name && pdev->name) { @@ -941,17 +1032,26 @@ static rt_bool_t pci_match(rt_driver_t drv, rt_device_t dev) static rt_err_t pci_probe(rt_device_t dev) { - rt_err_t err = RT_EOK; + rt_err_t err = RT_EOK; struct rt_pci_driver *pdrv = rt_container_of(dev->drv, struct rt_pci_driver, parent); struct rt_pci_device *pdev = rt_container_of(dev, struct rt_pci_device, parent); rt_pci_assign_irq(pdev); rt_pci_enable_wake(pdev, RT_PCI_D0, RT_TRUE); + err = rt_pci_enable_device(pdev); + + if (err) + { + rt_pci_enable_wake(pdev, RT_PCI_D0, RT_FALSE); + return err; + } + err = pdrv->probe(pdev); if (err) { + rt_pci_disable_device(pdev); rt_pci_enable_wake(pdev, RT_PCI_D0, RT_FALSE); } @@ -960,8 +1060,8 @@ static rt_err_t pci_probe(rt_device_t dev) static rt_err_t pci_remove(rt_device_t dev) { - rt_err_t err = RT_EOK; - struct rt_pci_bus *bus; + rt_err_t err = RT_EOK; + struct rt_pci_bus *bus; struct rt_pci_driver *pdrv = rt_container_of(dev->drv, struct rt_pci_driver, parent); struct rt_pci_device *pdev = rt_container_of(dev, struct rt_pci_device, parent); @@ -985,7 +1085,7 @@ static rt_err_t pci_remove(rt_device_t dev) static rt_err_t pci_shutdown(rt_device_t dev) { - struct rt_pci_bus *bus; + struct rt_pci_bus *bus; struct rt_pci_driver *pdrv = rt_container_of(dev->drv, struct rt_pci_driver, parent); struct rt_pci_device *pdev = rt_container_of(dev, struct rt_pci_device, parent); @@ -1004,12 +1104,11 @@ static rt_err_t pci_shutdown(rt_device_t dev) return RT_EOK; } -static struct rt_bus pci_bus = -{ - .name = "pci", - .match = pci_match, - .probe = pci_probe, - .remove = pci_remove, +static struct rt_bus pci_bus = { + .name = "pci", + .match = pci_match, + .probe = pci_probe, + .remove = pci_remove, .shutdown = pci_shutdown, }; diff --git a/components/drivers/pci/pci_ids.h b/components/drivers/pci/pci_ids.h index 2dab735a0a..f7be3cb089 100644 --- a/components/drivers/pci/pci_ids.h +++ b/components/drivers/pci/pci_ids.h @@ -243,6 +243,7 @@ #define PCI_VENDOR_ID_FUNGIBLE 0x1dad #define PCI_VENDOR_ID_HXT 0x1dbf #define PCI_VENDOR_ID_TEKRAM 0x1de1 +#define PCI_VENDOR_ID_RPI 0x1de4 #define PCI_VENDOR_ID_TEHUTI 0x1fc9 #define PCI_VENDOR_ID_SUNIX 0x1fd4 #define PCI_VENDOR_ID_HINT 0x3388 diff --git a/components/drivers/pci/probe.c b/components/drivers/pci/probe.c index 77cbb4185f..29fd7b7baf 100644 --- a/components/drivers/pci/probe.c +++ b/components/drivers/pci/probe.c @@ -19,6 +19,8 @@ #include "procfs.h" +static struct rt_dm_ida pci_domain_ida = RT_DM_IDA_INIT(CUSTOM); + rt_inline void spin_lock(struct rt_spinlock *spinlock) { rt_hw_spin_lock(&spinlock->lock); @@ -65,6 +67,29 @@ rt_err_t rt_pci_host_bridge_init(struct rt_pci_host_bridge *host_bridge) if (host_bridge->parent.ofw_node) { err = rt_pci_ofw_host_bridge_init(host_bridge->parent.ofw_node, host_bridge); + + if (err) + { + return err; + } + + if (host_bridge->domain == RT_UINT32_MAX) + { + host_bridge->domain = rt_dm_ida_alloc(&pci_domain_ida); + + if ((int)(host_bridge->domain) < 0) + { + return -RT_EFULL; + } + } + else + { + if (!rt_dm_ida_take(&pci_domain_ida, host_bridge->domain)) + { + LOG_E("Failed to take domain %u", host_bridge->domain); + return -RT_ERROR; + } + } } return err; @@ -109,9 +134,9 @@ struct rt_pci_device *rt_pci_alloc_device(struct rt_pci_bus *bus) struct rt_pci_device *rt_pci_scan_single_device(struct rt_pci_bus *bus, rt_uint32_t devfn) { - rt_err_t err; - struct rt_pci_device *pdev = RT_NULL; - rt_uint16_t vendor = PCI_ANY_ID, device = PCI_ANY_ID; + rt_err_t err; + struct rt_pci_device *pdev = RT_NULL; + rt_uint16_t vendor = PCI_ANY_ID, device = PCI_ANY_ID; if (!bus) { @@ -132,13 +157,13 @@ struct rt_pci_device *rt_pci_scan_single_device(struct rt_pci_bus *bus, rt_uint3 goto _end; } - pdev->devfn = devfn; + pdev->devfn = devfn; pdev->vendor = vendor; pdev->device = device; rt_dm_dev_set_name(&pdev->parent, "%04x:%02x:%02x.%u", - rt_pci_domain(pdev), pdev->bus->number, - RT_PCI_SLOT(pdev->devfn), RT_PCI_FUNC(pdev->devfn)); + rt_pci_domain(pdev), pdev->bus->number, + RT_PCI_SLOT(pdev->devfn), RT_PCI_FUNC(pdev->devfn)); if (rt_pci_setup_device(pdev)) { @@ -157,7 +182,7 @@ _end: static rt_bool_t pci_intx_mask_broken(struct rt_pci_device *pdev) { - rt_bool_t res = RT_FALSE; + rt_bool_t res = RT_FALSE; rt_uint16_t orig, toggle, new; rt_pci_read_config_u16(pdev, PCIR_COMMAND, &orig); @@ -203,7 +228,7 @@ static void pcie_set_port_type(struct rt_pci_device *pdev) static void pci_configure_ari(struct rt_pci_device *pdev) { - rt_uint32_t cap, ctl2_ari; + rt_uint32_t cap, ctl2_ari; struct rt_pci_device *bridge; if (!rt_pci_is_pcie(pdev) || pdev->devfn) @@ -228,13 +253,13 @@ static void pci_configure_ari(struct rt_pci_device *pdev) if (rt_pci_find_ext_capability(pdev, PCIZ_ARI)) { - ctl2_ari |= PCIEM_CTL2_ARI; - bridge->ari_enabled = RT_TRUE; + ctl2_ari |= PCIEM_CTL2_ARI; + bridge->ari_enabled = RT_TRUE; } else { - ctl2_ari &= ~PCIEM_CTL2_ARI; - bridge->ari_enabled = RT_FALSE; + ctl2_ari &= ~PCIEM_CTL2_ARI; + bridge->ari_enabled = RT_FALSE; } rt_pci_write_config_u32(bridge, bridge->pcie_cap + PCIER_DEVICE_CTL2, ctl2_ari); @@ -254,7 +279,7 @@ static rt_uint16_t pci_cfg_space_size_ext(struct rt_pci_device *pdev) static rt_uint16_t pci_cfg_space_size(struct rt_pci_device *pdev) { - int pos; + int pos; rt_uint32_t status; rt_uint16_t class = pdev->class >> 8; @@ -296,8 +321,8 @@ static void pci_init_capabilities(struct rt_pci_device *pdev) pdev->cfg_size = pci_cfg_space_size(pdev); pci_configure_ari(pdev); - pdev->no_msi = RT_FALSE; - pdev->msi_enabled = RT_FALSE; + pdev->no_msi = RT_FALSE; + pdev->msi_enabled = RT_FALSE; pdev->msix_enabled = RT_FALSE; } @@ -322,7 +347,7 @@ rt_err_t rt_pci_setup_device(struct rt_pci_device *pdev) rt_pci_read_config_u32(pdev, PCIR_REVID, &class); pdev->revision = class & 0xff; - pdev->class = class >> 8; /* Upper 3 bytes */ + pdev->class = class >> 8; /* Upper 3 bytes */ rt_pci_read_config_u8(pdev, PCIR_HDRTYPE, &pdev->hdr_type); /* Clear errors left from system firmware */ @@ -340,7 +365,7 @@ rt_err_t rt_pci_setup_device(struct rt_pci_device *pdev) } rt_dm_dev_set_name(&pdev->parent, "%04x:%02x:%02x.%u", rt_pci_domain(pdev), - pdev->bus->number, RT_PCI_SLOT(pdev->devfn), RT_PCI_FUNC(pdev->devfn)); + pdev->bus->number, RT_PCI_SLOT(pdev->devfn), RT_PCI_FUNC(pdev->devfn)); class = pdev->class >> 8; @@ -401,14 +426,14 @@ rt_err_t rt_pci_setup_device(struct rt_pci_device *pdev) static struct rt_pci_bus *pci_alloc_bus(struct rt_pci_bus *parent); static rt_err_t pci_child_bus_init(struct rt_pci_bus *bus, rt_uint32_t bus_no, - struct rt_pci_host_bridge *host_bridge, struct rt_pci_device *pdev) + struct rt_pci_host_bridge *host_bridge, struct rt_pci_device *pdev) { - rt_err_t err; + rt_err_t err; struct rt_pci_bus *parent_bus = bus->parent; bus->sysdata = parent_bus->sysdata; - bus->self = pdev; - bus->ops = host_bridge->child_ops ? : parent_bus->ops; + bus->self = pdev; + bus->ops = host_bridge->child_ops ?: parent_bus->ops; bus->number = bus_no; rt_sprintf(bus->name, "%04x:%02x", host_bridge->domain, bus_no); @@ -422,7 +447,7 @@ static rt_err_t pci_child_bus_init(struct rt_pci_bus *bus, rt_uint32_t bus_no, rt_pci_ofw_bus_free(bus); LOG_E("PCI-Bus<%s> add bus failed with err = %s", - bus->name, rt_strerror(err)); + bus->name, rt_strerror(err)); return err; } @@ -432,11 +457,11 @@ static rt_err_t pci_child_bus_init(struct rt_pci_bus *bus, rt_uint32_t bus_no, } static rt_bool_t pci_ea_fixed_busnrs(struct rt_pci_device *pdev, - rt_uint8_t *sec, rt_uint8_t *sub) + rt_uint8_t *sec, rt_uint8_t *sub) { - int pos, offset; + int pos, offset; rt_uint32_t dw; - rt_uint8_t ea_sec, ea_sub; + rt_uint8_t ea_sec, ea_sub; pos = rt_pci_find_capability(pdev, PCIY_EA); if (!pos) @@ -448,7 +473,7 @@ static rt_bool_t pci_ea_fixed_busnrs(struct rt_pci_device *pdev, rt_pci_read_config_u32(pdev, offset, &dw); ea_sec = PCIM_EA_SEC_NR(dw); ea_sub = PCIM_EA_SUB_NR(dw); - if (ea_sec == 0 || ea_sub < ea_sec) + if (ea_sec == 0 || ea_sub < ea_sec) { return RT_FALSE; } @@ -459,31 +484,50 @@ static rt_bool_t pci_ea_fixed_busnrs(struct rt_pci_device *pdev, return RT_TRUE; } +static rt_bool_t pci_is_pcie_port(struct rt_pci_device *pdev) +{ + rt_uint16_t exp_type; + + if (!pdev || !rt_pci_is_pcie(pdev)) + { + return RT_FALSE; + } + + exp_type = pdev->exp_flags & PCIEM_FLAGS_TYPE; + + return exp_type == PCIEM_TYPE_ROOT_PORT || + exp_type == PCIEM_TYPE_DOWNSTREAM_PORT || + exp_type == PCIEM_TYPE_PCIE_BRIDGE; +} + static void pcie_fixup_link(struct rt_pci_device *pdev) { - int pos = pdev->pcie_cap; + int pos = pdev->pcie_cap; rt_uint16_t exp_lnkctl, exp_lnkctl2, exp_lnksta; - rt_uint16_t exp_type = pdev->exp_flags & PCIEM_FLAGS_TYPE; if ((pdev->exp_flags & PCIEM_FLAGS_VERSION) < 2) { return; } - if (exp_type != PCIEM_TYPE_ROOT_PORT && - exp_type != PCIEM_TYPE_DOWNSTREAM_PORT && - exp_type != PCIEM_TYPE_PCIE_BRIDGE) + if (!pci_is_pcie_port(pdev)) { return; } rt_pci_read_config_u16(pdev, pos + PCIER_LINK_CTL, &exp_lnkctl); rt_pci_read_config_u16(pdev, pos + PCIER_LINK_CTL2, &exp_lnkctl2); + rt_pci_read_config_u16(pdev, pos + PCIER_LINK_STA, &exp_lnksta); + + if (exp_lnksta & PCIEM_LINK_STA_DL_ACTIVE) + { + return; + } rt_pci_write_config_u16(pdev, pos + PCIER_LINK_CTL2, - (exp_lnkctl2 & ~PCIEM_LNKCTL2_TLS) | PCIEM_LNKCTL2_TLS_2_5GT); + (exp_lnkctl2 & ~PCIEM_LNKCTL2_TLS) | PCIEM_LNKCTL2_TLS_2_5GT); rt_pci_write_config_u16(pdev, pos + PCIER_LINK_CTL, - exp_lnkctl | PCIEM_LINK_CTL_RETRAIN_LINK); + exp_lnkctl | PCIEM_LINK_CTL_RETRAIN_LINK); for (int i = 0; i < 20; ++i) { @@ -500,21 +544,134 @@ static void pcie_fixup_link(struct rt_pci_device *pdev) /* Fail, restore */ rt_pci_write_config_u16(pdev, pos + PCIER_LINK_CTL2, exp_lnkctl2); rt_pci_write_config_u16(pdev, pos + PCIER_LINK_CTL, - exp_lnkctl | PCIEM_LINK_CTL_RETRAIN_LINK); + exp_lnkctl | PCIEM_LINK_CTL_RETRAIN_LINK); _status_sync: /* Wait a while for success or failure */ rt_thread_mdelay(100); } -static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_device *pdev, - rt_uint32_t bus_no_start, rt_uint32_t buses, rt_bool_t reconfigured) +static rt_bool_t pci_needs_bridge_window(struct rt_pci_device *pdev) { - rt_bool_t fixed_buses; - rt_uint8_t fixed_sub, fixed_sec; - rt_uint8_t primary, secondary, subordinate; - rt_uint32_t value, bus_no = bus_no_start; - struct rt_pci_bus *next_bus; + if (!pdev) + { + return RT_FALSE; + } + + if (pdev->hdr_type == PCIM_HDRTYPE_BRIDGE) + { + return RT_TRUE; + } + + return pci_is_pcie_port(pdev); +} + +static void pci_program_bridge_windows(struct rt_pci_device *bridge, + rt_uint64_t mem_start, rt_uint64_t mem_end, + rt_uint64_t pref_start, rt_uint64_t pref_end) +{ + rt_uint32_t l; + rt_uint16_t cmd; + + if (!bridge || !pci_needs_bridge_window(bridge)) + { + return; + } + + if (mem_start <= mem_end) + { + l = ((rt_uint32_t)(mem_start >> 16) & 0xfff0) | (rt_uint32_t)(mem_end & 0xfff00000); + rt_pci_write_config_u32(bridge, PCIR_MEMBASE_1, l); + } + else + { + rt_pci_write_config_u32(bridge, PCIR_MEMBASE_1, 0x0000fff0); + } + + if (pref_start <= pref_end) + { + rt_uint32_t bu = 0, lu = 0; + + rt_pci_write_config_u32(bridge, PCIR_PMLIMITH_1, 0); + + l = ((rt_uint32_t)(pref_start >> 16) & 0xfff0) | (rt_uint32_t)(pref_end & 0xfff00000); + + if (pref_end > 0xffffffffULL || pref_start > 0xffffffffULL) + { + bu = rt_upper_32_bits(pref_start); + lu = rt_upper_32_bits(pref_end); + } + + rt_pci_write_config_u32(bridge, PCIR_PMBASEL_1, l); + rt_pci_write_config_u32(bridge, PCIR_PMBASEH_1, bu); + rt_pci_write_config_u32(bridge, PCIR_PMLIMITH_1, lu); + } + else + { + rt_pci_write_config_u32(bridge, PCIR_PMBASEL_1, 0x0000fff0); + rt_pci_write_config_u32(bridge, PCIR_PMBASEH_1, 0); + rt_pci_write_config_u32(bridge, PCIR_PMLIMITH_1, 0); + } + + rt_pci_read_config_u16(bridge, PCIR_COMMAND, &cmd); + cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN; + rt_pci_write_config_u16(bridge, PCIR_COMMAND, cmd); +} + +static void pci_bridge_program_host_windows(struct rt_pci_device *bridge, + struct rt_pci_host_bridge *host_bridge) +{ + rt_uint64_t mem_start = ~0ULL, mem_end = 0; + rt_uint64_t pref_start = ~0ULL, pref_end = 0; + + if (!bridge || !host_bridge) + { + return; + } + + for (int i = 0; i < host_bridge->bus_regions_nr; ++i) + { + rt_uint64_t start, end; + struct rt_pci_bus_region *region = &host_bridge->bus_regions[i]; + + start = region->phy_addr; + end = region->phy_addr + region->size - 1; + + if (region->flags == PCI_BUS_REGION_F_PREFETCH) + { + if (start < pref_start) + { + pref_start = start; + } + if (end > pref_end) + { + pref_end = end; + } + } + else if (region->flags == PCI_BUS_REGION_F_MEM) + { + if (start < mem_start) + { + mem_start = start; + } + if (end > mem_end) + { + mem_end = end; + } + } + } + + pci_program_bridge_windows(bridge, mem_start, mem_end, pref_start, pref_end); +} + +static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_device *pdev, + rt_uint32_t bus_no_start, rt_uint32_t buses, rt_bool_t reconfigured) +{ + rt_bool_t fixed_buses; + rt_uint8_t fixed_sub, fixed_sec; + rt_uint8_t primary, secondary, subordinate; + rt_uint32_t value, bus_no = bus_no_start; + struct rt_pci_bus *next_bus; struct rt_pci_host_bridge *host_bridge; /* We not supported init CardBus, it always used in the PC servers. */ @@ -526,8 +683,8 @@ static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_ } rt_pci_read_config_u32(pdev, PCIR_PRIBUS_1, &value); - primary = value & 0xff; - secondary = (value >> 8) & 0xff; + primary = value & 0xff; + secondary = (value >> 8) & 0xff; subordinate = (value >> 16) & 0xff; if (primary == bus->number && bus->number > secondary && secondary > subordinate) @@ -538,7 +695,7 @@ static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_ } LOG_I("Bridge configuration: primary(%02x) secondary(%02x) subordinate(%02x)", - primary, secondary, subordinate); + primary, secondary, subordinate); } if (pdev->pcie_cap) @@ -566,23 +723,30 @@ static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_ /* Clear bus info */ rt_pci_write_config_u32(pdev, PCIR_PRIBUS_1, value & ~0xffffff); - if (!(next_bus = pci_alloc_bus(bus))) - { - LOG_E("Alloc bus(%02x) fail", bus_no); - goto _end; - } - if (pci_child_bus_init(next_bus, bus_no, host_bridge, pdev)) { goto _end; } + spin_lock(&bus->lock); + rt_list_insert_before(&bus->children_nodes, &next_bus->list); + spin_unlock(&bus->lock); + /* Fill primary, secondary */ value = (buses & 0xff000000) | (bus->number << 0) | (next_bus->number << 8); rt_pci_write_config_u32(pdev, PCIR_PRIBUS_1, value); + /* + * Open bridge MEM/prefetch windows to host ranges before downstream + * scan (BAR sizing/assign touches MMIO), then again after scan in + * case config writes disturbed the aperture. + */ + pci_bridge_program_host_windows(pdev, host_bridge); + bus_no = rt_pci_scan_child_buses(next_bus, buses); + pci_bridge_program_host_windows(pdev, host_bridge); + /* Fill subordinate */ value |= next_bus->number + rt_list_len(&next_bus->children_nodes); rt_pci_write_config_u32(pdev, PCIR_PRIBUS_1, value); @@ -598,7 +762,7 @@ _end: } rt_uint32_t rt_pci_scan_bridge(struct rt_pci_bus *bus, struct rt_pci_device *pdev, - rt_uint32_t bus_no_start, rt_bool_t reconfigured) + rt_uint32_t bus_no_start, rt_bool_t reconfigured) { if (!bus || !pdev) { @@ -610,35 +774,19 @@ rt_uint32_t rt_pci_scan_bridge(struct rt_pci_bus *bus, struct rt_pci_device *pde rt_inline rt_bool_t only_one_child(struct rt_pci_bus *bus) { - struct rt_pci_device *pdev; - if (rt_pci_is_root_bus(bus)) { return RT_FALSE; } - pdev = bus->self; - - if (rt_pci_is_pcie(pdev)) - { - rt_uint16_t exp_type = pdev->exp_flags & PCIEM_FLAGS_TYPE; - - if (exp_type == PCIEM_TYPE_ROOT_PORT || - exp_type == PCIEM_TYPE_DOWNSTREAM_PORT || - exp_type == PCIEM_TYPE_PCIE_BRIDGE) - { - return RT_TRUE; - } - } - - return RT_FALSE; + return pci_is_pcie_port(bus->self); } static int next_fn(struct rt_pci_bus *bus, struct rt_pci_device *pdev, int fn) { if (!rt_pci_is_root_bus(bus) && bus->self->ari_enabled) { - int pos, next_fn; + int pos, next_fn; rt_uint16_t cap = 0; if (!pdev) @@ -679,7 +827,7 @@ static int next_fn(struct rt_pci_bus *bus, struct rt_pci_device *pdev, int fn) rt_size_t rt_pci_scan_slot(struct rt_pci_bus *bus, rt_uint32_t devfn) { - rt_size_t nr = 0; + rt_size_t nr = 0; struct rt_pci_device *pdev = RT_NULL; if (!bus) @@ -716,7 +864,7 @@ rt_size_t rt_pci_scan_slot(struct rt_pci_bus *bus, rt_uint32_t devfn) rt_uint32_t rt_pci_scan_child_buses(struct rt_pci_bus *bus, rt_size_t buses) { - rt_uint32_t bus_no; + rt_uint32_t bus_no; struct rt_pci_device *pdev = RT_NULL; if (!bus) @@ -729,8 +877,8 @@ rt_uint32_t rt_pci_scan_child_buses(struct rt_pci_bus *bus, rt_size_t buses) bus_no = bus->number; for (rt_uint32_t devfn = 0; - devfn < RT_PCI_DEVFN(RT_PCI_DEVICE_MAX - 1, RT_PCI_FUNCTION_MAX - 1); - devfn += RT_PCI_FUNCTION_MAX) + devfn < RT_PCI_DEVFN(RT_PCI_DEVICE_MAX - 1, RT_PCI_FUNCTION_MAX - 1); + devfn += RT_PCI_FUNCTION_MAX) { rt_pci_scan_slot(bus, devfn); } @@ -792,9 +940,9 @@ rt_err_t rt_pci_host_bridge_register(struct rt_pci_host_bridge *host_bridge) host_bridge->root_bus = bus; - bus->sysdata = host_bridge->sysdata; + bus->sysdata = host_bridge->sysdata; bus->host_bridge = host_bridge; - bus->ops = host_bridge->ops; + bus->ops = host_bridge->ops; bus->number = host_bridge->bus_range[0]; rt_sprintf(bus->name, "%04x:%02x", host_bridge->domain, bus->number); @@ -852,6 +1000,11 @@ rt_err_t rt_pci_host_bridge_remove(struct rt_pci_host_bridge *host_bridge) { rt_pci_enum_device(host_bridge->root_bus, pci_remove_bus_device, RT_NULL); host_bridge->root_bus = RT_NULL; + + if (host_bridge->domain != RT_UINT32_MAX) + { + rt_dm_ida_free(&pci_domain_ida, host_bridge->domain); + } } else {