[U-Boot] [PATCH 1/3] dm: pci: Assign correct driver data when binding a driver

The correct driver data comes from the matching 'id' instead of 'find_id' in pci_find_and_bind_driver().
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/pci/pci-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 46e9c71..7e16ad1 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -690,7 +690,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, if (ret) goto error; debug("%s: Match found: %s\n", __func__, drv->name); - dev->driver_data = find_id->driver_data; + dev->driver_data = id->driver_data; *devp = dev; return 0; }

Currently we don't have a complete list of capability and extended capability ids. This adds them.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
include/pci.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/include/pci.h b/include/pci.h index 8e27cbf..cce69c4 100644 --- a/include/pci.h +++ b/include/pci.h @@ -333,7 +333,21 @@ #define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ #define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ -#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ +#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ +#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ +#define PCI_CAP_ID_VNDR 0x09 /* Vendor-Specific */ +#define PCI_CAP_ID_DBG 0x0A /* Debug port */ +#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ +#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ +#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ +#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ +#define PCI_CAP_ID_SECDEV 0x0F /* Secure Device */ +#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ +#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ +#define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */ +#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */ +#define PCI_CAP_ID_EA 0x14 /* PCI Enhanced Allocation */ +#define PCI_CAP_ID_MAX PCI_CAP_ID_EA #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ #define PCI_CAP_SIZEOF 4 @@ -449,6 +463,10 @@ #define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe Capability */ #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ +#define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ +#define PCI_EXT_CAP_ID_L1SS 0x1E /* L1 PM Substates */ +#define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM
/* Include the ID list */

On 25 July 2018 at 03:39, Bin Meng bmeng.cn@gmail.com wrote:
Currently we don't have a complete list of capability and extended capability ids. This adds them.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
include/pci.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

This introduces two new APIs dm_pci_find_capability() and dm_pci_find_ext_capability() to get PCI capability address and PCI express extended capability address for a given PCI device.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/pci/pci-uclass.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 7e16ad1..c887989 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1319,6 +1319,74 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); }
+int dm_pci_find_capability(struct udevice *dev, int cap) +{ + u16 status; + u8 header_type; + int ttl = PCI_FIND_CAP_TTL; + u8 id; + u16 ent; + u8 pos; + + dm_pci_read_config16(dev, PCI_STATUS, &status); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + + dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); + if (header_type == PCI_HEADER_TYPE_CARDBUS) + pos = PCI_CB_CAPABILITY_LIST; + else + pos = PCI_CAPABILITY_LIST; + + dm_pci_read_config8(dev, pos, &pos); + while (ttl--) { + if (pos < PCI_STD_HEADER_SIZEOF) + break; + pos &= ~3; + dm_pci_read_config16(dev, pos, &ent); + + id = ent & 0xff; + if (id == 0xff) + break; + if (id == cap) + return pos; + pos = (ent >> 8); + } + + return 0; +} + +int dm_pci_find_ext_capability(struct udevice *dev, int cap) +{ + u32 header; + int ttl; + int pos = PCI_CFG_SPACE_SIZE; + + /* minimum 8 bytes per capability */ + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; + + dm_pci_read_config32(dev, pos, &header); + /* + * If we have no capabilities, this is indicated by cap ID, + * cap version and next pointer all being 0. + */ + if (header == 0) + return 0; + + while (ttl--) { + if (PCI_EXT_CAP_ID(header) == cap) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < PCI_CFG_SPACE_SIZE) + break; + + dm_pci_read_config32(dev, pos, &header); + } + + return 0; +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index cce69c4..602c834 100644 --- a/include/pci.h +++ b/include/pci.h @@ -17,6 +17,7 @@ * Under PCI, each device has 256 bytes of configuration address space, * of which the first 64 bytes are standardized as follows: */ +#define PCI_STD_HEADER_SIZEOF 64 #define PCI_VENDOR_ID 0x00 /* 16 bits */ #define PCI_DEVICE_ID 0x02 /* 16 bits */ #define PCI_COMMAND 0x04 /* 16 bits */ @@ -1326,6 +1327,51 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, */ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags);
+/** + * dm_pci_find_capability() - find a capability + * + * Tell if a device supports a given PCI capability. Returns the + * address of the requested capability structure within the device's + * PCI configuration space or 0 in case the device does not support it. + * + * Possible values for @cap: + * + * %PCI_CAP_ID_MSI Message Signalled Interrupts + * %PCI_CAP_ID_PCIX PCI-X + * %PCI_CAP_ID_EXP PCI Express + * %PCI_CAP_ID_MSIX MSI-X + * + * See PCI_CAP_ID_xxx for the complete capability ID codes. + * + * @dev: PCI device to query + * @cap: capability code + * @return: capability address or 0 if not supported + */ +int dm_pci_find_capability(struct udevice *dev, int cap); + +/** + * dm_pci_find_ext_capability() - find an extended capability + * + * Tell if a device supports a given PCI express extended capability. + * Returns the address of the requested extended capability structure + * within the device's PCI configuration space or 0 in case the device + * does not support it. + * + * Possible values for @cap: + * + * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting + * %PCI_EXT_CAP_ID_VC Virtual Channel + * %PCI_EXT_CAP_ID_DSN Device Serial Number + * %PCI_EXT_CAP_ID_PWR Power Budgeting + * + * See PCI_EXT_CAP_ID_xxx for the complete extended capability ID codes. + * + * @dev: PCI device to query + * @cap: extended capability code + * @return: extended capability address or 0 if not supported + */ +int dm_pci_find_ext_capability(struct udevice *dev, int cap); + #define dm_pci_virt_to_bus(dev, addr, flags) \ dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags)) #define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \

Hi Bin,
On 25 July 2018 at 03:39, Bin Meng bmeng.cn@gmail.com wrote:
This introduces two new APIs dm_pci_find_capability() and dm_pci_find_ext_capability() to get PCI capability address and PCI express extended capability address for a given PCI device.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/pci/pci-uclass.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Could you create a test for these two functions?
Regards, Simon

On 25 July 2018 at 03:39, Bin Meng bmeng.cn@gmail.com wrote:
The correct driver data comes from the matching 'id' instead of 'find_id' in pci_find_and_bind_driver().
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/pci/pci-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
Perhaps the pci test should be updated to check this.

Hi Simon,
On Fri, Jul 27, 2018 at 8:35 AM, Simon Glass sjg@chromium.org wrote:
On 25 July 2018 at 03:39, Bin Meng bmeng.cn@gmail.com wrote:
The correct driver data comes from the matching 'id' instead of 'find_id' in pci_find_and_bind_driver().
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/pci/pci-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
Perhaps the pci test should be updated to check this.
I looked at this and found out that the test to pci_bind_bus_devices(), the API that calls pci_find_and_bind_driver(), cannot be done due to a chicken and egg issue. pci_find_and_bind_driver() will only get called if no PCI device is explicitly declared in the device tree, however:
- without a emulation device (eg: "sandbox,swap-case") in the device tree, the emulation device won't be probed, hence pci_config_read() to the emulation device returns nothing - without a vendor id & device id from pci_config_read() results, pci_find_and_bind_driver() won't work.
Do you have better ideas?
Regards, Bin

Hi Simon,
On Fri, Jul 27, 2018 at 11:51 AM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Jul 27, 2018 at 8:35 AM, Simon Glass sjg@chromium.org wrote:
On 25 July 2018 at 03:39, Bin Meng bmeng.cn@gmail.com wrote:
The correct driver data comes from the matching 'id' instead of 'find_id' in pci_find_and_bind_driver().
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/pci/pci-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
Perhaps the pci test should be updated to check this.
I looked at this and found out that the test to pci_bind_bus_devices(), the API that calls pci_find_and_bind_driver(), cannot be done due to a chicken and egg issue. pci_find_and_bind_driver() will only get called if no PCI device is explicitly declared in the device tree, however:
- without a emulation device (eg: "sandbox,swap-case") in the device
tree, the emulation device won't be probed, hence pci_config_read() to the emulation device returns nothing
- without a vendor id & device id from pci_config_read() results,
pci_find_and_bind_driver() won't work.
Do you have better ideas?
Looks I figured out a way. I will send v2 to include test cases.
Regards, Bin
participants (2)
-
Bin Meng
-
Simon Glass