~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-mstar/mstarv7.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 41 static void __iomem *l3bridge;
 42 
 43 static 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  */
 61 static 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
 74 static 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 
108 static const struct smp_operations __initdata mstarv7_smp_ops = {
109         .smp_boot_secondary = mstarv7_boot_secondary,
110 };
111 #endif
112 
113 static 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 
125 DT_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),
129 MACHINE_END
130 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php