Re: [PATCH u-boot-next 2/4] pci: pcie-brcmstb: Use PCIE_ECAM_OFFSET() macro

2021-11-30 Thread nicolas saenz julienne
On Wed, 2021-11-24 at 18:00 +0100, Pali Rohár wrote:
> Replace custom driver macros by PCIE_ECAM_OFFSET() macro from pci.h
> 
> Signed-off-by: Pali Rohár 
> ---

Reviewed-by: Nicolas Saenz Julienne 

Regards,
Nicolas


Re: [PATCH] arm: rpi: perform XHCI firmware upload only once

2021-09-17 Thread nicolas saenz julienne
On Fri, 2021-09-17 at 10:19 +0200, Marek Szyprowski wrote:
> XHCI firmware upload must be performed only once after initializing the
> PCI bridge. This fixes USB stack initialization after calling "usb stop;
> usb start" on Raspberry Pi 4B.
> 
> Signed-off-by: Marek Szyprowski 
> ---

Reviewed-by: Nicolas Saenz Julienne 

Regards,
Nicolas



[PATCH] mailmap: Update mail address for Nicolas Saenz julienne

2021-09-16 Thread Nicolas Saenz Julienne
From: Nicolas Saenz Julienne 

The @suse.de address doesn't exist anymore. Update it to something not
dependent on my workplace.

Signed-off-by: Nicolas Saenz Julienne 
---
 .mailmap | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.mailmap b/.mailmap
index b76f02283c..b09fc321bd 100644
--- a/.mailmap
+++ b/.mailmap
@@ -32,6 +32,7 @@ Jagan Teki 
 Igor Opaniuk  
 Igor Opaniuk  
 Markus Klotzbuecher 
+Nicolas Saenz Julienne  
 Patrice Chotard  
 Patrick Delaunay  
 Paul Burton  
-- 
2.31.1



Re: [PATCH] ARM: bcm283x: change the virtual address of the XHCI PCI device base

2021-06-18 Thread nicolas saenz julienne
On Thu, 2021-06-17 at 11:22 +0200, Marek Szyprowski wrote:
> Move the XHCI PCI device base up in the virtual address space. This fixes
> initialization failure observed with newer Raspberry Pi firmware, later
> than 63b1922311 ("firmware: arm_loader: Update armstubs with those from
> PR 117). It looks that chosing 0xff80 as the XHCI PCI device base
> conflicts with the updated ARM/VideoCore firmware.
> 
> This also requires to reduce the size of the mapped PCI device region
> from 8MiB to 4MiB to fit into 32bit address space. This is still enough
> for the XHCI PCI device.
> 
> Signed-off-by: Marek Szyprowski 
> Reviewed-by: Jaehoon Chung 
> ---
> This fixes the issue observed on ARM 32bit after upgrading the RPi4
> firmware files, described some time ago here:
> https://lists.denx.de/pipermail/u-boot/2021-February/442317.html
> ---

Reviewed-by: Nicolas Saenz Julienne 

Regards,
Nicolas


signature.asc
Description: This is a digitally signed message part


Re: Running u-boot 2021.04 on Raspberry Pi 4

2021-04-09 Thread Nicolas Saenz Julienne
[ Adding Matthias for the SMBIOS part ]

On Fri, 2021-04-09 at 00:00 -0700, Roman Shaposhnik wrote:
> On Thu, Apr 8, 2021 at 8:59 PM Sean Anderson  wrote:
> > On 4/8/21 8:18 PM, Roman Shaposhnik wrote:
> > > Hi!
> > > 
> > > first time poster, long time lurker here. Over at Project EVE
> > > https://github.com/lf-edge/eve I've been trying to migrate
> > > from our current u-boot v2020.07 + patches:
> > > 
> > > https://github.com/lf-edge/eve/tree/master/pkg/u-boot/patches/patches-v2020.07
> > > to the latest u-boot 2021.04.
> > > 
> > > Great news is that most of the patches we dependent
> > > on seem to have been pulled upstream. However, this
> > > single *chunk* of one patchset wasn't:
> > > 
> > > https://github.com/lf-edge/eve/blob/master/pkg/u-boot/patches/patches-v2020.07/0001-usb-xhci-Load-Raspberry-Pi-4-VL805-s-firmware.patch#L293
> > > 
> > > I'm wondering what was the reason for leaving it behind,
> > 
> > +CC Nicolas
> > 
> > >   - Get rid of PCI core patch as not needed with correct DT PCI topology 
> > 
> > also from the cover letter
> > 
> > > This also depends on a DT/bindings patch available on the linux-mailing 
> > > lists:
> > > https://www.mail-archive.com/linux-kernel@.../msg2205783.html
> > 
> > The merged version of this series is
> > 
> > https://patchwork.kernel.org/project/linux-usb/list/?series=310015&state=%2A&archive=both
> > 
> > > Here is the relevant bit for reference/discussion:
> > > 
> > >          &pcie0 {
> > >                 pci@1,0 {
> > >                         #address-cells = <3>;
> > >                         #size-cells = <2>;
> > >                         ranges;
> > > 
> > >                         reg = <0 0 0 0 0>;
> > > 
> > >                         usb@1,0 {
> > >                                 reg = <0x1 0 0 0 0>;
> > >                                 resets = <&reset 
> > > RASPBERRYPI_FIRMWARE_RESET_ID_USB>;
> > >                         };
> > >                 };
> > >          };
> > 

Yes, instead of using a PCI quirk we settled on a reset controller. All in all
it is less hacky. But needs changes in DT.

> Aha! Thank you so much -- this is super helpful!
>  
> > > since without it I don't seem to have functioning USB
> > > devices on my  Raspberry Pi 4. In fact, adding it back:
> > > 
> > > https://github.com/rvs/eve/tree/u-boot/pkg/u-boot/patches/patches-v2021.04
> > > (just that one chunk -- 'cuz the reset got upstreamed)
> > > seems to solve the issue for me.
> > > 
> > > Another question I have is that the new u-boot seems to have
> > > some kind of a regression that I can't quite debug. The SMBIOS
> > > tables that it constructs during EFI boot sequence seem to be
> > > broken (see the dmidecode output below). Again, this seems
> > > to be a regression compared to  v2020.07. Any ideas on what
> > > could be wrong or how can I start debugging it would be
> > 
> > You can always bisect it ;)
> > 
> 
> 
> LOL -- true! I was just hoping someone would recognize the issue perhaps.
> 
> Thanks,
> Roman. 




signature.asc
Description: This is a digitally signed message part


Re: [RFC] dev_phys_to_bus() and PCI

2021-03-19 Thread Nicolas Saenz Julienne
Hi Mark,

> Hi Nicolas,
> 
> > On Sat, 2021-03-13 at 10:24 +0100, Mark Kettenis wrote:
> > [...]
> > > Fortunately Nicolas Saenz Julienne recently introduced
> > > dev_phys_to_bus() and dev_bus_to_phys() interfaces to do this.  Those
> > > interfaces make use of a dma-ranges property in the device tree which
> > > doesn't work so well for PCI devices though.
> > 
> > Why doesn't it work with PCI devices? Raspberry Pi 4 has a PCIe bus
> > that needs DMA translations. This is handled by parsing its
> > 'dma-ranges' property. Here's how rpi4's devicetree looks like[1]:
> > 
> > pcie0: pcie@7d50 {
> > compatible = "brcm,bcm2711-pcie";
> > ranges = <0x0200 0x0 0xf800 0x6 0x 0x0 
> > 0x0400>;
> > /*
> >  * The wrapper around the PCIe block has a bug preventing it
> >  * from accessing beyond the first 3GB of memory.
> >  */
> > dma-ranges = <0x0200 0x0 0x 0x0 0x 0x0 
> > 0xc000>;
> > };
> 
> Does that work even though there are no device tree nodes for the PCI
> devices themselves?

'dma-ranges' only makes sense on bus nodes. So whenever you perform a DMA
address tranlation you start parsing from the endpoint device's parent. In this
case the PCIe root bridge, which has a proper DT node.

> > > However, the PCI code in U-Boot already has a way to describe DMA address
> > > translation through its regions support.
> > 
> > regions contain a representation of devicetree's 'ranges' property, which
> > doesn't describe the DMA address translations, but CPU's view of PCI memory.
> 
> It describes both.  The DMA address translations are described by
> regions that have the PCI_REGION_SYS_MEMORY flag set.  Some of the PCI
> host bridge drivers set up these regions, and the generic DM_PCI code
> by default adds such regions for the system RAM banks.  And there is a
> fdt_pci_dma_ranges() function to populate a "dma-ranges" property
> based on these regions.

Sorry, I wasn't aware PCI_REGION_SYS_MEMORY existed.

> The benefit of the PCI regions code is that it can describe more complex
> setups where a single translation offset isn't enough. And the code will
> print a warbing if you try to do DMA to memory that isn't "visable" for the
> PCI device.
> 
> In the particular example of the M1 code I don't really want to add a
> dma-ranges property to the device tree since the IOMMU setup is only
> used by u-boot and not really usable by Linux or another OS as it only
> covers a (relatively) small part of system memory.

So I understand that this region will be hard-coded in your PCI driver. And
there will be no trace of it in DT. If so, I think I understand your strategy.

> > > diff --git a/include/phys2bus.h b/include/phys2bus.h
> > > index 866b8b51a8..13d23ef4bb 100645
> > > --- a/include/phys2bus.h
> > > +++ b/include/phys2bus.h
> > > @@ -23,14 +23,21 @@ static inline unsigned long bus_to_phys(unsigned long 
> > > bus)
> > >  
> > > 
> > >  #if CONFIG_IS_ENABLED(DM)
> > >  #include 
> > > +#include 
> > >  
> > > 
> > >  static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, 
> > > phys_addr_t phys)
> > >  {
> > > + if (device_is_on_pci_bus(dev))
> > > + return dm_pci_phys_to_bus(dev, phys, PCI_REGION_SYS_MEMORY);
> > > +
> > 
> > Note that this would break USB support on RPi4.
> 
> It should work if the PCI host bridge driver sets up the regions
> properly based on the dma-ranges property.  Looks like the current
> driver doesn't do this, so I'll have to fix that.

That would work. But it would be better to integrate your setup with struct
udevice's DMA tranlation attributes. It's as simple as performing the
PCI_REGION_SYS_MEMORY parsing in device_get_dma_constraints(). Then you'd be
able to use plain, generic, dev_phys_to_bus(). With the added benefit of not
having the parse all resources everytime you perform a translation, and not
having to add churn in pcie-brcmstb.

Regards,
Nicolas






signature.asc
Description: This is a digitally signed message part


Re: [RFC] dev_phys_to_bus() and PCI

2021-03-15 Thread Nicolas Saenz Julienne
Hi Mark!

On Sat, 2021-03-13 at 10:24 +0100, Mark Kettenis wrote:
[...]
> Fortunately Nicolas Saenz Julienne recently introduced
> dev_phys_to_bus() and dev_bus_to_phys() interfaces to do this.  Those
> interfaces make use of a dma-ranges property in the device tree which
> doesn't work so well for PCI devices though.

Why doesn't it work with PCI devices? Raspberry Pi 4 has a PCIe bus that needs
DMA translations. This is handled by parsing its 'dma-ranges' property. Here's
how rpi4's devicetree looks like[1]:

pcie0: pcie@7d50 {
compatible = "brcm,bcm2711-pcie";
ranges = <0x0200 0x0 0xf800 0x6 0x 0x0 
0x0400>;
/*
 * The wrapper around the PCIe block has a bug preventing it
 * from accessing beyond the first 3GB of memory.
 */
dma-ranges = <0x0200 0x0 0x 0x0 0x 0x0 
0xc000>;
};

> However, the PCI code in U-Boot already has a way to describe DMA address
> translation through its regions support.

regions contain a representation of devicetree's 'ranges' property, which
doesn't describe the DMA address translations, but CPU's view of PCI memory.

> diff --git a/include/phys2bus.h b/include/phys2bus.h
> index 866b8b51a8..13d23ef4bb 100644
> --- a/include/phys2bus.h
> +++ b/include/phys2bus.h
> @@ -23,14 +23,21 @@ static inline unsigned long bus_to_phys(unsigned long bus)
>  
> 
>  #if CONFIG_IS_ENABLED(DM)
>  #include 
> +#include 
>  
> 
>  static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t 
> phys)
>  {
> + if (device_is_on_pci_bus(dev))
> + return dm_pci_phys_to_bus(dev, phys, PCI_REGION_SYS_MEMORY);
> +

Note that this would break USB support on RPi4.

Regards,
Nicolas

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/bcm2711.dtsi?h=v5.12-rc3#n506



signature.asc
Description: This is a digitally signed message part


Re: u-boot on RPi4 32bit - issue after upgrading the firmware

2021-02-25 Thread Nicolas Saenz Julienne
On Thu, 2021-02-25 at 11:43 +0100, Marek Szyprowski wrote:
> Hi!
> 
> Recently I've upgraded a video core firmware on my RPi4 and I've noticed 
> that u-boot in ARM 32bit mode stopped working properly or even randomly 
> crashes. I've bisected the firmware releases and the issue appears for 
> the first time in the commit 63b1922311 ("firmware: arm_loader: Update 
> armstubs with those from PR 117 See: 
> https://github.com/raspberrypi/tools/pull/117";).

Just for confirmation, 
> 
> This issue can be easily observed as a failure of the xhci. See the 
> attached log:
> 
> Read start4x.elf bytes  2984808 hnd 0x06e2 sha256 d21bf9d3954fea04
> Read fixup4x.dat bytes 8432 hnd 0x06dd sha256 10d3b073ab232613
> 0x00a03111 0x 0x001f
> MEM GPU: 76 ARM: 948 TOTAL: 1024
> Starting start4x.elf @ 0xfec00200 partition 0
> PCI reset
> +
> 
> MESS:00:00:04.800023:0: arasan: arasan_emmc_open
> MESS:00:00:04.975752:0: brfs: File read: /mfs/sd/config.txt
> MESS:00:00:04.979162:0: brfs: File read: 2153 bytes
> MESS:00:00:05.046081:0: brfs: File read: /mfs/sd/config.txt
> MESS:00:00:06.121174:0: gpioman: gpioman_get_pin_num: pin 
> DISPLAY_DSI_PORT not defined
> MESS:00:00:06.128433:0: *** Restart logging
> MESS:00:00:06.129897:0: brfs: File read: 2153 bytes
> MESS:00:00:06.148533:0: hdmi: HDMI:hdmi_get_state is deprecated, use 
> hdmi_get_display_state instead
> MESS:00:00:06.154474:0: HDMI0: hdmi_pixel_encoding: 3
> MESS:00:00:06.159948:0: HDMI1: hdmi_pixel_encoding: 3
> MESS:00:00:06.166901:0: dtb_file 'bcm2711-rpi-4-b.dtb'
> MESS:00:00:06.178359:0: brfs: File read: /mfs/sd/bcm2711-rpi-4-b.dtb
> MESS:00:00:06.181601:0: Loading 'bcm2711-rpi-4-b.dtb' to 0x100 size 0xc901
> MESS:00:00:06.201386:0: brfs: File read: 51457 bytes
> MESS:00:00:06.267975:0: brfs: File read: /mfs/sd/config.txt
> MESS:00:00:06.270915:0: dtparam: audio=on
> MESS:00:00:06.283974:0: brfs: File read: 2153 bytes
> MESS:00:00:06.286148:0: Failed to load overlay 'vc4-fkms-v3d'
> MESS:00:00:06.291378:0: brfs: File read: /mfs/sd/overlays/vc4-fkms-v3d.dtbo
> MESS:00:00:06.304096:0: Failed to open command line file 'cmdline.txt'
> MESS:00:00:07.484256:0: brfs: File read: /mfs/sd/u-boot.bin
> MESS:00:00:07.486726:0: Loading 'u-boot.bin' to 0x8000 size 0x84cf4
> MESS:00:00:07.492726:0: Device tree loaded to 0x2eff3100 (size 0xce24)
> MESS:00:00:07.500863:0: uart: Set PL011 baud rate to 103448.30 Hz
> MESS:00:00:07.508031:0: uart: Baud rate change done...
> MESS:00:00:07.510053:0:
> 
> U-Boot 2021.04-rc2 (Feb 25 2021 - 11:21:44 +0100)

Can you try with today's master branch, I'm specially interested in seeing if
56f1bcc4b7fb helps.

> DRAM:  948 MiB
> RPI 4 Model B (0xa03111)
> MMC:   mmcnr@7e30: 1, emmc2@7e34: 0
> Loading Environment from FAT... OK
> In:    serial
> Out:   serial
> Err:   serial
> Net:   eth0: ethernet@7d58
> Hit any key to stop autoboot:  0
> U-Boot> pci enum
> PCIe BRCM: link up, 5.0 Gbps x1 (SSC)
> U-Boot> usb start
> starting USB...
> Bus xhci_pci: Host not halted after 16000 microseconds.
> probe failed, error -16
> No working controllers found
> U-Boot>
> 
> Is it a known issue? In ARM64 mode everything works fine, but this not 
> very surprising, because the firmware change in the mentioned commit is 
> related to the ARM 32bit mode. Does anyone have an idea how to fix this 
> issue? I've checked also the latest version of the RPi firmware, but the 
> issue is still there.
> 
> Best regards




signature.asc
Description: This is a digitally signed message part


Re: [EXT] USB3 XHCI crashing with USB 3 hub on Octeon

2021-02-23 Thread Nicolas Saenz Julienne
On Tue, 2021-02-23 at 10:25 +0100, Stefan Roese wrote:
> Hi Nicolas,
> 
> On 23.02.21 10:23, Nicolas Saenz Julienne wrote:
> > On Tue, 2021-02-23 at 09:15 +0100, Stefan Roese wrote:
> > > Hi Bin,
> > > Hi Aaron,
> > > 
> > > I've added Nicolas to Cc, as he also recently did some work on the
> > > physical vs virtual addresses in the xHCI driver.
> > > 
> > > On 23.02.21 09:07, Bin Meng wrote:
> > > > Hi Aaron,
> > > > 
> > > > On Tue, Feb 23, 2021 at 3:31 PM Aaron Williams  
> > > > wrote:
> > > > > 
> > > > > I have a follow-up. USB is working on our OcteonTX boards running 
> > > > > 2020.10. It
> > > > > may be something specific to the Octeon port. Note that I did see a 
> > > > > problem
> > > > > where the scratchpad memory is using direct pointers instead of 
> > > > > physical
> > > > > addresses (which will not work on MIPS). As far as I know, however, 
> > > > > the Octeon
> > > > > XHCI controller does not use the scratchpad memory.
> > > > > 
> > > > 
> > > > Do you plan to send a patch to convert the scratchpad pointer to
> > > > physical address?
> > > 
> > > Nicolas, did your patch also address the scratchpad area (sorry for not
> > > looking myself).
> > 
> > Yes, my patch took care of that :).
> 
> Great. IIRC, your patchset may need a rebase on top of current mainline
> because of a recent xHCI patch of mine. If this is the case, could you
> please rebase the patchset and send the new version soon?

My series was merged upstream some days ago. Nothing to worry though, I added
your patch as a fixup to mine (see 1a474559d90a) in master.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [EXT] USB3 XHCI crashing with USB 3 hub on Octeon

2021-02-23 Thread Nicolas Saenz Julienne
On Tue, 2021-02-23 at 09:15 +0100, Stefan Roese wrote:
> Hi Bin,
> Hi Aaron,
> 
> I've added Nicolas to Cc, as he also recently did some work on the
> physical vs virtual addresses in the xHCI driver.
> 
> On 23.02.21 09:07, Bin Meng wrote:
> > Hi Aaron,
> > 
> > On Tue, Feb 23, 2021 at 3:31 PM Aaron Williams  
> > wrote:
> > > 
> > > I have a follow-up. USB is working on our OcteonTX boards running 
> > > 2020.10. It
> > > may be something specific to the Octeon port. Note that I did see a 
> > > problem
> > > where the scratchpad memory is using direct pointers instead of physical
> > > addresses (which will not work on MIPS). As far as I know, however, the 
> > > Octeon
> > > XHCI controller does not use the scratchpad memory.
> > > 
> > 
> > Do you plan to send a patch to convert the scratchpad pointer to
> > physical address?
> 
> Nicolas, did your patch also address the scratchpad area (sorry for not
> looking myself).

Yes, my patch took care of that :).

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v1] usb: kbd: destroy device after console is stopped

2021-02-03 Thread Nicolas Saenz Julienne
Andy, Tony,
Sorry for my late reply, but I got a bad cold.

On Thu, 2021-01-28 at 15:46 -0500, Tom Rini wrote:
> On Thu, Jan 28, 2021 at 10:35:37PM +0200, Andy Shevchenko wrote:
> > On Thu, Jan 28, 2021 at 06:19:56PM +0100, Nicolas Saenz Julienne wrote:
> > > Hi Andy,
> > > 
> > > On Thu, 2021-01-28 at 18:55 +0200, Andy Shevchenko wrote:
> > > > In case of IOMUX enabled it assumes that console devices in the list
> > > > are available to get them stopped properly via ->stop() callback.
> > > > However, the USB keyboard driver violates this assumption and tries
> > > > to play tricks so the device get destroyed while being listed as
> > > > an active console.
> > > > 
> > > > Swap the order of device deregistration and IOMUX update to avoid
> > > > the use-after-free.
> > > > 
> > > > Fixes: 3cbcb2892809 ("usb: Fix usb_kbd_deregister when console-muxing 
> > > > is used")
> > > > Fixes: 8a8348703081 ("dm: usb: Add a remove() method for USB keyboards")
> > > > Reported-by: Nicolas Saenz Julienne 
> > > > Signed-off-by: Andy Shevchenko 
> > > > ---
> > > > v2: Nicolas, can you test this one instead of yours?
> > > 
> > > Sadly this doesn't seem to work, and breaks a bunch of other tests in the
> > > process. You can try it yourself by running: './test/py/test.py --bd 
> > > sandbox
> > > --build'
> > 
> > Now I'm able to run test cases. I see some of them failing even without my
> > patch, but few definitely related. Can you give a list of failed ones on 
> > your
> > side?  I can compare that we are on the same page here.
> 
> Running this here on sandbox I get:
> FAILED test/py/tests/test_ut.py::test_ut[ut_dm_bootcount] - OSError: [Errno 
> 5] Input/output ...
> FAILED test/py/tests/test_ut.py::test_ut[ut_dm_usb_flash] - OSError: [Errno 
> 5] Input/output ...
> FAILED test/py/tests/test_ut.py::test_ut[ut_dm_usb_multi] - OSError: [Errno 
> 5] Input/output ...
> FAILED test/py/tests/test_ut.py::test_ut[ut_dm_video_ansi] - OSError: [Errno 
> 5] Input/output...

This is what I'm seeing too.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH] rpi: limit size of the RAM to the multiple of the MMU_SECTION_SIZE

2021-02-03 Thread Nicolas Saenz Julienne
On Mon, 2021-02-01 at 12:16 +0100, Marek Szyprowski wrote:
> When RPi4 is booted from USB Mass Storage, the firmware reports 947MiB of
> the ARM memory (948 in case of the standard SD-card boot). This value is
> not MMU_SECTION_SIZE aligned, so the dram_bank_mmu_setup() skips mapping
> of the last 1MiB. This later causes u-boot in ARM 32bit mode to freeze,
> because it relocated itself into that unmapped memory and fails to
> execute.
> 
> Fix this by limiting the size of the first bank to the multiple of
> MMU_SECTION_SIZE.
> 
> Signed-off-by: Marek Szyprowski 
> ---

Reviewed-by: Nicolas Saenz Julienne 

Regards,
Nicolas




signature.asc
Description: This is a digitally signed message part


Re: [PATCH v1] usb: kbd: destroy device after console is stopped

2021-01-28 Thread Nicolas Saenz Julienne
Hi Andy,

On Thu, 2021-01-28 at 18:55 +0200, Andy Shevchenko wrote:
> In case of IOMUX enabled it assumes that console devices in the list
> are available to get them stopped properly via ->stop() callback.
> However, the USB keyboard driver violates this assumption and tries
> to play tricks so the device get destroyed while being listed as
> an active console.
> 
> Swap the order of device deregistration and IOMUX update to avoid
> the use-after-free.
> 
> Fixes: 3cbcb2892809 ("usb: Fix usb_kbd_deregister when console-muxing is 
> used")
> Fixes: 8a8348703081 ("dm: usb: Add a remove() method for USB keyboards")
> Reported-by: Nicolas Saenz Julienne 
> Signed-off-by: Andy Shevchenko 
> ---
> v2: Nicolas, can you test this one instead of yours?

Sadly this doesn't seem to work, and breaks a bunch of other tests in the
process. You can try it yourself by running: './test/py/test.py --bd sandbox
--build'

Regards,
Nicolas

>  common/usb_kbd.c | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/common/usb_kbd.c b/common/usb_kbd.c
> index b316807844b1..e09d9f7794c8 100644
> --- a/common/usb_kbd.c
> +++ b/common/usb_kbd.c
> @@ -617,12 +617,12 @@ int usb_kbd_deregister(int force)
>   if (dev) {
>   usb_kbd_dev = (struct usb_device *)dev->priv;
>   data = usb_kbd_dev->privptr;
> - if (stdio_deregister_dev(dev, force) != 0)
> - return 1;
>  #if CONFIG_IS_ENABLED(CONSOLE_MUX)
>   if (iomux_doenv(stdin, env_get("stdin")) != 0)
>   return 1;
>  #endif
> + if (stdio_deregister_dev(dev, force) != 0)
> + return 1;
>  #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
>   destroy_int_queue(usb_kbd_dev, data->intq);
>  #endif
> @@ -660,16 +660,16 @@ static int usb_kbd_remove(struct udevice *dev)
>   goto err;
>   }
>   data = udev->privptr;
> - if (stdio_deregister_dev(sdev, true)) {
> - ret = -EPERM;
> - goto err;
> - }
>  #if CONFIG_IS_ENABLED(CONSOLE_MUX)
>   if (iomux_doenv(stdin, env_get("stdin"))) {
>   ret = -ENOLINK;
>   goto err;
>   }
>  #endif
> + if (stdio_deregister_dev(sdev, true)) {
> + ret = -EPERM;
> + goto err;
> + }
>  #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
>   destroy_int_queue(udev, data->intq);
>  #endif





signature.asc
Description: This is a digitally signed message part


[PATCH v2 2/2] console: Don't start/stop console if stdio device invalid

2021-01-28 Thread Nicolas Saenz Julienne
Don't start/stop an stdio device that might have been already freed.

Signed-off-by: Nicolas Saenz Julienne 
Fixes: 70c2525c0d3c ("IOMUX: Stop dropped consoles")

---
Changes since v1:
 - Add comment stating this should be properly fixed

 common/console.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/common/console.c b/common/console.c
index f3cc45cab5..570f26d149 100644
--- a/common/console.c
+++ b/common/console.c
@@ -252,6 +252,15 @@ static bool console_needs_start_stop(int file, struct 
stdio_dev *sdev)
 {
int i, j;
 
+   /*
+* TODO: This is a workaround to avoid accessing freed memory:
+* console_stop() might be called on an stdio_dev that has already been
+* de-registered, due to the fact that stdio_deregister_dev()
+* doesn't update the global console_devices array.
+*/
+   if (!stdio_valid(sdev))
+   return false;
+
for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
if (i == file)
continue;
-- 
2.30.0



[PATCH v2 1/2] stdio: Introduce stdio_valid()

2021-01-28 Thread Nicolas Saenz Julienne
stdio_valid() will confirm that a struct stdio_dev pointer is indeed
valid.

Signed-off-by: Nicolas Saenz Julienne 

---

Changes since v1:
 - Properly document function

 common/stdio.c  | 11 +++
 include/stdio_dev.h | 11 +++
 2 files changed, 22 insertions(+)

diff --git a/common/stdio.c b/common/stdio.c
index abf9b1e915..69b7d2692d 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -157,6 +157,17 @@ static int stdio_probe_device(const char *name, enum 
uclass_id id,
return 0;
 }
 
+bool stdio_valid(struct stdio_dev *dev)
+{
+   struct stdio_dev *sdev;
+
+   list_for_each_entry(sdev, &devs.list, list)
+   if (sdev == dev)
+   return true;
+
+   return false;
+}
+
 struct stdio_dev *stdio_get_by_name(const char *name)
 {
struct list_head *pos;
diff --git a/include/stdio_dev.h b/include/stdio_dev.h
index 48871a6a22..e9d610a840 100644
--- a/include/stdio_dev.h
+++ b/include/stdio_dev.h
@@ -98,6 +98,17 @@ struct list_head *stdio_get_list(void);
 struct stdio_dev *stdio_get_by_name(const char *name);
 struct stdio_dev *stdio_clone(struct stdio_dev *dev);
 
+/**
+ * stdio_valid() - Validate stdio device exists
+ *
+ * Verifies that dev is contained in the global list of stdio devices.
+ *
+ * @dev: Stdio device pointer
+ *
+ * returns 'true' when valid, 'false' otherwise
+ */
+bool stdio_valid(struct stdio_dev *dev);
+
 int drv_lcd_init(void);
 int drv_video_init(void);
 int drv_keyboard_init(void);
-- 
2.30.0



[PATCH v2 0/2] Console/stdio use after free

2021-01-28 Thread Nicolas Saenz Julienne
With today's master, 70c2525c0d3c ('IOMUX: Stop dropped consoles')
introduces a use after free in usb_kbd_remove():

- usbkbd's stdio device is de-registered with stdio_deregister_dev(),
  the struct stdio_dev is freed.

- iomux_doenv() is called, usbkbd removed from the console list, and
  console_stop() is called on the struct stdio_dev pointer that no
  longer exists.

This series mitigates this by making sure the pointer is really a stdio
device prior performing the stop operation. It's not ideal, but I
couldn't figure out a nicer way to fix this.

Regards,
Nicolas

---

Changes since v1:
 - Comment new function
 - Add comment stating this needs a proper fix

Nicolas Saenz Julienne (2):
  stdio: Introduce stdio_valid()
  console: Don't start/stop console if stdio device invalid

 common/console.c|  9 +
 common/stdio.c  | 11 +++
 include/stdio_dev.h | 11 +++
 3 files changed, 31 insertions(+)

-- 
2.30.0



Re: [PATCH 1/2] stdio: Introduce stdio_valid()

2021-01-25 Thread Nicolas Saenz Julienne
On Sat, 2021-01-23 at 19:03 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Wed, 20 Jan 2021 at 07:05, Nicolas Saenz Julienne
>  wrote:
> > 
> > stdio_valid() will confirm that a struct stdio_dev pointer is indeed
> > valid.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > ---
> >  common/stdio.c  | 11 +++
> >  include/stdio_dev.h |  1 +
> >  2 files changed, 12 insertions(+)
> > 
> > diff --git a/common/stdio.c b/common/stdio.c
> > index abf9b1e915..69b7d2692d 100644
> > --- a/common/stdio.c
> > +++ b/common/stdio.c
> > @@ -157,6 +157,17 @@ static int stdio_probe_device(const char *name, enum 
> > uclass_id id,
> > return 0;
> >  }
> > 
> > +bool stdio_valid(struct stdio_dev *dev)
> > +{
> > +   struct stdio_dev *sdev;
> > +
> > +   list_for_each_entry(sdev, &devs.list, list)
> > +   if (sdev == dev)
> > +   return true;
> > +
> > +   return false;
> > +}
> > +
> >  struct stdio_dev *stdio_get_by_name(const char *name)
> >  {
> > struct list_head *pos;
> > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > index 48871a6a22..f341439b03 100644
> > --- a/include/stdio_dev.h
> > +++ b/include/stdio_dev.h
> > @@ -97,6 +97,7 @@ int stdio_deregister_dev(struct stdio_dev *dev, int 
> > force);
> >  struct list_head *stdio_get_list(void);
> >  struct stdio_dev *stdio_get_by_name(const char *name);
> >  struct stdio_dev *stdio_clone(struct stdio_dev *dev);
> > +bool stdio_valid(struct stdio_dev *dev);
> 
> Please add a full function comment and explain what valid means.

As discussed with Andy, this is a workaround that doesn't address the
underlying issue. If it's good enough for the time being I'll be happy to send
a v2.

I'll leave a comment stating that it's something to fix.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH 0/2] Console/stdio use after free

2021-01-25 Thread Nicolas Saenz Julienne
Hi Andy, Simon

On Wed, 2021-01-20 at 17:57 +0200, Andy Shevchenko wrote:
> On Wed, Jan 20, 2021 at 4:05 PM Nicolas Saenz Julienne
>  wrote:
> > 
> > With today's master, 70c2525c0d3c ('IOMUX: Stop dropped consoles')
> > introduces a use after free in usb_kbd_remove():
> > 
> > - usbkbd's stdio device is de-registered with stdio_deregister_dev(),
> >   the struct stdio_dev is freed.
> > 
> > - iomux_doenv() is called, usbkbd removed from the console list, and
> >   console_stop() is called on the struct stdio_dev pointer that no
> >   longer exists.
> > 
> > This series mitigates this by making sure the pointer is really a stdio
> > device prior performing the stop operation. It's not ideal, but I
> > couldn't figure out a nicer way to fix this.
> 
> Thanks for the report and indeed this sounds like a papering over the
> real issue somewhere else.
> If we have a device in the console_list, IOMUX may access it. So,
> whenever we drop device, we must update console_list accordingly.

Sorry, but I don't have time to address this ATM. If someone else can it'd be
nice.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH 0/2] Console/stdio use after free

2021-01-20 Thread Nicolas Saenz Julienne
On Wed, 2021-01-20 at 07:18 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Wed, 20 Jan 2021 at 07:04, Nicolas Saenz Julienne
>  wrote:
> > 
> > With today's master, 70c2525c0d3c ('IOMUX: Stop dropped consoles')
> > introduces a use after free in usb_kbd_remove():
> > 
> > - usbkbd's stdio device is de-registered with stdio_deregister_dev(),
> >   the struct stdio_dev is freed.
> > 
> > - iomux_doenv() is called, usbkbd removed from the console list, and
> >   console_stop() is called on the struct stdio_dev pointer that no
> >   longer exists.
> > 
> > This series mitigates this by making sure the pointer is really a stdio
> > device prior performing the stop operation. It's not ideal, but I
> > couldn't figure out a nicer way to fix this.
> 
> Your 'from' address is coming through as just your email. Could you
> please update it to include your name as well?

OK, do you want me to re-send the series?




signature.asc
Description: This is a digitally signed message part


[PATCH 2/2] console: Don't start/stop console if stdio device invalid

2021-01-20 Thread Nicolas Saenz Julienne
Don't start/stop an stdio device that might have been already freed.

Signed-off-by: Nicolas Saenz Julienne 
Fixes: 70c2525c0d3c ("IOMUX: Stop dropped consoles")
---
 common/console.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/console.c b/common/console.c
index f3cc45cab5..5c6b74b351 100644
--- a/common/console.c
+++ b/common/console.c
@@ -252,6 +252,9 @@ static bool console_needs_start_stop(int file, struct 
stdio_dev *sdev)
 {
int i, j;
 
+   if (!stdio_valid(sdev))
+   return false;
+
for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
if (i == file)
continue;
-- 
2.30.0



[PATCH 1/2] stdio: Introduce stdio_valid()

2021-01-20 Thread Nicolas Saenz Julienne
stdio_valid() will confirm that a struct stdio_dev pointer is indeed
valid.

Signed-off-by: Nicolas Saenz Julienne 
---
 common/stdio.c  | 11 +++
 include/stdio_dev.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/common/stdio.c b/common/stdio.c
index abf9b1e915..69b7d2692d 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -157,6 +157,17 @@ static int stdio_probe_device(const char *name, enum 
uclass_id id,
return 0;
 }
 
+bool stdio_valid(struct stdio_dev *dev)
+{
+   struct stdio_dev *sdev;
+
+   list_for_each_entry(sdev, &devs.list, list)
+   if (sdev == dev)
+   return true;
+
+   return false;
+}
+
 struct stdio_dev *stdio_get_by_name(const char *name)
 {
struct list_head *pos;
diff --git a/include/stdio_dev.h b/include/stdio_dev.h
index 48871a6a22..f341439b03 100644
--- a/include/stdio_dev.h
+++ b/include/stdio_dev.h
@@ -97,6 +97,7 @@ int stdio_deregister_dev(struct stdio_dev *dev, int force);
 struct list_head *stdio_get_list(void);
 struct stdio_dev *stdio_get_by_name(const char *name);
 struct stdio_dev *stdio_clone(struct stdio_dev *dev);
+bool stdio_valid(struct stdio_dev *dev);
 
 int drv_lcd_init(void);
 int drv_video_init(void);
-- 
2.30.0



[PATCH 0/2] Console/stdio use after free

2021-01-20 Thread Nicolas Saenz Julienne
With today's master, 70c2525c0d3c ('IOMUX: Stop dropped consoles')
introduces a use after free in usb_kbd_remove():

- usbkbd's stdio device is de-registered with stdio_deregister_dev(),
  the struct stdio_dev is freed.

- iomux_doenv() is called, usbkbd removed from the console list, and
  console_stop() is called on the struct stdio_dev pointer that no
  longer exists.

This series mitigates this by making sure the pointer is really a stdio
device prior performing the stop operation. It's not ideal, but I
couldn't figure out a nicer way to fix this.

Regards,
Nicolas

---

Nicolas Saenz Julienne (2):
  stdio: Introduce stdio_valid()
  console: Don't start/stop console if stdio device invalid

 common/console.c|  3 +++
 common/stdio.c  | 11 +++
 include/stdio_dev.h |  1 +
 3 files changed, 15 insertions(+)

-- 
2.30.0



Re: [PATCH] usb: xhci: Fix compare to use physical addresses in xhci_bulk_tx()

2021-01-15 Thread Nicolas Saenz Julienne
+Matthias, just so you're aware.

On Fri, 2021-01-15 at 11:33 +0100, Stefan Roese wrote:
> On 15.01.21 11:27, Nicolas Saenz Julienne wrote:
> > On Fri, 2021-01-15 at 08:52 +0100, Stefan Roese wrote:
> > > Testing with v2021.01 on MIPS Octeon has shown, that the latest patch
> > > for the "short packet event trb handling" did introduce a bug on
> > > platforms with virtual address != physical address. This patch fixes
> > > this issue by using the correct address types in the compare (both
> > > physical in this case).
> > > 
> > > Signed-off-by: Stefan Roese 
> > > Cc: Aaron Williams 
> > > Cc: Chandrakala Chavva 
> > > Cc: Ran Wang 
> > > Cc: Nicolas Saenz Julienne 
> > > Cc: Marek Vasut 
> > > Cc: Bin Meng 
> > > ---
> > >   drivers/usb/host/xhci-ring.c | 4 ++--
> > >   1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> > > index d708fc928b..d6c47d579b 100644
> > > --- a/drivers/usb/host/xhci-ring.c
> > > +++ b/drivers/usb/host/xhci-ring.c
> > > @@ -723,8 +723,8 @@ again:
> > >   return -ETIMEDOUT;
> > >   }
> > >   
> > > 
> > > 
> > > - if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer))
> > > - != (uintptr_t)last_transfer_trb_addr) {
> > > + if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
> > > + (uintptr_t)virt_to_phys(last_transfer_trb_addr)) {
> > >   available_length -=
> > >   
> > > (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));
> > >   xhci_acknowledge_event(ctrl);
> > 
> > FWIW I also addressed this in my Rpi400/CM4 enablement series:
> > https://lists.denx.de/pipermail/u-boot/2021-January/437150.html
> 
> Yes, thanks. I've seen your patch and also looked into it while
> debugging this issue on my MIPS platform this morning.
> 
> Actually I would prefer my fix, as it uses virt_to_phys() and not the
> other way around. Currently only virt_to_phys() is used in the USB code
> and not phys_to_virt(), which does not seem to work correctly on my
> platform BTW (as I discovered this morning).

Fair enough, I'll rebase my series on top of this once it's picked :).

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH] usb: xhci: Fix compare to use physical addresses in xhci_bulk_tx()

2021-01-15 Thread Nicolas Saenz Julienne
+Matthias, just so you're aware.

On Fri, 2021-01-15 at 11:33 +0100, Stefan Roese wrote:
> On 15.01.21 11:27, Nicolas Saenz Julienne wrote:
> > On Fri, 2021-01-15 at 08:52 +0100, Stefan Roese wrote:
> > > Testing with v2021.01 on MIPS Octeon has shown, that the latest patch
> > > for the "short packet event trb handling" did introduce a bug on
> > > platforms with virtual address != physical address. This patch fixes
> > > this issue by using the correct address types in the compare (both
> > > physical in this case).
> > > 
> > > Signed-off-by: Stefan Roese 
> > > Cc: Aaron Williams 
> > > Cc: Chandrakala Chavva 
> > > Cc: Ran Wang 
> > > Cc: Nicolas Saenz Julienne 
> > > Cc: Marek Vasut 
> > > Cc: Bin Meng 
> > > ---
> > >   drivers/usb/host/xhci-ring.c | 4 ++--
> > >   1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> > > index d708fc928b..d6c47d579b 100644
> > > --- a/drivers/usb/host/xhci-ring.c
> > > +++ b/drivers/usb/host/xhci-ring.c
> > > @@ -723,8 +723,8 @@ again:
> > >   return -ETIMEDOUT;
> > >   }
> > >   
> > > 
> > > 
> > > - if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer))
> > > - != (uintptr_t)last_transfer_trb_addr) {
> > > + if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
> > > + (uintptr_t)virt_to_phys(last_transfer_trb_addr)) {
> > >   available_length -=
> > >   
> > > (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));
> > >   xhci_acknowledge_event(ctrl);
> > 
> > FWIW I also addressed this in my Rpi400/CM4 enablement series:
> > https://lists.denx.de/pipermail/u-boot/2021-January/437150.html
> 
> Yes, thanks. I've seen your patch and also looked into it while
> debugging this issue on my MIPS platform this morning.
> 
> Actually I would prefer my fix, as it uses virt_to_phys() and not the
> other way around. Currently only virt_to_phys() is used in the USB code
> and not phys_to_virt(), which does not seem to work correctly on my
> platform BTW (as I discovered this morning).

Fair enough, I'll rebase my series on top of this once it's picked :).

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH] usb: xhci: Fix compare to use physical addresses in xhci_bulk_tx()

2021-01-15 Thread Nicolas Saenz Julienne
On Fri, 2021-01-15 at 08:52 +0100, Stefan Roese wrote:
> Testing with v2021.01 on MIPS Octeon has shown, that the latest patch
> for the "short packet event trb handling" did introduce a bug on
> platforms with virtual address != physical address. This patch fixes
> this issue by using the correct address types in the compare (both
> physical in this case).
> 
> Signed-off-by: Stefan Roese 
> Cc: Aaron Williams 
> Cc: Chandrakala Chavva 
> Cc: Ran Wang 
> Cc: Nicolas Saenz Julienne 
> Cc: Marek Vasut 
> Cc: Bin Meng 
> ---
>  drivers/usb/host/xhci-ring.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index d708fc928b..d6c47d579b 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -723,8 +723,8 @@ again:
>   return -ETIMEDOUT;
>   }
>  
> 
> - if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer))
> - != (uintptr_t)last_transfer_trb_addr) {
> + if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
> + (uintptr_t)virt_to_phys(last_transfer_trb_addr)) {
>   available_length -=
>   
> (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));
>   xhci_acknowledge_event(ctrl);

FWIW I also addressed this in my Rpi400/CM4 enablement series:
https://lists.denx.de/pipermail/u-boot/2021-January/437150.html

That said,

Reviewed-by: Nicolas Saenz Julienne 

Regards,
Nicolas




signature.asc
Description: This is a digitally signed message part


[PATCH 2/2] pci: brcmstb: Cleanup controller state before handover

2021-01-14 Thread Nicolas Saenz Julienne
Make sure we handover the PCIe controller in a clean state. Some of the
devices hanging from the PCIe bus might need to be properly reset
through #PERST in order for Linux to be able to initialize them.

This is specially important in order to properly initialize Raspberry Pi
4 B and 400's USB chip.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/pci/pcie_brcmstb.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index bd645d7896..90225f6779 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -577,6 +577,24 @@ static int brcm_pcie_probe(struct udevice *dev)
return 0;
 }
 
+static int brcm_pcie_remove(struct udevice *dev)
+{
+   struct brcm_pcie *pcie = dev_get_priv(dev);
+   void __iomem *base = pcie->base;
+
+   /* Assert fundamental reset */
+   setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
+
+   /* Turn off SerDes */
+   setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
+PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
+
+   /* Shutdown bridge */
+   setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
+
+   return 0;
+}
+
 static int brcm_pcie_of_to_plat(struct udevice *dev)
 {
struct brcm_pcie *pcie = dev_get_priv(dev);
@@ -616,6 +634,8 @@ U_BOOT_DRIVER(pcie_brcm_base) = {
.ops= &brcm_pcie_ops,
.of_match   = brcm_pcie_ids,
.probe  = brcm_pcie_probe,
+   .remove = brcm_pcie_remove,
.of_to_plat = brcm_pcie_of_to_plat,
.priv_auto  = sizeof(struct brcm_pcie),
+   .flags  = DM_FLAG_OS_PREPARE,
 };
-- 
2.29.2



[PATCH 1/2] usb: xhci-pci: Add DM_FLAG_OS_PREPARE flag

2021-01-14 Thread Nicolas Saenz Julienne
The PCIe bus the controller is connected to might need to be removed
prior the handover. Make sure xhci-pci is also removed so as to avoid
unexpected timeouts or hangs.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/usb/host/xhci-pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 2b445f21b5..d626929953 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -61,7 +61,7 @@ U_BOOT_DRIVER(xhci_pci) = {
.ops= &xhci_usb_ops,
.plat_auto  = sizeof(struct usb_plat),
.priv_auto  = sizeof(struct xhci_ctrl),
-   .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+   .flags  = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA,
 };
 
 static struct pci_device_id xhci_pci_supported[] = {
-- 
2.29.2



[PATCH 0/2] Raspberry Pi 4 PCIe handover

2021-01-14 Thread Nicolas Saenz Julienne
It's important for u-boot to properly reset RPi4's PCIe controller in
order for Linux to run the board's USB firmware load rountines.

---

Nicolas Saenz Julienne (2):
  usb: xhci-pci: Add DM_FLAG_OS_PREPARE flag
  pci: brcmstb: Cleanup controller state before handover

 drivers/pci/pcie_brcmstb.c  | 20 
 drivers/usb/host/xhci-pci.c |  2 +-
 2 files changed, 21 insertions(+), 1 deletion(-)

-- 
2.29.2



[PATCH v6 13/13] video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

2021-01-12 Thread Nicolas Saenz Julienne
The 'brcm,bcm2711-hdmi0' compatible string is used on RPi4 instead of
'brcm,bcm2835-hdmi' since the IP core was upgraded (now called VC6
instead of VC4). This has no functional change as far as u-boot driver
is concerned. So simply add the compatible string.

Signed-off-by: Nicolas Saenz Julienne 
Tested-by: Peter Robinson 
---
 drivers/video/bcm2835.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 9326999cd3..c2962932c9 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -52,6 +52,7 @@ static int bcm2835_video_probe(struct udevice *dev)
 
 static const struct udevice_id bcm2835_video_ids[] = {
{ .compatible = "brcm,bcm2835-hdmi" },
+   { .compatible = "brcm,bcm2711-hdmi0" },
{ .compatible = "brcm,bcm2708-fb" },
{ }
 };
-- 
2.29.2



[PATCH v6 12/13] configs: rpi4: Enable DM_DMA across all RPi4 configurations

2021-01-12 Thread Nicolas Saenz Julienne
The DM_DMA option is needed in order to translate physical address into
bus addresses on a per-device basis.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 configs/rpi_4_32b_defconfig | 1 +
 configs/rpi_4_defconfig | 1 +
 configs/rpi_arm64_defconfig | 1 +
 3 files changed, 3 insertions(+)

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 5ddd838fd5..0a5d3ff8cd 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 2590d0a696..b61cdc05f1 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 2639219a1a..4125a1feba 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-- 
2.29.2



[PATCH v6 10/13] xhci: translate virtual addresses into the bus's address space

2021-01-12 Thread Nicolas Saenz Julienne
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.

Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Reviewed-by: Stefan Roese 
Tested-by: Peter Robinson 
---

Changes since v5:
 - Add missing address tranlation

 drivers/usb/host/xhci-mem.c  | 45 +++-
 drivers/usb/host/xhci-ring.c | 13 +++
 drivers/usb/host/xhci.c  |  4 ++--
 include/usb/xhci.h   | 20 +++-
 4 files changed, 53 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b002d6f166..83147d51b5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
 
ctrl->dcbaa->dev_context_ptrs[0] = 0;
 
-   free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+   free(xhci_bus_to_virt(ctrl, 
le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return none
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-   struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment 
*prev,
+  struct xhci_segment *next, bool link_trbs)
 {
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
-   val_64 = virt_to_phys(next->trbs);
+   val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
 
@@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return pointer to the newly created RING
  */
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
num_segs,
+ bool link_trbs)
 {
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, 
bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
 
-   xhci_link_segments(prev, next, link_trbs);
+   xhci_link_segments(ctrl, prev, next, link_trbs);
 
prev = next;
num_segs--;
}
-   xhci_link_segments(prev, ring->first_seg, link_trbs);
+   xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+   uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
-   ctrl->dcbaa->dev_context_ptrs[0] =
-   cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+   val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+   ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
 
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
 
for (i = 0; i < num_sp; i++) {
-   uintptr_t ptr = (uintptr_t)buf + i * page_size;
-   scratchpad->sp_array[i] = cpu_to_le64(ptr);
+   val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+   scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
 
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned 

[PATCH v6 11/13] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2021-01-12 Thread Nicolas Saenz Julienne
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 drivers/mmc/sdhci.c | 12 +++-
 include/mmc.h   |  6 ++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0628934312..62e4f53b8b 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -14,12 +14,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
 
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
@@ -73,6 +73,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, 
struct mmc_data *data)
 static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
  int *is_aligned, int trans_bytes)
 {
+   dma_addr_t dma_addr;
unsigned char ctrl;
void *buf;
 
@@ -103,8 +104,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
struct mmc_data *data,
  mmc_get_dma_dir(data));
 
if (host->flags & USE_SDMA) {
-   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
-   SDHCI_DMA_ADDRESS);
+   dma_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), 
host->start_addr);
+   sdhci_writel(host, dma_addr, SDHCI_DMA_ADDRESS);
}
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
else if (host->flags & (USE_ADMA | USE_ADMA64)) {
@@ -162,8 +163,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
-   sdhci_writel(host, 
phys_to_bus((ulong)start_addr),
-SDHCI_DMA_ADDRESS);
+   start_addr = 
dev_phys_to_bus(mmc_to_dev(host->mmc),
+start_addr);
+   sdhci_writel(host, start_addr, 
SDHCI_DMA_ADDRESS);
}
}
if (timeout-- > 0)
diff --git a/include/mmc.h b/include/mmc.h
index 1d377e0281..c12c7a0b5c 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -736,6 +736,12 @@ struct mmc {
u8 hs400_tuning;
 };
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+#define mmc_to_dev(_mmc)   _mmc->dev
+#else
+#define mmc_to_dev(_mmc)   NULL
+#endif
+
 struct mmc_hwpart_conf {
struct {
uint enh_start; /* in 512-byte sectors */
-- 
2.29.2



[PATCH v6 09/13] dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()

2021-01-12 Thread Nicolas Saenz Julienne
By reusing DT nodes already available in sandbox's test DT introduce a
test to validate dev_phys_to_bus()/dev_bus_to_phys().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 test/dm/Makefile   |  1 +
 test/dm/phys2bus.c | 37 +
 2 files changed, 38 insertions(+)
 create mode 100644 test/dm/phys2bus.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5c52d8b6ea..ac86abaa88 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
 obj-$(CONFIG_UT_DM) += read.o
+obj-$(CONFIG_UT_DM) += phys2bus.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
new file mode 100644
index 00..342f2fa8eb
--- /dev/null
+++ b/test/dm/phys2bus.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_phys_to_bus(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   /* In this case it should be transparent, no dma-ranges in parent bus */
+   ut_asserteq_addr((void*)0xfULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0xf));
+
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_addr((void*)0x100fULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0x100f));
+
+   return 0;
+}
+DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v6 08/13] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()

2021-01-12 Thread Nicolas Saenz Julienne
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.

We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Reviewed-by: Stefan Roese 
Tested-by: Peter Robinson 
---
 include/phys2bus.h | 17 +
 1 file changed, 17 insertions(+)

diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..866b8b51a8 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,21 @@ static inline unsigned long bus_to_phys(unsigned long bus)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM)
+#include 
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t phys)
+{
+   return phys - dev_get_dma_offset(dev);
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, dma_addr_t bus)
+{
+   return bus + dev_get_dma_offset(dev);
+}
+#else
+#define dev_phys_to_bus(_, _addr)  _addr
+#define dev_bus_to_phys(_, _addr)  _addr
+#endif
+
 #endif
-- 
2.29.2



[PATCH v6 07/13] dm: test: Add test case for dev->dma_offset

2021-01-12 Thread Nicolas Saenz Julienne
Add test to validate dev->dma_offset is properly set on devices.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 arch/sandbox/dts/test.dts  |  4 
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 test/dm/core.c | 30 ++
 6 files changed, 38 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index b279903d2a..39efeaa5a7 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -308,6 +308,10 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
};
 
acpi_test1: acpi-test {
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 2066d0a292..d63e22c2bc 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -95,6 +95,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 58d4ef18c3..a96641a6d6 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -108,6 +108,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_flattree_defconfig 
b/configs/sandbox_flattree_defconfig
index efd99a92f1..00a4329537 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -76,6 +76,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index d193b18f47..fbb138805a 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -95,6 +95,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
 CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SYSCON=y
diff --git a/test/dm/core.c b/test/dm/core.c
index 1f5ca570dc..855449aac2 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -1085,3 +1085,33 @@ static int dm_test_all_have_seq(struct unit_test_state 
*uts)
return 0;
 }
 DM_TEST(dm_test_all_have_seq, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_dma_offset(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   /* Make sure the bus's dma-ranges aren't taken into account here */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   /* Device behind a bus with dma-ranges */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(-0x1000ULL, dev->dma_offset);
+
+   /* This one has no dma-ranges */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   node = ofnode_path("/mmio-bus@1/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   return 0;
+}
+DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v6 04/13] dm: Introduce xxx_get_dma_range()

2021-01-12 Thread Nicolas Saenz Julienne
Add the following functions to get a specific device's DMA ranges:
 - dev_get_dma_range()
 - ofnode_get_dma_range()
 - of_get_dma_range()
 - fdt_get_dma_range()
They are specially useful in oder to be able validate a physical address
space range into a bus's and to convert addresses from and to address
spaces.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 common/fdt_support.c   | 73 +++
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 +
 drivers/core/read.c|  6 
 include/dm/of_addr.h   | 17 +
 include/dm/ofnode.h| 16 +
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 
 8 files changed, 234 insertions(+)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 5ae75df3c6..bf855d26c8 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1342,6 +1342,79 @@ u64 fdt_translate_dma_address(const void *blob, int 
node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
 }
 
+int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct of_bus *bus_node;
+   const fdt32_t *ranges;
+   int na, ns, pna, pns;
+   int parent = node;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   while (parent >= 0) {
+   ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /* Once we find 'dma-ranges', then a missing one is an error */
+   if (found_dma_ranges && !ranges) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (ranges)
+   found_dma_ranges = true;
+
+   parent = fdt_parent_offset(blob, parent);
+   }
+
+   if (!ranges || parent < 0) {
+   debug("no dma-ranges found for node %s\n",
+ fdt_get_name(blob, node, NULL));
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /* switch to that node */
+   node = parent;
+   parent = fdt_parent_offset(blob, node);
+   if (parent < 0) {
+   printf("Found dma-ranges in root node, shoudln't happen\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
+   /* Get the address sizes both for the bus and its parent */
+   bus_node = of_match_bus(blob, node);
+   bus_node->count_cells(blob, node, &na, &ns);
+   if (!OF_CHECK_COUNTS(na, ns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, node, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   bus_node = of_match_bus(blob, parent);
+   bus_node->count_cells(blob, parent, &pna, &pns);
+   if (!OF_CHECK_COUNTS(pna, pns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, parent, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   *bus = fdt_read_number(ranges, na);
+   *cpu = fdt_translate_dma_address(blob, node, ranges + na);
+   *size = fdt_read_number(ranges + na + pna, ns);
+out:
+   return ret;
+}
+
 /**
  * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
  * who's reg property matches a physical cpu address
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index ca34d84922..703bc3e3f5 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -325,6 +325,84 @@ u64 of_translate_dma_address(const struct device_node 
*dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
 }
 
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct device_node *parent;
+   struct of_bus *bus_node;
+   int na, ns, pna, pns;
+   const __be32 *ranges;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   dev = of_node_get(dev);
+   while (dev) {
+   ranges = of_get_property(dev, "dma-ranges", &len);
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /* Once we find 'dma-ranges', then a missing one is an error */
+   if (found_dma_

[PATCH v6 06/13] dm: Introduce DMA constraints into the core device model

2021-01-12 Thread Nicolas Saenz Julienne
Calculating the DMA offset between a bus address space and CPU's every
time we call phys_to_bus() and bus_to_phys() isn't ideal performance
wise, as it implies traversing the device tree from the device's node up
to the root. Since this information is static and available before the
device's initialization, parse it before the probe call an provide the
DMA offset in 'struct udevice' for the address translation code to use
it.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---

Changes since v5:
 - Use dev_has_ofnode()

 drivers/core/Kconfig  | 10 ++
 drivers/core/device.c | 41 +
 include/dm/device.h   | 13 +
 3 files changed, 64 insertions(+)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 65a503e76d..0932ee23a7 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -129,6 +129,16 @@ config TPL_DM_INLINE_OFNODE
  This applies to several ofnode functions (see ofnode.h) which are
  seldom used. Inlining them can help reduce code size.
 
+config DM_DMA
+   bool "Support per-device DMA constraints"
+   depends on DM
+   default n
+   help
+ Enable this to extract per-device DMA constraints, only supported on
+ device-tree systems for now. This is needed in order translate
+ addresses on systems where different buses have different views of
+ the physical address space.
+
 config REGMAP
bool "Support register maps"
depends on DM
diff --git a/drivers/core/device.c b/drivers/core/device.c
index aeab3836ed..57424abf99 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -421,6 +421,43 @@ fail:
return ret;
 }
 
+/**
+ * device_get_dma_constraints() - Populate device's DMA constraints
+ *
+ * Gets a device's DMA constraints from firmware. This information is later
+ * used by drivers to translate physcal addresses to the device's bus address
+ * space. For now only device-tree is supported.
+ *
+ * @dev: Pointer to target device
+ * Return: 0 if OK or if no DMA constraints were found, error otherwise
+ */
+static int device_get_dma_constraints(struct udevice *dev)
+{
+   struct udevice *parent = dev->parent;
+   phys_addr_t cpu = 0;
+   dma_addr_t bus = 0;
+   u64 size = 0;
+   int ret;
+
+   if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent))
+   return 0;
+
+   /*
+* We start parsing for dma-ranges from the device's bus node. This is
+* specially important on nested buses.
+*/
+   ret = dev_get_dma_range(parent, &cpu, &bus, &size);
+   /* Don't return an error if no 'dma-ranges' were found */
+   if (ret && ret != -ENOENT) {
+   dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
+   return ret;
+   }
+
+   dev_set_dma_offset(dev, cpu - bus);
+
+   return 0;
+}
+
 int device_probe(struct udevice *dev)
 {
const struct driver *drv;
@@ -474,6 +511,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
 
+   ret = device_get_dma_constraints(dev);
+   if (ret)
+   goto fail;
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/include/dm/device.h b/include/dm/device.h
index f5b4cd6876..9ac96fa28d 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -148,6 +148,8 @@ enum {
  * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
  * add to this list. Memory so-allocated will be freed
  * automatically when the device is removed / unbound
+ * @dma_offset: Offset between the physical address space (CPU's) and the
+ * device's bus address space
  */
 struct udevice {
const struct driver *driver;
@@ -172,6 +174,9 @@ struct udevice {
 #ifdef CONFIG_DEVRES
struct list_head devres_head;
 #endif
+#if CONFIG_IS_ENABLED(DM_DMA)
+   ulong dma_offset;
+#endif
 };
 
 /* Maximum sequence number supported */
@@ -213,6 +218,14 @@ static inline ofnode dev_ofnode(const struct udevice *dev)
 /* Returns non-zero if the device is active (probed and not removed) */
 #define device_active(dev) (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+#define dev_set_dma_offset(_dev, _offset)  _dev->dma_offset = _offset
+#define dev_get_dma_offset(_dev)   _dev->dma_offset
+#else
+#define dev_set_dma_offset(_dev, _offset)
+#define dev_get_dma_offset(_dev)   0
+#endif
+
 static inline int dev_of_offset(const struct udevice *dev)
 {
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-- 
2.29.2



[PATCH v6 05/13] dm: test: Add test case for dev_get_dma_ranges()

2021-01-12 Thread Nicolas Saenz Julienne
Introduce some new nodes in sandbox's test device-tree and dm tests in
order to validate dev_get_dma_range().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Tested-by: Peter Robinson 
---
 arch/sandbox/dts/test.dts | 17 ++
 test/dm/Makefile  |  1 +
 test/dm/read.c| 49 +++
 3 files changed, 67 insertions(+)
 create mode 100644 test/dm/read.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c9b9b7b75e..b279903d2a 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -293,6 +293,23 @@
test5-gpios = <&gpio_a 19>;
};
 
+   mmio-bus@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   dma-ranges = <0x1000 0x 0x0004>;
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
+   };
+
+   mmio-bus@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   };
+
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076ed09..5c52d8b6ea 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_UT_DM) += test-fdt.o
 obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
+obj-$(CONFIG_UT_DM) += read.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/read.c b/test/dm/read.c
new file mode 100644
index 00..7768aa2968
--- /dev/null
+++ b/test/dm/read.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_dma_ranges(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   phys_addr_t cpu;
+   dma_addr_t bus;
+   ofnode node;
+   u64 size;
+
+   /* dma-ranges are on the device's node */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* dma-ranges are on the bus' node */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* No dma-ranges available */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
+
+   return 0;
+}
+DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v6 03/13] pci: pcie-brcmstb: Fix inbound window configurations

2021-01-12 Thread Nicolas Saenz Julienne
So far we've assumed a fixed configuration for inbound windows as we had
a single user for this controller. But the controller's DMA constraints
were improved starting with BCM2711's B1 revision of the SoC, notably
available in CM4 and Pi400. They allow for wider inbound windows. We can
now cover the whole address space, whereas before we where limited to
the lower 3GB.

This information is passed to us through DT's 'dma-ranges' property and
it's specially important for us to honor it since some interactions with
the board's co-processor assume we're doing so (specifically the XHCI
firmware load operation, which is handled by the co-processor after
u-boot has correctly configured the PCIe controller).

Signed-off-by: Nicolas Saenz Julienne 
Tested-by: Peter Robinson 
---
 drivers/pci/pcie_brcmstb.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dd2a4ef629..bd645d7896 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+   struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
-   /*
-* TODO: When support for other SoCs than BCM2711 is added we may
-* need to use the base address and size(s) provided in the dma-ranges
-* property.
-*/
-   rc_bar2_offset = 0;
-   rc_bar2_size = 0xc000;
+
+   pci_get_dma_regions(dev, ®ion, 0);
+   rc_bar2_offset = region.bus_start - region.phys_start;
+   rc_bar2_size = 1ULL << fls64(region.size - 1);
 
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
-- 
2.29.2



[PATCH v6 02/13] rpi: Add identifier for the new CM4

2021-01-12 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.

Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Peter Robinson 
Tested-by: Peter Robinson 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+   [0x14] = {
+   "Compute Module 4",
+   DTB_DIR "bcm2711-rpi-cm4.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v6 00/13] Raspberry Pi 400/Compute Module 4 support

2021-01-12 Thread Nicolas Saenz Julienne
This series could be split into at least two or even three parts, but I
kept it as is for now as it contains all the changes needed in order to
have u-boot working on the new Raspberry Pi 400 and Raspberry Pi Compute
Module 4.

There are core changes, specifically with regard to cpu to bus address
space translations. So far we had relied on hard-coded values but RPi
needs per device translations as it has at least three distinct bus
address spaces with different offsets. So it's a good opportunity to
implement bus translations the right way by parsing DT's dma-ranges.

Here's a more concrete example of what we're dealing with:

 - On a RPi4, SoC version BCM2711C0 with 8GB of memory

[0x0 0x2]   [0x2 0x4]  [0xc000 0x1] 
 [0x 0x1]
 phys/cpu address   PCIe bus address   Legacy peripheral
   emmc2 address
 space   space   address space  
  space

 - On a RPi4, SoC version BCM2711C0 with 4GB of memory

[0x0 0x1]   [0x1 0x2]  [0xc000 0x1] 
 [0x 0x1]
  phys/cpu address  PCIe bus address  Legacy peripheral 
   emmc2 address
space  spaceaddress space   
 space

- On a RPi4, SoC version BCM2711B0 with 8GB of memory (bus can only access the
  lower 3GB of memory because of a SoC routing bug)

[0x0 0x2]   [0x 0xC000]   [0xc000 0x1]
 phys/cpu address  PCIe bus address  Legacy peripheral
space  space   address space

---

Changes since v5:
 - Fix xhci patch
 - Rebase fixes

Changes since v4:
 - Get rid of #ifs all over the place

Changes since v3:
 - Add commit "video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible", it's
   pretty harmless
 - Get rid of non-device based phys2bus call in xhci & mmc
 - Simon's review changes in tests
 - Comment some of the APIs

Changes since v2:
 - Test builds not broken with buildman
 - Add tests to all DM changes
 - Make code conditional with config option
 - Correct OF refcount
 - Add config changes
 - Address small changes as per reviews

Changes since v1:
 - Fix some issues in 'dm: Introduce xxx_get_dma_range()'
 - Fix some typos in commit messages
 - Change DTB file name for RPi400
 - Address Matthias' comments

Nicolas Saenz Julienne (13):
  rpi: Add identifier for the new RPi400
  rpi: Add identifier for the new CM4
  pci: pcie-brcmstb: Fix inbound window configurations
  dm: Introduce xxx_get_dma_range()
  dm: test: Add test case for dev_get_dma_ranges()
  dm: Introduce DMA constraints into the core device model
  dm: test: Add test case for dev->dma_offset
  dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()
  dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()
  xhci: translate virtual addresses into the bus's address space
  mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()
  configs: rpi4: Enable DM_DMA across all RPi4 configurations
  video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

 arch/sandbox/dts/test.dts  | 21 
 board/raspberrypi/rpi/rpi.c| 10 
 common/fdt_support.c   | 73 
 configs/rpi_4_32b_defconfig|  1 +
 configs/rpi_4_defconfig|  1 +
 configs/rpi_arm64_defconfig|  1 +
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 drivers/core/Kconfig   | 10 
 drivers/core/device.c  | 41 
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 
 drivers/core/read.c|  6 +++
 drivers/mmc/sdhci.c| 12 +++--
 drivers/pci/pcie_brcmstb.c | 12 ++---
 drivers/usb/host/xhci-mem.c| 45 +
 drivers/usb/host/xhci-ring.c   | 13 +++--
 drivers/usb/host/xhci.c|  4 +-
 drivers/video/bcm2835.c|  1 +
 include/dm/device.h| 13 +
 include/dm/of_addr.h   | 17 +++
 include/dm/ofnode.h| 16 ++
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 ++
 include/mmc.h  |  6 +++
 include/phys2bus.h | 17 +++
 include/usb/xhci.h | 20 +++-
 test/dm/Makefile   |  2 +
 test/dm/core.c | 30 
 test/dm/phys2bus.c | 37 ++
 test/dm/read.c | 49 +++
 33 files changed, 543 insertions(+), 41 deletions(-)
 create mode 100644 test/dm/phys2bus.c
 create mode 100644 test/dm/read.c

-- 
2.29.2



[PATCH v6 01/13] rpi: Add identifier for the new RPi400

2021-01-12 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Peter Robinson 
Tested-by: Peter Robinson 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+   [0x13] = {
+   "400",
+   DTB_DIR "bcm2711-rpi-400.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



Re: [PATCH v5 00/13] Raspberry Pi 400/Compute Module 4 support

2021-01-12 Thread Nicolas Saenz Julienne
Hi Peter, sorry for the late reply, but I was on holidays.

On Mon, 2021-01-04 at 13:13 +, Peter Robinson wrote:
> On Sun, Jan 3, 2021 at 5:36 PM Nicolas Saenz Julienne
>  wrote:
> > 
> > Hi Peter, thanks for taking the time to test this, I'll send a new hopefully
> > definitive version soon.
> > 
> > On Tue, 2020-12-29 at 10:58 +, Peter Robinson wrote:
> > > Hi Nicolas,
> > > 
> > > With the xhci patch snippet the pci/xhci crash I was seeing is now gone.
> > 
> > Yes that was unfortunate, I tested most revisions of this series on a board 
> > on
> > which I had forgotten contained an older firmware version which failed to
> > update the dma-ranges in DT. Hence missing the XHCI fix.
> 
> One other thing to note, and I'm not sure if it's related to bits that
> U-Boot does or something else, but USB doesn't work in linux on the
> 8Gb model, does on all others inc the rpi-400, when booted on newer
> firmware Oct 15th works, Dec 15th doesn't.

Can you test if this Linux patch fixes thing for you?

>>>>>>>>
diff --git a/drivers/pci/controller/pcie-brcmstb.c 
b/drivers/pci/controller/pcie-brcmstb.c
index d41257f43a8f..e3456b058106 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -857,6 +857,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
 
/* Reset the bridge */
pcie->bridge_sw_init_set(pcie, 1);
+   pcie->perst_set(pcie, 1);
usleep_range(100, 200);
 
/* Take the bridge out of reset */
>>>>>>>>

> > > I am seeing an error which I need to test a bit more around mmc
> > > voltage select which I didn't see previously:
> > > 
> > > Card did not respond to voltage select! : -110
> > 
> > I'll look into this myself, but I doubt it's related to this series in
> > particular.
> 
> I did a bit more testing and I think it's unrelated as well, I'll try
> and dig some more when I get a moment.
> 
> > > I'm going to do some wider testing.
> > > 
> > > Overall this looks good
> > > Series Tested-by: Peter Robinson 
> > 
> > Thanks,
> > Nicolas
> > 





signature.asc
Description: This is a digitally signed message part


Re: [PATCH v5 00/13] Raspberry Pi 400/Compute Module 4 support

2021-01-03 Thread Nicolas Saenz Julienne
Hi Peter, thanks for taking the time to test this, I'll send a new hopefully
definitive version soon.

On Tue, 2020-12-29 at 10:58 +, Peter Robinson wrote:
> Hi Nicolas,
> 
> With the xhci patch snippet the pci/xhci crash I was seeing is now gone.

Yes that was unfortunate, I tested most revisions of this series on a board on
which I had forgotten contained an older firmware version which failed to
update the dma-ranges in DT. Hence missing the XHCI fix.

> I am seeing an error which I need to test a bit more around mmc
> voltage select which I didn't see previously:
> 
> Card did not respond to voltage select! : -110

I'll look into this myself, but I doubt it's related to this series in
particular.

> I'm going to do some wider testing.
> 
> Overall this looks good
> Series Tested-by: Peter Robinson 

Thanks,
Nicolas



Re: [PATCH v5 10/13] xhci: translate virtual addresses into the bus's address space

2020-12-24 Thread Nicolas Saenz Julienne
On Wed, 2020-12-23 at 19:55 +0100, Nicolas Saenz Julienne wrote:
> So far we've been content with passing physical addresses when
> configuring memory addresses into XHCI controllers, but not all
> platforms have buses with transparent mappings. Specifically the
> Raspberry Pi 4 might introduce an offset to memory accesses incoming
> from its PCIe port.
> 
> Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
> limitations, and make sure we don't break non DM users.
> 
> Signed-off-by: Nicolas Saenz Julienne 
> Reviewed-by: Simon Glass 
> Reviewed-by: Stefan Roese 
---

Upon testing this on more RPi4 variants I realized that I'm missing this:

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index eba2b89a88..6b31ad4398 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -726,7 +726,7 @@ again:
return -ETIMEDOUT;
}
 
-   if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer))
+   if ((uintptr_t)(le64_to_cpu(xhci_bus_to_virt(ctrl, 
event->trans_event.buffer)))
!= (uintptr_t)last_transfer_trb_addr) {
available_length -=

(int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));

Will update the patch on v6.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


[PATCH v5 12/13] configs: rpi4: Enable DM_DMA across all RPi4 configurations

2020-12-23 Thread Nicolas Saenz Julienne
The DM_DMA option is needed in order to translate physical address into
bus addresses on a per-device basis.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
---
 configs/rpi_4_32b_defconfig | 1 +
 configs/rpi_4_defconfig | 1 +
 configs/rpi_arm64_defconfig | 1 +
 3 files changed, 3 insertions(+)

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 5ddd838fd5..0a5d3ff8cd 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 2590d0a696..b61cdc05f1 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 2639219a1a..4125a1feba 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-- 
2.29.2



[PATCH v5 13/13] video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

2020-12-23 Thread Nicolas Saenz Julienne
The 'brcm,bcm2711-hdmi0' compatible string is used on RPi4 instead of
'brcm,bcm2835-hdmi' since the IP core was upgraded (now called VC6
instead of VC4). This has no functional change as far as u-boot driver
is concerned. So simply add the compatible string.

Signed-off-by: Nicolas Saenz Julienne 

---
Changes since v3:
 - Add this patch

 drivers/video/bcm2835.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 0888cb0019..51941c4f53 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -52,6 +52,7 @@ static int bcm2835_video_probe(struct udevice *dev)
 
 static const struct udevice_id bcm2835_video_ids[] = {
{ .compatible = "brcm,bcm2835-hdmi" },
+   { .compatible = "brcm,bcm2711-hdmi0" },
{ .compatible = "brcm,bcm2708-fb" },
{ }
 };
-- 
2.29.2



[PATCH v5 11/13] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-23 Thread Nicolas Saenz Julienne
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v4:
 - Introduce mmc->dev access macros to avoid ifdefs
 - No need to create mmc_phys_to_bus()

Changes since v3:
 - Don't call phys_to_bus()/bus_to_phys(), we only support DM

 drivers/mmc/sdhci.c | 12 +++-
 include/mmc.h   |  6 ++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0628934312..62e4f53b8b 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -14,12 +14,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
 
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
@@ -73,6 +73,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, 
struct mmc_data *data)
 static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
  int *is_aligned, int trans_bytes)
 {
+   dma_addr_t dma_addr;
unsigned char ctrl;
void *buf;
 
@@ -103,8 +104,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
struct mmc_data *data,
  mmc_get_dma_dir(data));
 
if (host->flags & USE_SDMA) {
-   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
-   SDHCI_DMA_ADDRESS);
+   dma_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), 
host->start_addr);
+   sdhci_writel(host, dma_addr, SDHCI_DMA_ADDRESS);
}
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
else if (host->flags & (USE_ADMA | USE_ADMA64)) {
@@ -162,8 +163,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
-   sdhci_writel(host, 
phys_to_bus((ulong)start_addr),
-SDHCI_DMA_ADDRESS);
+   start_addr = 
dev_phys_to_bus(mmc_to_dev(host->mmc),
+start_addr);
+   sdhci_writel(host, start_addr, 
SDHCI_DMA_ADDRESS);
}
}
if (timeout-- > 0)
diff --git a/include/mmc.h b/include/mmc.h
index 1d377e0281..c12c7a0b5c 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -736,6 +736,12 @@ struct mmc {
u8 hs400_tuning;
 };
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+#define mmc_to_dev(_mmc)   _mmc->dev
+#else
+#define mmc_to_dev(_mmc)   NULL
+#endif
+
 struct mmc_hwpart_conf {
struct {
uint enh_start; /* in 512-byte sectors */
-- 
2.29.2



[PATCH v5 10/13] xhci: translate virtual addresses into the bus's address space

2020-12-23 Thread Nicolas Saenz Julienne
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.

Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Reviewed-by: Stefan Roese 

---
Changes since v4:
 - Introduce macro to access ctrl->dev
 - No need to make code conditional on DM_DMA with new macros

Changes since v3:
 - Don't call phys_to_bus()/bus_to_phys(), we only support DM

 drivers/usb/host/xhci-mem.c  | 45 +++-
 drivers/usb/host/xhci-ring.c | 11 +
 drivers/usb/host/xhci.c  |  4 ++--
 include/usb/xhci.h   | 20 +++-
 4 files changed, 52 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b002d6f166..83147d51b5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
 
ctrl->dcbaa->dev_context_ptrs[0] = 0;
 
-   free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+   free(xhci_bus_to_virt(ctrl, 
le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return none
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-   struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment 
*prev,
+  struct xhci_segment *next, bool link_trbs)
 {
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
-   val_64 = virt_to_phys(next->trbs);
+   val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
 
@@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return pointer to the newly created RING
  */
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
num_segs,
+ bool link_trbs)
 {
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, 
bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
 
-   xhci_link_segments(prev, next, link_trbs);
+   xhci_link_segments(ctrl, prev, next, link_trbs);
 
prev = next;
num_segs--;
}
-   xhci_link_segments(prev, ring->first_seg, link_trbs);
+   xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+   uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
-   ctrl->dcbaa->dev_context_ptrs[0] =
-   cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+   val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+   ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
 
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
 
for (i = 0; i < num_sp; i++) {
-   uintptr_t ptr = (uintptr_t)buf + i * page_size;
-   scratchpad->sp_array[i] = cpu_to_le64(ptr);
+   val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+   scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
 
xhci_flush

[PATCH v5 09/13] dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()

2020-12-23 Thread Nicolas Saenz Julienne
By reusing DT nodes already available in sandbox's test DT introduce a
test to validate dev_phys_to_bus()/dev_bus_to_phys().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())
 - Use ut_assert_addr()

 test/dm/Makefile   |  1 +
 test/dm/phys2bus.c | 37 +
 2 files changed, 38 insertions(+)
 create mode 100644 test/dm/phys2bus.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5c52d8b6ea..ac86abaa88 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
 obj-$(CONFIG_UT_DM) += read.o
+obj-$(CONFIG_UT_DM) += phys2bus.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
new file mode 100644
index 00..342f2fa8eb
--- /dev/null
+++ b/test/dm/phys2bus.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_phys_to_bus(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   /* In this case it should be transparent, no dma-ranges in parent bus */
+   ut_asserteq_addr((void*)0xfULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0xf));
+
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_addr((void*)0x100fULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0x100f));
+
+   return 0;
+}
+DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v5 07/13] dm: test: Add test case for dev->dma_offset

2020-12-23 Thread Nicolas Saenz Julienne
Add test to validate dev->dma_offset is properly set on devices.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())

 arch/sandbox/dts/test.dts  |  4 
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 test/dm/core.c | 30 ++
 6 files changed, 38 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3a3b51f83b..78f0100282 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -307,6 +307,10 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
};
 
acpi_test1: acpi-test {
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 5fbbfd7236..2c189a8a00 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -94,6 +94,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f1ec701a9f..ac97c16cef 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -108,6 +108,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_flattree_defconfig 
b/configs/sandbox_flattree_defconfig
index edca7f1808..f5923bf713 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -75,6 +75,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 479f0226e3..0a4815770c 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -94,6 +94,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
 CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SYSCON=y
diff --git a/test/dm/core.c b/test/dm/core.c
index 6f380a574c..8ca49d09ee 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -1066,3 +1066,33 @@ static int dm_test_inactive_child(struct unit_test_state 
*uts)
return 0;
 }
 DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_dma_offset(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   /* Make sure the bus's dma-ranges aren't taken into account here */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   /* Device behind a bus with dma-ranges */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(-0x1000ULL, dev->dma_offset);
+
+   /* This one has no dma-ranges */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   node = ofnode_path("/mmio-bus@1/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   return 0;
+}
+DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v5 08/13] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()

2020-12-23 Thread Nicolas Saenz Julienne
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.

We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
Reviewed-by: Stefan Roese 

---
Changes since v4:
 - Introduce macros for !DM case to make API usage cleaner

Changes since v2:
 - Use CONFIG_DM_DMA

 include/phys2bus.h | 17 +
 1 file changed, 17 insertions(+)

diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..866b8b51a8 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,21 @@ static inline unsigned long bus_to_phys(unsigned long bus)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM)
+#include 
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t phys)
+{
+   return phys - dev_get_dma_offset(dev);
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, dma_addr_t bus)
+{
+   return bus + dev_get_dma_offset(dev);
+}
+#else
+#define dev_phys_to_bus(_, _addr)  _addr
+#define dev_bus_to_phys(_, _addr)  _addr
+#endif
+
 #endif
-- 
2.29.2



[PATCH v5 04/13] dm: Introduce xxx_get_dma_range()

2020-12-23 Thread Nicolas Saenz Julienne
Add the following functions to get a specific device's DMA ranges:
 - dev_get_dma_range()
 - ofnode_get_dma_range()
 - of_get_dma_range()
 - fdt_get_dma_range()
They are specially useful in oder to be able validate a physical address
space range into a bus's and to convert addresses from and to address
spaces.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v2:
 - Return ENOENT instead of ENODEV
 - Refcount of nodes

Changes since v1:
 - Fix wrong arguments in of_get_dma_range()'s call to 
of_translate_dma_address()
 - Fix build in SPL/TPL and no LIBFDT supprt
 - Add missing declaration in 'core/read.c'
 - Address Matthias' comments

 common/fdt_support.c   | 73 +++
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 +
 drivers/core/read.c|  6 
 include/dm/of_addr.h   | 17 +
 include/dm/ofnode.h| 16 +
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 
 8 files changed, 234 insertions(+)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 5ae75df3c6..bf855d26c8 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1342,6 +1342,79 @@ u64 fdt_translate_dma_address(const void *blob, int 
node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
 }
 
+int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct of_bus *bus_node;
+   const fdt32_t *ranges;
+   int na, ns, pna, pns;
+   int parent = node;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   while (parent >= 0) {
+   ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /* Once we find 'dma-ranges', then a missing one is an error */
+   if (found_dma_ranges && !ranges) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (ranges)
+   found_dma_ranges = true;
+
+   parent = fdt_parent_offset(blob, parent);
+   }
+
+   if (!ranges || parent < 0) {
+   debug("no dma-ranges found for node %s\n",
+ fdt_get_name(blob, node, NULL));
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /* switch to that node */
+   node = parent;
+   parent = fdt_parent_offset(blob, node);
+   if (parent < 0) {
+   printf("Found dma-ranges in root node, shoudln't happen\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
+   /* Get the address sizes both for the bus and its parent */
+   bus_node = of_match_bus(blob, node);
+   bus_node->count_cells(blob, node, &na, &ns);
+   if (!OF_CHECK_COUNTS(na, ns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, node, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   bus_node = of_match_bus(blob, parent);
+   bus_node->count_cells(blob, parent, &pna, &pns);
+   if (!OF_CHECK_COUNTS(pna, pns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, parent, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   *bus = fdt_read_number(ranges, na);
+   *cpu = fdt_translate_dma_address(blob, node, ranges + na);
+   *size = fdt_read_number(ranges + na + pna, ns);
+out:
+   return ret;
+}
+
 /**
  * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
  * who's reg property matches a physical cpu address
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index ca34d84922..703bc3e3f5 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -325,6 +325,84 @@ u64 of_translate_dma_address(const struct device_node 
*dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
 }
 
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct device_node *parent;
+   struct of_bus *bus_node;
+   int na, ns, pna, pns;
+   const __be32 *ranges;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   dev = of_node_get(dev);
+   while (dev) {
+   ranges = of_get_property(dev, "dma-ranges", &l

[PATCH v5 06/13] dm: Introduce DMA constraints into the core device model

2020-12-23 Thread Nicolas Saenz Julienne
Calculating the DMA offset between a bus address space and CPU's every
time we call phys_to_bus() and bus_to_phys() isn't ideal performance
wise, as it implies traversing the device tree from the device's node up
to the root. Since this information is static and available before the
device's initialization, parse it before the probe call an provide the
DMA offset in 'struct udevice' for the address translation code to use
it.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v4:
 - Use macros to access dma_offset

Changes since v3:
 - Comment functions and struct variables
 - Correct typos

Changes since v2:
 - Return/Fail on error
 - Add config option
 - use ulong instead for u64 for dev->dma_offset

Changes since v1:
 - Update commit message so as to explain better the reasoning behind
   this

 drivers/core/Kconfig  | 10 ++
 drivers/core/device.c | 41 +
 include/dm/device.h   | 13 +
 3 files changed, 64 insertions(+)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index ffae6f9795..295cf2dd00 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -113,6 +113,16 @@ config SPL_DM_SEQ_ALIAS
  numbered devices (e.g. serial0 = &serial0). This feature can be
  disabled if it is not required, to save code space in SPL.
 
+config DM_DMA
+   bool "Support per-device DMA constraints"
+   depends on DM
+   default n
+   help
+ Enable this to extract per-device DMA constraints, only supported on
+ device-tree systems for now. This is needed in order translate
+ addresses on systems where different buses have different views of
+ the physical address space.
+
 config REGMAP
bool "Support register maps"
depends on DM
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 4b3dcb3b37..047032a1dd 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -421,6 +421,43 @@ fail:
return ret;
 }
 
+/**
+ * device_get_dma_constraints() - Populate device's DMA constraints
+ *
+ * Gets a device's DMA constraints from firmware. This information is later
+ * used by drivers to translate physcal addresses to the device's bus address
+ * space. For now only device-tree is supported.
+ *
+ * @dev: Pointer to target device
+ * Return: 0 if OK or if no DMA constraints were found, error otherwise
+ */
+static int device_get_dma_constraints(struct udevice *dev)
+{
+   struct udevice *parent = dev->parent;
+   phys_addr_t cpu = 0;
+   dma_addr_t bus = 0;
+   u64 size = 0;
+   int ret;
+
+   if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_of_valid(parent))
+   return 0;
+
+   /*
+* We start parsing for dma-ranges from the device's bus node. This is
+* specially important on nested buses.
+*/
+   ret = dev_get_dma_range(parent, &cpu, &bus, &size);
+   /* Don't return an error if no 'dma-ranges' were found */
+   if (ret && ret != -ENOENT) {
+   dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
+   return ret;
+   }
+
+   dev_set_dma_offset(dev, cpu - bus);
+
+   return 0;
+}
+
 int device_probe(struct udevice *dev)
 {
const struct driver *drv;
@@ -482,6 +519,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
 
+   ret = device_get_dma_constraints(dev);
+   if (ret)
+   goto fail;
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bef484247..b27889af01 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -138,6 +138,8 @@ enum {
  * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
  * add to this list. Memory so-allocated will be freed
  * automatically when the device is removed / unbound
+ * @dma_offset: Offset between the physical address space (CPU's) and the
+ * device's bus address space
  */
 struct udevice {
const struct driver *driver;
@@ -161,6 +163,9 @@ struct udevice {
 #ifdef CONFIG_DEVRES
struct list_head devres_head;
 #endif
+#if CONFIG_IS_ENABLED(DM_DMA)
+   ulong dma_offset;
+#endif
 };
 
 /* Maximum sequence number supported */
@@ -172,6 +177,14 @@ struct udevice {
 /* Returns non-zero if the device is active (probed and not removed) */
 #define device_active(dev) ((dev)->flags & DM_FLAG_ACTIVATED)
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+#define dev_set_dma_offset(_dev, _offset)  _dev->dma_offset = _offset
+#define dev_get_dma_offset(_dev)   _dev->dma_offset
+#else
+#define dev_set_dma_offset(_dev, _offset)
+#define dev_get_dma_offset(_dev)   0
+#endif
+
 static inline int dev_of_offset(const struct udevice *dev)
 {
return ofnode_to_offset(dev->node);
-- 
2.29.2



[PATCH v5 05/13] dm: test: Add test case for dev_get_dma_ranges()

2020-12-23 Thread Nicolas Saenz Julienne
Introduce some new nodes in sandbox's test device-tree and dm tests in
order to validate dev_get_dma_range().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())

 arch/sandbox/dts/test.dts | 17 ++
 test/dm/Makefile  |  1 +
 test/dm/read.c| 49 +++
 3 files changed, 67 insertions(+)
 create mode 100644 test/dm/read.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f3b766271d..3a3b51f83b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -292,6 +292,23 @@
test5-gpios = <&gpio_a 19>;
};
 
+   mmio-bus@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   dma-ranges = <0x1000 0x 0x0004>;
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
+   };
+
+   mmio-bus@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   };
+
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076ed09..5c52d8b6ea 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_UT_DM) += test-fdt.o
 obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
+obj-$(CONFIG_UT_DM) += read.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/read.c b/test/dm/read.c
new file mode 100644
index 00..7768aa2968
--- /dev/null
+++ b/test/dm/read.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_dma_ranges(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   phys_addr_t cpu;
+   dma_addr_t bus;
+   ofnode node;
+   u64 size;
+
+   /* dma-ranges are on the device's node */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* dma-ranges are on the bus' node */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* No dma-ranges available */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
+
+   return 0;
+}
+DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v5 03/13] pci: pcie-brcmstb: Fix inbound window configurations

2020-12-23 Thread Nicolas Saenz Julienne
So far we've assumed a fixed configuration for inbound windows as we had
a single user for this controller. But the controller's DMA constraints
were improved starting with BCM2711's B1 revision of the SoC, notably
available in CM4 and Pi400. They allow for wider inbound windows. We can
now cover the whole address space, whereas before we where limited to
the lower 3GB.

This information is passed to us through DT's 'dma-ranges' property and
it's specially important for us to honor it since some interactions with
the board's co-processor assume we're doing so (specifically the XHCI
firmware load operation, which is handled by the co-processor after
u-boot has correctly configured the PCIe controller).

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/pci/pcie_brcmstb.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dade79e9c8..f6e8ad0d0a 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+   struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
-   /*
-* TODO: When support for other SoCs than BCM2711 is added we may
-* need to use the base address and size(s) provided in the dma-ranges
-* property.
-*/
-   rc_bar2_offset = 0;
-   rc_bar2_size = 0xc000;
+
+   pci_get_dma_regions(dev, ®ion, 0);
+   rc_bar2_offset = region.bus_start - region.phys_start;
+   rc_bar2_size = 1ULL << fls64(region.size - 1);
 
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
-- 
2.29.2



[PATCH v5 02/13] rpi: Add identifier for the new CM4

2020-12-23 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.

Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.

Signed-off-by: Nicolas Saenz Julienne 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+   [0x14] = {
+   "Compute Module 4",
+   DTB_DIR "bcm2711-rpi-cm4.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v5 00/13] Raspberry Pi 400/Compute Module 4 support

2020-12-23 Thread Nicolas Saenz Julienne
This series could be split into at least two or even three parts, but I
kept it as is for now as it contains all the changes needed in order to
have u-boot working on the new Raspberry Pi 400 and Raspberry Pi Compute
Module 4.

There are core changes, specifically with regard to cpu to bus address
space translations. So far we had relied on hard-coded values but RPi
needs per device translations as it has at least three distinct bus
address spaces with different offsets. So it's a good opportunity to
implement bus translations the right way by parsing DT's dma-ranges.

Here's a more concrete example of what we're dealing with:

 - On a RPi4, SoC version BCM2711C0 with 8GB of memory

[0x0 0x2]   [0x2 0x4]  [0xc000 0x1] 
 [0x 0x1]
 phys/cpu address   PCIe bus address   Legacy peripheral
   emmc2 address
 space   space   address space  
  space

 - On a RPi4, SoC version BCM2711C0 with 4GB of memory

[0x0 0x1]   [0x1 0x2]  [0xc000 0x1] 
 [0x 0x1]
  phys/cpu address  PCIe bus address  Legacy peripheral 
   emmc2 address
space  spaceaddress space   
 space

- On a RPi4, SoC version BCM2711B0 with 8GB of memory (bus can only access the
  lower 3GB of memory because of a SoC routing bug)

[0x0 0x2]   [0x 0xC000]   [0xc000 0x1]
 phys/cpu address  PCIe bus address  Legacy peripheral
space  space   address space

---

Changes since v4:
 - Get rid of #ifs all over the place

Changes since v3:
 - Add commit "video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible", it's
   pretty harmless
 - Get rid of non-device based phys2bus call in xhci & mmc
 - Simon's review changes in tests
 - Comment some of the APIs

Changes since v2:
 - Test builds not broken with buildman
 - Add tests to all DM changes
 - Make code conditional with config option
 - Correct OF refcount
 - Add config changes
 - Address small changes as per reviews

Changes since v1:
 - Fix some issues in 'dm: Introduce xxx_get_dma_range()'
 - Fix some typos in commit messages
 - Change DTB file name for RPi400
 - Address Matthias' comments

Nicolas Saenz Julienne (13):
  rpi: Add identifier for the new RPi400
  rpi: Add identifier for the new CM4
  pci: pcie-brcmstb: Fix inbound window configurations
  dm: Introduce xxx_get_dma_range()
  dm: test: Add test case for dev_get_dma_ranges()
  dm: Introduce DMA constraints into the core device model
  dm: test: Add test case for dev->dma_offset
  dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()
  dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()
  xhci: translate virtual addresses into the bus's address space
  mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()
  configs: rpi4: Enable DM_DMA across all RPi4 configurations
  video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

 arch/sandbox/dts/test.dts  | 21 
 board/raspberrypi/rpi/rpi.c| 10 
 common/fdt_support.c   | 73 
 configs/rpi_4_32b_defconfig|  1 +
 configs/rpi_4_defconfig|  1 +
 configs/rpi_arm64_defconfig|  1 +
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 drivers/core/Kconfig   | 10 
 drivers/core/device.c  | 41 
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 
 drivers/core/read.c|  6 +++
 drivers/mmc/sdhci.c| 12 +++--
 drivers/pci/pcie_brcmstb.c | 12 ++---
 drivers/usb/host/xhci-mem.c| 45 +
 drivers/usb/host/xhci-ring.c   | 11 +++--
 drivers/usb/host/xhci.c|  4 +-
 drivers/video/bcm2835.c|  1 +
 include/dm/device.h| 13 +
 include/dm/of_addr.h   | 17 +++
 include/dm/ofnode.h| 16 ++
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 ++
 include/mmc.h  |  6 +++
 include/phys2bus.h | 17 +++
 include/usb/xhci.h | 20 +++-
 test/dm/Makefile   |  2 +
 test/dm/core.c | 30 
 test/dm/phys2bus.c | 37 ++
 test/dm/read.c | 49 +++
 33 files changed, 542 insertions(+), 40 deletions(-)
 create mode 100644 test/dm/phys2bus.c
 create mode 100644 test/dm/read.c

-- 
2.29.2



[PATCH v5 01/13] rpi: Add identifier for the new RPi400

2020-12-23 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.

Signed-off-by: Nicolas Saenz Julienne 

---

Changes since v1:
 - The RPi Foundation introduced a RPi400 specific device tree, so use
   that file name instead of the fallback (RPi4b).

 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+   [0x13] = {
+   "400",
+   DTB_DIR "bcm2711-rpi-400.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v4 13/13] video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

2020-12-22 Thread Nicolas Saenz Julienne
The 'brcm,bcm2711-hdmi0' compatible string is used on RPi4 instead of
'brcm,bcm2835-hdmi' since the IP core was upgraded (now called VC6
instead of VC4). This has no functional change as far as u-boot driver
is concerned. So simply add the compatible string.

Signed-off-by: Nicolas Saenz Julienne 

---
Changes since v3:
 - Add this patch

 drivers/video/bcm2835.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 0888cb0019..51941c4f53 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -52,6 +52,7 @@ static int bcm2835_video_probe(struct udevice *dev)
 
 static const struct udevice_id bcm2835_video_ids[] = {
{ .compatible = "brcm,bcm2835-hdmi" },
+   { .compatible = "brcm,bcm2711-hdmi0" },
{ .compatible = "brcm,bcm2708-fb" },
{ }
 };
-- 
2.29.2



[PATCH v4 12/13] configs: rpi4: Enable DM_DMA across all RPi4 configurations

2020-12-22 Thread Nicolas Saenz Julienne
The DM_DMA option is needed in order to translate physical address into
bus addresses on a per-device basis.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 
---
 configs/rpi_4_32b_defconfig | 1 +
 configs/rpi_4_defconfig | 1 +
 configs/rpi_arm64_defconfig | 1 +
 3 files changed, 3 insertions(+)

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 5ddd838fd5..0a5d3ff8cd 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 2590d0a696..b61cdc05f1 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 2639219a1a..4125a1feba 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-- 
2.29.2



[PATCH v4 10/13] xhci: translate virtual addresses into the bus's address space

2020-12-22 Thread Nicolas Saenz Julienne
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.

Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Don't call phys_to_bus()/bus_to_phys(), we only support DM

 drivers/usb/host/xhci-mem.c  | 45 +++-
 drivers/usb/host/xhci-ring.c | 11 +
 drivers/usb/host/xhci.c  |  4 ++--
 include/usb/xhci.h   | 22 +-
 4 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b002d6f166..83147d51b5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
 
ctrl->dcbaa->dev_context_ptrs[0] = 0;
 
-   free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+   free(xhci_bus_to_virt(ctrl, 
le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return none
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-   struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment 
*prev,
+  struct xhci_segment *next, bool link_trbs)
 {
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
-   val_64 = virt_to_phys(next->trbs);
+   val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
 
@@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return pointer to the newly created RING
  */
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
num_segs,
+ bool link_trbs)
 {
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, 
bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
 
-   xhci_link_segments(prev, next, link_trbs);
+   xhci_link_segments(ctrl, prev, next, link_trbs);
 
prev = next;
num_segs--;
}
-   xhci_link_segments(prev, ring->first_seg, link_trbs);
+   xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+   uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
-   ctrl->dcbaa->dev_context_ptrs[0] =
-   cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+   val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+   ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
 
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
 
for (i = 0; i < num_sp; i++) {
-   uintptr_t ptr = (uintptr_t)buf + i * page_size;
-   scratchpad->sp_array[i] = cpu_to_le64(ptr);
+   val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+   scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
 
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned 
int slot_id)

[PATCH v4 11/13] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-22 Thread Nicolas Saenz Julienne
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3
 - Don't call phys_to_bus()/bus_to_phys(), we only support DM

 drivers/mmc/sdhci.c |  7 ---
 include/mmc.h   | 10 ++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0628934312..2086d7cdb1 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
@@ -103,7 +102,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
struct mmc_data *data,
  mmc_get_dma_dir(data));
 
if (host->flags & USE_SDMA) {
-   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)host->start_addr),
SDHCI_DMA_ADDRESS);
}
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
@@ -162,7 +162,8 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
-   sdhci_writel(host, 
phys_to_bus((ulong)start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)start_addr),
 SDHCI_DMA_ADDRESS);
}
}
diff --git a/include/mmc.h b/include/mmc.h
index 1d377e0281..393c08d5a9 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct bd_info;
 
@@ -977,4 +978,13 @@ static inline enum dma_data_direction 
mmc_get_dma_dir(struct mmc_data *data)
return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 }
 
+static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t addr)
+{
+#if CONFIG_IS_ENABLED(DM_DMA)
+   return dev_phys_to_bus(mmc->dev, addr);
+#else
+   return (dma_addr_t)addr;
+#endif
+}
+
 #endif /* _MMC_H_ */
-- 
2.29.2



[PATCH v4 09/13] dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()

2020-12-22 Thread Nicolas Saenz Julienne
By reusing DT nodes already available in sandbox's test DT introduce a
test to validate dev_phys_to_bus()/dev_bus_to_phys().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())
 - Use ut_assert_addr()

 test/dm/Makefile   |  1 +
 test/dm/phys2bus.c | 37 +
 2 files changed, 38 insertions(+)
 create mode 100644 test/dm/phys2bus.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5c52d8b6ea..ac86abaa88 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
 obj-$(CONFIG_UT_DM) += read.o
+obj-$(CONFIG_UT_DM) += phys2bus.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
new file mode 100644
index 00..342f2fa8eb
--- /dev/null
+++ b/test/dm/phys2bus.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_phys_to_bus(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   /* In this case it should be transparent, no dma-ranges in parent bus */
+   ut_asserteq_addr((void*)0xfULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0xf));
+
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_addr((void*)0x100fULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_addr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0x100f));
+
+   return 0;
+}
+DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v4 07/13] dm: test: Add test case for dev->dma_offset

2020-12-22 Thread Nicolas Saenz Julienne
Add test to validate dev->dma_offset is properly set on devices.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())

 arch/sandbox/dts/test.dts  |  4 
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 test/dm/core.c | 30 ++
 6 files changed, 38 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3a3b51f83b..78f0100282 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -307,6 +307,10 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
};
 
acpi_test1: acpi-test {
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 5fbbfd7236..2c189a8a00 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -94,6 +94,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f1ec701a9f..ac97c16cef 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -108,6 +108,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_flattree_defconfig 
b/configs/sandbox_flattree_defconfig
index edca7f1808..f5923bf713 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -75,6 +75,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 479f0226e3..0a4815770c 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -94,6 +94,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
 CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SYSCON=y
diff --git a/test/dm/core.c b/test/dm/core.c
index 6f380a574c..8ca49d09ee 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -1066,3 +1066,33 @@ static int dm_test_inactive_child(struct unit_test_state 
*uts)
return 0;
 }
 DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_dma_offset(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   /* Make sure the bus's dma-ranges aren't taken into account here */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   /* Device behind a bus with dma-ranges */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(-0x1000ULL, dev->dma_offset);
+
+   /* This one has no dma-ranges */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   node = ofnode_path("/mmio-bus@1/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   return 0;
+}
+DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v4 08/13] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()

2020-12-22 Thread Nicolas Saenz Julienne
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.

We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v2:
 - Use CONFIG_DM_DMA

 include/phys2bus.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..516d630aea 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,20 @@ static inline unsigned long bus_to_phys(unsigned long bus)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+#include 
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev,
+phys_addr_t phys)
+{
+   return phys - dev->dma_offset;
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev,
+ dma_addr_t bus)
+{
+   return bus + dev->dma_offset;
+}
+#endif
+
 #endif
-- 
2.29.2



[PATCH v4 04/13] dm: Introduce xxx_get_dma_range()

2020-12-22 Thread Nicolas Saenz Julienne
Add the following functions to get a specific device's DMA ranges:
 - dev_get_dma_range()
 - ofnode_get_dma_range()
 - of_get_dma_range()
 - fdt_get_dma_range()
They are specially useful in oder to be able validate a physical address
space range into a bus's and to convert addresses from and to address
spaces.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v2:
 - Return ENOENT instead of ENODEV
 - Refcount of nodes

Changes since v1:
 - Fix wrong arguments in of_get_dma_range()'s call to 
of_translate_dma_address()
 - Fix build in SPL/TPL and no LIBFDT supprt
 - Add missing declaration in 'core/read.c'
 - Address Matthias' comments

 common/fdt_support.c   | 73 +++
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 +
 drivers/core/read.c|  6 
 include/dm/of_addr.h   | 17 +
 include/dm/ofnode.h| 16 +
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 
 8 files changed, 234 insertions(+)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 5ae75df3c6..bf855d26c8 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1342,6 +1342,79 @@ u64 fdt_translate_dma_address(const void *blob, int 
node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
 }
 
+int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct of_bus *bus_node;
+   const fdt32_t *ranges;
+   int na, ns, pna, pns;
+   int parent = node;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   while (parent >= 0) {
+   ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /* Once we find 'dma-ranges', then a missing one is an error */
+   if (found_dma_ranges && !ranges) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (ranges)
+   found_dma_ranges = true;
+
+   parent = fdt_parent_offset(blob, parent);
+   }
+
+   if (!ranges || parent < 0) {
+   debug("no dma-ranges found for node %s\n",
+ fdt_get_name(blob, node, NULL));
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /* switch to that node */
+   node = parent;
+   parent = fdt_parent_offset(blob, node);
+   if (parent < 0) {
+   printf("Found dma-ranges in root node, shoudln't happen\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
+   /* Get the address sizes both for the bus and its parent */
+   bus_node = of_match_bus(blob, node);
+   bus_node->count_cells(blob, node, &na, &ns);
+   if (!OF_CHECK_COUNTS(na, ns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, node, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   bus_node = of_match_bus(blob, parent);
+   bus_node->count_cells(blob, parent, &pna, &pns);
+   if (!OF_CHECK_COUNTS(pna, pns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, parent, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   *bus = fdt_read_number(ranges, na);
+   *cpu = fdt_translate_dma_address(blob, node, ranges + na);
+   *size = fdt_read_number(ranges + na + pna, ns);
+out:
+   return ret;
+}
+
 /**
  * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
  * who's reg property matches a physical cpu address
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index ca34d84922..703bc3e3f5 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -325,6 +325,84 @@ u64 of_translate_dma_address(const struct device_node 
*dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
 }
 
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct device_node *parent;
+   struct of_bus *bus_node;
+   int na, ns, pna, pns;
+   const __be32 *ranges;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   dev = of_node_get(dev);
+   while (dev) {
+   ranges = of_get_property(dev, "dma-ranges", &l

[PATCH v4 03/13] pci: pcie-brcmstb: Fix inbound window configurations

2020-12-22 Thread Nicolas Saenz Julienne
So far we've assumed a fixed configuration for inbound windows as we had
a single user for this controller. But the controller's DMA constraints
were improved starting with BCM2711's B1 revision of the SoC, notably
available in CM4 and Pi400. They allow for wider inbound windows. We can
now cover the whole address space, whereas before we where limited to
the lower 3GB.

This information is passed to us through DT's 'dma-ranges' property and
it's specially important for us to honor it since some interactions with
the board's co-processor assume we're doing so (specifically the XHCI
firmware load operation, which is handled by the co-processor after
u-boot has correctly configured the PCIe controller).

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/pci/pcie_brcmstb.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dade79e9c8..f6e8ad0d0a 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+   struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
-   /*
-* TODO: When support for other SoCs than BCM2711 is added we may
-* need to use the base address and size(s) provided in the dma-ranges
-* property.
-*/
-   rc_bar2_offset = 0;
-   rc_bar2_size = 0xc000;
+
+   pci_get_dma_regions(dev, ®ion, 0);
+   rc_bar2_offset = region.bus_start - region.phys_start;
+   rc_bar2_size = 1ULL << fls64(region.size - 1);
 
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
-- 
2.29.2



[PATCH v4 05/13] dm: test: Add test case for dev_get_dma_ranges()

2020-12-22 Thread Nicolas Saenz Julienne
Introduce some new nodes in sandbox's test device-tree and dm tests in
order to validate dev_get_dma_range().

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v3:
 - Use ut_assertok() instead of ut_assert(!func())

 arch/sandbox/dts/test.dts | 17 ++
 test/dm/Makefile  |  1 +
 test/dm/read.c| 49 +++
 3 files changed, 67 insertions(+)
 create mode 100644 test/dm/read.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f3b766271d..3a3b51f83b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -292,6 +292,23 @@
test5-gpios = <&gpio_a 19>;
};
 
+   mmio-bus@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   dma-ranges = <0x1000 0x 0x0004>;
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
+   };
+
+   mmio-bus@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   };
+
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076ed09..5c52d8b6ea 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_UT_DM) += test-fdt.o
 obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
+obj-$(CONFIG_UT_DM) += read.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/read.c b/test/dm/read.c
new file mode 100644
index 00..7768aa2968
--- /dev/null
+++ b/test/dm/read.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_dma_ranges(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   phys_addr_t cpu;
+   dma_addr_t bus;
+   ofnode node;
+   u64 size;
+
+   /* dma-ranges are on the device's node */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* dma-ranges are on the bus' node */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* No dma-ranges available */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
+
+   return 0;
+}
+DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v4 02/13] rpi: Add identifier for the new CM4

2020-12-22 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.

Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.

Signed-off-by: Nicolas Saenz Julienne 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+   [0x14] = {
+   "Compute Module 4",
+   DTB_DIR "bcm2711-rpi-cm4.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v4 06/13] dm: Introduce DMA constraints into the core device model

2020-12-22 Thread Nicolas Saenz Julienne
Calculating the DMA offset between a bus address space and CPU's every
time we call phys_to_bus() and bus_to_phys() isn't ideal performance
wise, as it implies traversing the device tree from the device's node up
to the root. Since this information is static and available before the
device's initialization, parse it before the probe call an provide the
DMA offset in 'struct udevice' for the address translation code to use
it.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v2:
 - Comment functions and struct variables
 - Correct typos

Changes since v2:
 - Return/Fail on error
 - Add config option
 - use ulong instead for u64 for dev->dma_offset

Changes since v1:
 - Update commit message so as to explain better the reasoning behind
   this

 drivers/core/Kconfig  | 10 ++
 drivers/core/device.c | 45 +++
 include/dm/device.h   |  5 +
 3 files changed, 60 insertions(+)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index ffae6f9795..295cf2dd00 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -113,6 +113,16 @@ config SPL_DM_SEQ_ALIAS
  numbered devices (e.g. serial0 = &serial0). This feature can be
  disabled if it is not required, to save code space in SPL.
 
+config DM_DMA
+   bool "Support per-device DMA constraints"
+   depends on DM
+   default n
+   help
+ Enable this to extract per-device DMA constraints, only supported on
+ device-tree systems for now. This is needed in order translate
+ addresses on systems where different buses have different views of
+ the physical address space.
+
 config REGMAP
bool "Support register maps"
depends on DM
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 4b3dcb3b37..e88a60 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -421,6 +421,47 @@ fail:
return ret;
 }
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+/**
+ * device_get_dma_constraints() - Populate device's DMA constraints
+ *
+ * Gets a device's DMA constraints from firmware. This information is later
+ * used by drivers to translate physcal addresses to the device's bus address
+ * space. For now only device-tree is supported.
+ *
+ * @dev: Pointer to target device
+ * Return: 0 if OK or if no DMA constraints were found, error otherwise
+ */
+static int device_get_dma_constraints(struct udevice *dev)
+{
+   struct udevice *parent = dev->parent;
+   phys_addr_t cpu = 0;
+   dma_addr_t bus = 0;
+   u64 size = 0;
+   int ret;
+
+   if (!parent || !dev_of_valid(parent))
+   return 0;
+
+   /*
+* We start parsing for dma-ranges from the device's bus node. This is
+* specially important on nested buses.
+*/
+   ret = dev_get_dma_range(parent, &cpu, &bus, &size);
+   /* Don't return an error if no 'dma-ranges' were found */
+   if (ret && ret != -ENOENT) {
+   dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
+   return ret;
+   }
+
+   dev->dma_offset = cpu - bus;
+
+   return 0;
+}
+#else
+static int device_get_dma_constraints(struct udevice *dev) { return 0; }
+#endif
+
 int device_probe(struct udevice *dev)
 {
const struct driver *drv;
@@ -482,6 +523,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
 
+   ret = device_get_dma_constraints(dev);
+   if (ret)
+   goto fail;
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bef484247..f51d274c82 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -138,6 +138,8 @@ enum {
  * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
  * add to this list. Memory so-allocated will be freed
  * automatically when the device is removed / unbound
+ * @dma_offset: Offset between the physical address space (CPU's) and the
+ * device's bus address space
  */
 struct udevice {
const struct driver *driver;
@@ -161,6 +163,9 @@ struct udevice {
 #ifdef CONFIG_DEVRES
struct list_head devres_head;
 #endif
+#ifdef CONFIG_DM_DMA
+   ulong dma_offset;
+#endif
 };
 
 /* Maximum sequence number supported */
-- 
2.29.2



[PATCH v4 01/13] rpi: Add identifier for the new RPi400

2020-12-22 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.

Signed-off-by: Nicolas Saenz Julienne 

---

Changes since v1:
 - The RPi Foundation introduced a RPi400 specific device tree, so use
   that file name instead of the fallback (RPi4b).

 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+   [0x13] = {
+   "400",
+   DTB_DIR "bcm2711-rpi-400.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v4 00/13] Raspberry Pi 400/Compute Module 4 support

2020-12-22 Thread Nicolas Saenz Julienne
@Simon: I had to roll back all "if (CONFIG_IS_ENABLED(DM_DMA)" uses. As
per buildman it breaks compilation when !DM or !DM_DMA due to access to
undefined variables, namely dev and dev->dma_offset. I figure in u-boot
we root for small Image sizes, so defining the variables regarless of
them being needed is not an option.

---

This series could be split into at least two or even three parts, but I
kept it as is for now as it contains all the changes needed in order to
have u-boot working on the new Raspberry Pi 400 and Raspberry Pi Compute
Module 4.

There are core changes, specifically with regard to cpu to bus address
space translations. So far we had relied on hard-coded values but RPi
needs per device translations as it has at least three distinct bus
address spaces with different offsets. So it's a good opportunity to
implement bus translations the right way by parsing DT's dma-ranges.

Here's a more concrete example of what we're dealing with:

 - On a RPi4, SoC version BCM2711C0 with 8GB of memory

[0x0 0x2]   [0x2 0x4]  [0xc000 0x1] 
 [0x 0x1]
 phys/cpu address   PCIe bus address   Legacy peripheral
   emmc2 address
 space   space   address space  
  space

 - On a RPi4, SoC version BCM2711C0 with 4GB of memory

[0x0 0x1]   [0x1 0x2]  [0xc000 0x1] 
 [0x 0x1]
  phys/cpu address  PCIe bus address  Legacy peripheral 
   emmc2 address
space  spaceaddress space   
 space

- On a RPi4, SoC version BCM2711B0 with 8GB of memory (bus can only access the
  lower 3GB of memory because of a SoC routing bug)

[0x0 0x2]   [0x 0xC000]   [0xc000 0x1]
 phys/cpu address  PCIe bus address  Legacy peripheral
space  space   address space

---

Changes since v3:
 - Add commit "video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible", it's
   pretty harmless
 - Get rid of non-device based phys2bus call in xhci & mmc
 - Simon's review changes in tests
 - Comment some of the APIs

Changes since v2:
 - Test builds not broken with buildman
 - Add tests to all DM changes
 - Make code conditional with config option
 - Correct OF refcount
 - Add config changes
 - Address small changes as per reviews

Changes since v1:
 - Fix some issues in 'dm: Introduce xxx_get_dma_range()'
 - Fix some typos in commit messages
 - Change DTB file name for RPi400
 - Address Matthias' comments

Nicolas Saenz Julienne (13):
  rpi: Add identifier for the new RPi400
  rpi: Add identifier for the new CM4
  pci: pcie-brcmstb: Fix inbound window configurations
  dm: Introduce xxx_get_dma_range()
  dm: test: Add test case for dev_get_dma_ranges()
  dm: Introduce DMA constraints into the core device model
  dm: test: Add test case for dev->dma_offset
  dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()
  dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()
  xhci: translate virtual addresses into the bus's address space
  mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()
  configs: rpi4: Enable DM_DMA across all RPi4 configurations
  video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible

 arch/sandbox/dts/test.dts  | 21 
 board/raspberrypi/rpi/rpi.c| 10 
 common/fdt_support.c   | 73 
 configs/rpi_4_32b_defconfig|  1 +
 configs/rpi_4_defconfig|  1 +
 configs/rpi_arm64_defconfig|  1 +
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 drivers/core/Kconfig   | 10 
 drivers/core/device.c  | 45 +
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 
 drivers/core/read.c|  6 +++
 drivers/mmc/sdhci.c|  7 +--
 drivers/pci/pcie_brcmstb.c | 12 ++---
 drivers/usb/host/xhci-mem.c| 45 +
 drivers/usb/host/xhci-ring.c   | 11 +++--
 drivers/usb/host/xhci.c|  4 +-
 drivers/video/bcm2835.c|  1 +
 include/dm/device.h|  5 ++
 include/dm/of_addr.h   | 17 +++
 include/dm/ofnode.h| 16 ++
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 ++
 include/mmc.h  | 10 
 include/phys2bus.h | 16 ++
 include/usb/xhci.h | 22 -
 test/dm/Makefile   |  2 +
 test/dm/core.c | 30 
 test/dm/phys2bu

Re: [PATCH v3 11/12] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-21 Thread Nicolas Saenz Julienne
On Mon, 2020-12-21 at 09:47 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Mon, 21 Dec 2020 at 07:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> > > On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
> > >  wrote:
> > > > 
> > > > This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
> > > > when relevant.
> > > > 
> > > > Signed-off-by: Nicolas Saenz Julienne 
> > > > ---
> > > >  drivers/mmc/sdhci.c |  7 ---
> > > >  include/mmc.h   | 10 ++
> > > >  2 files changed, 14 insertions(+), 3 deletions(-)
> > > 
> > > Reviewed-by: Simon Glass 
> > > 
> > > 
> > > > 
> > > > diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> > > > index 0628934312..2086d7cdb1 100644
> > > > --- a/drivers/mmc/sdhci.c
> > > > +++ b/drivers/mmc/sdhci.c
> > > > @@ -19,7 +19,6 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > -#include 
> > > > 
> > > >  static void sdhci_reset(struct sdhci_host *host, u8 mask)
> > > >  {
> > > > @@ -103,7 +102,8 @@ static void sdhci_prepare_dma(struct sdhci_host 
> > > > *host, struct mmc_data *data,
> > > >   mmc_get_dma_dir(data));
> > > > 
> > > > if (host->flags & USE_SDMA) {
> > > > -   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
> > > > +   sdhci_writel(host,
> > > > +mmc_phys_to_bus(host->mmc, 
> > > > (ulong)host->start_addr),
> > > > SDHCI_DMA_ADDRESS);
> > > > }
> > > >  #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
> > > > @@ -162,7 +162,8 @@ static int sdhci_transfer_data(struct sdhci_host 
> > > > *host, struct mmc_data *data)
> > > > start_addr &=
> > > > ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
> > > > start_addr += 
> > > > SDHCI_DEFAULT_BOUNDARY_SIZE;
> > > > -   sdhci_writel(host, 
> > > > phys_to_bus((ulong)start_addr),
> > > > +   sdhci_writel(host,
> > > > +mmc_phys_to_bus(host->mmc, 
> > > > (ulong)start_addr),
> > > >  SDHCI_DMA_ADDRESS);
> > > > }
> > > > }
> > > > diff --git a/include/mmc.h b/include/mmc.h
> > > > index 1d377e0281..5fe1ef1dfc 100644
> > > > --- a/include/mmc.h
> > > > +++ b/include/mmc.h
> > > > @@ -15,6 +15,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > > 
> > > >  struct bd_info;
> > > > 
> > > > @@ -977,4 +978,13 @@ static inline enum dma_data_direction 
> > > > mmc_get_dma_dir(struct mmc_data *data)
> > > > return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : 
> > > > DMA_FROM_DEVICE;
> > > >  }
> > > > 
> > > > +static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t 
> > > > addr)
> > > > +{
> > > > +#if CONFIG_IS_ENABLED(DM_DMA)
> > > 
> > > if() ?
> > 
> > Noted.
> > 
> > > Also makes me wonder if dev_phys_to_bus() should call phys_to_bus() if
> > > DM_DMA is not enabled?
> > 
> > I'd still need some sort per-subsystem macro to cater for !DM configurations
> > where the device pointer isn't defined in the controller struct. Which IMO
> > isn't much of an enhancement to this approach.
> 
> We don't need to worry about non-DM for new features. In fact we don't
> generally accept code that adds new features to non-DM code. It is
> deprecated and slated for removal, so it just prolongs the migration.

Understood, so let's not call the plain phys_to_bus() and assume a 1:1 address
translation on non DM_DMA users (for both mmc and xhci). I'd say it's pretty
safe to do anyway, as it seems phys2bus.h was introduced specially for the RPi
family.

There still are some rogue users of the non dev dependent phys_to_bus() API in
RPi platform code. I'll try to clean that up in a subsequent series.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v3 11/12] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-21 Thread Nicolas Saenz Julienne
On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
> > when relevant.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > ---
> >  drivers/mmc/sdhci.c |  7 ---
> >  include/mmc.h   | 10 ++
> >  2 files changed, 14 insertions(+), 3 deletions(-)
> 
> Reviewed-by: Simon Glass 
> 
> 
> > 
> > diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> > index 0628934312..2086d7cdb1 100644
> > --- a/drivers/mmc/sdhci.c
> > +++ b/drivers/mmc/sdhci.c
> > @@ -19,7 +19,6 @@
> >  #include 
> >  #include 
> >  #include 
> > -#include 
> > 
> >  static void sdhci_reset(struct sdhci_host *host, u8 mask)
> >  {
> > @@ -103,7 +102,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
> > struct mmc_data *data,
> >   mmc_get_dma_dir(data));
> > 
> > if (host->flags & USE_SDMA) {
> > -   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
> > +   sdhci_writel(host,
> > +mmc_phys_to_bus(host->mmc, 
> > (ulong)host->start_addr),
> > SDHCI_DMA_ADDRESS);
> > }
> >  #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
> > @@ -162,7 +162,8 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
> > struct mmc_data *data)
> > start_addr &=
> > ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
> > start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
> > -   sdhci_writel(host, 
> > phys_to_bus((ulong)start_addr),
> > +   sdhci_writel(host,
> > +mmc_phys_to_bus(host->mmc, 
> > (ulong)start_addr),
> >  SDHCI_DMA_ADDRESS);
> > }
> > }
> > diff --git a/include/mmc.h b/include/mmc.h
> > index 1d377e0281..5fe1ef1dfc 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -15,6 +15,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> > 
> >  struct bd_info;
> > 
> > @@ -977,4 +978,13 @@ static inline enum dma_data_direction 
> > mmc_get_dma_dir(struct mmc_data *data)
> > return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : 
> > DMA_FROM_DEVICE;
> >  }
> > 
> > +static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t addr)
> > +{
> > +#if CONFIG_IS_ENABLED(DM_DMA)
> 
> if() ?

Noted.

> Also makes me wonder if dev_phys_to_bus() should call phys_to_bus() if
> DM_DMA is not enabled?

I'd still need some sort per-subsystem macro to cater for !DM configurations
where the device pointer isn't defined in the controller struct. Which IMO
isn't much of an enhancement to this approach.

What I'd like to have is some sort of subsystem independent way of doing
'controller->dev' regardless of CONFIG_DM (falling back to NULL when not
enabled). The easy way would be defining the variable regardless of CONFIG_DM,
but I guess that isn't ideal WRT image sizes.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v3 10/12] xhci: translate virtual addresses into the bus's address space

2020-12-21 Thread Nicolas Saenz Julienne
On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > So far we've been content with passing physical addresses when
> > configuring memory addresses into XHCI controllers, but not all
> > platforms have buses with transparent mappings. Specifically the
> > Raspberry Pi 4 might introduce an offset to memory accesses incoming
> > from its PCIe port.
> > 
> > Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
> > limitations, and make sure we don't break non DM users.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > ---
> >  drivers/usb/host/xhci-mem.c  | 45 +++-
> >  drivers/usb/host/xhci-ring.c | 11 +
> >  drivers/usb/host/xhci.c  |  4 ++--
> >  include/usb/xhci.h   | 22 +-
> >  4 files changed, 54 insertions(+), 28 deletions(-)
> 
> Reviewed-by: Simon Glass 
> 
> nits below
> 
> [..]
> 
> > diff --git a/include/usb/xhci.h b/include/usb/xhci.h
> > index e1d382369a..b87210b9ba 100644
> > --- a/include/usb/xhci.h
> > +++ b/include/usb/xhci.h
> > @@ -16,6 +16,7 @@
> >  #ifndef HOST_XHCI_H_
> >  #define HOST_XHCI_H_
> > 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -1250,7 +1251,8 @@ int xhci_check_maxpacket(struct usb_device *udev);
> >  void xhci_flush_cache(uintptr_t addr, u32 type_len);
> >  void xhci_inval_cache(uintptr_t addr, u32 type_len);
> >  void xhci_cleanup(struct xhci_ctrl *ctrl);
> > -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
> > +struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
> > num_segs,
> > + bool link_trbs);
> 
> Can you please add a comment while you are here?

The comment is in the xhci-mem.c. Should I move it here?

> >  int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id);
> >  int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
> >   struct xhci_hcor *hcor);
> > @@ -1278,4 +1280,22 @@ extern struct dm_usb_ops xhci_usb_ops;
> > 
> >  struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev);
> > 
> > +static inline dma_addr_t xhci_virt_to_bus(struct xhci_ctrl *ctrl, void 
> > *addr)
> > +{
> > +#if CONFIG_IS_ENABLED(DM_DMA)
> 
> Can this use if() ?

Yes, will do.

> > +   return dev_phys_to_bus(ctrl->dev, virt_to_phys(addr));
> > +#else
> > +   return phys_to_bus(virt_to_phys(addr));
> > +#endif
> > +}
> > +
> > +static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t 
> > addr)
> > +{
> > +#if CONFIG_IS_ENABLED(DM_DMA)
> > +   return phys_to_virt(dev_bus_to_phys(ctrl->dev, addr));
> > +#else
> > +   return phys_to_virt(bus_to_phys(addr));
> > +#endif
> > +}
> > +
> >  #endif /* HOST_XHCI_H_ */
> > --
> > 2.29.2
> > 
> 
> Regards,
> Simon





signature.asc
Description: This is a digitally signed message part


Re: [PATCH v3 09/12] dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()

2020-12-21 Thread Nicolas Saenz Julienne
On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > By reusing DT nodes already available in sandbox's test DT introduce a
> > test to validate dev_phys_to_bus()/dev_bus_to_phys().
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > ---
> >  test/dm/Makefile   |  1 +
> >  test/dm/phys2bus.c | 36 
> >  2 files changed, 37 insertions(+)
> >  create mode 100644 test/dm/phys2bus.c
> 
> Reviewed-by: Simon Glass 
> 
> comment below
> 
> > 
> > diff --git a/test/dm/Makefile b/test/dm/Makefile
> > index 5c52d8b6ea..ac86abaa88 100644
> > --- a/test/dm/Makefile
> > +++ b/test/dm/Makefile
> > @@ -16,6 +16,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
> > 
> >  obj-$(CONFIG_UT_DM) += core.o
> >  obj-$(CONFIG_UT_DM) += read.o
> > +obj-$(CONFIG_UT_DM) += phys2bus.o
> >  ifneq ($(CONFIG_SANDBOX),)
> >  obj-$(CONFIG_ACPIGEN) += acpi.o
> >  obj-$(CONFIG_ACPIGEN) += acpigen.o
> > diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
> > new file mode 100644
> > index 00..06a045c168
> > --- /dev/null
> > +++ b/test/dm/phys2bus.c
> > @@ -0,0 +1,36 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2020 Nicolas Saenz Julienne 
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +static int dm_test_phys_to_bus(struct unit_test_state *uts)
> > +{
> > +   struct udevice *dev;
> > +   ofnode node;
> > +
> > +   node = ofnode_path("/mmio-bus@0");
> > +   ut_assert(ofnode_valid(node));
> > +   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, 
> > &dev));
> > +   /* In this case it should be transparent, no dma-ranges in parent 
> > bus */
> > +   ut_asserteq_ptr((void*)0xfULL, (void*)dev_phys_to_bus(dev, 
> > 0xf));
> 
> ut_asserteq_addr() might be better here? Not sure.

That function uses map_to_sysmem() under the hood, which AFAIR didn't play well
with these addresses.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v3 07/12] dm: test: Add test case for dev->dma_offset

2020-12-21 Thread Nicolas Saenz Julienne
On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > Add test to validate dev->dma_offset is properly set on devices.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > ---
> >  arch/sandbox/dts/test.dts  |  4 
> >  configs/sandbox64_defconfig|  1 +
> >  configs/sandbox_defconfig  |  1 +
> >  configs/sandbox_flattree_defconfig |  1 +
> >  configs/sandbox_spl_defconfig  |  1 +
> >  test/dm/core.c | 30 ++
> >  6 files changed, 38 insertions(+)
> 
> Reviewed-by: Simon Glass 
> 
> We normally use ut_assertok() instead of ut_assert(!xxx), since 0 means OK.

Will fix this across all tests.



signature.asc
Description: This is a digitally signed message part


Re: [PATCH v3 04/12] dm: Introduce xxx_get_dma_range()

2020-12-21 Thread Nicolas Saenz Julienne
Hi Simon, thanks for the review.

On Fri, 2020-12-18 at 19:28 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Tue, 15 Dec 2020 at 10:23, Nicolas Saenz Julienne
>  wrote:
> > 
> > Add the following functions to get a specific device's DMA ranges:
> >  - dev_get_dma_range()
> >  - ofnode_get_dma_range()
> >  - of_get_dma_range()
> >  - fdt_get_dma_range()
> > They are specially useful in oder to be able validate a physical address
> > space range into a bus's and to convert addresses from and to address
> > spaces.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > 
> > ---
> > Changes since v2:
> >  - Return ENOENT instead of ENODEV
> >  - Refcount OF nodes
> > 
> > Changes since v1:
> >  - Fix wrong arguments in of_get_dma_range()'s call to 
> > of_translate_dma_address()
> >  - Fix build in SPL/TPL and no LIBFDT supprt
> >  - Add missing declaration in 'core/read.c'
> >  - Address Matthias' comments
> > 
> >  common/fdt_support.c   | 73 +++
> >  drivers/core/of_addr.c | 78 ++
> >  drivers/core/ofnode.c  |  9 +
> >  drivers/core/read.c|  6 
> >  include/dm/of_addr.h   | 17 +
> >  include/dm/ofnode.h| 16 +
> >  include/dm/read.h  | 21 
> >  include/fdt_support.h  | 14 
> >  8 files changed, 234 insertions(+)
> 
> Reviewed-by: Simon Glass 
> 
> I don't suppose it is worth writing a version that uses the ofnode API
> and thus reduce code size? Probably not since if livetree is enabled,
> I doubt we would ever call the flattree one. Also it is nice to have
> the same livetree code as Linux, where possible.

As far as the logic is concerned we'd be able to mimic what linux does so it
shouldn't be a problem.

But I'd be forced to port low level DT code to ofnode. Notably 'of_match_bus()'
and 'struct of_bus', which IMO have no place in ofnode: it seems to me that
ofnode is an abstraction geared towards simplifying DT consumers. This wouldn't
provide much benefit to them, with the downside of divering from upstream
Linux's implementation.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


[PATCH v3 12/12] configs: rpi4: Enable DM_DMA across all RPi4 configurations

2020-12-15 Thread Nicolas Saenz Julienne
The DM_DMA option is needed in order to translate physical address into
bus addresses on a per-device basis.

Signed-off-by: Nicolas Saenz Julienne 
---
 configs/rpi_4_32b_defconfig | 1 +
 configs/rpi_4_defconfig | 1 +
 configs/rpi_arm64_defconfig | 1 +
 3 files changed, 3 insertions(+)

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 5ddd838fd5..0a5d3ff8cd 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 2590d0a696..b61cdc05f1 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DFU_MMC=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 2639219a1a..4125a1feba 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
 CONFIG_DM_KEYBOARD=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
-- 
2.29.2



[PATCH v3 10/12] xhci: translate virtual addresses into the bus's address space

2020-12-15 Thread Nicolas Saenz Julienne
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.

Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/usb/host/xhci-mem.c  | 45 +++-
 drivers/usb/host/xhci-ring.c | 11 +
 drivers/usb/host/xhci.c  |  4 ++--
 include/usb/xhci.h   | 22 +-
 4 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b002d6f166..83147d51b5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
 
ctrl->dcbaa->dev_context_ptrs[0] = 0;
 
-   free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+   free(xhci_bus_to_virt(ctrl, 
le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return none
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-   struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment 
*prev,
+  struct xhci_segment *next, bool link_trbs)
 {
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
-   val_64 = virt_to_phys(next->trbs);
+   val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
 
@@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return pointer to the newly created RING
  */
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
num_segs,
+ bool link_trbs)
 {
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, 
bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
 
-   xhci_link_segments(prev, next, link_trbs);
+   xhci_link_segments(ctrl, prev, next, link_trbs);
 
prev = next;
num_segs--;
}
-   xhci_link_segments(prev, ring->first_seg, link_trbs);
+   xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+   uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
-   ctrl->dcbaa->dev_context_ptrs[0] =
-   cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+   val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+   ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
 
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
 
for (i = 0; i < num_sp; i++) {
-   uintptr_t ptr = (uintptr_t)buf + i * page_size;
-   scratchpad->sp_array[i] = cpu_to_le64(ptr);
+   val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+   scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
 
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned 
int slot_id)
}
 
/* Allocate endpoint 0 ring */
-   virt_dev->eps[0].ring = xhci_ring_alloc(1, true);

[PATCH v3 11/12] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-15 Thread Nicolas Saenz Julienne
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/mmc/sdhci.c |  7 ---
 include/mmc.h   | 10 ++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0628934312..2086d7cdb1 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
@@ -103,7 +102,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
struct mmc_data *data,
  mmc_get_dma_dir(data));
 
if (host->flags & USE_SDMA) {
-   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)host->start_addr),
SDHCI_DMA_ADDRESS);
}
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
@@ -162,7 +162,8 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
-   sdhci_writel(host, 
phys_to_bus((ulong)start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)start_addr),
 SDHCI_DMA_ADDRESS);
}
}
diff --git a/include/mmc.h b/include/mmc.h
index 1d377e0281..5fe1ef1dfc 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct bd_info;
 
@@ -977,4 +978,13 @@ static inline enum dma_data_direction 
mmc_get_dma_dir(struct mmc_data *data)
return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 }
 
+static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t addr)
+{
+#if CONFIG_IS_ENABLED(DM_DMA)
+   return dev_phys_to_bus(mmc->dev, addr);
+#else
+   return phys_to_bus(addr);
+#endif
+}
+
 #endif /* _MMC_H_ */
-- 
2.29.2



[PATCH v3 09/12] dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()

2020-12-15 Thread Nicolas Saenz Julienne
By reusing DT nodes already available in sandbox's test DT introduce a
test to validate dev_phys_to_bus()/dev_bus_to_phys().

Signed-off-by: Nicolas Saenz Julienne 
---
 test/dm/Makefile   |  1 +
 test/dm/phys2bus.c | 36 
 2 files changed, 37 insertions(+)
 create mode 100644 test/dm/phys2bus.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5c52d8b6ea..ac86abaa88 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
 obj-$(CONFIG_UT_DM) += read.o
+obj-$(CONFIG_UT_DM) += phys2bus.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
new file mode 100644
index 00..06a045c168
--- /dev/null
+++ b/test/dm/phys2bus.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_phys_to_bus(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   /* In this case it should be transparent, no dma-ranges in parent bus */
+   ut_asserteq_ptr((void*)0xfULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_ptr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0xf));
+
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_ptr((void*)0x100fULL, (void*)dev_phys_to_bus(dev, 
0xf));
+   ut_asserteq_ptr((void*)0xfULL, (void*)(ulong)dev_bus_to_phys(dev, 
0x100f));
+
+   return 0;
+}
+DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v3 08/12] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()

2020-12-15 Thread Nicolas Saenz Julienne
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.

We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.

Signed-off-by: Nicolas Saenz Julienne 
Reviewed-by: Simon Glass 

---
Changes since v2:
 - Use CONFIG_DM_DMA

 include/phys2bus.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..516d630aea 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,20 @@ static inline unsigned long bus_to_phys(unsigned long bus)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+#include 
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev,
+phys_addr_t phys)
+{
+   return phys - dev->dma_offset;
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev,
+ dma_addr_t bus)
+{
+   return bus + dev->dma_offset;
+}
+#endif
+
 #endif
-- 
2.29.2



[PATCH v3 07/12] dm: test: Add test case for dev->dma_offset

2020-12-15 Thread Nicolas Saenz Julienne
Add test to validate dev->dma_offset is properly set on devices.

Signed-off-by: Nicolas Saenz Julienne 
---
 arch/sandbox/dts/test.dts  |  4 
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 test/dm/core.c | 30 ++
 6 files changed, 38 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3a3b51f83b..78f0100282 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -307,6 +307,10 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
};
 
acpi_test1: acpi-test {
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 5fbbfd7236..2c189a8a00 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -94,6 +94,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f1ec701a9f..ac97c16cef 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -108,6 +108,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_flattree_defconfig 
b/configs/sandbox_flattree_defconfig
index edca7f1808..f5923bf713 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -75,6 +75,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_DEVRES=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 479f0226e3..0a4815770c 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -94,6 +94,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
 CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SYSCON=y
diff --git a/test/dm/core.c b/test/dm/core.c
index 6f380a574c..998874ffee 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -1066,3 +1066,33 @@ static int dm_test_inactive_child(struct unit_test_state 
*uts)
return 0;
 }
 DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_dma_offset(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   ofnode node;
+
+   /* Make sure the bus's dma-ranges aren't taken into account here */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   /* Device behind a bus with dma-ranges */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(-0x1000ULL, dev->dma_offset);
+
+   /* This one has no dma-ranges */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   node = ofnode_path("/mmio-bus@1/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_asserteq_64(0, dev->dma_offset);
+
+   return 0;
+}
+DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v3 04/12] dm: Introduce xxx_get_dma_range()

2020-12-15 Thread Nicolas Saenz Julienne
Add the following functions to get a specific device's DMA ranges:
 - dev_get_dma_range()
 - ofnode_get_dma_range()
 - of_get_dma_range()
 - fdt_get_dma_range()
They are specially useful in oder to be able validate a physical address
space range into a bus's and to convert addresses from and to address
spaces.

Signed-off-by: Nicolas Saenz Julienne 

---
Changes since v2:
 - Return ENOENT instead of ENODEV
 - Refcount OF nodes

Changes since v1:
 - Fix wrong arguments in of_get_dma_range()'s call to 
of_translate_dma_address()
 - Fix build in SPL/TPL and no LIBFDT supprt
 - Add missing declaration in 'core/read.c'
 - Address Matthias' comments

 common/fdt_support.c   | 73 +++
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 +
 drivers/core/read.c|  6 
 include/dm/of_addr.h   | 17 +
 include/dm/ofnode.h| 16 +
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 
 8 files changed, 234 insertions(+)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 5ae75df3c6..bf855d26c8 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1342,6 +1342,79 @@ u64 fdt_translate_dma_address(const void *blob, int 
node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
 }
 
+int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct of_bus *bus_node;
+   const fdt32_t *ranges;
+   int na, ns, pna, pns;
+   int parent = node;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   while (parent >= 0) {
+   ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /* Once we find 'dma-ranges', then a missing one is an error */
+   if (found_dma_ranges && !ranges) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (ranges)
+   found_dma_ranges = true;
+
+   parent = fdt_parent_offset(blob, parent);
+   }
+
+   if (!ranges || parent < 0) {
+   debug("no dma-ranges found for node %s\n",
+ fdt_get_name(blob, node, NULL));
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /* switch to that node */
+   node = parent;
+   parent = fdt_parent_offset(blob, node);
+   if (parent < 0) {
+   printf("Found dma-ranges in root node, shoudln't happen\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
+   /* Get the address sizes both for the bus and its parent */
+   bus_node = of_match_bus(blob, node);
+   bus_node->count_cells(blob, node, &na, &ns);
+   if (!OF_CHECK_COUNTS(na, ns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, node, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   bus_node = of_match_bus(blob, parent);
+   bus_node->count_cells(blob, parent, &pna, &pns);
+   if (!OF_CHECK_COUNTS(pna, pns)) {
+   printf("%s: Bad cell count for %s\n", __FUNCTION__,
+  fdt_get_name(blob, parent, NULL));
+   return -EINVAL;
+   goto out;
+   }
+
+   *bus = fdt_read_number(ranges, na);
+   *cpu = fdt_translate_dma_address(blob, node, ranges + na);
+   *size = fdt_read_number(ranges + na + pna, ns);
+out:
+   return ret;
+}
+
 /**
  * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
  * who's reg property matches a physical cpu address
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index ca34d84922..703bc3e3f5 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -325,6 +325,84 @@ u64 of_translate_dma_address(const struct device_node 
*dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
 }
 
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+dma_addr_t *bus, u64 *size)
+{
+   bool found_dma_ranges = false;
+   struct device_node *parent;
+   struct of_bus *bus_node;
+   int na, ns, pna, pns;
+   const __be32 *ranges;
+   int ret = 0;
+   int len;
+
+   /* Find the closest dma-ranges property */
+   dev = of_node_get(dev);
+   while (dev) {
+   ranges = of_get_property(dev, "dma-ranges", &len);
+
+   /* Ign

[PATCH v3 06/12] dm: Introduce DMA constraints into the core device model

2020-12-15 Thread Nicolas Saenz Julienne
Calculating the DMA offset between a bus address space and CPU's every
time we call phys_to_bus() and bus_to_phys() isn't ideal performance
wise, as it implies traversing the device tree from the device's node up
to the root. Since this information is static and available before the
device's initialization, parse it before the probe call an provide the
DMA offset in 'struct udevice' for the address translation code to use
it.

Signed-off-by: Nicolas Saenz Julienne 

---
Changes since v2:
 - Return/Fail on error
 - Add config option
 - use ulong instead for u64 for dev->dma_offset

Changes since v1:
 - Update commit message so as to explain better the reasoning behind
   this

 drivers/core/Kconfig  | 10 ++
 drivers/core/device.c | 35 +++
 include/dm/device.h   |  3 +++
 3 files changed, 48 insertions(+)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index ffae6f9795..153be25351 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -113,6 +113,16 @@ config SPL_DM_SEQ_ALIAS
  numbered devices (e.g. serial0 = &serial0). This feature can be
  disabled if it is not required, to save code space in SPL.
 
+config DM_DMA
+   bool "Support per device DMA constraints"
+   depends on DM
+   default n
+   help
+ Enable this to extract per-device DMA constraints, only supported on
+ device-tree systems for now. This is needed in order translate
+ addresses on systems where different buses have different views of
+ the physical address space.
+
 config REGMAP
bool "Support register maps"
depends on DM
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 4b3dcb3b37..21285432d8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -421,6 +421,37 @@ fail:
return ret;
 }
 
+#if CONFIG_IS_ENABLED(DM_DMA)
+static int device_get_dma_constraints(struct udevice *dev)
+{
+   struct udevice *parent = dev->parent;
+   phys_addr_t cpu = 0;
+   dma_addr_t bus = 0;
+   u64 size = 0;
+   int ret;
+
+   if (!parent || !dev_of_valid(parent))
+   return 0;
+
+   /*
+* We start parsing for dma-ranges from the device's bus node. This is
+* specially important on nested buses.
+*/
+   ret = dev_get_dma_range(parent, &cpu, &bus, &size);
+   /* Don't return an error if no 'dma-ranges' were found */
+   if (ret && ret != -ENOENT) {
+   dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
+   return ret;
+   }
+
+   dev->dma_offset = cpu - bus;
+
+   return 0;
+}
+#else
+static int device_get_dma_constraints(struct udevice *dev) { return 0; }
+#endif
+
 int device_probe(struct udevice *dev)
 {
const struct driver *drv;
@@ -482,6 +513,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
 
+   ret = device_get_dma_constraints(dev);
+   if (ret)
+   goto fail;
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bef484247..9126dc00fe 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -161,6 +161,9 @@ struct udevice {
 #ifdef CONFIG_DEVRES
struct list_head devres_head;
 #endif
+#ifdef CONFIG_DM_DMA
+   ulong dma_offset;
+#endif
 };
 
 /* Maximum sequence number supported */
-- 
2.29.2



[PATCH v3 03/12] pci: pcie-brcmstb: Fix inbound window configurations

2020-12-15 Thread Nicolas Saenz Julienne
So far we've assumed a fixed configuration for inbound windows as we had
a single user for this controller. But the controller's DMA constraints
were improved starting with BCM2711's B1 revision of the SoC, notably
available in CM4 and Pi400. They allow for wider inbound windows. We can
now cover the whole address space, whereas before we where limited to
the lower 3GB.

This information is passed to us through DT's 'dma-ranges' property and
it's specially important for us to honor it since some interactions with
the board's co-processor assume we're doing so (specifically the XHCI
firmware load operation, which is handled by the co-processor after
u-boot has correctly configured the PCIe controller).

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/pci/pcie_brcmstb.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dade79e9c8..f6e8ad0d0a 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+   struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
-   /*
-* TODO: When support for other SoCs than BCM2711 is added we may
-* need to use the base address and size(s) provided in the dma-ranges
-* property.
-*/
-   rc_bar2_offset = 0;
-   rc_bar2_size = 0xc000;
+
+   pci_get_dma_regions(dev, ®ion, 0);
+   rc_bar2_offset = region.bus_start - region.phys_start;
+   rc_bar2_size = 1ULL << fls64(region.size - 1);
 
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
-- 
2.29.2



[PATCH v3 05/12] dm: test: Add test case for dev_get_dma_ranges()

2020-12-15 Thread Nicolas Saenz Julienne
Introduce some new nodes in sandbox's test device-tree and dm tests in
order to validate dev_get_dma_range().

Signed-off-by: Nicolas Saenz Julienne 
---
 arch/sandbox/dts/test.dts | 17 ++
 test/dm/Makefile  |  1 +
 test/dm/read.c| 49 +++
 3 files changed, 67 insertions(+)
 create mode 100644 test/dm/read.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f3b766271d..3a3b51f83b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -292,6 +292,23 @@
test5-gpios = <&gpio_a 19>;
};
 
+   mmio-bus@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   dma-ranges = <0x1000 0x 0x0004>;
+
+   subnode@0 {
+   compatible = "denx,u-boot-fdt-test";
+   };
+   };
+
+   mmio-bus@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "denx,u-boot-test-bus";
+   };
+
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076ed09..5c52d8b6ea 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_UT_DM) += test-fdt.o
 obj-$(CONFIG_UT_DM) += test-uclass.o
 
 obj-$(CONFIG_UT_DM) += core.o
+obj-$(CONFIG_UT_DM) += read.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_ACPIGEN) += acpi.o
 obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/read.c b/test/dm/read.c
new file mode 100644
index 00..090eee0544
--- /dev/null
+++ b/test/dm/read.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_dma_ranges(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   phys_addr_t cpu;
+   dma_addr_t bus;
+   ofnode node;
+   u64 size;
+
+   /* dma-ranges are on the device's node */
+   node = ofnode_path("/mmio-bus@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_assert(!dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* dma-ranges are on the bus' node */
+   node = ofnode_path("/mmio-bus@0/subnode@0");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+   ut_assert(!dev_get_dma_range(dev, &cpu, &bus, &size));
+   ut_asserteq_64(0x4, size);
+   ut_asserteq_64(0x0, cpu);
+   ut_asserteq_64(0x1000, bus);
+
+   /* No dma-ranges available */
+   node = ofnode_path("/mmio-bus@1");
+   ut_assert(ofnode_valid(node));
+   ut_assert(!uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+   ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
+
+   return 0;
+}
+DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-- 
2.29.2



[PATCH v3 02/12] rpi: Add identifier for the new CM4

2020-12-15 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.

Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.

Signed-off-by: Nicolas Saenz Julienne 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+   [0x14] = {
+   "Compute Module 4",
+   DTB_DIR "bcm2711-rpi-cm4.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v3 00/12] Raspberry Pi 400/Compute Module 4 support

2020-12-15 Thread Nicolas Saenz Julienne
This series could be split into at least two or even three parts, but I
kept it as is for now as it contains all the changes needed in order to
have u-boot working on the new Raspberry Pi 400 and Raspberry Pi Compute
Module 4.

There are core changes, specifically with regard to cpu to bus address
space translations. So far we had relied on hard-coded values but RPi
needs per device translations as it has at least three distinct bus
address spaces with different offsets. So it's a good opportunity to
implement bus translations the right way by parsing DT's dma-ranges.

Here's a more concrete example of what we're dealing with:

 - On a RPi4, SoC version BCM2711C0 with 8GB of memory

[0x0 0x2]   [0x2 0x4]  [0xc000 0x1] 
 [0x 0x1]
 phys/cpu address   PCIe bus address   Legacy peripheral
   emmc2 address
 space   space   address space  
  space

 - On a RPi4, SoC version BCM2711C0 with 4GB of memory

[0x0 0x1]   [0x1 0x2]  [0xc000 0x1] 
 [0x 0x1]
  phys/cpu address  PCIe bus address  Legacy peripheral 
   emmc2 address
space  spaceaddress space   
 space

- On a RPi4, SoC version BCM2711B0 with 8GB of memory (bus can only access the
  lower 3GB of memory because of a SoC routing bug)

[0x0 0x2]   [0x 0xC000]   [0xc000 0x1]
 phys/cpu address  PCIe bus address  Legacy peripheral
space  space   address space

---

Changes since v2:
 - Test builds not broken with buildman
 - Add tests to all DM changes
 - Make code conditional with config option
 - Correct OF refcount
 - Add config changes
 - Address small changes as per reviews

Changes since v1:
 - Fix some issues in 'dm: Introduce xxx_get_dma_range()'
 - Fix some typos in commit messages
 - Change DTB file name for RPi400
 - Address Matthias' comments

Nicolas Saenz Julienne (12):
  rpi: Add identifier for the new RPi400
  rpi: Add identifier for the new CM4
  pci: pcie-brcmstb: Fix inbound window configurations
  dm: Introduce xxx_get_dma_range()
  dm: test: Add test case for dev_get_dma_ranges()
  dm: Introduce DMA constraints into the core device model
  dm: test: Add test case for dev->dma_offset
  dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()
  dm: test: Add test case for dev_phys_to_bus()/dev_bus_to_phys()
  xhci: translate virtual addresses into the bus's address space
  mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()
  configs: rpi4: Enable DM_DMA across all RPi4 configurations

 arch/sandbox/dts/test.dts  | 21 
 board/raspberrypi/rpi/rpi.c| 10 
 common/fdt_support.c   | 73 
 configs/rpi_4_32b_defconfig|  1 +
 configs/rpi_4_defconfig|  1 +
 configs/rpi_arm64_defconfig|  1 +
 configs/sandbox64_defconfig|  1 +
 configs/sandbox_defconfig  |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_spl_defconfig  |  1 +
 drivers/core/Kconfig   | 10 
 drivers/core/device.c  | 35 ++
 drivers/core/of_addr.c | 78 ++
 drivers/core/ofnode.c  |  9 
 drivers/core/read.c|  6 +++
 drivers/mmc/sdhci.c|  7 +--
 drivers/pci/pcie_brcmstb.c | 12 ++---
 drivers/usb/host/xhci-mem.c| 45 +
 drivers/usb/host/xhci-ring.c   | 11 +++--
 drivers/usb/host/xhci.c|  4 +-
 include/dm/device.h|  3 ++
 include/dm/of_addr.h   | 17 +++
 include/dm/ofnode.h| 16 ++
 include/dm/read.h  | 21 
 include/fdt_support.h  | 14 ++
 include/mmc.h  | 10 
 include/phys2bus.h | 16 ++
 include/usb/xhci.h | 22 -
 test/dm/Makefile   |  2 +
 test/dm/core.c | 30 
 test/dm/phys2bus.c | 36 ++
 test/dm/read.c | 49 +++
 32 files changed, 526 insertions(+), 38 deletions(-)
 create mode 100644 test/dm/phys2bus.c
 create mode 100644 test/dm/read.c

-- 
2.29.2



[PATCH v3 01/12] rpi: Add identifier for the new RPi400

2020-12-15 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.

Signed-off-by: Nicolas Saenz Julienne 

---

Changes since v1:
 - The RPi Foundation introduced a RPi400 specific device tree, so use
   that file name instead of the fallback (RPi4b).

 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+   [0x13] = {
+   "400",
+   DTB_DIR "bcm2711-rpi-400.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



Re: [PATCH v2 4/8] dm: Introduce xxx_get_dma_range()

2020-12-14 Thread Nicolas Saenz Julienne
On Sat, 2020-12-12 at 08:39 -0700, Simon Glass wrote:
> Hi Nicolas,
> 
> On Thu, 10 Dec 2020 at 04:39, Nicolas Saenz Julienne
>  wrote:
> > 
> > Add the following functions to get a specific device's DMA ranges:
> >  - dev_get_dma_range()
> >  - ofnode_get_dma_range()
> >  - of_get_dma_range()
> >  - fdt_get_dma_range()
> > They are specially useful in oder to be able validate a physical address
> > space range into a bus's and to convert addresses from and to address
> > spaces.
> > 
> > Signed-off-by: Nicolas Saenz Julienne 
> > 
> > ---
> > Changes since v1:
> >  - Fix wrong arguments in of_get_dma_range()'s call to 
> > of_translate_dma_address()
> >  - Fix build in SPL/TPL and no LIBFDT supprt
> >  - Add missing declaration in 'core/read.c'
> >  - Address Matthias' comments
> 
> Please see my additional comments on v1

Took note of your comments. Thanks for the review!

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


Re: [PATCH 4/8] dm: Introduce xxx_get_dma_range()

2020-12-10 Thread Nicolas Saenz Julienne
Hi Peter,

On Thu, 2020-12-10 at 17:03 +, Peter Robinson wrote:
> Hi Nicolas,
> 
> 
> On Thu, Nov 19, 2020 at 5:50 PM Nicolas Saenz Julienne
>  wrote:
> > 
> > Add the follwing functions to get a specific device's DMA ranges:
> >  - dev_get_dma_range()
> >  - ofnode_get_dma_range()
> >  - of_get_dma_range()
> >  - fdt_get_dma_range()
> > They are specially useful in oder to be able validate a physical address
> > space range into a bus's and to convert addresses from and to address
> > spaces.
> 
> I'm seeing issues with this patch, with the just posted v2 as well
> (it's not arrived in my inbox as yet).

I think didn't directly CC you, sorry for that. I'll keep it in mind for the
next round.

> I get the following linking error when building across a number of devices
> such as Jetson boards like jetson-tk1, p3450-, as well as puma-rk3399,
> marsboard, udoo, udoo_neo. The error is:

Thanks for having a lookg at this. I've been strugling to test my series
against all posible configurations. What are you using catch the regressions?
Is something I can run locally?

>   /usr/bin/arm-linux-gnu-ld.bfd  -pie --gc-sections -Bstatic
> --no-dynamic-linker -Ttext 0x8780 -o u-boot -T u-boot.lds
> arch/arm/cpu/armv7/start.o --start-group  arch/arm/cpu/built-in.o
> arch/arm/cpu/armv7/built-in.o  arch/arm/lib/built-in.o
> arch/arm/mach-imx/built-in.o  board/udoo/neo/built-in.o
> cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o
>  drivers/dma/built-in.o  drivers/gpio/built-in.o
> drivers/i2c/built-in.o  drivers/net/built-in.o
> drivers/net/phy/built-in.o  drivers/power/built-in.o
> drivers/power/battery/built-in.o  drivers/power/domain/built-in.o
> drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o
> drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o
> drivers/serial/built-in.o  drivers/spi/built-in.o
> drivers/usb/cdns3/built-in.o  drivers/usb/common/built-in.o
> drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o
> drivers/usb/eth/built-in.o  drivers/usb/host/built-in.o
> drivers/usb/mtu3/built-in.o  drivers/usb/musb-new/built-in.o
> drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o
> drivers/usb/ulpi/built-in.o  env/built-in.o  fs/built-in.o
> lib/built-in.o  net/built-in.o --end-group arch/arm/lib/eabi_compat.o
> arch/arm/lib/lib.a -Map u-boot.map;  true
> /usr/bin/arm-linux-gnu-ld.bfd: drivers/built-in.o: in function
> `dev_get_dma_range':
> /home/perobins/fedora/packages/uboot-tools/u-boot-2021.01-rc3/include/dm/read.h:1025:
> undefined reference to `ofnode_get_dma_range'
> make[1]: *** 
> [/home/perobins/fedora/packages/uboot-tools/u-boot-2021.01-rc3/Makefile:1757:
> u-boot] Error 1
> make[1]: Leaving directory
> '/home/perobins/fedora/packages/uboot-tools/u-boot-2021.01-rc3/builds/udoo_neo'

I reproduced it locally, thanks! I'll fit it.

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part


[PATCH v2 6/8] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()

2020-12-10 Thread Nicolas Saenz Julienne
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.

We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.

Signed-off-by: Nicolas Saenz Julienne 
---
 include/phys2bus.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..a380063af4 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,20 @@ static inline unsigned long bus_to_phys(unsigned long bus)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM)
+#include 
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev,
+phys_addr_t phys)
+{
+   return phys - dev->dma_offset;
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev,
+ dma_addr_t bus)
+{
+   return bus + dev->dma_offset;
+}
+#endif
+
 #endif
-- 
2.29.2



[PATCH v2 5/8] dm: Introduce DMA constraints into the core device model

2020-12-10 Thread Nicolas Saenz Julienne
Calculating the DMA offset between a bus address space and CPU's every
time we call phys_to_bus() and bus_to_phys() isn't ideal performance
wise, as it implies traversing the device tree from the device's node up
to the root. Since this information is static and available before the
device's initialization, parse it before the probe call an provide the
DMA offset in 'struct udevice' for the address translation code to use
it.

Signed-off-by: Nicolas Saenz Julienne 

---
Changes since v1:
 - Update commit message so as to explain better the reasoning behind
   this

 drivers/core/device.c | 24 
 include/dm/device.h   |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 4b3dcb3b37..4255bea24d 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -421,6 +421,28 @@ fail:
return ret;
 }
 
+void device_get_dma_constraints(struct udevice *dev)
+{
+   phys_addr_t cpu;
+   dma_addr_t bus;
+   u64 size;
+   int ret;
+
+   if (!dev_of_valid(dev))
+   return;
+
+   ret = dev_get_dma_range(dev, &cpu, &bus, &size);
+   if (ret) {
+   /* Don't complain if no 'dma-ranges' were found */
+   if (ret != -ENODEV)
+   dm_warn("%s: failed to get DMA range, %d\n",
+   dev->name, ret);
+   return;
+   }
+
+   dev->dma_offset = cpu - bus;
+}
+
 int device_probe(struct udevice *dev)
 {
const struct driver *drv;
@@ -482,6 +504,8 @@ int device_probe(struct udevice *dev)
goto fail;
}
 
+   device_get_dma_constraints(dev);
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bef484247..59f711e3dd 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -161,6 +161,7 @@ struct udevice {
 #ifdef CONFIG_DEVRES
struct list_head devres_head;
 #endif
+   u64 dma_offset;
 };
 
 /* Maximum sequence number supported */
-- 
2.29.2



[PATCH v2 1/8] rpi: Add identifier for the new RPi400

2020-12-10 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.

Signed-off-by: Nicolas Saenz Julienne 

---

Changes since v1:
 - The RPi Foundation introduced a RPi400 specific device tree, so use
   that file name instead of the fallback (RPi4b).

 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+   [0x13] = {
+   "400",
+   DTB_DIR "bcm2711-rpi-400.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v2 2/8] rpi: Add identifier for the new CM4

2020-12-10 Thread Nicolas Saenz Julienne
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.

Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.

Signed-off-by: Nicolas Saenz Julienne 
---
 board/raspberrypi/rpi/rpi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+   [0x14] = {
+   "Compute Module 4",
+   DTB_DIR "bcm2711-rpi-cm4.dtb",
+   true,
+   },
 };
 
 static const struct rpi_model rpi_models_old_scheme[] = {
-- 
2.29.2



[PATCH v2 8/8] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()

2020-12-10 Thread Nicolas Saenz Julienne
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/mmc/sdhci.c |  7 ---
 include/mmc.h   | 10 ++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 0628934312..2086d7cdb1 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 static void sdhci_reset(struct sdhci_host *host, u8 mask)
 {
@@ -103,7 +102,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, 
struct mmc_data *data,
  mmc_get_dma_dir(data));
 
if (host->flags & USE_SDMA) {
-   sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)host->start_addr),
SDHCI_DMA_ADDRESS);
}
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
@@ -162,7 +162,8 @@ static int sdhci_transfer_data(struct sdhci_host *host, 
struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
-   sdhci_writel(host, 
phys_to_bus((ulong)start_addr),
+   sdhci_writel(host,
+mmc_phys_to_bus(host->mmc, 
(ulong)start_addr),
 SDHCI_DMA_ADDRESS);
}
}
diff --git a/include/mmc.h b/include/mmc.h
index 1d377e0281..805a3b2215 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct bd_info;
 
@@ -977,4 +978,13 @@ static inline enum dma_data_direction 
mmc_get_dma_dir(struct mmc_data *data)
return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 }
 
+static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t addr)
+{
+#if CONFIG_IS_ENABLED(DM_MMC)
+   return dev_phys_to_bus(mmc->dev, addr);
+#else
+   return phys_to_bus(addr);
+#endif
+}
+
 #endif /* _MMC_H_ */
-- 
2.29.2



[PATCH v2 7/8] xhci: translate virtual addresses into the bus's address space

2020-12-10 Thread Nicolas Saenz Julienne
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.

Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.

Signed-off-by: Nicolas Saenz Julienne 
---
 drivers/usb/host/xhci-mem.c  | 45 +++-
 drivers/usb/host/xhci-ring.c | 11 +
 drivers/usb/host/xhci.c  |  4 ++--
 include/usb/xhci.h   | 22 +-
 4 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b002d6f166..83147d51b5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
 
ctrl->dcbaa->dev_context_ptrs[0] = 0;
 
-   free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+   free(xhci_bus_to_virt(ctrl, 
le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return none
  */
-static void xhci_link_segments(struct xhci_segment *prev,
-   struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment 
*prev,
+  struct xhci_segment *next, bool link_trbs)
 {
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
-   val_64 = virt_to_phys(next->trbs);
+   val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
 
@@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
  * @param link_trbsflag to indicate whether to link the trbs or NOT
  * @return pointer to the newly created RING
  */
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int 
num_segs,
+ bool link_trbs)
 {
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, 
bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
 
-   xhci_link_segments(prev, next, link_trbs);
+   xhci_link_segments(ctrl, prev, next, link_trbs);
 
prev = next;
num_segs--;
}
-   xhci_link_segments(prev, ring->first_seg, link_trbs);
+   xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+   uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
-   ctrl->dcbaa->dev_context_ptrs[0] =
-   cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+   val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+   ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
 
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
 
for (i = 0; i < num_sp; i++) {
-   uintptr_t ptr = (uintptr_t)buf + i * page_size;
-   scratchpad->sp_array[i] = cpu_to_le64(ptr);
+   val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+   scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
 
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned 
int slot_id)
}
 
/* Allocate endpoint 0 ring */
-   virt_dev->eps[0].ring = xhci_ring_alloc(1, true);

  1   2   3   >