pci/layerscape: set LUT and msi-map for discovered PCI devices
PATCH v6 5/5 pci/layerscape: set LUT and msi-map for discovered PCI devices
From: Stuart Yoder <[email protected]>
msi-map properties are used to tell an OS how PCI requester IDs are mapped to ARM SMMU stream IDs.
for all PCI devices discovered in a system:
-allocate a LUT (look-up-table) entry in that PCI controller -allocate a stream ID for the device
-program and enable a LUT entry (maps PCI requester id to stream ID) -set the msi-map property on the controller reflecting the
LUT mapping
basic bus scanning loop/logic was taken from drivers/pci/pci.c pci_hose_scan_bus().
---
-v6: squashed lut, stream id, and msi-map helper functions
(previously patches 4-6) into this patch
drivers/pci/pcie_layerscape.c | 147 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+)
drivers/pci/pcie_layerscape.c +147 -0
@@ -93,6 +93,7 @@ struct ls_pcie {void __iomem *dbi;void __iomem *va_cfg0;void __iomem *va_cfg1; +int next_lut_index;struct pci_controller hose; };
@@ -482,6 +483,147 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info) } } +#ifdef CONFIG_FSL_LSCH3 +/* +* Return next available LUT index. +*/ +static int ls_pcie_next_lut_index (struct ls_pcie *pcie) +{ +if (pcie->next_lut_index <PCIE_LUT_ENTRY_COUNT ) +return pcie->next_lut_index++; +else +return -1 ;/* LUT is full */ +} + +/* +* Program a single LUT entry +*/ +static void ls_pcie_lut_set_mapping (struct ls_pcie *pcie,int index,u32 devid, +u32 streamid) +{ +void __iomem *lut; + + lut = pcie->dbi +PCIE_LUT_BASE ; + +/* leave mask as all zeroes, want to match all bits */ +writel ((devid <<16 ), lut +PCIE_LUT_UDR (index)); +writel (streamid |PCIE_LUT_ENABLE , lut +PCIE_LUT_LDR (index)); +} + +/* returns the next available streamid */ +static u32 ls_pcie_next_streamid (void ) +{ +static int next_stream_id =FSL_PEX_STREAM_ID_START ; + +if (next_stream_id >FSL_PEX_STREAM_ID_END ) +return 0xffffffff ; + +return next_stream_id++; +} + +/* +* An msi-map is a property to be added to the pci controller +* node. It is a table, where each entry consists of 4 fields +* e.g.: +* +* msi-map = <[devid] [phandle-to-msi-ctrl] [stream-id] [count] +* [devid] [phandle-to-msi-ctrl] [stream-id] [count]>; +*/ +static void fdt_pcie_set_msi_map_entry (void *blob,struct ls_pcie *pcie, +u32 devid,u32 streamid) +{ +char pcie_path[19 ]; +u32 *prop; +u32 phandle; +int nodeoffset; + +/* find pci controller node */ +snprintf (pcie_path,sizeof (pcie_path),"/soc/pcie@%llx" , + (u64 )pcie->dbi); + nodeoffset =fdt_path_offset (blob, pcie_path); +if (nodeoffset <0 ) { +printf ("\n%s: ERROR: unable to update PCIe node: %s\n" , + __func__, pcie_path); +return ; + } + +/* get phandle to MSI controller */ + prop = (u32 *)fdt_getprop (blob, nodeoffset,"msi-parent" ,0 ); +if (prop ==NULL ) { +printf ("\n%s: ERROR: missing msi-parent: %s\n" , __func__, + pcie_path); +return ; + } + phandle =be32_to_cpu (*prop); + +/* set one msi-map row */ +fdt_appendprop_u32 (blob, nodeoffset,"msi-map" , devid); +fdt_appendprop_u32 (blob, nodeoffset,"msi-map" , phandle); +fdt_appendprop_u32 (blob, nodeoffset,"msi-map" , streamid); +fdt_appendprop_u32 (blob, nodeoffset,"msi-map" ,1 ); +} + +static void fdt_fixup_pcie (void *blob) +{ +unsigned int found_multi =0 ; +unsigned char header_type; +int index; +u32 streamid; +pci_dev_t dev; +int bus; +unsigned short id; +struct pci_controller *hose; +struct ls_pcie *pcie; +int i; + +for (i =0 , hose =pci_get_hose_head (); hose; hose = hose->next, i++) { + pcie = hose->priv_data; +for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { + +for (dev =PCI_BDF (bus,0 ,0 ); + dev <PCI_BDF (bus,PCI_MAX_PCI_DEVICES -1 , +PCI_MAX_PCI_FUNCTIONS -1 ); + dev +=PCI_BDF (0 ,0 ,1 )) { + +if (PCI_FUNC (dev) && !found_multi) +continue ; + +pci_read_config_word (dev,PCI_VENDOR_ID , &id); + +pci_read_config_byte (dev,PCI_HEADER_TYPE , + &header_type); + +if ((id ==0xFFFF ) || (id ==0x0000 )) +continue ; + +if (!PCI_FUNC (dev)) + found_multi = header_type &0x80 ; + + streamid =ls_pcie_next_streamid (); +if (streamid ==0xffffffff ) { +printf ("ERROR: no stream ids free\n" ); +continue ; + } + + index =ls_pcie_next_lut_index (pcie); +if (index <0 ) { +printf ("ERROR: no LUT indexes free\n" ); +continue ; + } + +/* map PCI b.d.f to streamID in LUT */ +ls_pcie_lut_set_mapping (pcie, index, dev >>8 , + streamid); + +/* update msi-map in device tree */ +fdt_pcie_set_msi_map_entry (blob, pcie, dev >>8 , + streamid); + } + } + } +} +#endif +int ls_pcie_init_ctrl (int busno,enum srds_prtcl dev,struct ls_pcie_info *info) {struct ls_pcie *pcie;
@@ -513,6 +655,7 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) pcie->va_cfg1 =map_physmem (info->cfg1_phys, info->cfg1_size,MAP_NOCACHE ); + pcie->next_lut_index =0 ;/* outbound memory */ pci_set_region(&hose->regions[0],
@@ -657,6 +800,10 @@ void ft_pci_setup(void *blob, bd_t *bd)#ifdef CONFIG_PCIE4 ft_pcie_ls_setup (blob,FSL_PCIE_COMPAT ,CONFIG_SYS_PCIE4_ADDR ,PCIE4 );#endif + +#ifdef CONFIG_FSL_LSCH3 +fdt_fixup_pcie (blob); + #endif }#else
Signature · 1 line
1.7.9.5
PATCH v6 5/5 pci/layerscape: set LUT and msi-map for discovered PCI devices
Quoted 15 lines · Stuart Yoder
From: Stuart Yoder <[email protected]>
msi-map properties are used to tell an OS how PCI requester IDs are mapped to ARM SMMU stream IDs.
for all PCI devices discovered in a system:
-allocate a LUT (look-up-table) entry in that PCI controller -allocate a stream ID for the device
-program and enable a LUT entry (maps PCI requester id to stream ID) -set the msi-map property on the controller reflecting the
LUT mappingbasic bus scanning loop/logic was taken from
drivers/pci/pci.cpci_hose_scan_bus().
Quoted 8 lines
Signed-off-by Stuart Yoder <[email protected]>---
-v6: squashed lut, stream id, and msi-map helper functions
(previously patches 4-6) into this patchdrivers/pci/pcie_layerscape.c | 147 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+)
Applied to u-boot-fsl-qoriq, awaiting upstream.
Thanks.
York