#define        GICD_BASE       (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
 #define        GICC_BASE       (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
 
+/*
+ * R40 is different from other single cluster SoCs.
+ *
+ * The power clamps are located in the unused space after the per-core
+ * reset controls for core 3. The secondary core entry address register
+ * is in the SRAM controller address range.
+ */
+#define SUN8I_R40_PWROFF                       (0x110)
+#define SUN8I_R40_PWR_CLAMP(cpu)               (0x120 + (cpu) * 0x4)
+#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0                (0xbc)
+
 static void __secure cp15_write_cntp_tval(u32 tval)
 {
        asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
 static void __secure clamp_release(u32 __maybe_unused *clamp)
 {
 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-       defined(CONFIG_MACH_SUN8I_H3)
+       defined(CONFIG_MACH_SUN8I_H3) || \
+       defined(CONFIG_MACH_SUN8I_R40)
        u32 tmp = 0x1ff;
        do {
                tmp >>= 1;
 static void __secure clamp_set(u32 __maybe_unused *clamp)
 {
 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-       defined(CONFIG_MACH_SUN8I_H3)
+       defined(CONFIG_MACH_SUN8I_H3) || \
+       defined(CONFIG_MACH_SUN8I_R40)
        writel(0xff, clamp);
 #endif
 }
        sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
                           on, 0);
 }
-#else /* ! CONFIG_MACH_SUN7I */
+#elif defined CONFIG_MACH_SUN8I_R40
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
+{
+       struct sunxi_cpucfg_reg *cpucfg =
+               (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+       sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
+                          (void *)cpucfg + SUN8I_R40_PWROFF,
+                          on, 0);
+}
+#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
 static void __secure sunxi_cpu_set_power(int cpu, bool on)
 {
        struct sunxi_prcm_reg *prcm =
        psci_save_target_pc(cpu, pc);
 
        /* Set secondary core power on PC */
+#ifdef CONFIG_MACH_SUN8I_R40
+       /* secondary core entry address is programmed differently */
+       writel((u32)&psci_cpu_entry,
+              SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+#else
        writel((u32)&psci_cpu_entry, &cpucfg->priv0);
+#endif
 
        /* Assert reset on target CPU */
        writel(0, &cpucfg->cpu[cpu].rst);