linux/arch/arm/mach-aspeed/platsmp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2// Copyright (C) ASPEED Technology Inc.
   3// Copyright IBM Corp.
   4
   5#include <linux/of_address.h>
   6#include <linux/io.h>
   7#include <linux/of.h>
   8#include <linux/smp.h>
   9
  10#define BOOT_ADDR       0x00
  11#define BOOT_SIG        0x04
  12
  13static struct device_node *secboot_node;
  14
  15static int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle)
  16{
  17        void __iomem *base;
  18
  19        base = of_iomap(secboot_node, 0);
  20        if (!base) {
  21                pr_err("could not map the secondary boot base!");
  22                return -ENODEV;
  23        }
  24
  25        writel_relaxed(0, base + BOOT_ADDR);
  26        writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR);
  27        writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG);
  28
  29        dsb_sev();
  30
  31        iounmap(base);
  32
  33        return 0;
  34}
  35
  36static void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus)
  37{
  38        void __iomem *base;
  39
  40        secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem");
  41        if (!secboot_node) {
  42                pr_err("secboot device node found!!\n");
  43                return;
  44        }
  45
  46        base = of_iomap(secboot_node, 0);
  47        if (!base) {
  48                pr_err("could not map the secondary boot base!");
  49                return;
  50        }
  51        __raw_writel(0xBADABABA, base + BOOT_SIG);
  52
  53        iounmap(base);
  54}
  55
  56static const struct smp_operations aspeed_smp_ops __initconst = {
  57        .smp_prepare_cpus       = aspeed_g6_smp_prepare_cpus,
  58        .smp_boot_secondary     = aspeed_g6_boot_secondary,
  59};
  60
  61CPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops);
  62