root/arch/arc/plat-hsdk/platform.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hsdk_init_per_cpu
  2. hsdk_enable_gpio_intc_wire
  3. hsdk_tweak_node_coherency
  4. hsdk_init_memory_bridge_axi_dmac
  5. hsdk_init_memory_bridge
  6. hsdk_init_early

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ARC HSDK Platform support code
   4  *
   5  * Copyright (C) 2017 Synopsys, Inc. (www.synopsys.com)
   6  */
   7 
   8 #include <linux/init.h>
   9 #include <linux/of_fdt.h>
  10 #include <linux/libfdt.h>
  11 #include <linux/smp.h>
  12 #include <asm/arcregs.h>
  13 #include <asm/io.h>
  14 #include <asm/mach_desc.h>
  15 
  16 int arc_hsdk_axi_dmac_coherent __section(.data) = 0;
  17 
  18 #define ARC_CCM_UNUSED_ADDR     0x60000000
  19 
  20 static void __init hsdk_init_per_cpu(unsigned int cpu)
  21 {
  22         /*
  23          * By default ICCM is mapped to 0x7z while this area is used for
  24          * kernel virtual mappings, so move it to currently unused area.
  25          */
  26         if (cpuinfo_arc700[cpu].iccm.sz)
  27                 write_aux_reg(ARC_REG_AUX_ICCM, ARC_CCM_UNUSED_ADDR);
  28 
  29         /*
  30          * By default DCCM is mapped to 0x8z while this area is used by kernel,
  31          * so move it to currently unused area.
  32          */
  33         if (cpuinfo_arc700[cpu].dccm.sz)
  34                 write_aux_reg(ARC_REG_AUX_DCCM, ARC_CCM_UNUSED_ADDR);
  35 }
  36 
  37 #define ARC_PERIPHERAL_BASE     0xf0000000
  38 #define CREG_BASE               (ARC_PERIPHERAL_BASE + 0x1000)
  39 
  40 #define SDIO_BASE               (ARC_PERIPHERAL_BASE + 0xA000)
  41 #define SDIO_UHS_REG_EXT        (SDIO_BASE + 0x108)
  42 #define SDIO_UHS_REG_EXT_DIV_2  (2 << 30)
  43 
  44 #define HSDK_GPIO_INTC          (ARC_PERIPHERAL_BASE + 0x3000)
  45 
  46 static void __init hsdk_enable_gpio_intc_wire(void)
  47 {
  48         /*
  49          * Peripherals on CPU Card are wired to cpu intc via intermediate
  50          * DW APB GPIO blocks (mainly for debouncing)
  51          *
  52          *         ---------------------
  53          *        |  snps,archs-intc  |
  54          *        ---------------------
  55          *                  |
  56          *        ----------------------
  57          *        | snps,archs-idu-intc |
  58          *        ----------------------
  59          *         |   |     |   |    |
  60          *         | [eth] [USB]    [... other peripherals]
  61          *         |
  62          * -------------------
  63          * | snps,dw-apb-intc |
  64          * -------------------
  65          *  |      |   |   |
  66          * [Bt] [HAPS]   [... other peripherals]
  67          *
  68          * Current implementation of "irq-dw-apb-ictl" driver doesn't work well
  69          * with stacked INTCs. In particular problem happens if its master INTC
  70          * not yet instantiated. See discussion here -
  71          * https://lkml.org/lkml/2015/3/4/755
  72          *
  73          * So setup the first gpio block as a passive pass thru and hide it from
  74          * DT hardware topology - connect intc directly to cpu intc
  75          * The GPIO "wire" needs to be init nevertheless (here)
  76          *
  77          * One side adv is that peripheral interrupt handling avoids one nested
  78          * intc ISR hop
  79          *
  80          * According to HSDK User's Manual [1], "Table 2 Interrupt Mapping"
  81          * we have the following GPIO input lines used as sources of interrupt:
  82          * - GPIO[0] - Bluetooth interrupt of RS9113 module
  83          * - GPIO[2] - HAPS interrupt (on HapsTrak 3 connector)
  84          * - GPIO[3] - Audio codec (MAX9880A) interrupt
  85          * - GPIO[8-23] - Available on Arduino and PMOD_x headers
  86          * For now there's no use of Arduino and PMOD_x headers in Linux
  87          * use-case so we only enable lines 0, 2 and 3.
  88          *
  89          * [1] https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/wiki/docs/ARC_HSDK_User_Guide.pdf
  90          */
  91 #define GPIO_INTEN              (HSDK_GPIO_INTC + 0x30)
  92 #define GPIO_INTMASK            (HSDK_GPIO_INTC + 0x34)
  93 #define GPIO_INTTYPE_LEVEL      (HSDK_GPIO_INTC + 0x38)
  94 #define GPIO_INT_POLARITY       (HSDK_GPIO_INTC + 0x3c)
  95 #define GPIO_INT_CONNECTED_MASK 0x0d
  96 
  97         iowrite32(0xffffffff, (void __iomem *) GPIO_INTMASK);
  98         iowrite32(~GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTMASK);
  99         iowrite32(0x00000000, (void __iomem *) GPIO_INTTYPE_LEVEL);
 100         iowrite32(0xffffffff, (void __iomem *) GPIO_INT_POLARITY);
 101         iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN);
 102 }
 103 
 104 static int __init hsdk_tweak_node_coherency(const char *path, bool coherent)
 105 {
 106         void *fdt = initial_boot_params;
 107         const void *prop;
 108         int node, ret;
 109         bool dt_coh_set;
 110 
 111         node = fdt_path_offset(fdt, path);
 112         if (node < 0)
 113                 goto tweak_fail;
 114 
 115         prop = fdt_getprop(fdt, node, "dma-coherent", &ret);
 116         if (!prop && ret != -FDT_ERR_NOTFOUND)
 117                 goto tweak_fail;
 118 
 119         dt_coh_set = ret != -FDT_ERR_NOTFOUND;
 120         ret = 0;
 121 
 122         /* need to remove "dma-coherent" property */
 123         if (dt_coh_set && !coherent)
 124                 ret = fdt_delprop(fdt, node, "dma-coherent");
 125 
 126         /* need to set "dma-coherent" property */
 127         if (!dt_coh_set && coherent)
 128                 ret = fdt_setprop(fdt, node, "dma-coherent", NULL, 0);
 129 
 130         if (ret < 0)
 131                 goto tweak_fail;
 132 
 133         return 0;
 134 
 135 tweak_fail:
 136         pr_err("failed to tweak %s to %scoherent\n", path, coherent ? "" : "non");
 137         return -EFAULT;
 138 }
 139 
 140 enum hsdk_axi_masters {
 141         M_HS_CORE = 0,
 142         M_HS_RTT,
 143         M_AXI_TUN,
 144         M_HDMI_VIDEO,
 145         M_HDMI_AUDIO,
 146         M_USB_HOST,
 147         M_ETHERNET,
 148         M_SDIO,
 149         M_GPU,
 150         M_DMAC_0,
 151         M_DMAC_1,
 152         M_DVFS
 153 };
 154 
 155 #define UPDATE_VAL      1
 156 
 157 /*
 158  * This is modified configuration of AXI bridge. Default settings
 159  * are specified in "Table 111 CREG Address Decoder register reset values".
 160  *
 161  * AXI_M_m_SLV{0|1} - Slave Select register for master 'm'.
 162  * Possible slaves are:
 163  *  - 0  => no slave selected
 164  *  - 1  => DDR controller port #1
 165  *  - 2  => SRAM controller
 166  *  - 3  => AXI tunnel
 167  *  - 4  => EBI controller
 168  *  - 5  => ROM controller
 169  *  - 6  => AXI2APB bridge
 170  *  - 7  => DDR controller port #2
 171  *  - 8  => DDR controller port #3
 172  *  - 9  => HS38x4 IOC
 173  *  - 10 => HS38x4 DMI
 174  * AXI_M_m_OFFSET{0|1} - Addr Offset register for master 'm'
 175  *
 176  * Please read ARC HS Development IC Specification, section 17.2 for more
 177  * information about apertures configuration.
 178  *
 179  * m    master          AXI_M_m_SLV0    AXI_M_m_SLV1    AXI_M_m_OFFSET0 AXI_M_m_OFFSET1
 180  * 0    HS (CBU)        0x11111111      0x63111111      0xFEDCBA98      0x0E543210
 181  * 1    HS (RTT)        0x77777777      0x77777777      0xFEDCBA98      0x76543210
 182  * 2    AXI Tunnel      0x88888888      0x88888888      0xFEDCBA98      0x76543210
 183  * 3    HDMI-VIDEO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 184  * 4    HDMI-ADUIO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
 185  * 5    USB-HOST        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 186  * 6    ETHERNET        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 187  * 7    SDIO            0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
 188  * 8    GPU             0x77777777      0x77777777      0xFEDCBA98      0x76543210
 189  * 9    DMAC (port #1)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 190  * 10   DMAC (port #2)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
 191  * 11   DVFS            0x00000000      0x60000000      0x00000000      0x00000000
 192  */
 193 
 194 #define CREG_AXI_M_SLV0(m)  ((void __iomem *)(CREG_BASE + 0x20 * (m)))
 195 #define CREG_AXI_M_SLV1(m)  ((void __iomem *)(CREG_BASE + 0x20 * (m) + 0x04))
 196 #define CREG_AXI_M_OFT0(m)  ((void __iomem *)(CREG_BASE + 0x20 * (m) + 0x08))
 197 #define CREG_AXI_M_OFT1(m)  ((void __iomem *)(CREG_BASE + 0x20 * (m) + 0x0C))
 198 #define CREG_AXI_M_UPDT(m)  ((void __iomem *)(CREG_BASE + 0x20 * (m) + 0x14))
 199 
 200 #define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010))
 201 
 202 #define CREG_PAE                ((void __iomem *)(CREG_BASE + 0x180))
 203 #define CREG_PAE_UPDT           ((void __iomem *)(CREG_BASE + 0x194))
 204 
 205 static void __init hsdk_init_memory_bridge_axi_dmac(void)
 206 {
 207         bool coherent = !!arc_hsdk_axi_dmac_coherent;
 208         u32 axi_m_slv1, axi_m_oft1;
 209 
 210         /*
 211          * Don't tweak memory bridge configuration if we failed to tweak DTB
 212          * as we will end up in a inconsistent state.
 213          */
 214         if (hsdk_tweak_node_coherency("/soc/dmac@80000", coherent))
 215                 return;
 216 
 217         if (coherent) {
 218                 axi_m_slv1 = 0x77999999;
 219                 axi_m_oft1 = 0x76DCBA98;
 220         } else {
 221                 axi_m_slv1 = 0x77777777;
 222                 axi_m_oft1 = 0x76543210;
 223         }
 224 
 225         writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
 226         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
 227         writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_0));
 228         writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_0));
 229         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
 230 
 231         writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
 232         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
 233         writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_1));
 234         writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_1));
 235         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
 236 }
 237 
 238 static void __init hsdk_init_memory_bridge(void)
 239 {
 240         u32 reg;
 241 
 242         /*
 243          * M_HS_CORE has one unique register - BOOT.
 244          * We need to clean boot mirror (BOOT[1:0]) bits in them to avoid first
 245          * aperture to be masked by 'boot mirror'.
 246          */
 247         reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3);
 248         writel(reg, CREG_AXI_M_HS_CORE_BOOT);
 249         writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE));
 250         writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
 251         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE));
 252         writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
 253         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
 254 
 255         writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT));
 256         writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT));
 257         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT));
 258         writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT));
 259         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT));
 260 
 261         writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN));
 262         writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN));
 263         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN));
 264         writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN));
 265         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN));
 266 
 267         writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO));
 268         writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO));
 269         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO));
 270         writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO));
 271         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO));
 272 
 273         writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO));
 274         writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO));
 275         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO));
 276         writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO));
 277         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO));
 278 
 279         writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST));
 280         writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST));
 281         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST));
 282         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST));
 283         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
 284 
 285         writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET));
 286         writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET));
 287         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET));
 288         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET));
 289         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
 290 
 291         writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO));
 292         writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO));
 293         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO));
 294         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO));
 295         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
 296 
 297         writel(0x77777777, CREG_AXI_M_SLV0(M_GPU));
 298         writel(0x77777777, CREG_AXI_M_SLV1(M_GPU));
 299         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU));
 300         writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
 301         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
 302 
 303         writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
 304         writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
 305         writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
 306         writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
 307         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
 308 
 309         hsdk_init_memory_bridge_axi_dmac();
 310 
 311         /*
 312          * PAE remapping for DMA clients does not work due to an RTL bug, so
 313          * CREG_PAE register must be programmed to all zeroes, otherwise it
 314          * will cause problems with DMA to/from peripherals even if PAE40 is
 315          * not used.
 316          */
 317         writel(0x00000000, CREG_PAE);
 318         writel(UPDATE_VAL, CREG_PAE_UPDT);
 319 }
 320 
 321 static void __init hsdk_init_early(void)
 322 {
 323         hsdk_init_memory_bridge();
 324 
 325         /*
 326          * Switch SDIO external ciu clock divider from default div-by-8 to
 327          * minimum possible div-by-2.
 328          */
 329         iowrite32(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *) SDIO_UHS_REG_EXT);
 330 
 331         hsdk_enable_gpio_intc_wire();
 332 }
 333 
 334 static const char *hsdk_compat[] __initconst = {
 335         "snps,hsdk",
 336         NULL,
 337 };
 338 
 339 MACHINE_START(SIMULATION, "hsdk")
 340         .dt_compat      = hsdk_compat,
 341         .init_early     = hsdk_init_early,
 342         .init_per_cpu   = hsdk_init_per_cpu,
 343 MACHINE_END

/* [<][>][^][v][top][bottom][index][help] */