[U-Boot] [PATCH] board: ls1028a: set up integrated PCI stream IDs and cache attributes
Alex Marginean
alexm.osslist at gmail.com
Fri Aug 9 14:31:40 UTC 2019
On 8/9/2019 4:27 PM, Bin Meng wrote:
> Hi Alex,
>
> On Fri, Aug 9, 2019 at 9:15 PM Alex Marginean <alexm.osslist at gmail.com> wrote:
>>
>> Hi Bin,
>>
>> On 8/9/2019 12:58 PM, Bin Meng wrote:
>>> Hi Alex,
>>>
>>> On Fri, Aug 9, 2019 at 3:59 PM Alex Marginean
>>> <alexandru.marginean at nxp.com> wrote:
>>>>
>>>> Configure stream IDs for integrated PCI devices. There are hardware
>>>> defaults but unfortunately they are outside the acceptable range for
>>>> SMMU, so we need to tune them down. Use values based on Linux device tree
>>>> iommu-map or, if missing, start from HW base value shifted down by 4.
>>>>
>>>> Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
>>>> ---
>>>> board/freescale/ls1028a/ls1028a.c | 64 +++++++++++++++++++++++++++++++
>>>> 1 file changed, 64 insertions(+)
>>>>
>>>> diff --git a/board/freescale/ls1028a/ls1028a.c b/board/freescale/ls1028a/ls1028a.c
>>>> index 49a9292c31..05eac6f9c4 100644
>>>> --- a/board/freescale/ls1028a/ls1028a.c
>>>> +++ b/board/freescale/ls1028a/ls1028a.c
>>>> @@ -118,6 +118,67 @@ void detail_board_ddr_info(void)
>>>> }
>>>>
>>>> #ifdef CONFIG_OF_BOARD_SETUP
>>>> +
>>>> +/*
>>>> + * Hardware default stream IDs are 0x4000 + PCI function #, but that's outside
>>>> + * the acceptable range for SMMU. Use Linux DT values instead or at least
>>>> + * smaller defaults.
>>>> + */
>>>> +#define ECAM_NUM_PFS 7
>>>> +#define ECAM_IERB_BASE 0x1F0800000
>>>> +#define ECAM_PFAMQ(pf, vf) ((ECAM_IERB_BASE + 0x800 + (pf) * \
>>>> + 0x1000 + (vf) * 4))
>>>> +/* cache related transaction attributes for PCIe functions */
>>>> +#define ECAM_IERB_MSICAR (ECAM_IERB_BASE + 0xa400)
>>>> +#define ECAM_IERB_MSICAR_VALUE 0x30
>>>> +
>>>> +/* number of VFs per PF, VFs have their own AMQ settings */
>>>> +static const u8 enetc_vfs[ECAM_NUM_PFS] = { 2, 2 };
>>>> +
>>>> +void setup_ecam_amq(void *blob)
>>>
>>> nits: this should be static
>>
>> I'll send a v2.
>>
>>>
>>>> +{
>>>> + int streamid, sid_base, off;
>>>> + int pf, vf, vfnn = 1;
>>>> + u32 iommu_map[4];
>>>> + int err;
>>>> +
>>>> + /*
>>>> + * Look up the stream ID settings in the DT, if found apply the values
>>>> + * to HW, otherwise use HW values shifted down by 4.
>>>> + */
>>>> + off = fdt_node_offset_by_compatible(blob, 0, "pci-host-ecam-generic");
>>>> + if (off < 0) {
>>>> + debug("ECAM node not found\n");
>>>> + return;
>>>> + }
>>>> +
>>>> + err = fdtdec_get_int_array(blob, off, "iommu-map", iommu_map, 4);
>>>> + if (err) {
>>>> + sid_base = in_le32(ECAM_PFAMQ(0, 0)) >> 4;
>>>> + debug("\"iommu-map\" not found, using default SID base %04x\n",
>>>> + sid_base);
>>>> + } else {
>>>> + sid_base = iommu_map[2];
>>>> + }
>>>> + /* set up AMQs for all integrated PCI functions */
>>>> + for (pf = 0; pf < ECAM_NUM_PFS; pf++) {
>>>> + streamid = sid_base + pf;
>>>> + out_le32(ECAM_PFAMQ(pf, 0), streamid);
>>>> +
>>>> + /* set up AMQs for VFs, if any */
>>>> + for (vf = 0; vf < enetc_vfs[pf]; vf++, vfnn++) {
>>>> + streamid = sid_base + ECAM_NUM_PFS + vfnn;
>>>> + out_le32(ECAM_PFAMQ(pf, vf + 1), streamid);
>>>> + }
>>>> + }
>>>> +}
>>>> +
>>>> +void setup_ecam_cacheattr(void)
>>>
>>> ditto
>>>
>>>> +{
>>>> + /* set MSI cache attributes */
>>>> + out_le32(ECAM_IERB_MSICAR, ECAM_IERB_MSICAR_VALUE);
>>>> +}
>>>> +
>>>> int ft_board_setup(void *blob, bd_t *bd)
>>>> {
>>>> u64 base[CONFIG_NR_DRAM_BANKS];
>>>> @@ -143,6 +204,9 @@ int ft_board_setup(void *blob, bd_t *bd)
>>>>
>>>> fdt_fixup_memory_banks(blob, base, size, 2);
>>>>
>>>> + setup_ecam_amq(blob);
>>>> + setup_ecam_cacheattr();
>>>> +
>>>> return 0;
>>>> }
>>>> #endif
>>>
>>> Not only programming the registers, but also I think we will need fix
>>> up the <msi-map> property used by the "pci-host-ecam-generic", just
>>> like what it was done in fdt_pcie_set_msi_map_entry() in
>>> pcie_layerscape_fixup.c
>>
>> The DT loaded with the kernel has the two maps (iommu and msi) in sync,
>> they are both present and they start from same base ID. For integrated
>
> OK, I checked arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi, and
> found pcie at 1f0000000 (ecam) node has <msi-map> and <iommu-map>
> properties, both of which have the same ID 0x17.
>
>> PCI we use that as a reference in U-Boot rather than assign the value
>> from U-Boot. Layerscape PCI node as far as I remember doesn't have the
>> msi/iommu-map properties, they are added by U-Boot using IDs it
>> allocates, but we don't do that here. The intent is to try to keep
>
> In the same kernel fsl-ls1028a.dtsi, I did not find any layescape PCI
> nodes. I suspect they are not upstreamed yet?
I don't know for a fact, I assume they have been submitted but not
merged yet.
> So if the we are doing layersacpe PCI <msi-map> fix in U-Boot, but for
> ECAM we are doing the other way around, I don't think it is
> consistent. I believe we should either have DT provide <msi-map> and
> <iommu-map> for layersacpe PCI nodes and use that as a reference in
> U-Boot, or we fix up all in U-Boot.
It's not consistent, no argument there. For what is worth I would like
to stick to the concept of integrated HW using by default a valid set of
IDs and not do any fix-up at all. I suppose the next best thing along
that line is to right shift the ID range for ECAM in U-Boot and
integrate this as a erratum work-around, rather than a fix-up. Linux DT
would be written using the right shifted values and U-Boot wouldn't need
to touch it. How does that sound? Nipun, does it look OK to you?
>> fixups to a minimum, in this case the code is needed only because the HW
>> defaults are not OK.
>
> Speaking of keeping fixups to a minimum, should we move
> setup_ecam_amq() and setup_ecam_cacheattr() to somewhere else? They
> are inside ft_board_setup() which is supposed to do board-level DT fix
> up but here we are actually not doing any DT fixup.
If the code needs access to Linux DT, it has to be in one of the
ft_... functions. It looks like ft_board_setup and ft_system_setup and
others are all intended just for editing the DT.
Anyway, approaching this as a work-around means access to Linux DT is no
longer needed and the code can go in board_init.
Thank you!
Alex
>
>> For what is worth I tested ping in Linux with this U-Boot change and it
>> works.
>>
>> I suppose one potential issue is to make sure U-Boot won't
>> allocate in the same range as the values used in DT for ECAM. The
>> values we use now in Linux DT are OK in the sense that they are over the
>> range used by U-Boot (FSL_PEX_STREAM_ID_START-FSL_PEX_STREAM_ID_END).
>> There is no explicit check for overlap between layerscape PCI stream IDs
>> and ECAM stream IDs, I am guessing such a configuration issue would be
>> noticeable in Linux though.
>>
>
> Regards,
> Bin
>
More information about the U-Boot
mailing list