Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: [plat-hsdk]: allow to switch between AXI DMAC port configurations

We want to use DW AXI DMAC on HSDK board in our automated verification
to test cache & dma kernel code changes. This is perfect candidate
as we don't depend on any external peripherals like MMC card / USB
storage / etc.
To increase test coverage we want to test both options:
* DW AXI DMAC is connected through IOC port & dma direct ops used
* DW AXI DMAC is connected to DDR port & dma noncoherent ops used

Introduce 'arc_hsdk_axi_dmac_coherent' global variable which can be
modified by debugger (same way as we patch 'ioc_enable') to switch
between these options without recompiling the kernel.
Depend on this value we tweak memory bridge configuration and
"dma-coherent" DTS property of DW AXI DMAC.

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Acked-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>

authored by

Eugeniy Paltsev and committed by
Vineet Gupta
ce0eff0d da31076f

+78 -12
+3
arch/arc/boot/dts/Makefile
··· 12 12 # for CONFIG_OF_ALL_DTBS test 13 13 dtstree := $(srctree)/$(src) 14 14 dtb- := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) 15 + 16 + # board-specific dtc flags 17 + DTC_FLAGS_hsdk += --pad 20
+75 -12
arch/arc/plat-hsdk/platform.c
··· 6 6 */ 7 7 8 8 #include <linux/init.h> 9 + #include <linux/of_fdt.h> 10 + #include <linux/libfdt.h> 9 11 #include <linux/smp.h> 10 12 #include <asm/arcregs.h> 11 13 #include <asm/io.h> 12 14 #include <asm/mach_desc.h> 15 + 16 + int arc_hsdk_axi_dmac_coherent __section(.data) = 0; 13 17 14 18 #define ARC_CCM_UNUSED_ADDR 0x60000000 15 19 ··· 101 97 iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN); 102 98 } 103 99 100 + static int __init hsdk_tweak_node_coherency(const char *path, bool coherent) 101 + { 102 + void *fdt = initial_boot_params; 103 + const void *prop; 104 + int node, ret; 105 + bool dt_coh_set; 106 + 107 + node = fdt_path_offset(fdt, path); 108 + if (node < 0) 109 + goto tweak_fail; 110 + 111 + prop = fdt_getprop(fdt, node, "dma-coherent", &ret); 112 + if (!prop && ret != -FDT_ERR_NOTFOUND) 113 + goto tweak_fail; 114 + 115 + dt_coh_set = ret != -FDT_ERR_NOTFOUND; 116 + ret = 0; 117 + 118 + /* need to remove "dma-coherent" property */ 119 + if (dt_coh_set && !coherent) 120 + ret = fdt_delprop(fdt, node, "dma-coherent"); 121 + 122 + /* need to set "dma-coherent" property */ 123 + if (!dt_coh_set && coherent) 124 + ret = fdt_setprop(fdt, node, "dma-coherent", NULL, 0); 125 + 126 + if (ret < 0) 127 + goto tweak_fail; 128 + 129 + return 0; 130 + 131 + tweak_fail: 132 + pr_err("failed to tweak %s to %scoherent\n", path, coherent ? "" : "non"); 133 + return -EFAULT; 134 + } 135 + 104 136 enum hsdk_axi_masters { 105 137 M_HS_CORE = 0, 106 138 M_HS_RTT, ··· 201 161 202 162 #define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180)) 203 163 #define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194)) 164 + 165 + static void __init hsdk_init_memory_bridge_axi_dmac(void) 166 + { 167 + bool coherent = !!arc_hsdk_axi_dmac_coherent; 168 + u32 axi_m_slv1, axi_m_oft1; 169 + 170 + /* 171 + * Don't tweak memory bridge configuration if we failed to tweak DTB 172 + * as we will end up in a inconsistent state. 173 + */ 174 + if (hsdk_tweak_node_coherency("/soc/dmac@80000", coherent)) 175 + return; 176 + 177 + if (coherent) { 178 + axi_m_slv1 = 0x77999999; 179 + axi_m_oft1 = 0x76DCBA98; 180 + } else { 181 + axi_m_slv1 = 0x77777777; 182 + axi_m_oft1 = 0x76543210; 183 + } 184 + 185 + writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0)); 186 + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0)); 187 + writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_0)); 188 + writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_0)); 189 + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0)); 190 + 191 + writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1)); 192 + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1)); 193 + writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_1)); 194 + writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_1)); 195 + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1)); 196 + } 204 197 205 198 static void __init hsdk_init_memory_bridge(void) 206 199 { ··· 300 227 writel(0x76543210, CREG_AXI_M_OFT1(M_GPU)); 301 228 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU)); 302 229 303 - writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0)); 304 - writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0)); 305 - writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0)); 306 - writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0)); 307 - writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0)); 308 - 309 - writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1)); 310 - writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1)); 311 - writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1)); 312 - writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1)); 313 - writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1)); 314 - 315 230 writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS)); 316 231 writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS)); 317 232 writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS)); 318 233 writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS)); 319 234 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS)); 235 + 236 + hsdk_init_memory_bridge_axi_dmac(); 320 237 321 238 /* 322 239 * PAE remapping for DMA clients does not work due to an RTL bug, so