cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

platform.c (10709B)


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