bcm2835: Getting DMA-busaddress for HW-register

Stephen Warren swarren at wwwdotorg.org
Mon May 11 19:59:46 PDT 2015


On 05/10/2015 10:36 AM, Noralf Trønnes wrote:
> 
> Den 10.05.2015 14:35, skrev Martin Sperl:
>> To make the dma implementation of spi-bcm2835.c portable
>> I need to get the DMA address for the registers somewhere.
>>
>> platform_get_resource only gives me the address of the register
>> in arm-address-space (so for SPI: start=20204000 end=20204fff)
>>
>> Is there a better (and portable) way to get the dma_addr_t
>> other than using the following (as per sound/soc/bcm/bcm2835-i2s.c):
>>
>> #define BCM2835_VCMMU_SHIFT             (0x7E000000 - 0x20000000)
>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> dma_reg = res->start + BCM2835_VCMMU_SHIFT + BCM2835_SPI_FIFO;
>>
>> This obviously does not/will not work with a rpi2 where it would
>> need to be defined as:
>> #define BCM2835_VCMMU_SHIFT             (0x7E000000 - 0x3F000000)
>>
>> Another option would be hard-coding the base-address
>> (as it can not change anyway):
>> dma_reg = 0x7E204000 + BCM2835_SPI_FIFO;
>>
>> In principle the information is in the device-tree:
>>          soc {
>>                  compatible = "simple-bus";
>>                  ranges = <0x7e000000 0x20000000 0x2000000>;
>> ...
>>                  spi at 7e204000 {
>>                          reg = <0x7e204000 0x1000>;
>>
>> So how can I get the base address from the device tree?
> 
> Apparently dma_regs is the same as the reg DT property:
> 
> --- workdir/linux/drivers/spi/spi-bcm2835.c.dma    2015-05-10
> 18:18:28.955545580 +0200
> +++ workdir/linux/drivers/spi/spi-bcm2835.c    2015-05-10
> 18:20:26.315255619 +0200

> @@ -793,6 +794,15 @@
>  #define BCM2835_VCMMU_SHIFT             (0x7E000000 - 0x20000000)
>      bs->dma_regs = res->start + BCM2835_VCMMU_SHIFT;
> 
> +    {
> +    const __be32 *addrp;
> +
> +    pr_info("%s: bs->dma_regs=%pad\n", __func__, &bs->dma_regs);
> +    addrp = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
> +    if (addrp)
> +        pr_info("%s: reg=0x%x\n", __func__, be32_to_cpup(addrp));
> +    }

The DT property shouldn't ever be read directly; parsing the raw data
without using the DT helpers to do so will result in the ranges
properties etc. not being correctly applied. While this does result in
getting the value you /want/, it's not a legal way to get that value.

Instead, you want something that ends up using the dma-ranges property.
Eric Anholt sent a patch to do this upstream recently:

https://lkml.org/lkml/2015/5/4/657
[PATCH] ARM: bcm2835: Use 0x4 prefix for DMA bus addresses
which contains:
> diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
> index 5734650..2df1b5c 100644
> --- a/arch/arm/boot/dts/bcm2835.dtsi
> +++ b/arch/arm/boot/dts/bcm2835.dtsi
> @@ -15,6 +15,7 @@
>  		#address-cells = <1>;
>  		#size-cells = <1>;
>  		ranges = <0x7e000000 0x20000000 0x02000000>;
> +		dma-ranges = <0x40000000 0x00000000 0x1f000000>;

> +
>      bs->clk = devm_clk_get(&pdev->dev, NULL);
>      if (IS_ERR(bs->clk)) {
>          err = PTR_ERR(bs->clk);
> 
> Results in:
> [    5.934687] bcm2835_spi_probe: bs->dma_regs=0x7e204000
> [    6.066097] bcm2835_spi_probe: reg=0x7e204000




More information about the linux-rpi-kernel mailing list