Hi,
We've had for quite some time to hack around in our drivers to take into account the fact that our DMA accesses are not done through the parent node, but through another bus with a different mapping than the CPU for the RAM (0 instead of 0x40000000 for most SoCs).
After some discussion after the submission of a camera device suffering of the same hacks, I've decided to put together a serie that introduce a property called dma-parent that allows to express the DMA relationship between a master and its bus, even if they are not direct parents in the DT.
This is re-sent, since the previous iteration barely had any feedback.
Let me know what you think, Maxime
Maxime Ripard (7): dt-bindings: Add a dma-parent property dt-bindings: bus: Add binding for the Allwinner MBUS controller of: address: Add parent pointer to the __of_translate_address args of: address: Add support for the dma-parent property drm/sun4i: Rely on dma-parent for our RAM offset clk: sunxi-ng: sun5i: Export the MBUS clock ARM: dts: sun5i: Add the MBUS controller
Documentation/devicetree/bindings/sunxi-mbus.txt | 35 ++++++++++++++- Documentation/devicetree/booting-without-of.txt | 10 ++++- arch/arm/boot/dts/sun5i.dtsi | 11 ++++- drivers/clk/sunxi-ng/ccu-sun5i.h | 4 +-- drivers/gpu/drm/sun4i/sun4i_backend.c | 28 ++++++++--- drivers/of/address.c | 43 ++++++++++++----- include/dt-bindings/clock/sun5i-ccu.h | 2 +- 7 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 Documentation/devicetree/bindings/sunxi-mbus.txt
base-commit: ce397d215ccd07b8ae3f71db689aedb85d56ab40
The current DT bindings assume that the DMA will be performed by the devices through their parent DT node, and rely on that assumption for the address translation using dma-ranges.
However, some SoCs have devices that will perform DMA through another bus, with separate address translation rules. We therefore need to express that relationship, through the dma-parent property.
Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- Documentation/devicetree/booting-without-of.txt | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt index e86bd2f64117..4a65c943c02d 100644 --- a/Documentation/devicetree/booting-without-of.txt +++ b/Documentation/devicetree/booting-without-of.txt @@ -1403,8 +1403,15 @@ In addition, each DMA master device on the DMA bus may or may not support coherent DMA operations. The "dma-coherent" property is intended to be used for identifying devices supported coherent DMA operations in DT.
+Some devices will also perform DMA through another bus than their parent +control bus. In such a case, the "dma-parent" property is intended to express +that relationship to another device in DT that will be the DMA parent bus. + * DMA Bus master Optional property: +- #dma-parent-cells: <integer> + The #dma-parent-cells property defines the width of the cells used to + represent the DMA parent. - dma-ranges: <prop-encoded-array> encoded as arbitrary number of triplets of (child-bus-address, parent-bus-address, length). Each triplet specified describes a contiguous DMA address range. @@ -1420,6 +1427,9 @@ Optional property: - dma-ranges: <empty> value. if present - It means that DMA addresses translation has to be enabled for this device. - dma-coherent: Present if dma operations are coherent +- dma-parent: List of phandles and their optional arguments according to the + #dma-parent-cells from the provider. Expresses the routing of DMA if it + doesn't go through the parent node, but some other node in the device tree.
Example: soc {
The MBUS controller drives the MBUS that other devices in the SoC will use to perform DMA. It also has a register interface that allows to monitor and control the bandwidth and priorities for masters on that bus.
Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- Documentation/devicetree/bindings/sunxi-mbus.txt | 35 +++++++++++++++++- 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/sunxi-mbus.txt
diff --git a/Documentation/devicetree/bindings/sunxi-mbus.txt b/Documentation/devicetree/bindings/sunxi-mbus.txt new file mode 100644 index 000000000000..436df0cac9d0 --- /dev/null +++ b/Documentation/devicetree/bindings/sunxi-mbus.txt @@ -0,0 +1,35 @@ +Allwinner Memory Bus (MBUS) controller + +The MBUS controller drives the MBUS that other devices in the SoC will +use to perform DMA. It also has a register interface that allows to +monitor and control the bandwidth and priorities for masters on that +bus. + +Required properties: + - compatible: Must be one of: + - allwinner,sun5i-a13-mbus + - reg: Offset and length of the register set for the controller + - clocks: phandle to the clock driving the controller + - dma-ranges: see booting-without-of.txt + - #dma-parent-cells: Must be one, with the argument being the MBUS port + ID + +Each device having to perform their DMA through the MBUS must have the +dma-parent property set to the MBUS controller, as documented in +booting-without-of.txt. + +Example: + +mbus: dram-controller@1c01000 { + compatible = "allwinner,sun5i-a13-mbus"; + reg = <0x01c01000 0x1000>; + clocks = <&ccu CLK_MBUS>; + dma-ranges = <0x00000000 0x40000000 0x20000000>; + #dma-parent-cells = <1>; +}; + +fe0: display-frontend@1e00000 { + compatible = "allwinner,sun5i-a13-display-frontend"; + ... + dma-parent = <&mbus 19>; +};
The __of_translate_address function is used to translate the device tree addresses to physical addresses using the various ranges property to create the offset.
However, it's shared between the CPU addresses (based on the ranges property) and the DMA addresses (based on dma-ranges). Since we're going to add support for a DMA parent node that is not the DT parent node, we need to change the logic a bit to have an optional parent node that we should use.
Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- drivers/of/address.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c index 53349912ac75..9e637bf8102c 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -569,10 +569,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * relative to that node. */ static u64 __of_translate_address(struct device_node *dev, + struct device_node *parent, const __be32 *in_addr, const char *rprop, struct device_node **host) { - struct device_node *parent = NULL; struct of_bus *bus, *pbus; __be32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; @@ -583,11 +583,14 @@ static u64 __of_translate_address(struct device_node *dev, /* Increase refcount at current level */ of_node_get(dev);
- *host = NULL; - /* Get parent & match bus type */ - parent = of_get_parent(dev); - if (parent == NULL) - goto bail; + if (!parent) { + *host = NULL; + /* Get parent & match bus type */ + parent = of_get_parent(dev); + if (parent == NULL) + goto bail; + } + bus = of_match_bus(parent);
/* Count address cells & copy address locally */ @@ -665,7 +668,7 @@ u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) struct device_node *host; u64 ret;
- ret = __of_translate_address(dev, in_addr, "ranges", &host); + ret = __of_translate_address(dev, NULL, in_addr, "ranges", &host); if (host) { of_node_put(host); return OF_BAD_ADDR; @@ -680,7 +683,7 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) struct device_node *host; u64 ret;
- ret = __of_translate_address(dev, in_addr, "dma-ranges", &host); + ret = __of_translate_address(dev, NULL, in_addr, "dma-ranges", &host);
if (host) { of_node_put(host);
Hi Maxime,
I love your patch! Yet something to improve:
[auto build test ERROR on ]
url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/sunxi-Add-DT-represen... base: config: x86_64-randconfig-x011-201828 (attached as .config) compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers//of/address.c: In function 'of_translate_ioport':
drivers//of/address.c:742:38: error: passing argument 2 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types]
taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~ drivers//of/address.c:571:12: note: expected 'struct device_node *' but argument is of type 'const __be32 * {aka const unsigned int *}' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ drivers//of/address.c:742:47: error: passing argument 3 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types] taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~~ drivers//of/address.c:571:12: note: expected 'const __be32 * {aka const unsigned int *}' but argument is of type 'char *' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ drivers//of/address.c:742:57: error: passing argument 4 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types] taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers//of/address.c:571:12: note: expected 'const char *' but argument is of type 'struct device_node **' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~
drivers//of/address.c:742:10: error: too few arguments to function '__of_translate_address'
taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~~~~~~~~~~~~~~~~ drivers//of/address.c:571:12: note: declared here static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors
vim +/__of_translate_address +742 drivers//of/address.c
dbbdee94 Grant Likely 2010-06-08 556 dbbdee94 Grant Likely 2010-06-08 557 /* dbbdee94 Grant Likely 2010-06-08 558 * Translate an address from the device-tree into a CPU physical address, dbbdee94 Grant Likely 2010-06-08 559 * this walks up the tree and applies the various bus mappings on the dbbdee94 Grant Likely 2010-06-08 560 * way. dbbdee94 Grant Likely 2010-06-08 561 * dbbdee94 Grant Likely 2010-06-08 562 * Note: We consider that crossing any level with #size-cells == 0 to mean dbbdee94 Grant Likely 2010-06-08 563 * that translation is impossible (that is we are not dealing with a value dbbdee94 Grant Likely 2010-06-08 564 * that can be mapped to a cpu physical address). This is not really specified dbbdee94 Grant Likely 2010-06-08 565 * that way, but this is traditionally the way IBM at least do things 65af618d Zhichang Yuan 2018-03-15 566 * 65af618d Zhichang Yuan 2018-03-15 567 * Whenever the translation fails, the *host pointer will be set to the 65af618d Zhichang Yuan 2018-03-15 568 * device that had registered logical PIO mapping, and the return code is 65af618d Zhichang Yuan 2018-03-15 569 * relative to that node. dbbdee94 Grant Likely 2010-06-08 570 */ 47b1e689 Kim Phillips 2012-10-08 @571 static u64 __of_translate_address(struct device_node *dev, 0e8dae87 Maxime Ripard 2018-07-20 572 struct device_node *parent, 65af618d Zhichang Yuan 2018-03-15 573 const __be32 *in_addr, const char *rprop, 65af618d Zhichang Yuan 2018-03-15 574 struct device_node **host) dbbdee94 Grant Likely 2010-06-08 575 { dbbdee94 Grant Likely 2010-06-08 576 struct of_bus *bus, *pbus; 47b1e689 Kim Phillips 2012-10-08 577 __be32 addr[OF_MAX_ADDR_CELLS]; dbbdee94 Grant Likely 2010-06-08 578 int na, ns, pna, pns; dbbdee94 Grant Likely 2010-06-08 579 u64 result = OF_BAD_ADDR; dbbdee94 Grant Likely 2010-06-08 580 0d638a07 Rob Herring 2017-06-01 581 pr_debug("** translation for device %pOF **\n", dev); dbbdee94 Grant Likely 2010-06-08 582 dbbdee94 Grant Likely 2010-06-08 583 /* Increase refcount at current level */ dbbdee94 Grant Likely 2010-06-08 584 of_node_get(dev); dbbdee94 Grant Likely 2010-06-08 585 0e8dae87 Maxime Ripard 2018-07-20 586 if (!parent) { 65af618d Zhichang Yuan 2018-03-15 587 *host = NULL; dbbdee94 Grant Likely 2010-06-08 588 /* Get parent & match bus type */ dbbdee94 Grant Likely 2010-06-08 589 parent = of_get_parent(dev); dbbdee94 Grant Likely 2010-06-08 590 if (parent == NULL) dbbdee94 Grant Likely 2010-06-08 591 goto bail; 0e8dae87 Maxime Ripard 2018-07-20 592 } 0e8dae87 Maxime Ripard 2018-07-20 593 dbbdee94 Grant Likely 2010-06-08 594 bus = of_match_bus(parent); dbbdee94 Grant Likely 2010-06-08 595 59f5ca48 Andrew Murray 2012-12-13 596 /* Count address cells & copy address locally */ dbbdee94 Grant Likely 2010-06-08 597 bus->count_cells(dev, &na, &ns); dbbdee94 Grant Likely 2010-06-08 598 if (!OF_CHECK_COUNTS(na, ns)) { 0d638a07 Rob Herring 2017-06-01 599 pr_debug("Bad cell count for %pOF\n", dev); dbbdee94 Grant Likely 2010-06-08 600 goto bail; dbbdee94 Grant Likely 2010-06-08 601 } dbbdee94 Grant Likely 2010-06-08 602 memcpy(addr, in_addr, na * 4); dbbdee94 Grant Likely 2010-06-08 603 0d638a07 Rob Herring 2017-06-01 604 pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n", 0d638a07 Rob Herring 2017-06-01 605 bus->name, na, ns, parent); 606ad42a Rob Herring 2016-06-15 606 of_dump_addr("translating address:", addr, na); dbbdee94 Grant Likely 2010-06-08 607 dbbdee94 Grant Likely 2010-06-08 608 /* Translate */ dbbdee94 Grant Likely 2010-06-08 609 for (;;) { 65af618d Zhichang Yuan 2018-03-15 610 struct logic_pio_hwaddr *iorange; 65af618d Zhichang Yuan 2018-03-15 611 dbbdee94 Grant Likely 2010-06-08 612 /* Switch to parent bus */ dbbdee94 Grant Likely 2010-06-08 613 of_node_put(dev); dbbdee94 Grant Likely 2010-06-08 614 dev = parent; dbbdee94 Grant Likely 2010-06-08 615 parent = of_get_parent(dev); dbbdee94 Grant Likely 2010-06-08 616 dbbdee94 Grant Likely 2010-06-08 617 /* If root, we have finished */ dbbdee94 Grant Likely 2010-06-08 618 if (parent == NULL) { 606ad42a Rob Herring 2016-06-15 619 pr_debug("reached root node\n"); dbbdee94 Grant Likely 2010-06-08 620 result = of_read_number(addr, na); dbbdee94 Grant Likely 2010-06-08 621 break; dbbdee94 Grant Likely 2010-06-08 622 } dbbdee94 Grant Likely 2010-06-08 623 65af618d Zhichang Yuan 2018-03-15 624 /* 65af618d Zhichang Yuan 2018-03-15 625 * For indirectIO device which has no ranges property, get 65af618d Zhichang Yuan 2018-03-15 626 * the address from reg directly. 65af618d Zhichang Yuan 2018-03-15 627 */ 65af618d Zhichang Yuan 2018-03-15 628 iorange = find_io_range_by_fwnode(&dev->fwnode); 65af618d Zhichang Yuan 2018-03-15 629 if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) { 65af618d Zhichang Yuan 2018-03-15 630 result = of_read_number(addr + 1, na - 1); 65af618d Zhichang Yuan 2018-03-15 631 pr_debug("indirectIO matched(%pOF) 0x%llx\n", 65af618d Zhichang Yuan 2018-03-15 632 dev, result); 65af618d Zhichang Yuan 2018-03-15 633 *host = of_node_get(dev); 65af618d Zhichang Yuan 2018-03-15 634 break; 65af618d Zhichang Yuan 2018-03-15 635 } 65af618d Zhichang Yuan 2018-03-15 636 dbbdee94 Grant Likely 2010-06-08 637 /* Get new parent bus and counts */ dbbdee94 Grant Likely 2010-06-08 638 pbus = of_match_bus(parent); dbbdee94 Grant Likely 2010-06-08 639 pbus->count_cells(dev, &pna, &pns); dbbdee94 Grant Likely 2010-06-08 640 if (!OF_CHECK_COUNTS(pna, pns)) { 0d638a07 Rob Herring 2017-06-01 641 pr_err("Bad cell count for %pOF\n", dev); dbbdee94 Grant Likely 2010-06-08 642 break; dbbdee94 Grant Likely 2010-06-08 643 } dbbdee94 Grant Likely 2010-06-08 644 0d638a07 Rob Herring 2017-06-01 645 pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n", 0d638a07 Rob Herring 2017-06-01 646 pbus->name, pna, pns, parent); dbbdee94 Grant Likely 2010-06-08 647 dbbdee94 Grant Likely 2010-06-08 648 /* Apply bus translation */ dbbdee94 Grant Likely 2010-06-08 649 if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) dbbdee94 Grant Likely 2010-06-08 650 break; dbbdee94 Grant Likely 2010-06-08 651 dbbdee94 Grant Likely 2010-06-08 652 /* Complete the move up one level */ dbbdee94 Grant Likely 2010-06-08 653 na = pna; dbbdee94 Grant Likely 2010-06-08 654 ns = pns; dbbdee94 Grant Likely 2010-06-08 655 bus = pbus; dbbdee94 Grant Likely 2010-06-08 656 606ad42a Rob Herring 2016-06-15 657 of_dump_addr("one level translation:", addr, na); dbbdee94 Grant Likely 2010-06-08 658 } dbbdee94 Grant Likely 2010-06-08 659 bail: dbbdee94 Grant Likely 2010-06-08 660 of_node_put(parent); dbbdee94 Grant Likely 2010-06-08 661 of_node_put(dev); dbbdee94 Grant Likely 2010-06-08 662 dbbdee94 Grant Likely 2010-06-08 663 return result; dbbdee94 Grant Likely 2010-06-08 664 } dbbdee94 Grant Likely 2010-06-08 665 0131d897 Sebastian Andrzej Siewior 2010-12-01 666 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) dbbdee94 Grant Likely 2010-06-08 667 { 65af618d Zhichang Yuan 2018-03-15 668 struct device_node *host; 65af618d Zhichang Yuan 2018-03-15 669 u64 ret; 65af618d Zhichang Yuan 2018-03-15 670 0e8dae87 Maxime Ripard 2018-07-20 671 ret = __of_translate_address(dev, NULL, in_addr, "ranges", &host); 65af618d Zhichang Yuan 2018-03-15 672 if (host) { 65af618d Zhichang Yuan 2018-03-15 673 of_node_put(host); 65af618d Zhichang Yuan 2018-03-15 674 return OF_BAD_ADDR; 65af618d Zhichang Yuan 2018-03-15 675 } 65af618d Zhichang Yuan 2018-03-15 676 65af618d Zhichang Yuan 2018-03-15 677 return ret; dbbdee94 Grant Likely 2010-06-08 678 } dbbdee94 Grant Likely 2010-06-08 679 EXPORT_SYMBOL(of_translate_address); dbbdee94 Grant Likely 2010-06-08 680 0131d897 Sebastian Andrzej Siewior 2010-12-01 681 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) dbbdee94 Grant Likely 2010-06-08 682 { 65af618d Zhichang Yuan 2018-03-15 683 struct device_node *host; 65af618d Zhichang Yuan 2018-03-15 684 u64 ret; 65af618d Zhichang Yuan 2018-03-15 685 0e8dae87 Maxime Ripard 2018-07-20 686 ret = __of_translate_address(dev, NULL, in_addr, "dma-ranges", &host); 65af618d Zhichang Yuan 2018-03-15 687 65af618d Zhichang Yuan 2018-03-15 688 if (host) { 65af618d Zhichang Yuan 2018-03-15 689 of_node_put(host); 65af618d Zhichang Yuan 2018-03-15 690 return OF_BAD_ADDR; 65af618d Zhichang Yuan 2018-03-15 691 } 65af618d Zhichang Yuan 2018-03-15 692 65af618d Zhichang Yuan 2018-03-15 693 return ret; dbbdee94 Grant Likely 2010-06-08 694 } dbbdee94 Grant Likely 2010-06-08 695 EXPORT_SYMBOL(of_translate_dma_address); dbbdee94 Grant Likely 2010-06-08 696 0131d897 Sebastian Andrzej Siewior 2010-12-01 697 const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, dbbdee94 Grant Likely 2010-06-08 698 unsigned int *flags) dbbdee94 Grant Likely 2010-06-08 699 { 0131d897 Sebastian Andrzej Siewior 2010-12-01 700 const __be32 *prop; dbbdee94 Grant Likely 2010-06-08 701 unsigned int psize; dbbdee94 Grant Likely 2010-06-08 702 struct device_node *parent; dbbdee94 Grant Likely 2010-06-08 703 struct of_bus *bus; dbbdee94 Grant Likely 2010-06-08 704 int onesize, i, na, ns; dbbdee94 Grant Likely 2010-06-08 705 dbbdee94 Grant Likely 2010-06-08 706 /* Get parent & match bus type */ dbbdee94 Grant Likely 2010-06-08 707 parent = of_get_parent(dev); dbbdee94 Grant Likely 2010-06-08 708 if (parent == NULL) dbbdee94 Grant Likely 2010-06-08 709 return NULL; dbbdee94 Grant Likely 2010-06-08 710 bus = of_match_bus(parent); dbbdee94 Grant Likely 2010-06-08 711 bus->count_cells(dev, &na, &ns); dbbdee94 Grant Likely 2010-06-08 712 of_node_put(parent); 5d61b165 Stephen Warren 2012-07-25 713 if (!OF_CHECK_ADDR_COUNT(na)) dbbdee94 Grant Likely 2010-06-08 714 return NULL; dbbdee94 Grant Likely 2010-06-08 715 dbbdee94 Grant Likely 2010-06-08 716 /* Get "reg" or "assigned-addresses" property */ dbbdee94 Grant Likely 2010-06-08 717 prop = of_get_property(dev, bus->addresses, &psize); dbbdee94 Grant Likely 2010-06-08 718 if (prop == NULL) dbbdee94 Grant Likely 2010-06-08 719 return NULL; dbbdee94 Grant Likely 2010-06-08 720 psize /= 4; dbbdee94 Grant Likely 2010-06-08 721 dbbdee94 Grant Likely 2010-06-08 722 onesize = na + ns; dbbdee94 Grant Likely 2010-06-08 723 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) dbbdee94 Grant Likely 2010-06-08 724 if (i == index) { dbbdee94 Grant Likely 2010-06-08 725 if (size) dbbdee94 Grant Likely 2010-06-08 726 *size = of_read_number(prop + na, ns); dbbdee94 Grant Likely 2010-06-08 727 if (flags) dbbdee94 Grant Likely 2010-06-08 728 *flags = bus->get_flags(prop); dbbdee94 Grant Likely 2010-06-08 729 return prop; dbbdee94 Grant Likely 2010-06-08 730 } dbbdee94 Grant Likely 2010-06-08 731 return NULL; dbbdee94 Grant Likely 2010-06-08 732 } dbbdee94 Grant Likely 2010-06-08 733 EXPORT_SYMBOL(of_get_address); dbbdee94 Grant Likely 2010-06-08 734 65af618d Zhichang Yuan 2018-03-15 735 static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, 65af618d Zhichang Yuan 2018-03-15 736 u64 size) 65af618d Zhichang Yuan 2018-03-15 737 { 65af618d Zhichang Yuan 2018-03-15 738 u64 taddr; 65af618d Zhichang Yuan 2018-03-15 739 unsigned long port; 65af618d Zhichang Yuan 2018-03-15 740 struct device_node *host; 65af618d Zhichang Yuan 2018-03-15 741 65af618d Zhichang Yuan 2018-03-15 @742 taddr = __of_translate_address(dev, in_addr, "ranges", &host); 65af618d Zhichang Yuan 2018-03-15 743 if (host) { 65af618d Zhichang Yuan 2018-03-15 744 /* host-specific port access */ 65af618d Zhichang Yuan 2018-03-15 745 port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); 65af618d Zhichang Yuan 2018-03-15 746 of_node_put(host); 65af618d Zhichang Yuan 2018-03-15 747 } else { 65af618d Zhichang Yuan 2018-03-15 748 /* memory-mapped I/O range */ 65af618d Zhichang Yuan 2018-03-15 749 port = pci_address_to_pio(taddr); 65af618d Zhichang Yuan 2018-03-15 750 } 65af618d Zhichang Yuan 2018-03-15 751 65af618d Zhichang Yuan 2018-03-15 752 if (port == (unsigned long)-1) 65af618d Zhichang Yuan 2018-03-15 753 return OF_BAD_ADDR; 65af618d Zhichang Yuan 2018-03-15 754 65af618d Zhichang Yuan 2018-03-15 755 return port; 65af618d Zhichang Yuan 2018-03-15 756 } 65af618d Zhichang Yuan 2018-03-15 757
:::::: The code at line 742 was first introduced by commit :::::: 65af618d2c559f8eb19d80d03a23029651a59de4 of: Add missing I/O range exception for indirect-IO devices
:::::: TO: Zhichang Yuan yuanzhichang@hisilicon.com :::::: CC: Bjorn Helgaas helgaas@kernel.org
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Maxime,
I love your patch! Perhaps something to improve:
[auto build test WARNING on ]
url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/sunxi-Add-DT-represen... base: config: i386-randconfig-a1-201828 (attached as .config) compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4 reproduce: # save the attached .config to linux build tree make ARCH=i386
All warnings (new ones prefixed by >>):
drivers/of/address.c: In function 'of_translate_ioport':
drivers/of/address.c:742:38: warning: passing argument 2 of '__of_translate_address' from incompatible pointer type
taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers/of/address.c:571:12: note: expected 'struct device_node *' but argument is of type 'const __be32 *' static u64 __of_translate_address(struct device_node *dev, ^ drivers/of/address.c:742:47: warning: passing argument 3 of '__of_translate_address' from incompatible pointer type taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers/of/address.c:571:12: note: expected 'const __be32 *' but argument is of type 'char *' static u64 __of_translate_address(struct device_node *dev, ^ drivers/of/address.c:742:57: warning: passing argument 4 of '__of_translate_address' from incompatible pointer type taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers/of/address.c:571:12: note: expected 'const char *' but argument is of type 'struct device_node **' static u64 __of_translate_address(struct device_node *dev, ^ drivers/of/address.c:742:10: error: too few arguments to function '__of_translate_address' taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers/of/address.c:571:12: note: declared here static u64 __of_translate_address(struct device_node *dev, ^
vim +/__of_translate_address +742 drivers/of/address.c
dbbdee94 Grant Likely 2010-06-08 734 65af618d Zhichang Yuan 2018-03-15 735 static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, 65af618d Zhichang Yuan 2018-03-15 736 u64 size) 65af618d Zhichang Yuan 2018-03-15 737 { 65af618d Zhichang Yuan 2018-03-15 738 u64 taddr; 65af618d Zhichang Yuan 2018-03-15 739 unsigned long port; 65af618d Zhichang Yuan 2018-03-15 740 struct device_node *host; 65af618d Zhichang Yuan 2018-03-15 741 65af618d Zhichang Yuan 2018-03-15 @742 taddr = __of_translate_address(dev, in_addr, "ranges", &host); 65af618d Zhichang Yuan 2018-03-15 743 if (host) { 65af618d Zhichang Yuan 2018-03-15 744 /* host-specific port access */ 65af618d Zhichang Yuan 2018-03-15 745 port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); 65af618d Zhichang Yuan 2018-03-15 746 of_node_put(host); 65af618d Zhichang Yuan 2018-03-15 747 } else { 65af618d Zhichang Yuan 2018-03-15 748 /* memory-mapped I/O range */ 65af618d Zhichang Yuan 2018-03-15 749 port = pci_address_to_pio(taddr); 65af618d Zhichang Yuan 2018-03-15 750 } 65af618d Zhichang Yuan 2018-03-15 751 65af618d Zhichang Yuan 2018-03-15 752 if (port == (unsigned long)-1) 65af618d Zhichang Yuan 2018-03-15 753 return OF_BAD_ADDR; 65af618d Zhichang Yuan 2018-03-15 754 65af618d Zhichang Yuan 2018-03-15 755 return port; 65af618d Zhichang Yuan 2018-03-15 756 } 65af618d Zhichang Yuan 2018-03-15 757
:::::: The code at line 742 was first introduced by commit :::::: 65af618d2c559f8eb19d80d03a23029651a59de4 of: Add missing I/O range exception for indirect-IO devices
:::::: TO: Zhichang Yuan yuanzhichang@hisilicon.com :::::: CC: Bjorn Helgaas helgaas@kernel.org
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Maxime,
I love your patch! Perhaps something to improve:
[auto build test WARNING on ]
url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/sunxi-Add-DT-represen... base: reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
drivers/of/address.c:742:45: sparse: incorrect type in argument 2 (different base types) @@ expected struct device_node *[assigned] parent @@ got restrstruct device_node *[assigned] parent @@
drivers/of/address.c:742:45: expected struct device_node *[assigned] parent drivers/of/address.c:742:45: got restricted __be32 const [usertype] *in_addr
drivers/of/address.c:742:54: sparse: incorrect type in argument 3 (different base types) @@ expected restricted __be32 const [usertype] *in_addr @@ got ype] *in_addr @@
drivers/of/address.c:742:54: expected restricted __be32 const [usertype] *in_addr drivers/of/address.c:742:54: got char *<noident>
drivers/of/address.c:742:65: sparse: incorrect type in argument 4 (different base types) @@ expected char const *rprop @@ got struct dechar const *rprop @@
drivers/of/address.c:742:65: expected char const *rprop drivers/of/address.c:742:65: got struct device_node **<noident>
drivers/of/address.c:742:39: sparse: not enough arguments for function __of_translate_address
drivers/of/address.c: In function 'of_translate_ioport': drivers/of/address.c:742:38: error: passing argument 2 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types] taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~ drivers/of/address.c:571:12: note: expected 'struct device_node *' but argument is of type 'const __be32 * {aka const unsigned int *}' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ drivers/of/address.c:742:47: error: passing argument 3 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types] taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~~ drivers/of/address.c:571:12: note: expected 'const __be32 * {aka const unsigned int *}' but argument is of type 'char *' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ drivers/of/address.c:742:57: error: passing argument 4 of '__of_translate_address' from incompatible pointer type [-Werror=incompatible-pointer-types] taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^ drivers/of/address.c:571:12: note: expected 'const char *' but argument is of type 'struct device_node **' static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ drivers/of/address.c:742:10: error: too few arguments to function '__of_translate_address' taddr = __of_translate_address(dev, in_addr, "ranges", &host); ^~~~~~~~~~~~~~~~~~~~~~ drivers/of/address.c:571:12: note: declared here static u64 __of_translate_address(struct device_node *dev, ^~~~~~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors
vim +742 drivers/of/address.c
dbbdee94 Grant Likely 2010-06-08 734 65af618d Zhichang Yuan 2018-03-15 735 static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, 65af618d Zhichang Yuan 2018-03-15 736 u64 size) 65af618d Zhichang Yuan 2018-03-15 737 { 65af618d Zhichang Yuan 2018-03-15 738 u64 taddr; 65af618d Zhichang Yuan 2018-03-15 739 unsigned long port; 65af618d Zhichang Yuan 2018-03-15 740 struct device_node *host; 65af618d Zhichang Yuan 2018-03-15 741 65af618d Zhichang Yuan 2018-03-15 @742 taddr = __of_translate_address(dev, in_addr, "ranges", &host); 65af618d Zhichang Yuan 2018-03-15 743 if (host) { 65af618d Zhichang Yuan 2018-03-15 744 /* host-specific port access */ 65af618d Zhichang Yuan 2018-03-15 745 port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); 65af618d Zhichang Yuan 2018-03-15 746 of_node_put(host); 65af618d Zhichang Yuan 2018-03-15 747 } else { 65af618d Zhichang Yuan 2018-03-15 748 /* memory-mapped I/O range */ 65af618d Zhichang Yuan 2018-03-15 749 port = pci_address_to_pio(taddr); 65af618d Zhichang Yuan 2018-03-15 750 } 65af618d Zhichang Yuan 2018-03-15 751 65af618d Zhichang Yuan 2018-03-15 752 if (port == (unsigned long)-1) 65af618d Zhichang Yuan 2018-03-15 753 return OF_BAD_ADDR; 65af618d Zhichang Yuan 2018-03-15 754 65af618d Zhichang Yuan 2018-03-15 755 return port; 65af618d Zhichang Yuan 2018-03-15 756 } 65af618d Zhichang Yuan 2018-03-15 757
:::::: The code at line 742 was first introduced by commit :::::: 65af618d2c559f8eb19d80d03a23029651a59de4 of: Add missing I/O range exception for indirect-IO devices
:::::: TO: Zhichang Yuan yuanzhichang@hisilicon.com :::::: CC: Bjorn Helgaas helgaas@kernel.org
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Some SoCs have devices that are using a separate bus from the main bus to perform DMA.
These buses might have some restrictions and/or different mapping than from the CPU side, so we'd need to express those using the usual dma-ranges, but using a different DT node than the node's parent.
Add support for a dma-parent property that links to the DMA bus used by the device in such a case.
Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- drivers/of/address.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c index 9e637bf8102c..e4c8207871d1 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -680,10 +680,18 @@ EXPORT_SYMBOL(of_translate_address);
u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) { + struct of_phandle_args args; + struct device_node *parent = NULL; struct device_node *host; u64 ret;
- ret = __of_translate_address(dev, NULL, in_addr, "dma-ranges", &host); + ret = of_parse_phandle_with_args(dev, "dma-parent", + "#dma-parent-cells", + 0, &args); + if (!ret) + parent = args.np; + + ret = __of_translate_address(dev, parent, in_addr, "dma-ranges", &host);
if (host) { of_node_put(host); @@ -909,11 +917,21 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz return -EINVAL;
while (1) { + struct of_phandle_args args; + naddr = of_n_addr_cells(node); nsize = of_n_size_cells(node); - node = of_get_next_parent(node); - if (!node) - break; + + ret = of_parse_phandle_with_args(node, "dma-parent", + "#dma-parent-cells", + 0, &args); + if (!ret) { + node = args.np; + } else { + node = of_get_next_parent(node); + if (!node) + break; + }
ranges = of_get_property(node, "dma-ranges", &len);
Now that we can express our DMA topology, rely on those property instead of hardcoding an offset from the dma_addr_t which wasn't really great.
We still need to add some code to deal with the old DT that would lack that property, but we move the offset to the DRM device dma_pfn_offset to be able to rely on just the dma_addr_t associated to the GEM object.
Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index de0a76dfa1a2..277f23a3115f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -377,13 +377,6 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, paddr = drm_fb_cma_get_gem_addr(fb, state, 0); DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
- /* - * backend DMA accesses DRAM directly, bypassing the system - * bus. As such, the address range is different and the buffer - * address needs to be corrected. - */ - paddr -= PHYS_OFFSET; - if (sun4i_backend_format_is_yuv(fb->format->format)) return sun4i_backend_update_yuv_buffer(backend, fb, paddr);
@@ -772,6 +765,27 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, dev_set_drvdata(dev, backend); spin_lock_init(&backend->frontend_lock);
+ if (of_find_property(dev->of_node, "dma-parent", NULL)) { + /* + * This assume we have the same DMA constraints for all our the + * devices in our pipeline (all the backends, but also the + * frontends). This sounds bad, but it has always been the case + * for us, and DRM doesn't do per-device allocation either, so + * we would need to fix DRM first... + */ + ret = of_dma_configure(drm->dev, dev->of_node); + if (ret) + return ret; + } else { + /* + * If we don't have the dma-parent property, most likely + * because of an old DT, we need to set the DMA offset by hand + * on our device since the RAM mapping is at 0 for the DMA bus, + * unlike the CPU. + */ + drm->dev->dma_pfn_offset = PHYS_PFN_OFFSET; + } + backend->engine.node = dev->of_node; backend->engine.ops = &sun4i_backend_engine_ops; backend->engine.id = sun4i_backend_of_get_id(dev->of_node);
Hi Maxime,
I love your patch! Yet something to improve:
[auto build test ERROR on ]
url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/sunxi-Add-DT-represen... base: config: arm-sunxi_defconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=arm
All errors (new ones prefixed by >>):
drivers/gpu/drm/sun4i/sun4i_backend.c: In function 'sun4i_backend_bind':
drivers/gpu/drm/sun4i/sun4i_backend.c:776:9: error: too few arguments to function 'of_dma_configure'
ret = of_dma_configure(drm->dev, dev->of_node); ^~~~~~~~~~~~~~~~ In file included from drivers/gpu/drm/sun4i/sun4i_backend.c:24:0: include/linux/of_device.h:58:5: note: declared here int of_dma_configure(struct device *dev, ^~~~~~~~~~~~~~~~
vim +/of_dma_configure +776 drivers/gpu/drm/sun4i/sun4i_backend.c
749 750 static int sun4i_backend_bind(struct device *dev, struct device *master, 751 void *data) 752 { 753 struct platform_device *pdev = to_platform_device(dev); 754 struct drm_device *drm = data; 755 struct sun4i_drv *drv = drm->dev_private; 756 struct sun4i_backend *backend; 757 const struct sun4i_backend_quirks *quirks; 758 struct resource *res; 759 void __iomem *regs; 760 int i, ret; 761 762 backend = devm_kzalloc(dev, sizeof(*backend), GFP_KERNEL); 763 if (!backend) 764 return -ENOMEM; 765 dev_set_drvdata(dev, backend); 766 spin_lock_init(&backend->frontend_lock); 767 768 if (of_find_property(dev->of_node, "dma-parent", NULL)) { 769 /* 770 * This assume we have the same DMA constraints for all our the 771 * devices in our pipeline (all the backends, but also the 772 * frontends). This sounds bad, but it has always been the case 773 * for us, and DRM doesn't do per-device allocation either, so 774 * we would need to fix DRM first... 775 */
776 ret = of_dma_configure(drm->dev, dev->of_node);
777 if (ret) 778 return ret; 779 } else { 780 /* 781 * If we don't have the dma-parent property, most likely 782 * because of an old DT, we need to set the DMA offset by hand 783 * on our device since the RAM mapping is at 0 for the DMA bus, 784 * unlike the CPU. 785 */ 786 drm->dev->dma_pfn_offset = PHYS_PFN_OFFSET; 787 } 788 789 backend->engine.node = dev->of_node; 790 backend->engine.ops = &sun4i_backend_engine_ops; 791 backend->engine.id = sun4i_backend_of_get_id(dev->of_node); 792 if (backend->engine.id < 0) 793 return backend->engine.id; 794 795 backend->frontend = sun4i_backend_find_frontend(drv, dev->of_node); 796 if (IS_ERR(backend->frontend)) 797 dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n"); 798 799 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 800 regs = devm_ioremap_resource(dev, res); 801 if (IS_ERR(regs)) 802 return PTR_ERR(regs); 803 804 backend->reset = devm_reset_control_get(dev, NULL); 805 if (IS_ERR(backend->reset)) { 806 dev_err(dev, "Couldn't get our reset line\n"); 807 return PTR_ERR(backend->reset); 808 } 809 810 ret = reset_control_deassert(backend->reset); 811 if (ret) { 812 dev_err(dev, "Couldn't deassert our reset line\n"); 813 return ret; 814 } 815 816 backend->bus_clk = devm_clk_get(dev, "ahb"); 817 if (IS_ERR(backend->bus_clk)) { 818 dev_err(dev, "Couldn't get the backend bus clock\n"); 819 ret = PTR_ERR(backend->bus_clk); 820 goto err_assert_reset; 821 } 822 clk_prepare_enable(backend->bus_clk); 823 824 backend->mod_clk = devm_clk_get(dev, "mod"); 825 if (IS_ERR(backend->mod_clk)) { 826 dev_err(dev, "Couldn't get the backend module clock\n"); 827 ret = PTR_ERR(backend->mod_clk); 828 goto err_disable_bus_clk; 829 } 830 clk_prepare_enable(backend->mod_clk); 831 832 backend->ram_clk = devm_clk_get(dev, "ram"); 833 if (IS_ERR(backend->ram_clk)) { 834 dev_err(dev, "Couldn't get the backend RAM clock\n"); 835 ret = PTR_ERR(backend->ram_clk); 836 goto err_disable_mod_clk; 837 } 838 clk_prepare_enable(backend->ram_clk); 839 840 if (of_device_is_compatible(dev->of_node, 841 "allwinner,sun8i-a33-display-backend")) { 842 ret = sun4i_backend_init_sat(dev); 843 if (ret) { 844 dev_err(dev, "Couldn't init SAT resources\n"); 845 goto err_disable_ram_clk; 846 } 847 } 848 849 backend->engine.regs = devm_regmap_init_mmio(dev, regs, 850 &sun4i_backend_regmap_config); 851 if (IS_ERR(backend->engine.regs)) { 852 dev_err(dev, "Couldn't create the backend regmap\n"); 853 return PTR_ERR(backend->engine.regs); 854 } 855 856 list_add_tail(&backend->engine.list, &drv->engine_list); 857 858 /* 859 * Many of the backend's layer configuration registers have 860 * undefined default values. This poses a risk as we use 861 * regmap_update_bits in some places, and don't overwrite 862 * the whole register. 863 * 864 * Clear the registers here to have something predictable. 865 */ 866 for (i = 0x800; i < 0x1000; i += 4) 867 regmap_write(backend->engine.regs, i, 0); 868 869 /* Disable registers autoloading */ 870 regmap_write(backend->engine.regs, SUN4I_BACKEND_REGBUFFCTL_REG, 871 SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS); 872 873 /* Enable the backend */ 874 regmap_write(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, 875 SUN4I_BACKEND_MODCTL_DEBE_EN | 876 SUN4I_BACKEND_MODCTL_START_CTL); 877 878 /* Set output selection if needed */ 879 quirks = of_device_get_match_data(dev); 880 if (quirks->needs_output_muxing) { 881 /* 882 * We assume there is no dynamic muxing of backends 883 * and TCONs, so we select the backend with same ID. 884 * 885 * While dynamic selection might be interesting, since 886 * the CRTC is tied to the TCON, while the layers are 887 * tied to the backends, this means, we will need to 888 * switch between groups of layers. There might not be 889 * a way to represent this constraint in DRM. 890 */ 891 regmap_update_bits(backend->engine.regs, 892 SUN4I_BACKEND_MODCTL_REG, 893 SUN4I_BACKEND_MODCTL_OUT_SEL, 894 (backend->engine.id 895 ? SUN4I_BACKEND_MODCTL_OUT_LCD1 896 : SUN4I_BACKEND_MODCTL_OUT_LCD0)); 897 } 898 899 return 0; 900 901 err_disable_ram_clk: 902 clk_disable_unprepare(backend->ram_clk); 903 err_disable_mod_clk: 904 clk_disable_unprepare(backend->mod_clk); 905 err_disable_bus_clk: 906 clk_disable_unprepare(backend->bus_clk); 907 err_assert_reset: 908 reset_control_assert(backend->reset); 909 return ret; 910 } 911
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
The MBUS clock is used by the MBUS controller, so let's export it so that we can use it in our DT node.
Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- drivers/clk/sunxi-ng/ccu-sun5i.h | 4 ---- include/dt-bindings/clock/sun5i-ccu.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.h b/drivers/clk/sunxi-ng/ccu-sun5i.h index 93a275fbd9a9..b66abd4fd0bf 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.h +++ b/drivers/clk/sunxi-ng/ccu-sun5i.h @@ -60,10 +60,6 @@
/* The rest of the module clocks are exported */
-#define CLK_MBUS 99 - -/* And finally the IEP clock */ - #define CLK_NUMBER (CLK_IEP + 1)
#endif /* _CCU_SUN5I_H_ */ diff --git a/include/dt-bindings/clock/sun5i-ccu.h b/include/dt-bindings/clock/sun5i-ccu.h index 81f34d477aeb..2e6b9ddcc24e 100644 --- a/include/dt-bindings/clock/sun5i-ccu.h +++ b/include/dt-bindings/clock/sun5i-ccu.h @@ -100,7 +100,7 @@ #define CLK_AVS 96 #define CLK_HDMI 97 #define CLK_GPU 98 - +#define CLK_MBUS 99 #define CLK_IEP 100
#endif /* _DT_BINDINGS_CLK_SUN5I_H_ */
The MBUS (and its associated controller) is the bus in the Allwinner SoCs that DMA devices use in the system to access the memory.
Among other things (and depending on the SoC generation), it can also enforce priorities or report bandwidth usages on a per-master basis.
One of the most notable thing is that instead of having the same mapping for the RAM than the CPU, it maps it at address 0, which means we'll have to do address translation thanks to the dma-ranges property.
Signed-off-by: Maxime Ripard maxime.ripard@bootlin.com --- arch/arm/boot/dts/sun5i.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 07f2248ed5f8..acb24e537e0b 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -112,6 +112,7 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; + dma-ranges; ranges;
sram-controller@1c00000 { @@ -150,6 +151,14 @@ }; };
+ mbus: dram-controller@1c01000 { + compatible = "allwinner,sun5i-a13-mbus"; + reg = <0x01c01000 0x1000>; + clocks = <&ccu CLK_MBUS>; + dma-ranges = <0x00000000 0x40000000 0x20000000>; + #dma-parent-cells = <1>; + }; + dma: dma-controller@1c02000 { compatible = "allwinner,sun4i-a10-dma"; reg = <0x01c02000 0x1000>; @@ -677,6 +686,7 @@ clock-names = "ahb", "mod", "ram"; resets = <&ccu RST_DE_FE>; + dma-parent = <&mbus 19>; status = "disabled";
ports { @@ -705,6 +715,7 @@ clock-names = "ahb", "mod", "ram"; resets = <&ccu RST_DE_BE>; + dma-parent = <&mbus 18>; status = "disabled";
assigned-clocks = <&ccu CLK_DE_BE>;
dri-devel@lists.freedesktop.org