From: Felix Fietkau Date: Fri, 4 Sep 2020 18:42:42 +0200 Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA It improves performance by eliminating the need for a cache flush for DMA on attached devices Signed-off-by: Felix Fietkau --- --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -812,6 +812,8 @@ reg = <0 0x1a143000 0 0x1000>; reg-names = "port0"; mediatek,pcie-cfg = <&pciecfg>; + mediatek,hifsys = <&hifsys>; + mediatek,cci-control = <&cci_control2>; #address-cells = <3>; #size-cells = <2>; interrupts = ; @@ -829,6 +831,7 @@ bus-range = <0x00 0xff>; ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; status = "disabled"; + dma-coherent; slot0: pcie@0,0 { reg = <0x0000 0 0 0 0>; @@ -855,6 +858,8 @@ reg = <0 0x1a145000 0 0x1000>; reg-names = "port1"; mediatek,pcie-cfg = <&pciecfg>; + mediatek,hifsys = <&hifsys>; + mediatek,cci-control = <&cci_control2>; #address-cells = <3>; #size-cells = <2>; interrupts = ; @@ -873,6 +878,7 @@ bus-range = <0x00 0xff>; ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; status = "disabled"; + dma-coherent; slot1: pcie@1,0 { reg = <0x0800 0 0 0 0>; @@ -932,6 +938,11 @@ }; }; + hifsys: syscon@1af00000 { + compatible = "mediatek,mt7622-hifsys", "syscon"; + reg = <0 0x1af00000 0 0x70>; + }; + ethsys: syscon@1b000000 { compatible = "mediatek,mt7622-ethsys", "syscon"; --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +140,11 @@ #define PCIE_LINK_STATUS_V2 0x804 #define PCIE_PORT_LINKUP_V2 BIT(10) +/* DMA channel mapping */ +#define HIFSYS_DMA_AG_MAP 0x008 +#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) +#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) + struct mtk_pcie_port; /** @@ -1042,6 +1048,27 @@ static int mtk_pcie_setup(struct mtk_pci struct mtk_pcie_port *port, *tmp; int err; + if (of_dma_is_coherent(node)) { + struct regmap *con; + u32 mask; + + con = syscon_regmap_lookup_by_phandle(node, + "mediatek,cci-control"); + /* enable CPU/bus coherency */ + if (!IS_ERR(con)) + regmap_write(con, 0, 3); + + con = syscon_regmap_lookup_by_phandle(node, + "mediatek,hifsys"); + if (IS_ERR(con)) { + dev_err(dev, "missing hifsys node\n"); + return PTR_ERR(con); + } + + mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; + regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); + } + for_each_available_child_of_node(node, child) { int slot;