0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <asm/mach/arch.h>
0011 #include <asm/mach/map.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/io.h>
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #define MSTARV7_L3BRIDGE_FLUSH 0x14
0030 #define MSTARV7_L3BRIDGE_STATUS 0x40
0031 #define MSTARV7_L3BRIDGE_FLUSH_TRIGGER BIT(0)
0032 #define MSTARV7_L3BRIDGE_STATUS_DONE BIT(12)
0033
0034 #ifdef CONFIG_SMP
0035 #define MSTARV7_CPU1_BOOT_ADDR_HIGH 0x4c
0036 #define MSTARV7_CPU1_BOOT_ADDR_LOW 0x50
0037 #define MSTARV7_CPU1_UNLOCK 0x58
0038 #define MSTARV7_CPU1_UNLOCK_MAGIC 0xbabe
0039 #endif
0040
0041 static void __iomem *l3bridge;
0042
0043 static const char * const mstarv7_board_dt_compat[] __initconst = {
0044 "mstar,infinity",
0045 "mstar,infinity2m",
0046 "mstar,infinity3",
0047 "mstar,mercury5",
0048 NULL,
0049 };
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 static void mstarv7_mb(void)
0062 {
0063
0064 writel_relaxed(0, l3bridge + MSTARV7_L3BRIDGE_FLUSH);
0065 writel_relaxed(MSTARV7_L3BRIDGE_FLUSH_TRIGGER, l3bridge
0066 + MSTARV7_L3BRIDGE_FLUSH);
0067 while (!(readl_relaxed(l3bridge + MSTARV7_L3BRIDGE_STATUS)
0068 & MSTARV7_L3BRIDGE_STATUS_DONE)) {
0069
0070 }
0071 }
0072
0073 #ifdef CONFIG_SMP
0074 static int mstarv7_boot_secondary(unsigned int cpu, struct task_struct *idle)
0075 {
0076 struct device_node *np;
0077 u32 bootaddr = (u32) __pa_symbol(secondary_startup_arm);
0078 void __iomem *smpctrl;
0079
0080
0081
0082
0083
0084 if (cpu != 1)
0085 return -EINVAL;
0086
0087 np = of_find_compatible_node(NULL, NULL, "mstar,smpctrl");
0088 smpctrl = of_iomap(np, 0);
0089
0090 if (!smpctrl)
0091 return -ENODEV;
0092
0093
0094 writew(bootaddr & 0xffff, smpctrl + MSTARV7_CPU1_BOOT_ADDR_LOW);
0095 writew((bootaddr >> 16) & 0xffff, smpctrl + MSTARV7_CPU1_BOOT_ADDR_HIGH);
0096
0097
0098 writew(MSTARV7_CPU1_UNLOCK_MAGIC, smpctrl + MSTARV7_CPU1_UNLOCK);
0099
0100
0101 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0102
0103 iounmap(smpctrl);
0104
0105 return 0;
0106 }
0107
0108 static const struct smp_operations __initdata mstarv7_smp_ops = {
0109 .smp_boot_secondary = mstarv7_boot_secondary,
0110 };
0111 #endif
0112
0113 static void __init mstarv7_init(void)
0114 {
0115 struct device_node *np;
0116
0117 np = of_find_compatible_node(NULL, NULL, "mstar,l3bridge");
0118 l3bridge = of_iomap(np, 0);
0119 if (l3bridge)
0120 soc_mb = mstarv7_mb;
0121 else
0122 pr_warn("Failed to install memory barrier, DMA will be broken!\n");
0123 }
0124
0125 DT_MACHINE_START(MSTARV7_DT, "MStar/Sigmastar Armv7 (Device Tree)")
0126 .dt_compat = mstarv7_board_dt_compat,
0127 .init_machine = mstarv7_init,
0128 .smp = smp_ops(mstarv7_smp_ops),
0129 MACHINE_END