mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01:00 
			
		
		
		
	dm: pci: Add APIs to find capability and extended capability
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> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		| @@ -1320,6 +1320,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); | 	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 & 0x7f) == 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) = { | UCLASS_DRIVER(pci) = { | ||||||
| 	.id		= UCLASS_PCI, | 	.id		= UCLASS_PCI, | ||||||
| 	.name		= "pci", | 	.name		= "pci", | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  * Under PCI, each device has 256 bytes of configuration address space, |  * Under PCI, each device has 256 bytes of configuration address space, | ||||||
|  * of which the first 64 bytes are standardized as follows: |  * 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_VENDOR_ID		0x00	/* 16 bits */ | ||||||
| #define PCI_DEVICE_ID		0x02	/* 16 bits */ | #define PCI_DEVICE_ID		0x02	/* 16 bits */ | ||||||
| #define PCI_COMMAND		0x04	/* 16 bits */ | #define PCI_COMMAND		0x04	/* 16 bits */ | ||||||
| @@ -1311,6 +1312,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); | 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) \ | #define dm_pci_virt_to_bus(dev, addr, flags) \ | ||||||
| 	dm_pci_phys_to_bus(dev, (virt_to_phys(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) \ | #define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user