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

mstarv7.c (3562B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Device Tree support for MStar/Sigmastar Armv7 SoCs
      4 *
      5 * Copyright (c) 2020 thingy.jp
      6 * Author: Daniel Palmer <daniel@thingy.jp>
      7 */
      8
      9#include <linux/init.h>
     10#include <asm/mach/arch.h>
     11#include <asm/mach/map.h>
     12#include <linux/of.h>
     13#include <linux/of_address.h>
     14#include <linux/io.h>
     15
     16/*
     17 * In the u-boot code the area these registers are in is
     18 * called "L3 bridge" and there are register descriptions
     19 * for something in the same area called "AXI".
     20 *
     21 * It's not exactly known what this is but the vendor code
     22 * for both u-boot and linux share calls to "flush the miu pipe".
     23 * This seems to be to force pending CPU writes to memory so that
     24 * the state is right before DMA capable devices try to read
     25 * descriptors and data the CPU has prepared. Without doing this
     26 * ethernet doesn't work reliably for example.
     27 */
     28
     29#define MSTARV7_L3BRIDGE_FLUSH		0x14
     30#define MSTARV7_L3BRIDGE_STATUS		0x40
     31#define MSTARV7_L3BRIDGE_FLUSH_TRIGGER	BIT(0)
     32#define MSTARV7_L3BRIDGE_STATUS_DONE	BIT(12)
     33
     34#ifdef CONFIG_SMP
     35#define MSTARV7_CPU1_BOOT_ADDR_HIGH	0x4c
     36#define MSTARV7_CPU1_BOOT_ADDR_LOW	0x50
     37#define MSTARV7_CPU1_UNLOCK		0x58
     38#define MSTARV7_CPU1_UNLOCK_MAGIC	0xbabe
     39#endif
     40
     41static void __iomem *l3bridge;
     42
     43static const char * const mstarv7_board_dt_compat[] __initconst = {
     44	"mstar,infinity",
     45	"mstar,infinity2m",
     46	"mstar,infinity3",
     47	"mstar,mercury5",
     48	NULL,
     49};
     50
     51/*
     52 * This may need locking to deal with situations where an interrupt
     53 * happens while we are in here and mb() gets called by the interrupt handler.
     54 *
     55 * The vendor code did have a spin lock but it doesn't seem to be needed and
     56 * removing it hasn't caused any side effects so far.
     57 *
     58 * [writel|readl]_relaxed have to be used here because otherwise
     59 * we'd end up right back in here.
     60 */
     61static void mstarv7_mb(void)
     62{
     63	/* toggle the flush miu pipe fire bit */
     64	writel_relaxed(0, l3bridge + MSTARV7_L3BRIDGE_FLUSH);
     65	writel_relaxed(MSTARV7_L3BRIDGE_FLUSH_TRIGGER, l3bridge
     66			+ MSTARV7_L3BRIDGE_FLUSH);
     67	while (!(readl_relaxed(l3bridge + MSTARV7_L3BRIDGE_STATUS)
     68			& MSTARV7_L3BRIDGE_STATUS_DONE)) {
     69		/* wait for flush to complete */
     70	}
     71}
     72
     73#ifdef CONFIG_SMP
     74static int mstarv7_boot_secondary(unsigned int cpu, struct task_struct *idle)
     75{
     76	struct device_node *np;
     77	u32 bootaddr = (u32) __pa_symbol(secondary_startup_arm);
     78	void __iomem *smpctrl;
     79
     80	/*
     81	 * right now we don't know how to boot anything except
     82	 * cpu 1.
     83	 */
     84	if (cpu != 1)
     85		return -EINVAL;
     86
     87	np = of_find_compatible_node(NULL, NULL, "mstar,smpctrl");
     88	smpctrl = of_iomap(np, 0);
     89
     90	if (!smpctrl)
     91		return -ENODEV;
     92
     93	/* set the boot address for the second cpu */
     94	writew(bootaddr & 0xffff, smpctrl + MSTARV7_CPU1_BOOT_ADDR_LOW);
     95	writew((bootaddr >> 16) & 0xffff, smpctrl + MSTARV7_CPU1_BOOT_ADDR_HIGH);
     96
     97	/* unlock the second cpu */
     98	writew(MSTARV7_CPU1_UNLOCK_MAGIC, smpctrl + MSTARV7_CPU1_UNLOCK);
     99
    100	/* and away we go...*/
    101	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
    102
    103	iounmap(smpctrl);
    104
    105	return 0;
    106}
    107
    108static const struct smp_operations __initdata mstarv7_smp_ops = {
    109	.smp_boot_secondary = mstarv7_boot_secondary,
    110};
    111#endif
    112
    113static void __init mstarv7_init(void)
    114{
    115	struct device_node *np;
    116
    117	np = of_find_compatible_node(NULL, NULL, "mstar,l3bridge");
    118	l3bridge = of_iomap(np, 0);
    119	if (l3bridge)
    120		soc_mb = mstarv7_mb;
    121	else
    122		pr_warn("Failed to install memory barrier, DMA will be broken!\n");
    123}
    124
    125DT_MACHINE_START(MSTARV7_DT, "MStar/Sigmastar Armv7 (Device Tree)")
    126	.dt_compat	= mstarv7_board_dt_compat,
    127	.init_machine	= mstarv7_init,
    128	.smp		= smp_ops(mstarv7_smp_ops),
    129MACHINE_END