diff --git a/components/drivers/include/drivers/ofw_io.h b/components/drivers/include/drivers/ofw_io.h index f458435d0989..bbd9e0c57a44 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); @@ -30,22 +30,44 @@ rt_uint64_t rt_ofw_reverse_address(struct rt_ofw_node *np, const char *range_typ rt_inline rt_uint64_t rt_ofw_translate_dma2cpu(struct rt_ofw_node *np, rt_uint64_t address) { - rt_uint64_t bus_addr, cpu_addr; + rt_uint64_t 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; + cpu_addr = rt_ofw_translate_address(np, "ranges", address); + 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; + dma_addr = rt_ofw_reverse_address(np, "dma-ranges", address); + if (dma_addr != ~0ULL && dma_addr != address) + { + return dma_addr; + } + bus_addr = rt_ofw_reverse_address(np, "ranges", address); - dma_addr = rt_ofw_translate_address(np, "dma-ranges", bus_addr); + 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 dma_addr != ~0ULL ? dma_addr : address; + 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 414a0abf1ad1..a341efe615fc 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 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 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) struct rt_pci_bus_region { @@ -65,10 +64,10 @@ 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; }; @@ -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), \ .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 */ @@ -167,15 +166,15 @@ 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; @@ -217,9 +216,9 @@ 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 @@ -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,78 +350,77 @@ 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); + 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); + 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); @@ -428,7 +428,7 @@ 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) + 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) + 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))); + 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; } @@ -541,15 +541,15 @@ rt_inline rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev) } 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))) + 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); } @@ -570,37 +570,37 @@ rt_inline rt_err_t rt_pci_msi_enable(struct rt_pci_device *pdev) } 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) + 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) + 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 *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 *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 a84df210a6ef..ac8695aff131 100755 --- a/components/drivers/ofw/io.c +++ b/components/drivers/ofw/io.c @@ -154,7 +154,7 @@ 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; @@ -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; @@ -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,6 +246,37 @@ 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; @@ -285,7 +316,8 @@ 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 { + 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); @@ -293,7 +325,7 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p 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; } @@ -319,14 +351,15 @@ static struct bus_ranges *ofw_bus_ranges(struct rt_ofw_node *np, struct rt_ofw_p parent_addr = ranges->parent_addr; 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_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->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; } -rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) +static struct bus_ranges *ofw_get_bus_ranges(struct rt_ofw_node *bus, const char *range_type) { - rt_uint64_t cpu_addr = address; + rt_ssize_t len; + struct rt_ofw_prop *prop; + struct bus_ranges *ranges = RT_NULL; - if (!range_type) + prop = rt_ofw_get_prop(bus, range_type, &len); + + if (!prop || !len) { - range_type = "ranges"; + return RT_NULL; } - rt_ofw_foreach_parent_node(np) + for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) { - 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 (!_bus_ranges[i]) { - continue; + break; } - for (int i = 0; i < RT_ARRAY_SIZE(_bus_ranges); ++i) + if (_bus_ranges[i]->np == bus && + !rt_strcmp(_bus_ranges[i]->range_type, range_type)) { - if (!_bus_ranges[i]) - { - break; - } - - if (_bus_ranges[i]->np == np) - { - ranges = _bus_ranges[i]; - break; - } + ranges = _bus_ranges[i]; + break; } + } - if (!ranges) - { - ranges = ofw_bus_ranges(np, prop); - } + if (!ranges) + { + ranges = ofw_bus_ranges(bus, 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]; + return ranges; +} - if (address >= child_addr && address < child_addr + child_size) - { - cpu_addr = address + (ranges->parent_addr[i] - child_addr); +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); - break; - } - } - } - else + 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) { - cpu_addr = ~0ULL; + return address + (ranges->parent_addr[i] - child_addr); } + } - rt_ofw_node_put(np); + 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); - break; + if (!ranges) + { + return ~0ULL; } - return cpu_addr; + 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_reverse_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) +rt_uint64_t rt_ofw_translate_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; 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_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) + address = translated; + } + + return address; +} + +rt_uint64_t rt_ofw_reverse_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) +{ + struct rt_ofw_node *bus; + struct rt_ofw_node *parents[OFW_NODE_MAX_DEPTH]; + int count = 0; + + if (!range_type) + { + range_type = "ranges"; + } + + for (bus = np ? np->parent : RT_NULL; bus; bus = bus->parent) + { + rt_ssize_t len; + + if (!rt_ofw_get_prop(bus, range_type, &len) || !len) { - ranges = ofw_bus_ranges(np, prop); + continue; } - if (ranges) + if (count < (int)RT_ARRAY_SIZE(parents)) { - 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]; + parents[count++] = bus; + } + } - if (address >= parent_addr && address < parent_addr + child_size) - { - bus_addr = ranges->child_addr[i] + (address - parent_addr); + while (count-- > 0) + { + rt_uint64_t reversed = ofw_reverse_at_bus(parents[count], range_type, address); - break; - } - } - } - else + if (reversed == ~0ULL) { - bus_addr = ~0ULL; + return ~0ULL; } - rt_ofw_node_put(np); - - break; + address = reversed; } - return bus_addr; + 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 0a8c7c8b234d..7778dbc4c566 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. */ @@ -51,6 +51,7 @@ struct bus_ranges { 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 8e3b7333e0ec..8659e1176859 100644 --- a/components/drivers/pci/msi/irq.c +++ b/components/drivers/pci/msi/irq.c @@ -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,8 +105,8 @@ 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; } diff --git a/components/drivers/pci/msi/msi.c b/components/drivers/pci/msi/msi.c index 11ccdcb10c8b..5d20b52d40b0 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; - 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 */ @@ -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; } @@ -471,7 +471,7 @@ static rt_err_t msi_verify_entries(struct rt_pci_device *pdev) } static rt_err_t msi_insert_desc(struct rt_pci_device *pdev, - struct rt_pci_msi_desc *init_desc) + struct rt_pci_msi_desc *init_desc) { rt_size_t msi_affinity_ptr_size = 0; struct rt_pci_msi_desc *msi_desc; @@ -591,7 +591,7 @@ 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; struct rt_pci_msi_desc *desc; @@ -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,7 +651,7 @@ 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; rt_size_t entries_nr; @@ -756,7 +756,7 @@ 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; struct rt_pci_msi_desc desc; @@ -789,8 +789,8 @@ static rt_err_t msix_setup_msi_descs(struct rt_pci_device *pdev, } 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))) + struct rt_pci_msix_entry *entries, int nvec, + RT_IRQ_AFFINITY_DECLARE((*affinities))) { rt_err_t err; rt_uint16_t msgctl; @@ -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; } @@ -879,8 +879,8 @@ static rt_ssize_t msix_capability_init(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))) + struct rt_pci_msix_entry *entries, int min, int max, + RT_IRQ_AFFINITY_DECLARE((*affinities))) { int nvec = max; rt_size_t entries_nr; @@ -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 450402d6bda6..7d0a476d8ba1 100644 --- a/components/drivers/pci/ofw.c +++ b/components/drivers/pci/ofw.c @@ -115,21 +115,21 @@ static rt_err_t pci_ofw_irq_parse(struct rt_pci_device *pdev, struct rt_ofw_cell 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; @@ -159,8 +159,8 @@ int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev, } 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; @@ -227,8 +227,7 @@ static rt_err_t pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, const char *pro 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) { @@ -246,7 +245,7 @@ static rt_err_t pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, const char *pro } rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) + struct rt_pci_host_bridge *host_bridge) { rt_err_t err; int phy_addr_cells = -1, phy_size_cells = -1, cpu_addr_cells; @@ -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; } @@ -299,7 +298,7 @@ rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np, } rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, - struct rt_pci_host_bridge *host_bridge) + struct rt_pci_host_bridge *host_bridge) { rt_err_t err; const char *propname; @@ -317,11 +316,19 @@ rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np, 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); @@ -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); } diff --git a/components/drivers/pci/pci.c b/components/drivers/pci/pci.c index 3ba3967e7d86..e2fa29395602 100644 --- a/components/drivers/pci/pci.c +++ b/components/drivers/pci/pci.c @@ -47,7 +47,7 @@ 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_uint16_t ent; @@ -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,7 +89,7 @@ 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_uint16_t status; @@ -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; @@ -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; @@ -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 */ @@ -526,7 +602,7 @@ 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; @@ -535,7 +611,7 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, rt_size_t bars_nr; rt_uint8_t hdr_type; rt_bool_t prefetch = RT_FALSE; - rt_uint16_t class, command = 0; + 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) @@ -579,6 +660,8 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, 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; @@ -596,11 +679,11 @@ 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; + bar_lo_mask = cfg & ~PCIM_BAR_IO_MASK; size = cfg & PCIM_BAR_IO_MASK; size &= ~(size - 1); @@ -608,6 +691,8 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, else { /* memory */ + bar_lo_mask = cfg & ~PCIM_BAR_MEM_MASK; + if ((cfg & PCIM_BAR_MEM_TYPE_MASK) == PCIM_BAR_MEM_TYPE_64) { /* 64bits */ @@ -615,6 +700,7 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, rt_uint64_t bar64; 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); @@ -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].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,7 +790,6 @@ 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; @@ -702,21 +797,17 @@ rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge, } } - 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,7 +822,7 @@ 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; @@ -859,7 +950,7 @@ void rt_pci_enum_device(struct rt_pci_bus *bus, } 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 *id) { if ((id->vendor == PCI_ANY_ID || id->vendor == pdev->vendor) && (id->device == PCI_ANY_ID || id->device == pdev->device) && @@ -874,7 +965,7 @@ const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev, } 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 *ids) { while (ids->vendor || ids->subsystem_vendor || ids->class_mask) { @@ -948,10 +1039,19 @@ static rt_err_t pci_probe(rt_device_t dev) 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); } @@ -1004,8 +1104,7 @@ static rt_err_t pci_shutdown(rt_device_t dev) return RT_EOK; } -static struct rt_bus pci_bus = -{ +static struct rt_bus pci_bus = { .name = "pci", .match = pci_match, .probe = pci_probe, diff --git a/components/drivers/pci/pci_ids.h b/components/drivers/pci/pci_ids.h index 2dab735a0a59..f7be3cb089c0 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 77cbb4185f70..321d79c45540 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; @@ -137,8 +162,8 @@ struct rt_pci_device *rt_pci_scan_single_device(struct rt_pci_bus *bus, rt_uint3 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)) { @@ -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; 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->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,7 +457,7 @@ 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; rt_uint32_t dw; @@ -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; 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,15 +544,128 @@ 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_bool_t pci_needs_bridge_window(struct rt_pci_device *pdev) +{ + 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_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; @@ -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 @@ static rt_uint32_t pci_scan_bridge_extend(struct rt_pci_bus *bus, struct rt_pci_ } 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,28 +774,12 @@ 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) @@ -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); } @@ -846,19 +994,24 @@ static rt_bool_t pci_remove_bus_device(struct rt_pci_device *pdev, void *data) rt_err_t rt_pci_host_bridge_remove(struct rt_pci_host_bridge *host_bridge) { - rt_err_t err = RT_EOK; + if (!host_bridge) + { + return -RT_EINVAL; + } - if (host_bridge && host_bridge->root_bus) + if (host_bridge->root_bus) { rt_pci_enum_device(host_bridge->root_bus, pci_remove_bus_device, RT_NULL); host_bridge->root_bus = RT_NULL; } - else + + if (host_bridge->domain != RT_UINT32_MAX) { - err = -RT_EINVAL; + rt_dm_ida_free(&pci_domain_ida, host_bridge->domain); + host_bridge->domain = RT_UINT32_MAX; } - return err; + return RT_EOK; } rt_err_t rt_pci_bus_remove(struct rt_pci_bus *bus)