This source file includes following definitions.
- sun6i_smp_prepare_cpus
- sun6i_smp_boot_secondary
- sun8i_smp_prepare_cpus
- sun8i_smp_boot_secondary
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 #include <linux/delay.h>
  17 #include <linux/init.h>
  18 #include <linux/io.h>
  19 #include <linux/memory.h>
  20 #include <linux/of.h>
  21 #include <linux/of_address.h>
  22 #include <linux/smp.h>
  23 
  24 #define CPUCFG_CPU_PWR_CLAMP_STATUS_REG(cpu)    ((cpu) * 0x40 + 0x64)
  25 #define CPUCFG_CPU_RST_CTRL_REG(cpu)            (((cpu) + 1) * 0x40)
  26 #define CPUCFG_CPU_CTRL_REG(cpu)                (((cpu) + 1) * 0x40 + 0x04)
  27 #define CPUCFG_CPU_STATUS_REG(cpu)              (((cpu) + 1) * 0x40 + 0x08)
  28 #define CPUCFG_GEN_CTRL_REG                     0x184
  29 #define CPUCFG_PRIVATE0_REG                     0x1a4
  30 #define CPUCFG_PRIVATE1_REG                     0x1a8
  31 #define CPUCFG_DBG_CTL0_REG                     0x1e0
  32 #define CPUCFG_DBG_CTL1_REG                     0x1e4
  33 
  34 #define PRCM_CPU_PWROFF_REG                     0x100
  35 #define PRCM_CPU_PWR_CLAMP_REG(cpu)             (((cpu) * 4) + 0x140)
  36 
  37 static void __iomem *cpucfg_membase;
  38 static void __iomem *prcm_membase;
  39 
  40 static DEFINE_SPINLOCK(cpu_lock);
  41 
  42 static void __init sun6i_smp_prepare_cpus(unsigned int max_cpus)
  43 {
  44         struct device_node *node;
  45 
  46         node = of_find_compatible_node(NULL, NULL, "allwinner,sun6i-a31-prcm");
  47         if (!node) {
  48                 pr_err("Missing A31 PRCM node in the device tree\n");
  49                 return;
  50         }
  51 
  52         prcm_membase = of_iomap(node, 0);
  53         of_node_put(node);
  54         if (!prcm_membase) {
  55                 pr_err("Couldn't map A31 PRCM registers\n");
  56                 return;
  57         }
  58 
  59         node = of_find_compatible_node(NULL, NULL,
  60                                        "allwinner,sun6i-a31-cpuconfig");
  61         if (!node) {
  62                 pr_err("Missing A31 CPU config node in the device tree\n");
  63                 return;
  64         }
  65 
  66         cpucfg_membase = of_iomap(node, 0);
  67         of_node_put(node);
  68         if (!cpucfg_membase)
  69                 pr_err("Couldn't map A31 CPU config registers\n");
  70 
  71 }
  72 
  73 static int sun6i_smp_boot_secondary(unsigned int cpu,
  74                                     struct task_struct *idle)
  75 {
  76         u32 reg;
  77         int i;
  78 
  79         if (!(prcm_membase && cpucfg_membase))
  80                 return -EFAULT;
  81 
  82         spin_lock(&cpu_lock);
  83 
  84         
  85         writel(__pa_symbol(secondary_startup),
  86                cpucfg_membase + CPUCFG_PRIVATE0_REG);
  87 
  88         
  89         writel(0, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu));
  90 
  91         
  92         reg = readl(cpucfg_membase + CPUCFG_GEN_CTRL_REG);
  93         writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_GEN_CTRL_REG);
  94 
  95         
  96         reg = readl(cpucfg_membase + CPUCFG_DBG_CTL1_REG);
  97         writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_DBG_CTL1_REG);
  98 
  99         
 100         for (i = 0; i <= 8; i++)
 101                 writel(0xff >> i, prcm_membase + PRCM_CPU_PWR_CLAMP_REG(cpu));
 102         mdelay(10);
 103 
 104         
 105         reg = readl(prcm_membase + PRCM_CPU_PWROFF_REG);
 106         writel(reg & ~BIT(cpu), prcm_membase + PRCM_CPU_PWROFF_REG);
 107         mdelay(1);
 108 
 109         
 110         writel(3, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu));
 111 
 112         
 113         reg = readl(cpucfg_membase + CPUCFG_DBG_CTL1_REG);
 114         writel(reg | BIT(cpu), cpucfg_membase + CPUCFG_DBG_CTL1_REG);
 115 
 116         spin_unlock(&cpu_lock);
 117 
 118         return 0;
 119 }
 120 
 121 static const struct smp_operations sun6i_smp_ops __initconst = {
 122         .smp_prepare_cpus       = sun6i_smp_prepare_cpus,
 123         .smp_boot_secondary     = sun6i_smp_boot_secondary,
 124 };
 125 CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops);
 126 
 127 static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus)
 128 {
 129         struct device_node *node;
 130 
 131         node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm");
 132         if (!node) {
 133                 pr_err("Missing A23 PRCM node in the device tree\n");
 134                 return;
 135         }
 136 
 137         prcm_membase = of_iomap(node, 0);
 138         of_node_put(node);
 139         if (!prcm_membase) {
 140                 pr_err("Couldn't map A23 PRCM registers\n");
 141                 return;
 142         }
 143 
 144         node = of_find_compatible_node(NULL, NULL,
 145                                        "allwinner,sun8i-a23-cpuconfig");
 146         if (!node) {
 147                 pr_err("Missing A23 CPU config node in the device tree\n");
 148                 return;
 149         }
 150 
 151         cpucfg_membase = of_iomap(node, 0);
 152         of_node_put(node);
 153         if (!cpucfg_membase)
 154                 pr_err("Couldn't map A23 CPU config registers\n");
 155 
 156 }
 157 
 158 static int sun8i_smp_boot_secondary(unsigned int cpu,
 159                                     struct task_struct *idle)
 160 {
 161         u32 reg;
 162 
 163         if (!(prcm_membase && cpucfg_membase))
 164                 return -EFAULT;
 165 
 166         spin_lock(&cpu_lock);
 167 
 168         
 169         writel(__pa_symbol(secondary_startup),
 170                cpucfg_membase + CPUCFG_PRIVATE0_REG);
 171 
 172         
 173         writel(0, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu));
 174 
 175         
 176         reg = readl(cpucfg_membase + CPUCFG_GEN_CTRL_REG);
 177         writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_GEN_CTRL_REG);
 178 
 179         
 180         reg = readl(prcm_membase + PRCM_CPU_PWROFF_REG);
 181         writel(reg & ~BIT(cpu), prcm_membase + PRCM_CPU_PWROFF_REG);
 182         mdelay(1);
 183 
 184         
 185         writel(3, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu));
 186 
 187         spin_unlock(&cpu_lock);
 188 
 189         return 0;
 190 }
 191 
 192 static const struct smp_operations sun8i_smp_ops __initconst = {
 193         .smp_prepare_cpus       = sun8i_smp_prepare_cpus,
 194         .smp_boot_secondary     = sun8i_smp_boot_secondary,
 195 };
 196 CPU_METHOD_OF_DECLARE(sun8i_a23_smp, "allwinner,sun8i-a23", &sun8i_smp_ops);