dm: pci: tegra: Convert Tegra PCI to driver model
Subsystems (5)
cover dm: pci: tegra: Convert Tegra PCI to driver model
This series converts all Tegra boards to use driver model for PCI. The net effect should be no change in functionality.
A few additional features are added to make this possible:
- Helper functions to support accessing 8- and 16-bit values within a 32-bit word
- Fixing a build error for CONFIG_CMD_PCI_ENUM
- Decoding the PCI ranges property such that configuration ranges are ignored
- Supporting bus-master devices on boards where RAM does not start at 0
This series is tested on beaver. It is available at u-boot-dm/tegra-working.
Simon Glass (8):
dm: tegra: pci: Move CONFIG_PCI_TEGRA to Kconfig
dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
RFC: dm: pci: Set up the SDRAM mapping correctly
dm: pci: Support decoding ranges with duplicate entries
dm: pci: Add functions to emulate 8- and 16-bit access
dm: pci: Add a function to get the controller for a bus
dm: pci: Add a function to find the regions for a PCI bus
dm: tegra: pci: Convert tegra boards to driver model for PCI
arch/arm/mach-tegra/Kconfig | 1 + common/cmd_pci.c | 4 + configs/apalis_t30_defconfig | 1 + configs/beaver_defconfig | 1 + configs/cardhu_defconfig | 1 + configs/jetson-tk1_defconfig | 1 + configs/trimslice_defconfig | 1 + drivers/pci/Kconfig | 10 ++ drivers/pci/pci-uclass.c | 99 ++++++++++- drivers/pci/pci_tegra.c | 402 +++++++++++++++---------------------------- include/configs/apalis_t30.h | 1 - include/configs/beaver.h | 1 - include/configs/cardhu.h | 1 - include/configs/jetson-tk1.h | 1 - include/configs/trimslice.h | 1 - include/fdtdec.h | 3 - include/pci.h | 51 ++++++ lib/fdtdec.c | 3 - 18 files changed, 305 insertions(+), 278 deletions(-)
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 1/8 dm: tegra: pci: Move CONFIG_PCI_TEGRA to Kconfig
Move this option to Kconig and fix up all users.
---
configs/apalis_t30_defconfig | 1 + configs/beaver_defconfig | 1 + configs/cardhu_defconfig | 1 + configs/jetson-tk1_defconfig | 1 + configs/trimslice_defconfig | 1 + drivers/pci/Kconfig | 10 ++++++++++ include/configs/apalis_t30.h | 1 - include/configs/beaver.h | 1 - include/configs/cardhu.h | 1 - include/configs/jetson-tk1.h | 1 - include/configs/trimslice.h | 1 - 11 files changed, 15 insertions(+), 5 deletions(-)
configs/apalis_t30_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_SYS_PROMPT="Apalis T30 # " # CONFIG_CMD_NFS is not set CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_PCI_TEGRA=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USE_PRIVATE_LIBGCC=y
configs/beaver_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_SYS_PROMPT="Tegra30 (Beaver) # " # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_NFS is not set CONFIG_SPI_FLASH=y +CONFIG_PCI_TEGRA=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USE_PRIVATE_LIBGCC=y
configs/cardhu_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_SYS_PROMPT="Tegra30 (Cardhu) # " # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_NFS is not set CONFIG_SPI_FLASH=y +CONFIG_PCI_TEGRA=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USE_PRIVATE_LIBGCC=y
configs/jetson-tk1_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_SYS_PROMPT="Tegra124 (Jetson TK1) # " # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_NFS is not set CONFIG_SPI_FLASH=y +CONFIG_PCI_TEGRA=y CONFIG_TEGRA114_SPI=y CONFIG_USB=y CONFIG_DM_USB=y
configs/trimslice_defconfig +1 -0
@@ -12,6 +12,7 @@ CONFIG_SYS_PROMPT="Tegra20 (TrimSlice) # " # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_NFS is not set CONFIG_SPI_FLASH=y +CONFIG_PCI_TEGRA=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USE_PRIVATE_LIBGCC=y
drivers/pci/Kconfig +10 -0
@@ -19,4 +19,14 @@ config PCI_SANDBOX the device tree but the normal PCI scan technique is used to find then. +config PCI_TEGRA + bool "Tegra PCI support" + depends on TEGRA + help + Enable support for the PCIe controller found on some generations of + Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has + 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports + with a total of 5 lanes. Some boards require this for Ethernet + support to work (e.g. beaver, jetson-tk1). + endmenu
include/configs/apalis_t30.h +0 -1
@@ -49,7 +49,6 @@/* PCI host support */ #define CONFIG_PCI -#define CONFIG_PCI_TEGRA #define CONFIG_PCI_PNP #define CONFIG_CMD_PCI #define CONFIG_CMD_PCI_ENUM
include/configs/beaver.h +0 -1
@@ -73,7 +73,6 @@/* PCI host support */ #define CONFIG_PCI -#define CONFIG_PCI_TEGRA #define CONFIG_PCI_PNP #define CONFIG_CMD_PCI #define CONFIG_CMD_PCI_ENUM
include/configs/cardhu.h +0 -1
@@ -75,7 +75,6 @@/* PCI host support */ #define CONFIG_PCI -#define CONFIG_PCI_TEGRA #define CONFIG_PCI_PNP #define CONFIG_CMD_PCI #define CONFIG_CMD_PCI_ENUM
include/configs/jetson-tk1.h +0 -1
@@ -59,7 +59,6 @@/* PCI host support */ #define CONFIG_PCI -#define CONFIG_PCI_TEGRA #define CONFIG_PCI_PNP #define CONFIG_CMD_PCI #define CONFIG_CMD_PCI_ENUM
include/configs/trimslice.h +0 -1
@@ -58,7 +58,6 @@/* PCI host support */ #define CONFIG_PCI -#define CONFIG_PCI_TEGRA #define CONFIG_PCI_PNP #define CONFIG_CMD_PCI #define CONFIG_CMD_PCI_ENUM
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 1/8 dm: tegra: pci: Move CONFIG_PCI_TEGRA to Kconfig
Quoted 1 line · Simon Glass
Move this option to Kconig and fix up all users.
What are your thoughts on how/when to merge this? The series (mainly the final patch) conflicts with my series to add Tegra210 support, plus one of them needs rebasing onto the other so that either the board support my series adds gets adjusted by this series, or my series is adjusted for all the changes in this series.
Obviously I'd hope my series gets merged first since I sent it much earlier:-)
FWIW, I rebased this series on top of my series to validate it, and pushed it to:
git://github.com/swarren/u-boot.git pci-dm-conversion-rebase
That seems to work OK, but the final patch I added there needs integration into earlier patches and/or cleanup work.
PATCH 1/8 dm: tegra: pci: Move CONFIG_PCI_TEGRA to Kconfig
Hi Stephen,
Quoted 14 lines · Stephen Warren
Quoted 2 lines · Simon Glass
Move this option to Kconig and fix up all users.
What are your thoughts on how/when to merge this? The series (mainly the final patch) conflicts with my series to add Tegra210 support, plus one of them needs rebasing onto the other so that either the board support my series adds gets adjusted by this series, or my series is adjusted for all the changes in this series.
Obviously I'd hope my series gets merged first since I sent it much earlier:-)
Quoted 7 lines
FWIW, I rebased this series on top of my series to validate it, and pushed it to:
git://github.com/swarren/u-boot.gitpci-dm-conversion-rebaseThat seems to work OK, but the final patch I added there needs integration into earlier patches and/or cleanup work.
I don't mind which order it goes in. I cannot test on T210 anyway so I may look to you to sort that out. Let me know what suits. I'll likely respin this early next week and if your stuff in applied to tegra by then then I'll base on top of it.
Regards,
Simon
PATCH 2/8 dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
In reply to Simon GlassThis is not supported with driver model, so print a message instead of generating a build error. Rescanning PCI is not yet implemented.
---
common/cmd_pci.c | 4 ++++ 1 file changed, 4 insertions(+)
common/cmd_pci.c +4 -0
@@ -457,7 +457,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return pci_cfg_display (bdf, addr, size, value);#ifdef CONFIG_CMD_PCI_ENUM case 'e' : +# ifdef CONFIG_DM_PCI +printf ("This command is not yet supported with driver model\n" ); +# else pci_init (); +# endif return 0 ;#endif case 'n' :/* next */
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 2/8 dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
Quoted 6 lines · Simon Glass
This is not supported with driver model, so print a message instead of generating a build error. Rescanning PCI is not yet implemented.
common/cmd_pci.c static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 464
Quoted 8 lines
common/cmd_pci.c +4
-0@@ -457,7 +457,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return pci_cfg_display (bdf, addr, size, value);#ifdef CONFIG_CMD_PCI_ENUM case 'e' : +# ifdef CONFIG_DM_PCI +printf ("This command is not yet supported with driver model\n" ); +# else pci_init (); +# endif
That feature is enabled on most/all Tegra boards with PCI support. Hopefully nobody will miss it; I guess I haven't used it so I don't object to this change.
However, wouldn't it be better to remove CONFIG_CMD_PCI_ENUM from the config header rather than leaving the command enabled yet non-functional? Or are you planning on implementing this path in the near future?
PATCH 2/8 dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
Hi Stephen,
Quoted 26 lines · Stephen Warren
Quoted 9 lines · Simon Glass
This is not supported with driver model, so print a message instead of generating a build error. Rescanning PCI is not yet implemented.
common/cmd_pci.c static int do_pci(cmd_tbl_t *cmdtp, int flag, int · line 466
Quoted 10 lines
common/cmd_pci.c +4
-0@@ -457,7 +457,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return pci_cfg_display (bdf, addr, size, value);#ifdef CONFIG_CMD_PCI_ENUM case 'e' : +# ifdef CONFIG_DM_PCI +printf ("This command is not yet supported with driver model\n"); +# else pci_init (); +# endif That feature is enabled on most/all Tegra boards with PCI support. Hopefully nobody will miss it; I guess I haven't used it so I don't object to this change.
Quoted 3 lines
However, wouldn't it be better to remove
CONFIG_CMD_PCI_ENUMfrom the config header rather than leaving the command enabled yet non-functional? Or are you planning on implementing this path in the near future?
I was looking for feedback on why anyone would use this option. It's not clear to me what it is for.
We can implement it for driver model if it is needed.
Regards,
Simon
PATCH 2/8 dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
Quoted 29 lines · Simon Glass
Hi Stephen,
Quoted 26 lines · Stephen Warren
Quoted 9 lines · Simon Glass
This is not supported with driver model, so print a message instead of generating a build error. Rescanning PCI is not yet implemented.
common/cmd_pci.c static int do_pci(cmd_tbl_t *cmdtp, int flag, int · line 466
Quoted 10 lines
common/cmd_pci.c +4
-0@@ -457,7 +457,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return pci_cfg_display (bdf, addr, size, value);#ifdef CONFIG_CMD_PCI_ENUM case 'e' : +# ifdef CONFIG_DM_PCI +printf ("This command is not yet supported with driver model\n"); +# else pci_init (); +# endif That feature is enabled on most/all Tegra boards with PCI support. Hopefully nobody will miss it; I guess I haven't used it so I don't object to this change.
Quoted 6 lines
Quoted 3 lines
However, wouldn't it be better to remove
CONFIG_CMD_PCI_ENUMfrom the config header rather than leaving the command enabled yet non-functional? Or are you planning on implementing this path in the near future?I was looking for feedback on why anyone would use this option. It's not clear to me what it is for.
I assume it's to support hot-pluggable PCI connectors? Or perhaps it's just useful during debug of PCI drivers?
Quoted 1 line
We can implement it for driver model if it is needed.
I'd be happy disabling it in the configs myself. Thierry, you enabled the option when you first implemented the Tegra PCIe controller driver. Do you have a preference?
PATCH 2/8 dm: pci: Avoid a driver model build error with CONFIG_CMD_PCI_ENUM
Quoted 37 lines · Stephen Warren
Quoted 29 lines · Simon Glass
Hi Stephen,
Quoted 26 lines · Stephen Warren
Quoted 9 lines · Simon Glass
This is not supported with driver model, so print a message instead of generating a build error. Rescanning PCI is not yet implemented.
common/cmd_pci.c static int do_pci(cmd_tbl_t *cmdtp, int flag, int · line 466
Quoted 10 lines
common/cmd_pci.c +4
-0@@ -457,7 +457,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])return pci_cfg_display (bdf, addr, size, value);#ifdef CONFIG_CMD_PCI_ENUM case 'e' : +# ifdef CONFIG_DM_PCI +printf ("This command is not yet supported with driver model\n"); +# else pci_init (); +# endif That feature is enabled on most/all Tegra boards with PCI support. Hopefully nobody will miss it; I guess I haven't used it so I don't object to this change.
Quoted 6 lines
Quoted 3 lines
However, wouldn't it be better to remove
CONFIG_CMD_PCI_ENUMfrom the config header rather than leaving the command enabled yet non-functional? Or are you planning on implementing this path in the near future?I was looking for feedback on why anyone would use this option. It's not clear to me what it is for.
Quoted 8 lines
I assume it's to support hot-pluggable PCI connectors? Or perhaps it's just useful during debug of PCI drivers?
Quoted 1 line
We can implement it for driver model if it is needed.
I'd be happy disabling it in the configs myself. Thierry, you enabled the option when you first implemented the Tegra PCIe controller driver. Do you have a preference?
Removing it from the configs is fine with me. I don't think I've actually ever used it since all the way back when I was working on the initial driver prototype.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20151109/58344b4f/attachment.sig>
PATCH 3/8 RFC: dm: pci: Set up the SDRAM mapping correctly
In reply to Simon GlassSDRAM doesn't always start at 0. Adjust the region mapping so that it works on platforms where SDRAM is somewhere else.
This needs testing on other platforms.
---
drivers/pci/pci-uclass.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/pci/pci-uclass.c +6 -3
@@ -674,8 +674,8 @@ static int decode_regions(struct pci_controller *hose, const void *blob, int parent_node, int node) { int pci_addr_cells, addr_cells, size_cells; +phys_addr_t base =0 , addr;int cells_per_record; -phys_addr_t addr;const u32 *prop;int len;int i;
@@ -729,8 +729,11 @@ static int decode_regions(struct pci_controller *hose, const void *blob, addr = gd->ram_size;if (gd->pci_ram_top && gd->pci_ram_top < addr) addr = gd->pci_ram_top; -pci_set_region (hose->regions + hose->region_count++,0 ,0 , addr, -PCI_REGION_MEM |PCI_REGION_SYS_MEMORY ); +#ifdef CONFIG_SYS_SDRAM_BASE + base =CONFIG_SYS_SDRAM_BASE ; +#endif +pci_set_region (hose->regions + hose->region_count++, base, base, + addr,PCI_REGION_MEM |PCI_REGION_SYS_MEMORY );return 0 ; }
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 3/8 RFC: dm: pci: Set up the SDRAM mapping correctly
Quoted 8 lines · Simon Glass
SDRAM doesn't always start at 0. Adjust the region mapping so that it works on platforms where SDRAM is somewhere else.
This needs testing on other platforms.
drivers/pci/pci-uclass.c static int decode_regions(struct pci_controller *hose, const void *blob, · line 736
Quoted 10 lines
drivers/pci/pci-uclass.c +5
-2@@ -729,8 +729,11 @@ static int decode_regions(struct pci_controller *hose, const void *blob, addr = gd->ram_size;if (gd->pci_ram_top && gd->pci_ram_top < addr) addr = gd->pci_ram_top; -pci_set_region (hose->regions + hose->region_count++,0 ,0 , addr, -PCI_REGION_MEM |PCI_REGION_SYS_MEMORY ); +#ifdef CONFIG_SYS_SDRAM_BASE + base =CONFIG_SYS_SDRAM_BASE ; +#endif +pci_set_region (hose->regions + hose->region_count++, base, base, + addr,PCI_REGION_MEM |PCI_REGION_SYS_MEMORY );
The variable naming here is extremely misleading; "addr" is actually the size of the region not its address. I think it'd be a good idea to rename the addr variable while you're fixing this bug, and also pci_ram_top too since that's really pci_ram_size.
FWIW, on Tegra210 when I set gd->pci_ram_top = 0x80000000 (coupled with SDRAM_BASE being 0x80000000) this function seems to do the right thing; at least a PCIe NIC works OK.
PATCH 4/8 dm: pci: Support decoding ranges with duplicate entries
In reply to Simon GlassAt present we add a new resource entry for every range entry. But some range entries refer to configuration regions. To make this work, avoid adding two regions of the same time. The later ranges will overwrite the earlier (configuration) ones.
There does not seem to be a way to distinguish the configuration ranges other than by ordering.
---
drivers/pci/pci-uclass.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/pci/pci-uclass.c +10 -3
@@ -698,6 +698,7 @@ static int decode_regions(struct pci_controller *hose, const void *blob,int space_code;u32 flags;int type; +int pos;if (len < cells_per_record)break ;
@@ -720,9 +721,15 @@ static int decode_regions(struct pci_controller *hose, const void *blob, }else {continue ; } -debug (" - type=%d\n" , type); -pci_set_region (hose->regions + hose->region_count++, pci_addr, - addr, size, type); + pos =-1 ; +for (i =0 ; i < hose->region_count; i++) { +if (hose->regions[i].flags == type) + pos = i; + } +if (pos ==-1 ) + pos = hose->region_count++; +debug (" - type=%d, pos=%d\n" , type, pos); +pci_set_region (hose->regions + pos, pci_addr, addr, size, type); }/* Add a region for our local memory */
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 4/8 dm: pci: Support decoding ranges with duplicate entries
Quoted 4 lines · Simon Glass
At present we add a new resource entry for every range entry. But some range entries refer to configuration regions. To make this work, avoid adding two regions of the same time. The later ranges will overwrite the earlier (configuration) ones.
s/time/type/ in the last-but-one line.
What's wrong with having two regions of the same type? Equally, if we can "get away" with not storing some of the regions that happen to have a duplicate type, why not recast the function so that it only stores regions of specific (useful/desired) types, and simply dropping all of the other regions. That'd be a lot more consistent than only storing a somewhat arbitrary subset of the regions.
Quoted 2 lines
There does not seem to be a way to distinguish the configuration ranges other than by ordering.
Well, they do have different addresses too. But yes, the DT binding is written so that the entries in ranges must appear in a specific order, so order is the correct way to index the entries.
drivers/pci/pci-uclass.c static int decode_regions(struct pci_controller *hose, const void *blob, · line 727
Quoted 13 lines
drivers/pci/pci-uclass.c +4
-3@@ -720,9 +721,15 @@ static int decode_regions(struct pci_controller *hose, const void *blob, }else {continue ; } -debug (" - type=%d\n" , type); -pci_set_region (hose->regions + hose->region_count++, pci_addr, - addr, size, type); + pos =-1 ; +for (i =0 ; i < hose->region_count; i++) { +if (hose->regions[i].flags == type) + pos = i;
and break too?
Quoted 6 lines
drivers/pci/pci-uclass.c +5
-0+ } +if (pos ==-1 ) + pos = hose->region_count++; +debug (" - type=%d, pos=%d\n" , type, pos); +pci_set_region (hose->regions + pos, pci_addr, addr, size, type); }
PATCH 4/8 dm: pci: Support decoding ranges with duplicate entries
Hi Stephen,
Quoted 10 lines · Stephen Warren
Quoted 7 lines · Simon Glass
At present we add a new resource entry for every range entry. But some range
entries refer to configuration regions. To make this work, avoid adding two
regions of the same time. The later ranges will overwrite the earlier (configuration) ones.
Quoted 8 lines
s/time/type/ in the last-but-one line.
What's wrong with having two regions of the same type? Equally, if we can "get away" with not storing some of the regions that happen to have a duplicate type, why not recast the function so that it only stores regions of specific (useful/desired) types, and simply dropping all of the other regions. That'd be a lot more consistent than only storing a somewhat arbitrary subset of the regions.
I'm not 100% sure that we want to disallow multiple regions. Although on non-x86 boards I've haven't seen hardware that supports multiple regions.
Quoted 12 lines
Quoted 3 lines
There does not seem to be a way to distinguish the configuration ranges other than by ordering.
Well, they do have different addresses too. But yes, the DT binding is written so that the entries in ranges must appear in a specific order, so order is the correct way to index the entries.
Quoted 1 line
drivers/pci/pci-uclass.c +0
-0
Quoted 16 lines
drivers/pci/pci-uclass.c static int decode_regions(struct pci_controller · line 729
Quoted 13 lines
drivers/pci/pci-uclass.c +4
-3@@ -720,9 +721,15 @@ static int decode_regions(struct pci_controller *hose, const void *blob, }else {continue ; } -debug (" - type=%d\n" , type); -pci_set_region (hose->regions + hose->region_count++, pci_addr, - addr, size, type); + pos =-1 ; +for (i =0 ; i < hose->region_count; i++) { +if (hose->regions[i].flags == type) + pos = i;and break too?
Could do, might be clearer.
Quoted 11 lines
Quoted 9 lines
drivers/pci/pci-uclass.c +5
-0+ } +if (pos ==-1 ) + pos = hose->region_count++; +debug (" - type=%d, pos=%d\n" , type, pos); +pci_set_region (hose->regions + pos, pci_addr, addr, size, type);}
Regards,
Simon
PATCH 5/8 dm: pci: Add functions to emulate 8- and 16-bit access
In reply to Simon GlassProvide a few functions to support using 32-bit access to emulate 8- and 16-bit access.
---
drivers/pci/pci-uclass.c | 39 +++++++++++++++++++++++++++++++++++++++ include/pci.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+)
drivers/pci/pci-uclass.c +39 -0
@@ -916,6 +916,45 @@ int pci_find_first_device(struct udevice **devp)return skip_to_next_device (bus, devp); } +ulong pci_conv_32_to_size (ulong value,uint offset,enum pci_size_t size) +{ +switch (size) { +case PCI_SIZE_8 : +return (value >> ((offset &3 ) *8 )) &0xff ; +case PCI_SIZE_16 : +return (value >> ((offset &2 ) *8 )) &0xffff ; +default : +return value; + } +} + +ulong pci_conv_size_to_32 (ulong old,ulong value,uint offset, +enum pci_size_t size) +{ +uint off_mask; +uint val_mask, shift; +ulong ldata, mask; + +switch (size) { +case PCI_SIZE_8 : + off_mask =3 ; + val_mask =0xff ; +break ; +case PCI_SIZE_16 : + off_mask =2 ; + val_mask =0xffff ; +break ; +default : +return value; + } + shift = (offset & off_mask) *8 ; + ldata = (value & val_mask) << shift; + mask = val_mask << shift; + value = (old & ~mask) | ldata; + +return value; +} +UCLASS_DRIVER (pci) = { .id =UCLASS_PCI , .name ="pci" ,
include/pci.h +31 -0
@@ -1092,6 +1092,37 @@ static inline int pci_read_config_byte(pci_dev_t pcidev, int offset, }/** +* pci_conv_32_to_size() - convert a 32-bit read value to the given size +* +* Some PCI buses must always perform 32-bit reads. The data must then be +* shifted and masked to reflect the required access size and offset. This +* function performs this transformation. +* +* @value: Value to transform (32-bit value read from @offset & ~3) +* @offset: Register offset that was read +* @size: Required size of the result +* @return the value that would have been obtained if the read had been +* performed@the given offset with the correct size +*/ +ulong pci_conv_32_to_size (ulong value,uint offset,enum pci_size_t size); + +/** +* pci_conv_size_to_32() - update a 32-bit value to prepare for a write +* +* Some PCI buses must always perform 32-bit writes. To emulate a smaller +* write the old 32-bit data must be read, updated with the required new data +* and written back as a 32-bit value. This function performs the +* transformation from the old value to the new value. +* +* @value: Value to transform (32-bit value read from @offset & ~3) +* @offset: Register offset that should be written +* @size: Required size of the write +* @return the value that should be written as a 32-bit access to @offset & ~3. +*/ +ulong pci_conv_size_to_32 (ulong old,ulong value,uint offset, +enum pci_size_t size); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops {
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 5/8 dm: pci: Add functions to emulate 8- and 16-bit access
Quoted 2 lines · Simon Glass
Provide a few functions to support using 32-bit access to emulate 8- and 16-bit access.
PATCH 6/8 dm: pci: Add a function to get the controller for a bus
In reply to Simon GlassA PCI bus may be a bridge device where the controller is the bridge's parent. Add a function to return the controller device, given a PCI device.
---
drivers/pci/pci-uclass.c | 8 ++++++++ include/pci.h | 8 ++++++++ 2 files changed, 16 insertions(+)
drivers/pci/pci-uclass.c +8 -0
@@ -53,6 +53,14 @@ struct pci_controller *pci_bus_to_hose(int busnum)return dev_get_uclass_priv (bus); } +struct udevice *pci_get_controller (struct udevice *dev) +{ +while (device_get_uclass_id (dev->parent) ==UCLASS_PCI ) + dev = dev->parent; + +return dev; +} +pci_dev_t pci_get_bdf (struct udevice *dev) {struct pci_child_platdata *pplat =dev_get_parent_platdata (dev);
include/pci.h +8 -0
@@ -1123,6 +1123,14 @@ ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, enum pci_size_t size);/** +* pci_get_controller() - obtain the controller to use for a bus +* +* @dev: Device to check +* @return pointer to the controller device for this bus +*/ +struct udevice *pci_get_controller (struct udevice *dev); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops {
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 6/8 dm: pci: Add a function to get the controller for a bus
Hi Simon,
Quoted 15 lines · Simon Glass
A PCI bus may be a bridge device where the controller is the bridge's parent. Add a function to return the controller device, given a PCI device.
Signed-off-by Simon Glass <[email protected]>---
drivers/pci/pci-uclass.c | 8 ++++++++ include/pci.h | 8 ++++++++ 2 files changed, 16 insertions(+)drivers/pci/pci-uclass.c +0
-0
drivers/pci/pci-uclass.c struct pci_controller *pci_bus_to_hose(int busnum) · line 58
Quoted 6 lines
drivers/pci/pci-uclass.c +3
-0@@ -53,6 +53,14 @@ struct pci_controller *pci_bus_to_hose(int busnum)return dev_get_uclass_priv (bus); } +struct udevice *pci_get_controller (struct udevice *dev) +{ +while (device_get_uclass_id (dev->parent) ==UCLASS_PCI )
Please use device_is_on_pci_bus() API.
Quoted 18 lines
drivers/pci/pci-uclass.c +5
-0+ dev = dev->parent; + +return dev; +} +pci_dev_t pci_get_bdf (struct udevice *dev) {struct pci_child_platdata *pplat =dev_get_parent_platdata (dev);include/pci.h +2
-0@@ -1123,6 +1123,14 @@ ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, enum pci_size_t size);/** +* pci_get_controller() - obtain the controller to use for a bus +*
include/pci.h ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,
Quoted 10 lines
include/pci.h +6
-1+* @dev: Device to check +* @return pointer to the controller device for this bus +*/ +struct udevice *pci_get_controller (struct udevice *dev); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops { --
Regards,
Bin
PATCH 7/8 dm: pci: Add a function to find the regions for a PCI bus
In reply to Simon GlassThis function looks up the controller and returns a pointer to each region type.
---
drivers/pci/pci-uclass.c | 30 ++++++++++++++++++++++++++++++ include/pci.h | 12 ++++++++++++ 2 files changed, 42 insertions(+)
drivers/pci/pci-uclass.c +30 -0
@@ -963,6 +963,36 @@ ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,return value; } +int pci_get_regions (struct udevice *dev,struct pci_region **iop, +struct pci_region **memp,struct pci_region **prefp) +{ +struct udevice *bus =pci_get_controller (dev); +struct pci_controller *hose =dev_get_uclass_priv (bus); +int i; + + *iop =NULL ; + *memp =NULL ; + *prefp =NULL ; +for (i =0 ; i < hose->region_count; i++) { +switch (hose->regions[i].flags) { +case PCI_REGION_IO : +if (!*iop || (*iop)->size < hose->regions[i].size) + *iop = hose->regions + i; +break ; +case PCI_REGION_MEM : +if (!*memp || (*memp)->size < hose->regions[i].size) + *memp = hose->regions + i; +break ; +case (PCI_REGION_MEM |PCI_REGION_PREFETCH ): +if (!*prefp || (*prefp)->size < hose->regions[i].size) + *prefp = hose->regions + i; +break ; + } + } + +return (*iop !=NULL ) + (*memp !=NULL ) + (*prefp !=NULL ); +} +UCLASS_DRIVER (pci) = { .id =UCLASS_PCI , .name ="pci" ,
include/pci.h +12 -0
@@ -1131,6 +1131,18 @@ ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,struct udevice *pci_get_controller (struct udevice *dev);/** +* pci_get_regions() - obtain pointers to all the region types +* +* @dev: Device to check +* @iop: Returns a pointer to the I/O region, or NULL if none +* @memp: Returns a pointer to the memory region, or NULL if none +* @prefp: Returns a pointer to the pre-fetch region, or NULL if none +* @return the number of non-NULL regions returned, normally 3 +*/ +int pci_get_regions (struct udevice *dev,struct pci_region **iop, +struct pci_region **memp,struct pci_region **prefp); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops {
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 7/8 dm: pci: Add a function to find the regions for a PCI bus
Quoted 2 lines · Simon Glass
This function looks up the controller and returns a pointer to each region type.
Patches 6, 7,
PATCH 8/8 dm: tegra: pci: Convert tegra boards to driver model for PCI
In reply to Simon GlassAdjust the Tegra PCI driver to support driver model and move all boards over at the same time. This can make use of some generic driver model code, such as the range decoding logic.
---
arch/arm/mach-tegra/Kconfig | 1 + drivers/pci/pci_tegra.c | 402 ++++++++++++++++---------------------------- include/fdtdec.h | 3 - lib/fdtdec.c | 3 - 4 files changed, 142 insertions(+), 267 deletions(-)
arch/arm/mach-tegra/Kconfig +1 -0
@@ -12,6 +12,7 @@ config TEGRA_ARMV7_COMMON select DM_I2C select DM_SPI select DM_GPIO + select DM_PCI choice prompt "Tegra SoC select"
drivers/pci/pci_tegra.c +141 -261
566 lines not on this page · raw message
include/fdtdec.h +0 -3
@@ -129,9 +129,6 @@ enum fdt_compat_id {COMPAT_NVIDIA_TEGRA124_SDMMC ,/* Tegra124 SDMMC controller */ COMPAT_NVIDIA_TEGRA30_SDMMC ,/* Tegra30 SDMMC controller */ COMPAT_NVIDIA_TEGRA20_SDMMC ,/* Tegra20 SDMMC controller */ -COMPAT_NVIDIA_TEGRA124_PCIE ,/* Tegra 124 PCIe controller */ -COMPAT_NVIDIA_TEGRA30_PCIE ,/* Tegra 30 PCIe controller */ -COMPAT_NVIDIA_TEGRA20_PCIE ,/* Tegra 20 PCIe controller */ COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL ,/* Tegra124 XUSB pad controller */ COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
lib/fdtdec.c +0 -3
@@ -35,9 +35,6 @@ static const char * const compat_names[COMPAT_COUNT] = {COMPAT (NVIDIA_TEGRA124_SDMMC ,"nvidia,tegra124-sdhci" ),COMPAT (NVIDIA_TEGRA30_SDMMC ,"nvidia,tegra30-sdhci" ),COMPAT (NVIDIA_TEGRA20_SDMMC ,"nvidia,tegra20-sdhci" ), -COMPAT (NVIDIA_TEGRA124_PCIE ,"nvidia,tegra124-pcie" ), -COMPAT (NVIDIA_TEGRA30_PCIE ,"nvidia,tegra30-pcie" ), -COMPAT (NVIDIA_TEGRA20_PCIE ,"nvidia,tegra20-pcie" ),COMPAT (NVIDIA_TEGRA124_XUSB_PADCTL ,"nvidia,tegra124-xusb-padctl" ),COMPAT (NVIDIA_TEGRA210_XUSB_PADCTL ,"nvidia,tegra210-xusb-padctl" ), COMPAT(SMSC_LAN9215, "smsc,lan9215"),
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH 8/8 dm: tegra: pci: Convert tegra boards to driver model for PCI
Quoted 3 lines · Simon Glass
Adjust the Tegra PCI driver to support driver model and move all boards over at the same time. This can make use of some generic driver model code, such as the range decoding logic.
FYI, this patch has quite a few conflicts with my series to add Tegra210 support. See the git branch I mentioned earlier for a quick-n-dirty resolution to the conflicts, and subsequent fixups.
arch/arm/mach-tegra/Kconfig config TEGRA_ARMV7_COMMON · line 15
Quoted 9 lines
arch/arm/mach-tegra/Kconfig +1
-0@@ -12,6 +12,7 @@ config TEGRA_ARMV7_COMMON select DM_I2C select DM_SPI select DM_GPIO + select DM_PCI
I wonder if we shouldn't create the TEGRA_COMMON config variable now, since many of the options are common to both TEGRA_ARMV7_COMMON and TEGRA210. Perhaps also TEGRA_ARMV8_COMMON too, although currently there's only support for a single ARMV8 Tegra chip in U-Boot.
drivers/pci/pci_tegra.c line 13
Quoted 3 lines
drivers/pci/pci_tegra.c +0
-1-#define DEBUG
I actually find the debug prints useful, but yes I suppose debug should be turned off!
Quoted 13 lines
drivers/pci/pci_tegra.c +5
-5-static int tegra_pcie_read_conf (struct pci_controller *hose,pci_dev_t bdf, -int where,u32 *value) +static int pci_tegra_read_config (struct udevice *bus,pci_dev_t bdf, +uint offset,ulong *valuep, +enum pci_size_t size) { -struct tegra_pcie *pcie =to_tegra_pcie (hose); -unsigned long address; +struct tegra_pcie *pcie =dev_get_priv (bus); +unsigned long address, value;int err; - err =tegra_pcie_conf_address (pcie, bdf, where, &address);
drivers/pci/pci_tegra.c static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf, · line 295
Quoted 10 lines
drivers/pci/pci_tegra.c +4
-3+ err =tegra_pcie_conf_address (pcie, bdf, offset, &address);if (err <0 ) { - *value =0xffffffff ; -return 1 ; + value =0xffffffff ; + goto done; } - *value =readl (address); + value =readl (address);
This function used to be used only for dword-sized reads. Presumably in that case, "where" was always dword-aligned. When used for word/byte-sized reads, the wrappers to do that (e.g. pci_hose_read_config_word_via_dword) used to force the address passed to this function to be dword-aligned. Now that this function handles all sizes of read, I think it needs to align the address itself, doesn't it; i.e. pass "offset & ~3" to tegra_pcie_conf_address() or "address & ~3" to readl()? Same for the write function below.
This seems to work in practice without generating any alignment faults though; I'm not sure why. Perhaps I'm missing something, or we're just getting lucky?
Quoted 1 line
+int
pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
The diff might be slightly smaller/clearer if this function wasn't moved?
PATCH 8/8 dm: tegra: pci: Convert tegra boards to driver model for PCI
Hi Stephen,
Quoted 9 lines · Stephen Warren
Quoted 6 lines · Simon Glass
Adjust the Tegra PCI driver to support driver model and move all boards over
at the same time. This can make use of some generic driver model code, such
as the range decoding logic.
Quoted 3 lines
FYI, this patch has quite a few conflicts with my series to add Tegra210 support. See the git branch I mentioned earlier for a quick-n-dirty resolution to the conflicts, and subsequent fixups.
I've rebased to mainline so hopefully we are OK now. I'd like to get this in as I have a PCI series on top of it.
Quoted 16 lines
arch/arm/mach-tegra/Kconfig config TEGRA_ARMV7_COMMON · line 15
Quoted 10 lines
arch/arm/mach-tegra/Kconfig +1
-0@@ -12,6 +12,7 @@ config TEGRA_ARMV7_COMMON select DM_I2C select DM_SPI select DM_GPIO + select DM_PCII wonder if we shouldn't create the
TEGRA_COMMONconfig variable now, since many of the options are common to bothTEGRA_ARMV7_COMMONand TEGRA210. Perhaps alsoTEGRA_ARMV8_COMMONtoo, although currently there's only support for a single ARMV8 Tegra chip in U-Boot.
Sounds like a good idea to me.
Quoted 44 lines
drivers/pci/pci_tegra.c line 13
Quoted 5 lines
drivers/pci/pci_tegra.c +0
-1-#define DEBUG I actually find the debug prints useful, but yes I suppose debug should be turned off!
Quoted 14 lines
-static int tegra_pcie_read_conf(struct
pci_controller*hose,pci_dev_tbdf,drivers/pci/pci_tegra.c +5
-4- int where, u32 *value) +static int pci_tegra_read_config (struct udevice *bus,pci_dev_t bdf, +uint offset,ulong *valuep, +enum pci_size_t size) { - struct tegra_pcie *pcie = to_tegra_pcie(hose); -unsigned long address; +struct tegra_pcie *pcie =dev_get_priv (bus); +unsigned long address, value;int err; - err =tegra_pcie_conf_address (pcie, bdf, where, &address);drivers/pci/pci_tegra.c static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf, · line 295
Quoted 10 lines
drivers/pci/pci_tegra.c +4
-3+ err =tegra_pcie_conf_address (pcie, bdf, offset, &address);if (err <0 ) { - *value =0xffffffff ; -return 1 ; + value =0xffffffff ; + goto done; } - *value =readl (address); + value =readl (address);This function used to be used only for dword-sized reads. Presumably in that case, "where" was always dword-aligned. When used for word/byte-sized reads, the wrappers to do that (e.g.
pci_hose_read_config_word_via_dword) used to force the address passed to this function to be dword-aligned. Now that this function handles all sizes of read, I think it needs to align the address itself, doesn't it; i.e. pass "offset & ~3" totegra_pcie_conf_address()or "address & ~3" toreadl()? Same for the write function below.
Quoted 3 lines
This seems to work in practice without generating any alignment faults though; I'm not sure why. Perhaps I'm missing something, or we're just getting lucky?
tegra_pcie_conf_address() should be doing that correctly.
Quoted 5 lines
Quoted 2 lines
+int
pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)The diff might be slightly smaller/clearer if this function wasn't moved?
OK, I'll leave it. I do like the U_BOOT_DRIVER() thing to be at the end of the file, but it is still very close to the end.
Regards,
Simon