F: arch/arm/boot/dts/arm-realview-*
F: arch/arm/boot/dts/integrator*
F: arch/arm/boot/dts/versatile*
-F: arch/arm/mach-integrator/
-F: arch/arm/mach-realview/
F: arch/arm/mach-versatile/
-F: arch/arm/plat-versatile/
F: drivers/bus/arm-integrator-lm.c
F: drivers/clk/versatile/
F: drivers/i2c/busses/i2c-versatile.c
source "arch/arm/mach-imx/Kconfig"
-source "arch/arm/mach-integrator/Kconfig"
-
source "arch/arm/mach-iop32x/Kconfig"
source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-realtek/Kconfig"
-source "arch/arm/mach-realview/Kconfig"
-
source "arch/arm/mach-rockchip/Kconfig"
source "arch/arm/mach-s3c/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
-source "arch/arm/mach-vexpress/Kconfig"
-
source "arch/arm/mach-vt8500/Kconfig"
source "arch/arm/mach-zynq/Kconfig"
machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_HISI) += hisi
-machine-$(CONFIG_ARCH_INTEGRATOR) += integrator
machine-$(CONFIG_ARCH_IOP32X) += iop32x
machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx
machine-$(CONFIG_ARCH_KEYSTONE) += keystone
machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx
machine-$(CONFIG_ARCH_MESON) += meson
machine-$(CONFIG_ARCH_MMP) += mmp
-machine-$(CONFIG_ARCH_MPS2) += vexpress
machine-$(CONFIG_ARCH_MOXART) += moxart
machine-$(CONFIG_ARCH_MV78XX0) += mv78xx0
machine-$(CONFIG_ARCH_MVEBU) += mvebu
machine-$(CONFIG_ARCH_QCOM) += qcom
machine-$(CONFIG_ARCH_RDA) += rda
machine-$(CONFIG_ARCH_REALTEK) += realtek
-machine-$(CONFIG_ARCH_REALVIEW) += realview
machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip
machine-$(CONFIG_ARCH_RPC) += rpc
machine-$(CONFIG_PLAT_SAMSUNG) += s3c
machine-$(CONFIG_ARCH_SUNXI) += sunxi
machine-$(CONFIG_ARCH_TEGRA) += tegra
machine-$(CONFIG_ARCH_U8500) += ux500
-machine-$(CONFIG_ARCH_VERSATILE) += versatile
-machine-$(CONFIG_ARCH_VEXPRESS) += vexpress
machine-$(CONFIG_ARCH_VT8500) += vt8500
machine-$(CONFIG_ARCH_ZYNQ) += zynq
+machine-$(CONFIG_PLAT_VERSATILE) += versatile
machine-$(CONFIG_PLAT_SPEAR) += spear
# Platform directory name. This list is sorted alphanumerically
plat-$(CONFIG_ARCH_OMAP) += omap
plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
-plat-$(CONFIG_PLAT_VERSATILE) += versatile
# The byte offset of the kernel image in RAM from the start of RAM.
TEXT_OFFSET := $(textofs-y)
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig ARCH_INTEGRATOR
- bool "ARM Ltd. Integrator family"
- depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6
- select ARM_AMBA
- select CMA
- select DMA_CMA
- select HAVE_TCM
- select CLK_ICST
- select MFD_SYSCON
- select PLAT_VERSATILE
- select POWER_RESET
- select POWER_RESET_VERSATILE
- select POWER_SUPPLY
- select SOC_INTEGRATOR_CM
- select VERSATILE_FPGA_IRQ
- help
- Support for ARM's Integrator platform.
-
-if ARCH_INTEGRATOR
-
-config ARCH_INTEGRATOR_AP
- bool "Support Integrator/AP and Integrator/PP2 platforms"
- select INTEGRATOR_AP_TIMER
- select SERIAL_AMBA_PL010 if TTY
- select SERIAL_AMBA_PL010_CONSOLE if TTY
- select SOC_BUS
- help
- Include support for the ARM(R) Integrator/AP and
- Integrator/PP2 platforms.
-
-config INTEGRATOR_IMPD1
- bool "Include support for Integrator/IM-PD1"
- depends on ARCH_INTEGRATOR_AP
- select ARM_VIC
- select GPIO_PL061
- select GPIOLIB
- select REGULATOR
- select REGULATOR_FIXED_VOLTAGE
- help
- The IM-PD1 is an add-on logic module for the Integrator which
- allows ARM(R) Ltd PrimeCells to be developed and evaluated.
- The IM-PD1 can be found on the Integrator/PP2 platform.
-
-config INTEGRATOR_CM720T
- bool "Integrator/CM720T core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V4T
- select CPU_ARM720T
-
-config INTEGRATOR_CM920T
- bool "Integrator/CM920T core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V4T
- select CPU_ARM920T
-
-config INTEGRATOR_CM922T_XA10
- bool "Integrator/CM922T-XA10 core module"
- depends on ARCH_MULTI_V4T
- depends on ARCH_INTEGRATOR_AP
- select CPU_ARM922T
-
-config INTEGRATOR_CM926EJS
- bool "Integrator/CM926EJ-S core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V5
- select CPU_ARM926T
-
-config INTEGRATOR_CM10200E_REV0
- bool "Integrator/CM10200E rev.0 core module"
- depends on ARCH_INTEGRATOR_AP && n
- depends on ARCH_MULTI_V5
- select CPU_ARM1020
-
-config INTEGRATOR_CM10200E
- bool "Integrator/CM10200E core module"
- depends on ARCH_INTEGRATOR_AP && n
- depends on ARCH_MULTI_V5
- select CPU_ARM1020E
-
-config INTEGRATOR_CM10220E
- bool "Integrator/CM10220E core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V5
- select CPU_ARM1022
-
-config INTEGRATOR_CM1026EJS
- bool "Integrator/CM1026EJ-S core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V5
- select CPU_ARM1026
-
-config INTEGRATOR_CM1136JFS
- bool "Integrator/CM1136JF-S core module"
- depends on ARCH_INTEGRATOR_AP
- depends on ARCH_MULTI_V6
- select CPU_V6
-
-config ARCH_INTEGRATOR_CP
- bool "Support Integrator/CP platform"
- depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
- select ARM_TIMER_SP804
- select SERIAL_AMBA_PL011 if TTY
- select SERIAL_AMBA_PL011_CONSOLE if TTY
- select SOC_BUS
- help
- Include support for the ARM(R) Integrator CP platform.
-
-config INTEGRATOR_CT926
- bool "Integrator/CT926 (ARM926EJ-S) core tile"
- depends on ARCH_INTEGRATOR_CP
- depends on ARCH_MULTI_V5
- select CPU_ARM926T
-
-config INTEGRATOR_CTB36
- bool "Integrator/CTB36 (ARM1136JF-S) core tile"
- depends on ARCH_INTEGRATOR_CP
- depends on ARCH_MULTI_V6
- select CPU_V6
-
-config ARCH_CINTEGRATOR
- depends on ARCH_INTEGRATOR_CP
- def_bool y
-
-endif
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y := core.o
-obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
-obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * access the core module control register.
- */
-u32 cm_get(void);
-void cm_control(u32, u32);
-
-struct device_node;
-void cm_init(void);
-void cm_clear_irqs(void);
-
-#define CM_CTRL_LED (1 << 0)
-#define CM_CTRL_nMBDET (1 << 1)
-#define CM_CTRL_REMAP (1 << 2)
-
-/*
- * Integrator/AP,PP2 specific
- */
-#define CM_CTRL_HIGHVECTORS (1 << 4)
-#define CM_CTRL_BIGENDIAN (1 << 5)
-#define CM_CTRL_FASTBUS (1 << 6)
-#define CM_CTRL_SYNC (1 << 7)
-
-/*
- * ARM926/946/966 Integrator/CP specific
- */
-#define CM_CTRL_LCDBIASEN (1 << 8)
-#define CM_CTRL_LCDBIASUP (1 << 9)
-#define CM_CTRL_LCDBIASDN (1 << 10)
-#define CM_CTRL_LCDMUXSEL_MASK (7 << 11)
-#define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11)
-#define CM_CTRL_LCDMUXSEL_VGA565_TFT555 (2 << 11)
-#define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11)
-#define CM_CTRL_LCDMUXSEL_VGA555_TFT555 (4 << 11)
-#define CM_CTRL_LCDEN0 (1 << 14)
-#define CM_CTRL_LCDEN1 (1 << 15)
-#define CM_CTRL_STATIC1 (1 << 16)
-#define CM_CTRL_STATIC2 (1 << 17)
-#define CM_CTRL_STATIC (1 << 18)
-#define CM_CTRL_n24BITEN (1 << 19)
-#define CM_CTRL_EBIWP (1 << 20)
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <linux/reboot.h>
-#include <linux/amba/serial.h>
-extern struct amba_pl010_data ap_uart_data;
-void integrator_init_early(void);
-int integrator_init(bool is_cp);
-void integrator_reserve(void);
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-integrator/core.c
- *
- * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/export.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/memblock.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/serial.h>
-#include <linux/io.h>
-#include <linux/stat.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pgtable.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/time.h>
-
-#include "hardware.h"
-#include "cm.h"
-#include "common.h"
-
-static DEFINE_RAW_SPINLOCK(cm_lock);
-static void __iomem *cm_base;
-
-/**
- * cm_get - get the value from the CM_CTRL register
- */
-u32 cm_get(void)
-{
- return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
-}
-
-/**
- * cm_control - update the CM_CTRL register.
- * @mask: bits to change
- * @set: bits to set
- */
-void cm_control(u32 mask, u32 set)
-{
- unsigned long flags;
- u32 val;
-
- raw_spin_lock_irqsave(&cm_lock, flags);
- val = readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask;
- writel(val | set, cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
- raw_spin_unlock_irqrestore(&cm_lock, flags);
-}
-
-void cm_clear_irqs(void)
-{
- /* disable core module IRQs */
- writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET +
- IRQ_ENABLE_CLEAR);
-}
-
-static const struct of_device_id cm_match[] = {
- { .compatible = "arm,core-module-integrator"},
- { },
-};
-
-void cm_init(void)
-{
- struct device_node *cm = of_find_matching_node(NULL, cm_match);
-
- if (!cm) {
- pr_crit("no core module node found in device tree\n");
- return;
- }
- cm_base = of_iomap(cm, 0);
- if (!cm_base) {
- pr_crit("could not remap core module\n");
- return;
- }
- cm_clear_irqs();
-}
-
-/*
- * We need to stop things allocating the low memory; ideally we need a
- * better implementation of GFP_DMA which does not assume that DMA-able
- * memory starts at zero.
- */
-void __init integrator_reserve(void)
-{
- memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
-}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * This file contains the hardware definitions of the Integrator.
- *
- * Copyright (C) 1998-1999 ARM Limited.
- */
-#ifndef INTEGRATOR_HARDWARE_H
-#define INTEGRATOR_HARDWARE_H
-
-/*
- * Where in virtual memory the IO devices (timers, system controllers
- * and so on)
- */
-#define IO_BASE 0xF0000000 // VA of IO
-#define IO_SIZE 0x0B000000 // How much?
-#define IO_START INTEGRATOR_HDR_BASE // PA of IO
-
-/* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
-#define __io_address(n) ((void __iomem *)IO_ADDRESS(n))
-
-/*
- * Integrator memory map
- */
-#define INTEGRATOR_BOOT_ROM_LO 0x00000000
-#define INTEGRATOR_BOOT_ROM_HI 0x20000000
-#define INTEGRATOR_BOOT_ROM_BASE INTEGRATOR_BOOT_ROM_HI /* Normal position */
-#define INTEGRATOR_BOOT_ROM_SIZE SZ_512K
-
-/*
- * New Core Modules have different amounts of SSRAM, the amount of SSRAM
- * fitted can be found in HDR_STAT.
- *
- * The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to
- * the minimum amount of SSRAM fitted on any core module.
- *
- * New Core Modules also alias the SSRAM.
- *
- */
-#define INTEGRATOR_SSRAM_BASE 0x00000000
-#define INTEGRATOR_SSRAM_ALIAS_BASE 0x10800000
-#define INTEGRATOR_SSRAM_SIZE SZ_256K
-
-#define INTEGRATOR_FLASH_BASE 0x24000000
-#define INTEGRATOR_FLASH_SIZE SZ_32M
-
-#define INTEGRATOR_MBRD_SSRAM_BASE 0x28000000
-#define INTEGRATOR_MBRD_SSRAM_SIZE SZ_512K
-
-/*
- * SDRAM is a SIMM therefore the size is not known.
- */
-#define INTEGRATOR_SDRAM_BASE 0x00040000
-
-#define INTEGRATOR_SDRAM_ALIAS_BASE 0x80000000
-#define INTEGRATOR_HDR0_SDRAM_BASE 0x80000000
-#define INTEGRATOR_HDR1_SDRAM_BASE 0x90000000
-#define INTEGRATOR_HDR2_SDRAM_BASE 0xA0000000
-#define INTEGRATOR_HDR3_SDRAM_BASE 0xB0000000
-
-/*
- * Logic expansion modules
- *
- */
-#define INTEGRATOR_LOGIC_MODULES_BASE 0xC0000000
-#define INTEGRATOR_LOGIC_MODULE0_BASE 0xC0000000
-#define INTEGRATOR_LOGIC_MODULE1_BASE 0xD0000000
-#define INTEGRATOR_LOGIC_MODULE2_BASE 0xE0000000
-#define INTEGRATOR_LOGIC_MODULE3_BASE 0xF0000000
-
-/*
- * Integrator header card registers
- */
-#define INTEGRATOR_HDR_ID_OFFSET 0x00
-#define INTEGRATOR_HDR_PROC_OFFSET 0x04
-#define INTEGRATOR_HDR_OSC_OFFSET 0x08
-#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C
-#define INTEGRATOR_HDR_STAT_OFFSET 0x10
-#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
-#define INTEGRATOR_HDR_SDRAM_OFFSET 0x20
-#define INTEGRATOR_HDR_INIT_OFFSET 0x24 /* CM9x6 */
-#define INTEGRATOR_HDR_IC_OFFSET 0x40
-#define INTEGRATOR_HDR_SPDBASE_OFFSET 0x100
-#define INTEGRATOR_HDR_SPDTOP_OFFSET 0x200
-
-#define INTEGRATOR_HDR_BASE 0x10000000
-#define INTEGRATOR_HDR_ID (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_ID_OFFSET)
-#define INTEGRATOR_HDR_PROC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_PROC_OFFSET)
-#define INTEGRATOR_HDR_OSC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_OSC_OFFSET)
-#define INTEGRATOR_HDR_CTRL (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_CTRL_OFFSET)
-#define INTEGRATOR_HDR_STAT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_STAT_OFFSET)
-#define INTEGRATOR_HDR_LOCK (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_LOCK_OFFSET)
-#define INTEGRATOR_HDR_SDRAM (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SDRAM_OFFSET)
-#define INTEGRATOR_HDR_INIT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_INIT_OFFSET)
-#define INTEGRATOR_HDR_IC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_IC_OFFSET)
-#define INTEGRATOR_HDR_SPDBASE (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDBASE_OFFSET)
-#define INTEGRATOR_HDR_SPDTOP (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDTOP_OFFSET)
-
-#define INTEGRATOR_HDR_CTRL_LED 0x01
-#define INTEGRATOR_HDR_CTRL_MBRD_DETECH 0x02
-#define INTEGRATOR_HDR_CTRL_REMAP 0x04
-#define INTEGRATOR_HDR_CTRL_RESET 0x08
-#define INTEGRATOR_HDR_CTRL_HIGHVECTORS 0x10
-#define INTEGRATOR_HDR_CTRL_BIG_ENDIAN 0x20
-#define INTEGRATOR_HDR_CTRL_FASTBUS 0x40
-#define INTEGRATOR_HDR_CTRL_SYNC 0x80
-
-#define INTEGRATOR_HDR_OSC_CORE_10MHz 0x102
-#define INTEGRATOR_HDR_OSC_CORE_15MHz 0x107
-#define INTEGRATOR_HDR_OSC_CORE_20MHz 0x10C
-#define INTEGRATOR_HDR_OSC_CORE_25MHz 0x111
-#define INTEGRATOR_HDR_OSC_CORE_30MHz 0x116
-#define INTEGRATOR_HDR_OSC_CORE_35MHz 0x11B
-#define INTEGRATOR_HDR_OSC_CORE_40MHz 0x120
-#define INTEGRATOR_HDR_OSC_CORE_45MHz 0x125
-#define INTEGRATOR_HDR_OSC_CORE_50MHz 0x12A
-#define INTEGRATOR_HDR_OSC_CORE_55MHz 0x12F
-#define INTEGRATOR_HDR_OSC_CORE_60MHz 0x134
-#define INTEGRATOR_HDR_OSC_CORE_65MHz 0x139
-#define INTEGRATOR_HDR_OSC_CORE_70MHz 0x13E
-#define INTEGRATOR_HDR_OSC_CORE_75MHz 0x143
-#define INTEGRATOR_HDR_OSC_CORE_80MHz 0x148
-#define INTEGRATOR_HDR_OSC_CORE_85MHz 0x14D
-#define INTEGRATOR_HDR_OSC_CORE_90MHz 0x152
-#define INTEGRATOR_HDR_OSC_CORE_95MHz 0x157
-#define INTEGRATOR_HDR_OSC_CORE_100MHz 0x15C
-#define INTEGRATOR_HDR_OSC_CORE_105MHz 0x161
-#define INTEGRATOR_HDR_OSC_CORE_110MHz 0x166
-#define INTEGRATOR_HDR_OSC_CORE_115MHz 0x16B
-#define INTEGRATOR_HDR_OSC_CORE_120MHz 0x170
-#define INTEGRATOR_HDR_OSC_CORE_125MHz 0x175
-#define INTEGRATOR_HDR_OSC_CORE_130MHz 0x17A
-#define INTEGRATOR_HDR_OSC_CORE_135MHz 0x17F
-#define INTEGRATOR_HDR_OSC_CORE_140MHz 0x184
-#define INTEGRATOR_HDR_OSC_CORE_145MHz 0x189
-#define INTEGRATOR_HDR_OSC_CORE_150MHz 0x18E
-#define INTEGRATOR_HDR_OSC_CORE_155MHz 0x193
-#define INTEGRATOR_HDR_OSC_CORE_160MHz 0x198
-#define INTEGRATOR_HDR_OSC_CORE_MASK 0x7FF
-
-#define INTEGRATOR_HDR_OSC_MEM_10MHz 0x10C000
-#define INTEGRATOR_HDR_OSC_MEM_15MHz 0x116000
-#define INTEGRATOR_HDR_OSC_MEM_20MHz 0x120000
-#define INTEGRATOR_HDR_OSC_MEM_25MHz 0x12A000
-#define INTEGRATOR_HDR_OSC_MEM_30MHz 0x134000
-#define INTEGRATOR_HDR_OSC_MEM_33MHz 0x13A000
-#define INTEGRATOR_HDR_OSC_MEM_40MHz 0x148000
-#define INTEGRATOR_HDR_OSC_MEM_50MHz 0x15C000
-#define INTEGRATOR_HDR_OSC_MEM_60MHz 0x170000
-#define INTEGRATOR_HDR_OSC_MEM_66MHz 0x17C000
-#define INTEGRATOR_HDR_OSC_MEM_MASK 0x7FF000
-
-#define INTEGRATOR_HDR_OSC_BUS_MODE_CM7x0 0x0
-#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x0 0x0800000
-#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x6 0x1000000
-#define INTEGRATOR_HDR_OSC_BUS_MODE_CM10x00 0x1800000
-#define INTEGRATOR_HDR_OSC_BUS_MODE_MASK 0x1800000
-
-#define INTEGRATOR_HDR_SDRAM_SPD_OK (1 << 5)
-
-/*
- * Integrator system registers
- */
-
-/*
- * System Controller
- */
-#define INTEGRATOR_SC_ID_OFFSET 0x00
-#define INTEGRATOR_SC_OSC_OFFSET 0x04
-#define INTEGRATOR_SC_CTRLS_OFFSET 0x08
-#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C
-#define INTEGRATOR_SC_DEC_OFFSET 0x10
-#define INTEGRATOR_SC_ARB_OFFSET 0x14
-#define INTEGRATOR_SC_LOCK_OFFSET 0x1C
-
-#define INTEGRATOR_SC_BASE 0x11000000
-#define INTEGRATOR_SC_ID (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ID_OFFSET)
-#define INTEGRATOR_SC_OSC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_OSC_OFFSET)
-#define INTEGRATOR_SC_CTRLS (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
-#define INTEGRATOR_SC_CTRLC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
-#define INTEGRATOR_SC_DEC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_DEC_OFFSET)
-#define INTEGRATOR_SC_ARB (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ARB_OFFSET)
-#define INTEGRATOR_SC_PCIENABLE (INTEGRATOR_SC_BASE + INTEGRATOR_SC_PCIENABLE_OFFSET)
-#define INTEGRATOR_SC_LOCK (INTEGRATOR_SC_BASE + INTEGRATOR_SC_LOCK_OFFSET)
-
-#define INTEGRATOR_SC_OSC_SYS_10MHz 0x20
-#define INTEGRATOR_SC_OSC_SYS_15MHz 0x34
-#define INTEGRATOR_SC_OSC_SYS_20MHz 0x48
-#define INTEGRATOR_SC_OSC_SYS_25MHz 0x5C
-#define INTEGRATOR_SC_OSC_SYS_33MHz 0x7C
-#define INTEGRATOR_SC_OSC_SYS_MASK 0xFF
-
-#define INTEGRATOR_SC_OSC_PCI_25MHz 0x100
-#define INTEGRATOR_SC_OSC_PCI_33MHz 0x0
-#define INTEGRATOR_SC_OSC_PCI_MASK 0x100
-
-#define INTEGRATOR_SC_CTRL_SOFTRST (1 << 0)
-#define INTEGRATOR_SC_CTRL_nFLVPPEN (1 << 1)
-#define INTEGRATOR_SC_CTRL_nFLWP (1 << 2)
-#define INTEGRATOR_SC_CTRL_URTS0 (1 << 4)
-#define INTEGRATOR_SC_CTRL_UDTR0 (1 << 5)
-#define INTEGRATOR_SC_CTRL_URTS1 (1 << 6)
-#define INTEGRATOR_SC_CTRL_UDTR1 (1 << 7)
-
-/*
- * External Bus Interface
- */
-#define INTEGRATOR_EBI_BASE 0x12000000
-
-#define INTEGRATOR_EBI_CSR0_OFFSET 0x00
-#define INTEGRATOR_EBI_CSR1_OFFSET 0x04
-#define INTEGRATOR_EBI_CSR2_OFFSET 0x08
-#define INTEGRATOR_EBI_CSR3_OFFSET 0x0C
-#define INTEGRATOR_EBI_LOCK_OFFSET 0x20
-
-#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET)
-#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
-#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET)
-#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET)
-#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
-
-#define INTEGRATOR_EBI_8_BIT 0x00
-#define INTEGRATOR_EBI_16_BIT 0x01
-#define INTEGRATOR_EBI_32_BIT 0x02
-#define INTEGRATOR_EBI_WRITE_ENABLE 0x04
-#define INTEGRATOR_EBI_SYNC 0x08
-#define INTEGRATOR_EBI_WS_2 0x00
-#define INTEGRATOR_EBI_WS_3 0x10
-#define INTEGRATOR_EBI_WS_4 0x20
-#define INTEGRATOR_EBI_WS_5 0x30
-#define INTEGRATOR_EBI_WS_6 0x40
-#define INTEGRATOR_EBI_WS_7 0x50
-#define INTEGRATOR_EBI_WS_8 0x60
-#define INTEGRATOR_EBI_WS_9 0x70
-#define INTEGRATOR_EBI_WS_10 0x80
-#define INTEGRATOR_EBI_WS_11 0x90
-#define INTEGRATOR_EBI_WS_12 0xA0
-#define INTEGRATOR_EBI_WS_13 0xB0
-#define INTEGRATOR_EBI_WS_14 0xC0
-#define INTEGRATOR_EBI_WS_15 0xD0
-#define INTEGRATOR_EBI_WS_16 0xE0
-#define INTEGRATOR_EBI_WS_17 0xF0
-
-
-#define INTEGRATOR_CT_BASE 0x13000000 /* Counter/Timers */
-#define INTEGRATOR_IC_BASE 0x14000000 /* Interrupt Controller */
-#define INTEGRATOR_RTC_BASE 0x15000000 /* Real Time Clock */
-#define INTEGRATOR_UART0_BASE 0x16000000 /* UART 0 */
-#define INTEGRATOR_UART1_BASE 0x17000000 /* UART 1 */
-#define INTEGRATOR_KBD_BASE 0x18000000 /* Keyboard */
-#define INTEGRATOR_MOUSE_BASE 0x19000000 /* Mouse */
-
-/*
- * LED's & Switches
- */
-#define INTEGRATOR_DBG_ALPHA_OFFSET 0x00
-#define INTEGRATOR_DBG_LEDS_OFFSET 0x04
-#define INTEGRATOR_DBG_SWITCH_OFFSET 0x08
-
-#define INTEGRATOR_DBG_BASE 0x1A000000
-#define INTEGRATOR_DBG_ALPHA (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_ALPHA_OFFSET)
-#define INTEGRATOR_DBG_LEDS (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_LEDS_OFFSET)
-#define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET)
-
-#define INTEGRATOR_AP_GPIO_BASE 0x1B000000 /* GPIO */
-
-#define INTEGRATOR_CP_MMC_BASE 0x1C000000 /* MMC */
-#define INTEGRATOR_CP_AACI_BASE 0x1D000000 /* AACI */
-#define INTEGRATOR_CP_ETH_BASE 0xC8000000 /* Ethernet */
-#define INTEGRATOR_CP_GPIO_BASE 0xC9000000 /* GPIO */
-#define INTEGRATOR_CP_SIC_BASE 0xCA000000 /* SIC */
-#define INTEGRATOR_CP_CTL_BASE 0xCB000000 /* CP system control */
-
-/* PS2 Keyboard interface */
-#define KMI0_BASE INTEGRATOR_KBD_BASE
-
-/* PS2 Mouse interface */
-#define KMI1_BASE INTEGRATOR_MOUSE_BASE
-
-/*
- * Integrator Interrupt Controllers
- *
- *
- * Offsets from interrupt controller base
- *
- * System Controller interrupt controller base is
- *
- * INTEGRATOR_IC_BASE + (header_number << 6)
- *
- * Core Module interrupt controller base is
- *
- * INTEGRATOR_HDR_IC
- */
-#define IRQ_STATUS 0
-#define IRQ_RAW_STATUS 0x04
-#define IRQ_ENABLE 0x08
-#define IRQ_ENABLE_SET 0x08
-#define IRQ_ENABLE_CLEAR 0x0C
-
-#define INT_SOFT_SET 0x10
-#define INT_SOFT_CLEAR 0x14
-
-#define FIQ_STATUS 0x20
-#define FIQ_RAW_STATUS 0x24
-#define FIQ_ENABLE 0x28
-#define FIQ_ENABLE_SET 0x28
-#define FIQ_ENABLE_CLEAR 0x2C
-
-
-/*
- * LED's
- */
-#define GREEN_LED 0x01
-#define YELLOW_LED 0x02
-#define RED_LED 0x04
-#define GREEN_LED_2 0x08
-#define ALL_LEDS 0x0F
-
-#define LED_BANK INTEGRATOR_DBG_LEDS
-
-/*
- * Timer definitions
- *
- * Only use timer 1 & 2
- * (both run at 24MHz and will need the clock divider set to 16).
- *
- * Timer 0 runs at bus frequency
- */
-#define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE
-#define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100)
-#define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200)
-
-#define INTEGRATOR_CSR_BASE 0x10000000
-#define INTEGRATOR_CSR_SIZE 0x10000000
-
-#endif /* INTEGRATOR_HARDWARE_H */
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/arch/arm/mach-integrator/integrator_ap.c
- *
- * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/syscore_ops.h>
-#include <linux/amba/bus.h>
-#include <linux/io.h>
-#include <linux/irqchip.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/termios.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "hardware.h"
-#include "cm.h"
-#include "common.h"
-
-/* Regmap to the AP system controller */
-static struct regmap *ap_syscon_map;
-
-/*
- * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
- * is the (PA >> 12).
- *
- * Setup a VA for the Integrator interrupt controller (for header #0,
- * just for now).
- */
-#define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE)
-
-/*
- * Logical Physical
- * f1400000 14000000 Interrupt controller
- * f1600000 16000000 UART 0
- */
-
-static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
- {
- .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
- .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
- .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }
-};
-
-static void __init ap_map_io(void)
-{
- iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
-}
-
-#ifdef CONFIG_PM
-static unsigned long ic_irq_enable;
-
-static int irq_suspend(void)
-{
- ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
- return 0;
-}
-
-static void irq_resume(void)
-{
- /* disable all irq sources */
- cm_clear_irqs();
- writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
- writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
-
- writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
-}
-#else
-#define irq_suspend NULL
-#define irq_resume NULL
-#endif
-
-static struct syscore_ops irq_syscore_ops = {
- .suspend = irq_suspend,
- .resume = irq_resume,
-};
-
-static int __init irq_syscore_init(void)
-{
- register_syscore_ops(&irq_syscore_ops);
-
- return 0;
-}
-
-device_initcall(irq_syscore_init);
-
-/*
- * For the PL010 found in the Integrator/AP some of the UART control is
- * implemented in the system controller and accessed using a callback
- * from the driver.
- */
-static void integrator_uart_set_mctrl(struct amba_device *dev,
- void __iomem *base, unsigned int mctrl)
-{
- unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
- u32 phybase = dev->res.start;
- int ret;
-
- if (phybase == INTEGRATOR_UART0_BASE) {
- /* UART0 */
- rts_mask = 1 << 4;
- dtr_mask = 1 << 5;
- } else {
- /* UART1 */
- rts_mask = 1 << 6;
- dtr_mask = 1 << 7;
- }
-
- if (mctrl & TIOCM_RTS)
- ctrlc |= rts_mask;
- else
- ctrls |= rts_mask;
-
- if (mctrl & TIOCM_DTR)
- ctrlc |= dtr_mask;
- else
- ctrls |= dtr_mask;
-
- ret = regmap_write(ap_syscon_map,
- INTEGRATOR_SC_CTRLS_OFFSET,
- ctrls);
- if (ret)
- pr_err("MODEM: unable to write PL010 UART CTRLS\n");
-
- ret = regmap_write(ap_syscon_map,
- INTEGRATOR_SC_CTRLC_OFFSET,
- ctrlc);
- if (ret)
- pr_err("MODEM: unable to write PL010 UART CRTLC\n");
-}
-
-struct amba_pl010_data ap_uart_data = {
- .set_mctrl = integrator_uart_set_mctrl,
-};
-
-void __init ap_init_early(void)
-{
-}
-
-static void __init ap_init_irq_of(void)
-{
- cm_init();
- irqchip_init();
-}
-
-/* For the Device Tree, add in the UART callbacks as AUXDATA */
-static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
- "uart0", &ap_uart_data),
- OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
- "uart1", &ap_uart_data),
- { /* sentinel */ },
-};
-
-static const struct of_device_id ap_syscon_match[] = {
- { .compatible = "arm,integrator-ap-syscon"},
- { },
-};
-
-static void __init ap_init_of(void)
-{
- struct device_node *syscon;
-
- of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
-
- syscon = of_find_matching_node(NULL, ap_syscon_match);
- if (!syscon)
- return;
- ap_syscon_map = syscon_node_to_regmap(syscon);
- if (IS_ERR(ap_syscon_map)) {
- pr_crit("could not find Integrator/AP system controller\n");
- return;
- }
-}
-
-static const char * ap_dt_board_compat[] = {
- "arm,integrator-ap",
- NULL,
-};
-
-DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
- .reserve = integrator_reserve,
- .map_io = ap_map_io,
- .init_early = ap_init_early,
- .init_irq = ap_init_irq_of,
- .init_machine = ap_init_of,
- .dt_compat = ap_dt_board_compat,
-MACHINE_END
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-integrator/integrator_cp.c
- *
- * Copyright (C) 2003 Deep Blue Solutions Ltd
- */
-#include <linux/kernel.h>
-#include <linux/amba/mmci.h>
-#include <linux/io.h>
-#include <linux/irqchip.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/sched_clock.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "hardware.h"
-#include "cm.h"
-#include "common.h"
-
-/* Base address to the core module header */
-static struct regmap *cm_map;
-/* Base address to the CP controller */
-static void __iomem *intcp_con_base;
-
-#define CM_COUNTER_OFFSET 0x28
-
-/*
- * Logical Physical
- * f1400000 14000000 Interrupt controller
- * f1600000 16000000 UART 0
- * fca00000 ca000000 SIC
- */
-
-static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
- {
- .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
- .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
- .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
- .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE
- }
-};
-
-static void __init intcp_map_io(void)
-{
- iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
-}
-
-/*
- * It seems that the card insertion interrupt remains active after
- * we've acknowledged it. We therefore ignore the interrupt, and
- * rely on reading it from the SIC. This also means that we must
- * clear the latched interrupt.
- */
-static unsigned int mmc_status(struct device *dev)
-{
- unsigned int status = readl(__io_address(0xca000000 + 4));
- writel(8, intcp_con_base + 8);
-
- return status & 8;
-}
-
-static struct mmci_platform_data mmc_data = {
- .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .status = mmc_status,
-};
-
-static u64 notrace intcp_read_sched_clock(void)
-{
- unsigned int val;
-
- /* MMIO so discard return code */
- regmap_read(cm_map, CM_COUNTER_OFFSET, &val);
- return val;
-}
-
-static void __init intcp_init_early(void)
-{
- cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
- if (IS_ERR(cm_map))
- return;
- sched_clock_register(intcp_read_sched_clock, 32, 24000000);
-}
-
-static void __init intcp_init_irq_of(void)
-{
- cm_init();
- irqchip_init();
-}
-
-/*
- * For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
- * and enforce the bus names since these are used for clock lookups.
- */
-static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
- "mmci", &mmc_data),
- { /* sentinel */ },
-};
-
-static const struct of_device_id intcp_syscon_match[] = {
- { .compatible = "arm,integrator-cp-syscon"},
- { },
-};
-
-static void __init intcp_init_of(void)
-{
- struct device_node *cpcon;
-
- cpcon = of_find_matching_node(NULL, intcp_syscon_match);
- if (!cpcon)
- return;
-
- intcp_con_base = of_iomap(cpcon, 0);
- if (!intcp_con_base)
- return;
-
- of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
-}
-
-static const char * intcp_dt_board_compat[] = {
- "arm,integrator-cp",
- NULL,
-};
-
-DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
- .reserve = integrator_reserve,
- .map_io = intcp_map_io,
- .init_early = intcp_init_early,
- .init_irq = intcp_init_irq_of,
- .init_machine = intcp_init_of,
- .dt_compat = intcp_dt_board_compat,
-MACHINE_END
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig ARCH_REALVIEW
- bool "ARM Ltd. RealView family"
- depends on ARCH_MULTI_V5 || ARCH_MULTI_V6 || ARCH_MULTI_V7
- select ARM_AMBA
- select ARM_GIC
- select ARM_TIMER_SP804
- select CLK_SP810
- select GPIO_PL061 if GPIOLIB
- select HAVE_ARM_SCU if SMP
- select HAVE_ARM_TWD if SMP
- select HAVE_PATA_PLATFORM
- select HAVE_TCM
- select CLK_ICST
- select MACH_REALVIEW_EB if ARCH_MULTI_V5
- select MFD_SYSCON
- select PLAT_VERSATILE
- select POWER_RESET
- select POWER_RESET_VERSATILE
- select POWER_SUPPLY
- select SOC_REALVIEW
- help
- This enables support for ARM Ltd RealView boards.
-
-if ARCH_REALVIEW
-
-config MACH_REALVIEW_EB
- bool "Support RealView(R) Emulation Baseboard"
- select ARM_GIC
- select CPU_ARM926T if ARCH_MULTI_V5
- help
- Include support for the ARM(R) RealView(R) Emulation Baseboard
- platform. On an ARMv5 kernel, this will include support for
- the ARM926EJ-S core tile, while on an ARMv6/v7 kernel, at least
- one of the ARM1136, ARM1176, ARM11MPCore or Cortex-A9MPCore
- core tile options should be enabled.
-
-config REALVIEW_EB_ARM1136
- bool "Support ARM1136J(F)-S Tile"
- depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
- select CPU_V6
- help
- Enable support for the ARM1136 tile fitted to the
- Realview(R) Emulation Baseboard platform.
-
-config REALVIEW_EB_ARM1176
- bool "Support ARM1176JZ(F)-S Tile"
- depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
- help
- Enable support for the ARM1176 tile fitted to the
- Realview(R) Emulation Baseboard platform.
-
-config REALVIEW_EB_A9MP
- bool "Support Multicore Cortex-A9 Tile"
- depends on MACH_REALVIEW_EB && ARCH_MULTI_V7
- help
- Enable support for the Cortex-A9MPCore tile fitted to the
- Realview(R) Emulation Baseboard platform.
-
-config REALVIEW_EB_ARM11MP
- bool "Support ARM11MPCore Tile"
- depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
- select HAVE_SMP
- help
- Enable support for the ARM11MPCore tile fitted to the Realview(R)
- Emulation Baseboard platform.
-
-config MACH_REALVIEW_PB11MP
- bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
- depends on ARCH_MULTI_V6
- select HAVE_SMP
- help
- Include support for the ARM(R) RealView(R) Platform Baseboard for
- the ARM11MPCore. This platform has an on-board ARM11MPCore and has
- support for PCI-E and Compact Flash.
-
-# ARMv6 CPU without K extensions, but does have the new exclusive ops
-config MACH_REALVIEW_PB1176
- bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
- depends on ARCH_MULTI_V6
- select CPU_V6
- select HAVE_TCM
- help
- Include support for the ARM(R) RealView(R) Platform Baseboard for
- ARM1176JZF-S.
-
-config MACH_REALVIEW_PBA8
- bool "Support RealView(R) Platform Baseboard for Cortex(tm)-A8 platform"
- depends on ARCH_MULTI_V7
- help
- Include support for the ARM(R) RealView Platform Baseboard for
- Cortex(tm)-A8. This platform has an on-board Cortex-A8 and has
- support for PCI-E and Compact Flash.
-
-config MACH_REALVIEW_PBX
- bool "Support RealView(R) Platform Baseboard Explore for Cortex-A9"
- depends on ARCH_MULTI_V7
- select ZONE_DMA
- help
- Include support for the ARM(R) RealView(R) Platform Baseboard
- Explore.
-
-endif
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the linux kernel.
-#
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/arch/arm/plat-versatile/include
-
-obj-y += realview-dt.o
-obj-$(CONFIG_SMP) += platsmp-dt.o
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Linus Walleij
- */
-#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-
-#include <asm/cacheflush.h>
-#include <asm/smp_plat.h>
-#include <asm/smp_scu.h>
-
-#include <plat/platsmp.h>
-
-#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
-
-static const struct of_device_id realview_scu_match[] = {
- { .compatible = "arm,arm11mp-scu", },
- { .compatible = "arm,cortex-a9-scu", },
- { .compatible = "arm,cortex-a5-scu", },
- { }
-};
-
-static const struct of_device_id realview_syscon_match[] = {
- { .compatible = "arm,core-module-integrator", },
- { .compatible = "arm,realview-eb-syscon", },
- { .compatible = "arm,realview-pb11mp-syscon", },
- { .compatible = "arm,realview-pbx-syscon", },
- { },
-};
-
-static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
-{
- struct device_node *np;
- void __iomem *scu_base;
- struct regmap *map;
- unsigned int ncores;
- int i;
-
- np = of_find_matching_node(NULL, realview_scu_match);
- if (!np) {
- pr_err("PLATSMP: No SCU base address\n");
- return;
- }
- scu_base = of_iomap(np, 0);
- of_node_put(np);
- if (!scu_base) {
- pr_err("PLATSMP: No SCU remap\n");
- return;
- }
-
- scu_enable(scu_base);
- ncores = scu_get_core_count(scu_base);
- pr_info("SCU: %d cores detected\n", ncores);
- for (i = 0; i < ncores; i++)
- set_cpu_possible(i, true);
- iounmap(scu_base);
-
- /* The syscon contains the magic SMP start address registers */
- np = of_find_matching_node(NULL, realview_syscon_match);
- if (!np) {
- pr_err("PLATSMP: No syscon match\n");
- return;
- }
- map = syscon_node_to_regmap(np);
- if (IS_ERR(map)) {
- pr_err("PLATSMP: No syscon regmap\n");
- return;
- }
- /* Put the boot address in this magic register */
- regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET,
- __pa_symbol(versatile_secondary_startup));
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-static void realview_cpu_die(unsigned int cpu)
-{
- return versatile_immitation_cpu_die(cpu, 0x20);
-}
-#endif
-
-static const struct smp_operations realview_dt_smp_ops __initconst = {
- .smp_prepare_cpus = realview_smp_prepare_cpus,
- .smp_secondary_init = versatile_secondary_init,
- .smp_boot_secondary = versatile_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
- .cpu_die = realview_cpu_die,
-#endif
-};
-CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2014 Linaro Ltd.
- *
- * Author: Linus Walleij <linus.walleij@linaro.org>
- */
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/cache-l2x0.h>
-
-static const char *const realview_dt_platform_compat[] __initconst = {
- "arm,realview-eb",
- "arm,realview-pb1176",
- "arm,realview-pb11mp",
- "arm,realview-pba8",
- "arm,realview-pbx",
- NULL,
-};
-
-DT_MACHINE_START(REALVIEW_DT, "ARM RealView Machine (Device Tree Support)")
-#ifdef CONFIG_ZONE_DMA
- .dma_zone_size = SZ_256M,
-#endif
- .dt_compat = realview_dt_platform_compat,
- .l2c_aux_val = 0x0,
- .l2c_aux_mask = ~0x0,
-MACHINE_END
help
This enables support for ARM Ltd Versatile board.
+menuconfig ARCH_INTEGRATOR
+ bool "ARM Ltd. Integrator family"
+ depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6
+ select ARM_AMBA
+ select CMA
+ select DMA_CMA
+ select HAVE_TCM
+ select CLK_ICST
+ select MFD_SYSCON
+ select PLAT_VERSATILE
+ select POWER_RESET
+ select POWER_RESET_VERSATILE
+ select POWER_SUPPLY
+ select SOC_INTEGRATOR_CM
+ select VERSATILE_FPGA_IRQ
+ help
+ Support for ARM's Integrator platform.
+
+if ARCH_INTEGRATOR
+
+config ARCH_INTEGRATOR_AP
+ bool "Support Integrator/AP and Integrator/PP2 platforms"
+ select INTEGRATOR_AP_TIMER
+ select SERIAL_AMBA_PL010 if TTY
+ select SERIAL_AMBA_PL010_CONSOLE if TTY
+ select SOC_BUS
+ help
+ Include support for the ARM(R) Integrator/AP and
+ Integrator/PP2 platforms.
+
+config INTEGRATOR_IMPD1
+ bool "Include support for Integrator/IM-PD1"
+ depends on ARCH_INTEGRATOR_AP
+ select ARM_VIC
+ select GPIO_PL061
+ select GPIOLIB
+ select REGULATOR
+ select REGULATOR_FIXED_VOLTAGE
+ help
+ The IM-PD1 is an add-on logic module for the Integrator which
+ allows ARM(R) Ltd PrimeCells to be developed and evaluated.
+ The IM-PD1 can be found on the Integrator/PP2 platform.
+
+config INTEGRATOR_CM720T
+ bool "Integrator/CM720T core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V4T
+ select CPU_ARM720T
+
+config INTEGRATOR_CM920T
+ bool "Integrator/CM920T core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V4T
+ select CPU_ARM920T
+
+config INTEGRATOR_CM922T_XA10
+ bool "Integrator/CM922T-XA10 core module"
+ depends on ARCH_MULTI_V4T
+ depends on ARCH_INTEGRATOR_AP
+ select CPU_ARM922T
+
+config INTEGRATOR_CM926EJS
+ bool "Integrator/CM926EJ-S core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V5
+ select CPU_ARM926T
+
+config INTEGRATOR_CM10200E_REV0
+ bool "Integrator/CM10200E rev.0 core module"
+ depends on ARCH_INTEGRATOR_AP && n
+ depends on ARCH_MULTI_V5
+ select CPU_ARM1020
+
+config INTEGRATOR_CM10200E
+ bool "Integrator/CM10200E core module"
+ depends on ARCH_INTEGRATOR_AP && n
+ depends on ARCH_MULTI_V5
+ select CPU_ARM1020E
+
+config INTEGRATOR_CM10220E
+ bool "Integrator/CM10220E core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V5
+ select CPU_ARM1022
+
+config INTEGRATOR_CM1026EJS
+ bool "Integrator/CM1026EJ-S core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V5
+ select CPU_ARM1026
+
+config INTEGRATOR_CM1136JFS
+ bool "Integrator/CM1136JF-S core module"
+ depends on ARCH_INTEGRATOR_AP
+ depends on ARCH_MULTI_V6
+ select CPU_V6
+
+config ARCH_INTEGRATOR_CP
+ bool "Support Integrator/CP platform"
+ depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
+ select ARM_TIMER_SP804
+ select SERIAL_AMBA_PL011 if TTY
+ select SERIAL_AMBA_PL011_CONSOLE if TTY
+ select SOC_BUS
+ help
+ Include support for the ARM(R) Integrator CP platform.
+
+config INTEGRATOR_CT926
+ bool "Integrator/CT926 (ARM926EJ-S) core tile"
+ depends on ARCH_INTEGRATOR_CP
+ depends on ARCH_MULTI_V5
+ select CPU_ARM926T
+
+config INTEGRATOR_CTB36
+ bool "Integrator/CTB36 (ARM1136JF-S) core tile"
+ depends on ARCH_INTEGRATOR_CP
+ depends on ARCH_MULTI_V6
+ select CPU_V6
+
+config ARCH_CINTEGRATOR
+ depends on ARCH_INTEGRATOR_CP
+ def_bool y
+
+endif
+
+menuconfig ARCH_REALVIEW
+ bool "ARM Ltd. RealView family"
+ depends on ARCH_MULTI_V5 || ARCH_MULTI_V6 || ARCH_MULTI_V7
+ select ARM_AMBA
+ select ARM_GIC
+ select ARM_TIMER_SP804
+ select CLK_SP810
+ select GPIO_PL061 if GPIOLIB
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select HAVE_PATA_PLATFORM
+ select HAVE_TCM
+ select CLK_ICST
+ select MACH_REALVIEW_EB if ARCH_MULTI_V5
+ select MFD_SYSCON
+ select PLAT_VERSATILE
+ select POWER_RESET
+ select POWER_RESET_VERSATILE
+ select POWER_SUPPLY
+ select SOC_REALVIEW
+ help
+ This enables support for ARM Ltd RealView boards.
+
+if ARCH_REALVIEW
+
+config MACH_REALVIEW_EB
+ bool "Support RealView(R) Emulation Baseboard"
+ select ARM_GIC
+ select CPU_ARM926T if ARCH_MULTI_V5
+ help
+ Include support for the ARM(R) RealView(R) Emulation Baseboard
+ platform. On an ARMv5 kernel, this will include support for
+ the ARM926EJ-S core tile, while on an ARMv6/v7 kernel, at least
+ one of the ARM1136, ARM1176, ARM11MPCore or Cortex-A9MPCore
+ core tile options should be enabled.
+
+config REALVIEW_EB_ARM1136
+ bool "Support ARM1136J(F)-S Tile"
+ depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
+ select CPU_V6
+ help
+ Enable support for the ARM1136 tile fitted to the
+ Realview(R) Emulation Baseboard platform.
+
+config REALVIEW_EB_ARM1176
+ bool "Support ARM1176JZ(F)-S Tile"
+ depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
+ help
+ Enable support for the ARM1176 tile fitted to the
+ Realview(R) Emulation Baseboard platform.
+
+config REALVIEW_EB_A9MP
+ bool "Support Multicore Cortex-A9 Tile"
+ depends on MACH_REALVIEW_EB && ARCH_MULTI_V7
+ help
+ Enable support for the Cortex-A9MPCore tile fitted to the
+ Realview(R) Emulation Baseboard platform.
+
+config REALVIEW_EB_ARM11MP
+ bool "Support ARM11MPCore Tile"
+ depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
+ select HAVE_SMP
+ help
+ Enable support for the ARM11MPCore tile fitted to the Realview(R)
+ Emulation Baseboard platform.
+
+config MACH_REALVIEW_PB11MP
+ bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
+ depends on ARCH_MULTI_V6
+ select HAVE_SMP
+ help
+ Include support for the ARM(R) RealView(R) Platform Baseboard for
+ the ARM11MPCore. This platform has an on-board ARM11MPCore and has
+ support for PCI-E and Compact Flash.
+
+# ARMv6 CPU without K extensions, but does have the new exclusive ops
+config MACH_REALVIEW_PB1176
+ bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
+ depends on ARCH_MULTI_V6
+ select CPU_V6
+ select HAVE_TCM
+ help
+ Include support for the ARM(R) RealView(R) Platform Baseboard for
+ ARM1176JZF-S.
+
+config MACH_REALVIEW_PBA8
+ bool "Support RealView(R) Platform Baseboard for Cortex(tm)-A8 platform"
+ depends on ARCH_MULTI_V7
+ help
+ Include support for the ARM(R) RealView Platform Baseboard for
+ Cortex(tm)-A8. This platform has an on-board Cortex-A8 and has
+ support for PCI-E and Compact Flash.
+
+config MACH_REALVIEW_PBX
+ bool "Support RealView(R) Platform Baseboard Explore for Cortex-A9"
+ depends on ARCH_MULTI_V7
+ select ZONE_DMA
+ help
+ Include support for the ARM(R) RealView(R) Platform Baseboard
+ Explore.
+
+endif
+
+menuconfig ARCH_VEXPRESS
+ bool "ARM Ltd. Versatile Express family"
+ depends on ARCH_MULTI_V7
+ select ARCH_SUPPORTS_BIG_ENDIAN
+ select ARM_AMBA
+ select ARM_GIC
+ select ARM_GLOBAL_TIMER
+ select ARM_TIMER_SP804
+ select GPIOLIB
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select HAVE_PATA_PLATFORM
+ select CLK_ICST
+ select NO_IOPORT_MAP
+ select PLAT_VERSATILE
+ select POWER_RESET
+ select POWER_RESET_VEXPRESS
+ select POWER_SUPPLY
+ select REGULATOR if MMC_ARMMMCI
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select VEXPRESS_CONFIG
+ help
+ This option enables support for systems using Cortex processor based
+ ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
+ for example:
+
+ - CoreTile Express A5x2 (V2P-CA5s)
+ - CoreTile Express A9x4 (V2P-CA9)
+ - CoreTile Express A15x2 (V2P-CA15)
+ - LogicTile Express 13MG (V2F-2XV6) with A5, A7, A9 or A15 SMMs
+ (Soft Macrocell Models)
+ - Versatile Express RTSMs (Models)
+
+ You must boot using a Flattened Device Tree in order to use these
+ platforms. The traditional (ATAGs) boot method is not usable on
+ these boards with this option.
+
+if ARCH_VEXPRESS
+
+config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
+ bool "Enable A5 and A9 only errata work-arounds"
+ default y
+ select ARM_ERRATA_643719 if SMP
+ select ARM_ERRATA_720789
+ select PL310_ERRATA_753970 if CACHE_L2X0
+ help
+ Provides common dependencies for Versatile Express platforms
+ based on Cortex-A5 and Cortex-A9 processors. In order to
+ build a working kernel, you must also enable relevant core
+ tile support or Flattened Device Tree based support options.
+
+config ARCH_VEXPRESS_DCSCB
+ bool "Dual Cluster System Control Block (DCSCB) support"
+ depends on MCPM
+ select ARM_CCI400_PORT_CTRL
+ help
+ Support for the Dual Cluster System Configuration Block (DCSCB).
+ This is needed to provide CPU and cluster power management
+ on RTSM implementing big.LITTLE.
+
+config ARCH_VEXPRESS_SPC
+ bool "Versatile Express Serial Power Controller (SPC)"
+ select PM_OPP
+ help
+ The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
+ block called Serial Power Controller (SPC) that provides the interface
+ between the dual cluster test-chip and the M3 microcontroller that
+ carries out power management.
+
+config ARCH_VEXPRESS_TC2_PM
+ bool "Versatile Express TC2 power management"
+ depends on MCPM
+ select ARM_CCI400_PORT_CTRL
+ select ARCH_VEXPRESS_SPC
+ select ARM_CPU_SUSPEND
+ help
+ Support for CPU and cluster power management on Versatile Express
+ with a TC2 (A15x2 A7x3) big.LITTLE core tile.
+
+endif
# Makefile for the linux kernel.
#
-obj-y := versatile_dt.o
+# versatile
+obj-$(CONFIG_ARCH_VERSATILE) += versatile.o
+
+# integrator
+obj-$(CONFIG_ARCH_INTEGRATOR) += integrator.o
+obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
+obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
+
+# realview
+obj-$(CONFIG_ARCH_REALVIEW) += realview.o
+
+# vexpress
+obj-$(CONFIG_ARCH_VEXPRESS) := v2m.o
+obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o
+CFLAGS_dcscb.o += -march=armv7-a
+CFLAGS_REMOVE_dcscb.o = -pg
+obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o
+CFLAGS_REMOVE_spc.o = -pg
+obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o
+CFLAGS_tc2_pm.o += -march=armv7-a
+CFLAGS_REMOVE_tc2_pm.o = -pg
+
+# mps2
+obj-$(CONFIG_ARCH_MPS2) += v2m-mps2.o
+
+ifdef CONFIG_SMP
+obj-y += headsmp.o platsmp.o
+obj-$(CONFIG_ARCH_REALVIEW) += platsmp-realview.o
+obj-$(CONFIG_ARCH_VEXPRESS) += platsmp-vexpress.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+endif
--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-only
+# Empty file waiting for deletion once Makefile.boot isn't needed any more.
+# Patch waits for application at
+# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * dcscb.c - Dual Cluster System Configuration Block
+ *
+ * Created by: Nicolas Pitre, May 2012
+ * Copyright: (C) 2012-2013 Linaro Limited
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+#include <linux/arm-cci.h>
+
+#include <asm/mcpm.h>
+#include <asm/proc-fns.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/cp15.h>
+
+#include "vexpress.h"
+
+#define RST_HOLD0 0x0
+#define RST_HOLD1 0x4
+#define SYS_SWRESET 0x8
+#define RST_STAT0 0xc
+#define RST_STAT1 0x10
+#define EAG_CFG_R 0x20
+#define EAG_CFG_W 0x24
+#define KFC_CFG_R 0x28
+#define KFC_CFG_W 0x2c
+#define DCS_CFG_R 0x30
+
+static void __iomem *dcscb_base;
+static int dcscb_allcpus_mask[2];
+
+static int dcscb_cpu_powerup(unsigned int cpu, unsigned int cluster)
+{
+ unsigned int rst_hold, cpumask = (1 << cpu);
+
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ if (cluster >= 2 || !(cpumask & dcscb_allcpus_mask[cluster]))
+ return -EINVAL;
+
+ rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+ rst_hold &= ~(cpumask | (cpumask << 4));
+ writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+ return 0;
+}
+
+static int dcscb_cluster_powerup(unsigned int cluster)
+{
+ unsigned int rst_hold;
+
+ pr_debug("%s: cluster %u\n", __func__, cluster);
+ if (cluster >= 2)
+ return -EINVAL;
+
+ /* remove cluster reset and add individual CPU's reset */
+ rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+ rst_hold &= ~(1 << 8);
+ rst_hold |= dcscb_allcpus_mask[cluster];
+ writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+ return 0;
+}
+
+static void dcscb_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
+{
+ unsigned int rst_hold;
+
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ BUG_ON(cluster >= 2 || !((1 << cpu) & dcscb_allcpus_mask[cluster]));
+
+ rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+ rst_hold |= (1 << cpu);
+ writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+}
+
+static void dcscb_cluster_powerdown_prepare(unsigned int cluster)
+{
+ unsigned int rst_hold;
+
+ pr_debug("%s: cluster %u\n", __func__, cluster);
+ BUG_ON(cluster >= 2);
+
+ rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+ rst_hold |= (1 << 8);
+ writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+}
+
+static void dcscb_cpu_cache_disable(void)
+{
+ /* Disable and flush the local CPU cache. */
+ v7_exit_coherency_flush(louis);
+}
+
+static void dcscb_cluster_cache_disable(void)
+{
+ /* Flush all cache levels for this cluster. */
+ v7_exit_coherency_flush(all);
+
+ /*
+ * A full outer cache flush could be needed at this point
+ * on platforms with such a cache, depending on where the
+ * outer cache sits. In some cases the notion of a "last
+ * cluster standing" would need to be implemented if the
+ * outer cache is shared across clusters. In any case, when
+ * the outer cache needs flushing, there is no concurrent
+ * access to the cache controller to worry about and no
+ * special locking besides what is already provided by the
+ * MCPM state machinery is needed.
+ */
+
+ /*
+ * Disable cluster-level coherency by masking
+ * incoming snoops and DVM messages:
+ */
+ cci_disable_port_by_cpu(read_cpuid_mpidr());
+}
+
+static const struct mcpm_platform_ops dcscb_power_ops = {
+ .cpu_powerup = dcscb_cpu_powerup,
+ .cluster_powerup = dcscb_cluster_powerup,
+ .cpu_powerdown_prepare = dcscb_cpu_powerdown_prepare,
+ .cluster_powerdown_prepare = dcscb_cluster_powerdown_prepare,
+ .cpu_cache_disable = dcscb_cpu_cache_disable,
+ .cluster_cache_disable = dcscb_cluster_cache_disable,
+};
+
+extern void dcscb_power_up_setup(unsigned int affinity_level);
+
+static int __init dcscb_init(void)
+{
+ struct device_node *node;
+ unsigned int cfg;
+ int ret;
+
+ if (!cci_probed())
+ return -ENODEV;
+
+ node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb");
+ if (!node)
+ return -ENODEV;
+ dcscb_base = of_iomap(node, 0);
+ if (!dcscb_base)
+ return -EADDRNOTAVAIL;
+ cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
+ dcscb_allcpus_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
+ dcscb_allcpus_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
+
+ ret = mcpm_platform_register(&dcscb_power_ops);
+ if (!ret)
+ ret = mcpm_sync_init(dcscb_power_up_setup);
+ if (ret) {
+ iounmap(dcscb_base);
+ return ret;
+ }
+
+ pr_info("VExpress DCSCB support installed\n");
+
+ /*
+ * Future entries into the kernel can now go
+ * through the cluster entry vectors.
+ */
+ vexpress_flags_set(__pa_symbol(mcpm_entry_point));
+
+ return 0;
+}
+
+early_initcall(dcscb_init);
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Created by: Dave Martin, 2012-06-22
+ * Copyright: (C) 2012-2013 Linaro Limited
+ */
+
+#include <linux/linkage.h>
+
+
+ENTRY(dcscb_power_up_setup)
+
+ cmp r0, #0 @ check affinity level
+ beq 2f
+
+/*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ * The ACTLR SMP bit does not need to be set here, because cpu_resume()
+ * already restores that.
+ *
+ * A15/A7 may not require explicit L2 invalidation on reset, dependent
+ * on hardware integration decisions.
+ * For now, this code assumes that L2 is either already invalidated,
+ * or invalidation is not required.
+ */
+
+ b cci_enable_port_for_self
+
+2: @ Implementation-specific local CPU setup operations should go here,
+ @ if any. In this case, there is nothing to do.
+
+ bx lr
+
+ENDPROC(dcscb_power_up_setup)
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+/*
+ * Realview/Versatile Express specific entry point for secondary CPUs.
+ * This provides a "holding pen" into which all secondary cores are held
+ * until we're ready for them to initialise.
+ */
+ENTRY(versatile_secondary_startup)
+ ARM_BE8(setend be)
+ mrc p15, 0, r0, c0, c0, 5
+ bic r0, #0xff000000
+ adr r4, 1f
+ ldmia r4, {r5, r6}
+ sub r4, r4, r5
+ add r6, r6, r4
+pen: ldr r7, [r6]
+ cmp r7, r0
+ bne pen
+
+ /*
+ * we've been released from the holding pen: secondary_stack
+ * should now contain the SVC stack for this core
+ */
+ b secondary_startup
+
+ .align
+1: .long .
+ .long versatile_cpu_release
+ENDPROC(versatile_secondary_startup)
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This hotplug implementation is _specific_ to the situation found on
+ * ARM development platforms where there is _no_ possibility of actually
+ * taking a CPU offline, resetting it, or otherwise. Real platforms must
+ * NOT copy this code.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_plat.h>
+#include <asm/cp15.h>
+
+#include "platsmp.h"
+
+static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
+{
+ unsigned int v;
+
+ asm volatile(
+ "mcr p15, 0, %1, c7, c5, 0\n"
+ " mcr p15, 0, %1, c7, c10, 4\n"
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, %3\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
+ : "cc");
+}
+
+static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
+{
+ unsigned int v;
+
+ asm volatile(
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ " orr %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " orr %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (CR_C), "Ir" (actrl_mask)
+ : "cc");
+}
+
+static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
+{
+ /*
+ * there is no power-control hardware on this platform, so all
+ * we can do is put the core into WFI; this is safe as the calling
+ * code will have already disabled interrupts.
+ *
+ * This code should not be used outside Versatile platforms.
+ */
+ for (;;) {
+ wfi();
+
+ if (versatile_cpu_release == cpu_logical_map(cpu)) {
+ /*
+ * OK, proper wakeup, we're done
+ */
+ break;
+ }
+
+ /*
+ * Getting here, means that we have come out of WFI without
+ * having been woken up - this shouldn't happen
+ *
+ * Just note it happening - when we're woken, we can report
+ * its occurrence.
+ */
+ (*spurious)++;
+ }
+}
+
+/*
+ * platform-specific code to shutdown a CPU.
+ * This code supports immitation-style CPU hotplug for Versatile/Realview/
+ * Versatile Express platforms that are unable to do real CPU hotplug.
+ */
+void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
+{
+ int spurious = 0;
+
+ versatile_immitation_enter_lowpower(actrl_mask);
+ versatile_immitation_do_lowpower(cpu, &spurious);
+ versatile_immitation_leave_lowpower(actrl_mask);
+
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * access the core module control register.
+ */
+u32 cm_get(void);
+void cm_control(u32, u32);
+
+struct device_node;
+void cm_init(void);
+void cm_clear_irqs(void);
+
+#define CM_CTRL_LED (1 << 0)
+#define CM_CTRL_nMBDET (1 << 1)
+#define CM_CTRL_REMAP (1 << 2)
+
+/*
+ * Integrator/AP,PP2 specific
+ */
+#define CM_CTRL_HIGHVECTORS (1 << 4)
+#define CM_CTRL_BIGENDIAN (1 << 5)
+#define CM_CTRL_FASTBUS (1 << 6)
+#define CM_CTRL_SYNC (1 << 7)
+
+/*
+ * ARM926/946/966 Integrator/CP specific
+ */
+#define CM_CTRL_LCDBIASEN (1 << 8)
+#define CM_CTRL_LCDBIASUP (1 << 9)
+#define CM_CTRL_LCDBIASDN (1 << 10)
+#define CM_CTRL_LCDMUXSEL_MASK (7 << 11)
+#define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA565_TFT555 (2 << 11)
+#define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA555_TFT555 (4 << 11)
+#define CM_CTRL_LCDEN0 (1 << 14)
+#define CM_CTRL_LCDEN1 (1 << 15)
+#define CM_CTRL_STATIC1 (1 << 16)
+#define CM_CTRL_STATIC2 (1 << 17)
+#define CM_CTRL_STATIC (1 << 18)
+#define CM_CTRL_n24BITEN (1 << 19)
+#define CM_CTRL_EBIWP (1 << 20)
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * This file contains the hardware definitions of the Integrator.
+ *
+ * Copyright (C) 1998-1999 ARM Limited.
+ */
+#ifndef INTEGRATOR_HARDWARE_H
+#define INTEGRATOR_HARDWARE_H
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+#define IO_BASE 0xF0000000 // VA of IO
+#define IO_SIZE 0x0B000000 // How much?
+#define IO_START INTEGRATOR_HDR_BASE // PA of IO
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
+#define __io_address(n) ((void __iomem *)IO_ADDRESS(n))
+
+/*
+ * Integrator memory map
+ */
+#define INTEGRATOR_BOOT_ROM_LO 0x00000000
+#define INTEGRATOR_BOOT_ROM_HI 0x20000000
+#define INTEGRATOR_BOOT_ROM_BASE INTEGRATOR_BOOT_ROM_HI /* Normal position */
+#define INTEGRATOR_BOOT_ROM_SIZE SZ_512K
+
+/*
+ * New Core Modules have different amounts of SSRAM, the amount of SSRAM
+ * fitted can be found in HDR_STAT.
+ *
+ * The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to
+ * the minimum amount of SSRAM fitted on any core module.
+ *
+ * New Core Modules also alias the SSRAM.
+ *
+ */
+#define INTEGRATOR_SSRAM_BASE 0x00000000
+#define INTEGRATOR_SSRAM_ALIAS_BASE 0x10800000
+#define INTEGRATOR_SSRAM_SIZE SZ_256K
+
+#define INTEGRATOR_FLASH_BASE 0x24000000
+#define INTEGRATOR_FLASH_SIZE SZ_32M
+
+#define INTEGRATOR_MBRD_SSRAM_BASE 0x28000000
+#define INTEGRATOR_MBRD_SSRAM_SIZE SZ_512K
+
+/*
+ * SDRAM is a SIMM therefore the size is not known.
+ */
+#define INTEGRATOR_SDRAM_BASE 0x00040000
+
+#define INTEGRATOR_SDRAM_ALIAS_BASE 0x80000000
+#define INTEGRATOR_HDR0_SDRAM_BASE 0x80000000
+#define INTEGRATOR_HDR1_SDRAM_BASE 0x90000000
+#define INTEGRATOR_HDR2_SDRAM_BASE 0xA0000000
+#define INTEGRATOR_HDR3_SDRAM_BASE 0xB0000000
+
+/*
+ * Logic expansion modules
+ *
+ */
+#define INTEGRATOR_LOGIC_MODULES_BASE 0xC0000000
+#define INTEGRATOR_LOGIC_MODULE0_BASE 0xC0000000
+#define INTEGRATOR_LOGIC_MODULE1_BASE 0xD0000000
+#define INTEGRATOR_LOGIC_MODULE2_BASE 0xE0000000
+#define INTEGRATOR_LOGIC_MODULE3_BASE 0xF0000000
+
+/*
+ * Integrator header card registers
+ */
+#define INTEGRATOR_HDR_ID_OFFSET 0x00
+#define INTEGRATOR_HDR_PROC_OFFSET 0x04
+#define INTEGRATOR_HDR_OSC_OFFSET 0x08
+#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C
+#define INTEGRATOR_HDR_STAT_OFFSET 0x10
+#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
+#define INTEGRATOR_HDR_SDRAM_OFFSET 0x20
+#define INTEGRATOR_HDR_INIT_OFFSET 0x24 /* CM9x6 */
+#define INTEGRATOR_HDR_IC_OFFSET 0x40
+#define INTEGRATOR_HDR_SPDBASE_OFFSET 0x100
+#define INTEGRATOR_HDR_SPDTOP_OFFSET 0x200
+
+#define INTEGRATOR_HDR_BASE 0x10000000
+#define INTEGRATOR_HDR_ID (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_ID_OFFSET)
+#define INTEGRATOR_HDR_PROC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_PROC_OFFSET)
+#define INTEGRATOR_HDR_OSC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_OSC_OFFSET)
+#define INTEGRATOR_HDR_CTRL (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_CTRL_OFFSET)
+#define INTEGRATOR_HDR_STAT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_STAT_OFFSET)
+#define INTEGRATOR_HDR_LOCK (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_LOCK_OFFSET)
+#define INTEGRATOR_HDR_SDRAM (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SDRAM_OFFSET)
+#define INTEGRATOR_HDR_INIT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_INIT_OFFSET)
+#define INTEGRATOR_HDR_IC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_IC_OFFSET)
+#define INTEGRATOR_HDR_SPDBASE (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDBASE_OFFSET)
+#define INTEGRATOR_HDR_SPDTOP (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDTOP_OFFSET)
+
+#define INTEGRATOR_HDR_CTRL_LED 0x01
+#define INTEGRATOR_HDR_CTRL_MBRD_DETECH 0x02
+#define INTEGRATOR_HDR_CTRL_REMAP 0x04
+#define INTEGRATOR_HDR_CTRL_RESET 0x08
+#define INTEGRATOR_HDR_CTRL_HIGHVECTORS 0x10
+#define INTEGRATOR_HDR_CTRL_BIG_ENDIAN 0x20
+#define INTEGRATOR_HDR_CTRL_FASTBUS 0x40
+#define INTEGRATOR_HDR_CTRL_SYNC 0x80
+
+#define INTEGRATOR_HDR_OSC_CORE_10MHz 0x102
+#define INTEGRATOR_HDR_OSC_CORE_15MHz 0x107
+#define INTEGRATOR_HDR_OSC_CORE_20MHz 0x10C
+#define INTEGRATOR_HDR_OSC_CORE_25MHz 0x111
+#define INTEGRATOR_HDR_OSC_CORE_30MHz 0x116
+#define INTEGRATOR_HDR_OSC_CORE_35MHz 0x11B
+#define INTEGRATOR_HDR_OSC_CORE_40MHz 0x120
+#define INTEGRATOR_HDR_OSC_CORE_45MHz 0x125
+#define INTEGRATOR_HDR_OSC_CORE_50MHz 0x12A
+#define INTEGRATOR_HDR_OSC_CORE_55MHz 0x12F
+#define INTEGRATOR_HDR_OSC_CORE_60MHz 0x134
+#define INTEGRATOR_HDR_OSC_CORE_65MHz 0x139
+#define INTEGRATOR_HDR_OSC_CORE_70MHz 0x13E
+#define INTEGRATOR_HDR_OSC_CORE_75MHz 0x143
+#define INTEGRATOR_HDR_OSC_CORE_80MHz 0x148
+#define INTEGRATOR_HDR_OSC_CORE_85MHz 0x14D
+#define INTEGRATOR_HDR_OSC_CORE_90MHz 0x152
+#define INTEGRATOR_HDR_OSC_CORE_95MHz 0x157
+#define INTEGRATOR_HDR_OSC_CORE_100MHz 0x15C
+#define INTEGRATOR_HDR_OSC_CORE_105MHz 0x161
+#define INTEGRATOR_HDR_OSC_CORE_110MHz 0x166
+#define INTEGRATOR_HDR_OSC_CORE_115MHz 0x16B
+#define INTEGRATOR_HDR_OSC_CORE_120MHz 0x170
+#define INTEGRATOR_HDR_OSC_CORE_125MHz 0x175
+#define INTEGRATOR_HDR_OSC_CORE_130MHz 0x17A
+#define INTEGRATOR_HDR_OSC_CORE_135MHz 0x17F
+#define INTEGRATOR_HDR_OSC_CORE_140MHz 0x184
+#define INTEGRATOR_HDR_OSC_CORE_145MHz 0x189
+#define INTEGRATOR_HDR_OSC_CORE_150MHz 0x18E
+#define INTEGRATOR_HDR_OSC_CORE_155MHz 0x193
+#define INTEGRATOR_HDR_OSC_CORE_160MHz 0x198
+#define INTEGRATOR_HDR_OSC_CORE_MASK 0x7FF
+
+#define INTEGRATOR_HDR_OSC_MEM_10MHz 0x10C000
+#define INTEGRATOR_HDR_OSC_MEM_15MHz 0x116000
+#define INTEGRATOR_HDR_OSC_MEM_20MHz 0x120000
+#define INTEGRATOR_HDR_OSC_MEM_25MHz 0x12A000
+#define INTEGRATOR_HDR_OSC_MEM_30MHz 0x134000
+#define INTEGRATOR_HDR_OSC_MEM_33MHz 0x13A000
+#define INTEGRATOR_HDR_OSC_MEM_40MHz 0x148000
+#define INTEGRATOR_HDR_OSC_MEM_50MHz 0x15C000
+#define INTEGRATOR_HDR_OSC_MEM_60MHz 0x170000
+#define INTEGRATOR_HDR_OSC_MEM_66MHz 0x17C000
+#define INTEGRATOR_HDR_OSC_MEM_MASK 0x7FF000
+
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM7x0 0x0
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x0 0x0800000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x6 0x1000000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM10x00 0x1800000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_MASK 0x1800000
+
+#define INTEGRATOR_HDR_SDRAM_SPD_OK (1 << 5)
+
+/*
+ * Integrator system registers
+ */
+
+/*
+ * System Controller
+ */
+#define INTEGRATOR_SC_ID_OFFSET 0x00
+#define INTEGRATOR_SC_OSC_OFFSET 0x04
+#define INTEGRATOR_SC_CTRLS_OFFSET 0x08
+#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C
+#define INTEGRATOR_SC_DEC_OFFSET 0x10
+#define INTEGRATOR_SC_ARB_OFFSET 0x14
+#define INTEGRATOR_SC_LOCK_OFFSET 0x1C
+
+#define INTEGRATOR_SC_BASE 0x11000000
+#define INTEGRATOR_SC_ID (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ID_OFFSET)
+#define INTEGRATOR_SC_OSC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_OSC_OFFSET)
+#define INTEGRATOR_SC_CTRLS (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
+#define INTEGRATOR_SC_CTRLC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
+#define INTEGRATOR_SC_DEC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_DEC_OFFSET)
+#define INTEGRATOR_SC_ARB (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ARB_OFFSET)
+#define INTEGRATOR_SC_PCIENABLE (INTEGRATOR_SC_BASE + INTEGRATOR_SC_PCIENABLE_OFFSET)
+#define INTEGRATOR_SC_LOCK (INTEGRATOR_SC_BASE + INTEGRATOR_SC_LOCK_OFFSET)
+
+#define INTEGRATOR_SC_OSC_SYS_10MHz 0x20
+#define INTEGRATOR_SC_OSC_SYS_15MHz 0x34
+#define INTEGRATOR_SC_OSC_SYS_20MHz 0x48
+#define INTEGRATOR_SC_OSC_SYS_25MHz 0x5C
+#define INTEGRATOR_SC_OSC_SYS_33MHz 0x7C
+#define INTEGRATOR_SC_OSC_SYS_MASK 0xFF
+
+#define INTEGRATOR_SC_OSC_PCI_25MHz 0x100
+#define INTEGRATOR_SC_OSC_PCI_33MHz 0x0
+#define INTEGRATOR_SC_OSC_PCI_MASK 0x100
+
+#define INTEGRATOR_SC_CTRL_SOFTRST (1 << 0)
+#define INTEGRATOR_SC_CTRL_nFLVPPEN (1 << 1)
+#define INTEGRATOR_SC_CTRL_nFLWP (1 << 2)
+#define INTEGRATOR_SC_CTRL_URTS0 (1 << 4)
+#define INTEGRATOR_SC_CTRL_UDTR0 (1 << 5)
+#define INTEGRATOR_SC_CTRL_URTS1 (1 << 6)
+#define INTEGRATOR_SC_CTRL_UDTR1 (1 << 7)
+
+/*
+ * External Bus Interface
+ */
+#define INTEGRATOR_EBI_BASE 0x12000000
+
+#define INTEGRATOR_EBI_CSR0_OFFSET 0x00
+#define INTEGRATOR_EBI_CSR1_OFFSET 0x04
+#define INTEGRATOR_EBI_CSR2_OFFSET 0x08
+#define INTEGRATOR_EBI_CSR3_OFFSET 0x0C
+#define INTEGRATOR_EBI_LOCK_OFFSET 0x20
+
+#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET)
+#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
+#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET)
+#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET)
+#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
+
+#define INTEGRATOR_EBI_8_BIT 0x00
+#define INTEGRATOR_EBI_16_BIT 0x01
+#define INTEGRATOR_EBI_32_BIT 0x02
+#define INTEGRATOR_EBI_WRITE_ENABLE 0x04
+#define INTEGRATOR_EBI_SYNC 0x08
+#define INTEGRATOR_EBI_WS_2 0x00
+#define INTEGRATOR_EBI_WS_3 0x10
+#define INTEGRATOR_EBI_WS_4 0x20
+#define INTEGRATOR_EBI_WS_5 0x30
+#define INTEGRATOR_EBI_WS_6 0x40
+#define INTEGRATOR_EBI_WS_7 0x50
+#define INTEGRATOR_EBI_WS_8 0x60
+#define INTEGRATOR_EBI_WS_9 0x70
+#define INTEGRATOR_EBI_WS_10 0x80
+#define INTEGRATOR_EBI_WS_11 0x90
+#define INTEGRATOR_EBI_WS_12 0xA0
+#define INTEGRATOR_EBI_WS_13 0xB0
+#define INTEGRATOR_EBI_WS_14 0xC0
+#define INTEGRATOR_EBI_WS_15 0xD0
+#define INTEGRATOR_EBI_WS_16 0xE0
+#define INTEGRATOR_EBI_WS_17 0xF0
+
+
+#define INTEGRATOR_CT_BASE 0x13000000 /* Counter/Timers */
+#define INTEGRATOR_IC_BASE 0x14000000 /* Interrupt Controller */
+#define INTEGRATOR_RTC_BASE 0x15000000 /* Real Time Clock */
+#define INTEGRATOR_UART0_BASE 0x16000000 /* UART 0 */
+#define INTEGRATOR_UART1_BASE 0x17000000 /* UART 1 */
+#define INTEGRATOR_KBD_BASE 0x18000000 /* Keyboard */
+#define INTEGRATOR_MOUSE_BASE 0x19000000 /* Mouse */
+
+/*
+ * LED's & Switches
+ */
+#define INTEGRATOR_DBG_ALPHA_OFFSET 0x00
+#define INTEGRATOR_DBG_LEDS_OFFSET 0x04
+#define INTEGRATOR_DBG_SWITCH_OFFSET 0x08
+
+#define INTEGRATOR_DBG_BASE 0x1A000000
+#define INTEGRATOR_DBG_ALPHA (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_ALPHA_OFFSET)
+#define INTEGRATOR_DBG_LEDS (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_LEDS_OFFSET)
+#define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET)
+
+#define INTEGRATOR_AP_GPIO_BASE 0x1B000000 /* GPIO */
+
+#define INTEGRATOR_CP_MMC_BASE 0x1C000000 /* MMC */
+#define INTEGRATOR_CP_AACI_BASE 0x1D000000 /* AACI */
+#define INTEGRATOR_CP_ETH_BASE 0xC8000000 /* Ethernet */
+#define INTEGRATOR_CP_GPIO_BASE 0xC9000000 /* GPIO */
+#define INTEGRATOR_CP_SIC_BASE 0xCA000000 /* SIC */
+#define INTEGRATOR_CP_CTL_BASE 0xCB000000 /* CP system control */
+
+/* PS2 Keyboard interface */
+#define KMI0_BASE INTEGRATOR_KBD_BASE
+
+/* PS2 Mouse interface */
+#define KMI1_BASE INTEGRATOR_MOUSE_BASE
+
+/*
+ * Integrator Interrupt Controllers
+ *
+ *
+ * Offsets from interrupt controller base
+ *
+ * System Controller interrupt controller base is
+ *
+ * INTEGRATOR_IC_BASE + (header_number << 6)
+ *
+ * Core Module interrupt controller base is
+ *
+ * INTEGRATOR_HDR_IC
+ */
+#define IRQ_STATUS 0
+#define IRQ_RAW_STATUS 0x04
+#define IRQ_ENABLE 0x08
+#define IRQ_ENABLE_SET 0x08
+#define IRQ_ENABLE_CLEAR 0x0C
+
+#define INT_SOFT_SET 0x10
+#define INT_SOFT_CLEAR 0x14
+
+#define FIQ_STATUS 0x20
+#define FIQ_RAW_STATUS 0x24
+#define FIQ_ENABLE 0x28
+#define FIQ_ENABLE_SET 0x28
+#define FIQ_ENABLE_CLEAR 0x2C
+
+
+/*
+ * LED's
+ */
+#define GREEN_LED 0x01
+#define YELLOW_LED 0x02
+#define RED_LED 0x04
+#define GREEN_LED_2 0x08
+#define ALL_LEDS 0x0F
+
+#define LED_BANK INTEGRATOR_DBG_LEDS
+
+/*
+ * Timer definitions
+ *
+ * Only use timer 1 & 2
+ * (both run at 24MHz and will need the clock divider set to 16).
+ *
+ * Timer 0 runs at bus frequency
+ */
+#define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE
+#define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100)
+#define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200)
+
+#define INTEGRATOR_CSR_BASE 0x10000000
+#define INTEGRATOR_CSR_SIZE 0x10000000
+
+#endif /* INTEGRATOR_HARDWARE_H */
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/memblock.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/io.h>
+#include <linux/stat.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pgtable.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/time.h>
+
+#include "integrator-hardware.h"
+#include "integrator-cm.h"
+#include "integrator.h"
+
+static DEFINE_RAW_SPINLOCK(cm_lock);
+static void __iomem *cm_base;
+
+/**
+ * cm_get - get the value from the CM_CTRL register
+ */
+u32 cm_get(void)
+{
+ return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
+}
+
+/**
+ * cm_control - update the CM_CTRL register.
+ * @mask: bits to change
+ * @set: bits to set
+ */
+void cm_control(u32 mask, u32 set)
+{
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&cm_lock, flags);
+ val = readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask;
+ writel(val | set, cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
+ raw_spin_unlock_irqrestore(&cm_lock, flags);
+}
+
+void cm_clear_irqs(void)
+{
+ /* disable core module IRQs */
+ writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET +
+ IRQ_ENABLE_CLEAR);
+}
+
+static const struct of_device_id cm_match[] = {
+ { .compatible = "arm,core-module-integrator"},
+ { },
+};
+
+void cm_init(void)
+{
+ struct device_node *cm = of_find_matching_node(NULL, cm_match);
+
+ if (!cm) {
+ pr_crit("no core module node found in device tree\n");
+ return;
+ }
+ cm_base = of_iomap(cm, 0);
+ if (!cm_base) {
+ pr_crit("could not remap core module\n");
+ return;
+ }
+ cm_clear_irqs();
+}
+
+/*
+ * We need to stop things allocating the low memory; ideally we need a
+ * better implementation of GFP_DMA which does not assume that DMA-able
+ * memory starts at zero.
+ */
+void __init integrator_reserve(void)
+{
+ memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/reboot.h>
+#include <linux/amba/serial.h>
+extern struct amba_pl010_data ap_uart_data;
+void integrator_init_early(void);
+int integrator_init(bool is_cp);
+void integrator_reserve(void);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/syscore_ops.h>
+#include <linux/amba/bus.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/termios.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "integrator-hardware.h"
+#include "integrator-cm.h"
+#include "integrator.h"
+
+/* Regmap to the AP system controller */
+static struct regmap *ap_syscon_map;
+
+/*
+ * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
+ * is the (PA >> 12).
+ *
+ * Setup a VA for the Integrator interrupt controller (for header #0,
+ * just for now).
+ */
+#define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE)
+
+/*
+ * Logical Physical
+ * f1400000 14000000 Interrupt controller
+ * f1600000 16000000 UART 0
+ */
+
+static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
+ {
+ .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init ap_map_io(void)
+{
+ iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
+}
+
+#ifdef CONFIG_PM
+static unsigned long ic_irq_enable;
+
+static int irq_suspend(void)
+{
+ ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
+ return 0;
+}
+
+static void irq_resume(void)
+{
+ /* disable all irq sources */
+ cm_clear_irqs();
+ writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+ writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
+
+ writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
+}
+#else
+#define irq_suspend NULL
+#define irq_resume NULL
+#endif
+
+static struct syscore_ops irq_syscore_ops = {
+ .suspend = irq_suspend,
+ .resume = irq_resume,
+};
+
+static int __init irq_syscore_init(void)
+{
+ register_syscore_ops(&irq_syscore_ops);
+
+ return 0;
+}
+
+device_initcall(irq_syscore_init);
+
+/*
+ * For the PL010 found in the Integrator/AP some of the UART control is
+ * implemented in the system controller and accessed using a callback
+ * from the driver.
+ */
+static void integrator_uart_set_mctrl(struct amba_device *dev,
+ void __iomem *base, unsigned int mctrl)
+{
+ unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+ u32 phybase = dev->res.start;
+ int ret;
+
+ if (phybase == INTEGRATOR_UART0_BASE) {
+ /* UART0 */
+ rts_mask = 1 << 4;
+ dtr_mask = 1 << 5;
+ } else {
+ /* UART1 */
+ rts_mask = 1 << 6;
+ dtr_mask = 1 << 7;
+ }
+
+ if (mctrl & TIOCM_RTS)
+ ctrlc |= rts_mask;
+ else
+ ctrls |= rts_mask;
+
+ if (mctrl & TIOCM_DTR)
+ ctrlc |= dtr_mask;
+ else
+ ctrls |= dtr_mask;
+
+ ret = regmap_write(ap_syscon_map,
+ INTEGRATOR_SC_CTRLS_OFFSET,
+ ctrls);
+ if (ret)
+ pr_err("MODEM: unable to write PL010 UART CTRLS\n");
+
+ ret = regmap_write(ap_syscon_map,
+ INTEGRATOR_SC_CTRLC_OFFSET,
+ ctrlc);
+ if (ret)
+ pr_err("MODEM: unable to write PL010 UART CRTLC\n");
+}
+
+struct amba_pl010_data ap_uart_data = {
+ .set_mctrl = integrator_uart_set_mctrl,
+};
+
+void __init ap_init_early(void)
+{
+}
+
+static void __init ap_init_irq_of(void)
+{
+ cm_init();
+ irqchip_init();
+}
+
+/* For the Device Tree, add in the UART callbacks as AUXDATA */
+static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
+ "uart0", &ap_uart_data),
+ OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
+ "uart1", &ap_uart_data),
+ { /* sentinel */ },
+};
+
+static const struct of_device_id ap_syscon_match[] = {
+ { .compatible = "arm,integrator-ap-syscon"},
+ { },
+};
+
+static void __init ap_init_of(void)
+{
+ struct device_node *syscon;
+
+ of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
+
+ syscon = of_find_matching_node(NULL, ap_syscon_match);
+ if (!syscon)
+ return;
+ ap_syscon_map = syscon_node_to_regmap(syscon);
+ if (IS_ERR(ap_syscon_map)) {
+ pr_crit("could not find Integrator/AP system controller\n");
+ return;
+ }
+}
+
+static const char * ap_dt_board_compat[] = {
+ "arm,integrator-ap",
+ NULL,
+};
+
+DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
+ .reserve = integrator_reserve,
+ .map_io = ap_map_io,
+ .init_early = ap_init_early,
+ .init_irq = ap_init_irq_of,
+ .init_machine = ap_init_of,
+ .dt_compat = ap_dt_board_compat,
+MACHINE_END
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2003 Deep Blue Solutions Ltd
+ */
+#include <linux/kernel.h>
+#include <linux/amba/mmci.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sched_clock.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "integrator-hardware.h"
+#include "integrator-cm.h"
+#include "integrator.h"
+
+/* Base address to the core module header */
+static struct regmap *cm_map;
+/* Base address to the CP controller */
+static void __iomem *intcp_con_base;
+
+#define CM_COUNTER_OFFSET 0x28
+
+/*
+ * Logical Physical
+ * f1400000 14000000 Interrupt controller
+ * f1600000 16000000 UART 0
+ * fca00000 ca000000 SIC
+ */
+
+static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
+ {
+ .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init intcp_map_io(void)
+{
+ iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
+}
+
+/*
+ * It seems that the card insertion interrupt remains active after
+ * we've acknowledged it. We therefore ignore the interrupt, and
+ * rely on reading it from the SIC. This also means that we must
+ * clear the latched interrupt.
+ */
+static unsigned int mmc_status(struct device *dev)
+{
+ unsigned int status = readl(__io_address(0xca000000 + 4));
+ writel(8, intcp_con_base + 8);
+
+ return status & 8;
+}
+
+static struct mmci_platform_data mmc_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+};
+
+static u64 notrace intcp_read_sched_clock(void)
+{
+ unsigned int val;
+
+ /* MMIO so discard return code */
+ regmap_read(cm_map, CM_COUNTER_OFFSET, &val);
+ return val;
+}
+
+static void __init intcp_init_early(void)
+{
+ cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
+ if (IS_ERR(cm_map))
+ return;
+ sched_clock_register(intcp_read_sched_clock, 32, 24000000);
+}
+
+static void __init intcp_init_irq_of(void)
+{
+ cm_init();
+ irqchip_init();
+}
+
+/*
+ * For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
+ * and enforce the bus names since these are used for clock lookups.
+ */
+static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
+ "mmci", &mmc_data),
+ { /* sentinel */ },
+};
+
+static const struct of_device_id intcp_syscon_match[] = {
+ { .compatible = "arm,integrator-cp-syscon"},
+ { },
+};
+
+static void __init intcp_init_of(void)
+{
+ struct device_node *cpcon;
+
+ cpcon = of_find_matching_node(NULL, intcp_syscon_match);
+ if (!cpcon)
+ return;
+
+ intcp_con_base = of_iomap(cpcon, 0);
+ if (!intcp_con_base)
+ return;
+
+ of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
+}
+
+static const char * intcp_dt_board_compat[] = {
+ "arm,integrator-cp",
+ NULL,
+};
+
+DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
+ .reserve = integrator_reserve,
+ .map_io = intcp_map_io,
+ .init_early = intcp_init_early,
+ .init_irq = intcp_init_irq_of,
+ .init_machine = intcp_init_of,
+ .dt_compat = intcp_dt_board_compat,
+MACHINE_END
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Linus Walleij
+ */
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+#include "platsmp.h"
+
+#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
+
+static const struct of_device_id realview_scu_match[] = {
+ { .compatible = "arm,arm11mp-scu", },
+ { .compatible = "arm,cortex-a9-scu", },
+ { .compatible = "arm,cortex-a5-scu", },
+ { }
+};
+
+static const struct of_device_id realview_syscon_match[] = {
+ { .compatible = "arm,core-module-integrator", },
+ { .compatible = "arm,realview-eb-syscon", },
+ { .compatible = "arm,realview-pb11mp-syscon", },
+ { .compatible = "arm,realview-pbx-syscon", },
+ { },
+};
+
+static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np;
+ void __iomem *scu_base;
+ struct regmap *map;
+ unsigned int ncores;
+ int i;
+
+ np = of_find_matching_node(NULL, realview_scu_match);
+ if (!np) {
+ pr_err("PLATSMP: No SCU base address\n");
+ return;
+ }
+ scu_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!scu_base) {
+ pr_err("PLATSMP: No SCU remap\n");
+ return;
+ }
+
+ scu_enable(scu_base);
+ ncores = scu_get_core_count(scu_base);
+ pr_info("SCU: %d cores detected\n", ncores);
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+ iounmap(scu_base);
+
+ /* The syscon contains the magic SMP start address registers */
+ np = of_find_matching_node(NULL, realview_syscon_match);
+ if (!np) {
+ pr_err("PLATSMP: No syscon match\n");
+ return;
+ }
+ map = syscon_node_to_regmap(np);
+ if (IS_ERR(map)) {
+ pr_err("PLATSMP: No syscon regmap\n");
+ return;
+ }
+ /* Put the boot address in this magic register */
+ regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET,
+ __pa_symbol(versatile_secondary_startup));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void realview_cpu_die(unsigned int cpu)
+{
+ return versatile_immitation_cpu_die(cpu, 0x20);
+}
+#endif
+
+static const struct smp_operations realview_dt_smp_ops __initconst = {
+ .smp_prepare_cpus = realview_smp_prepare_cpus,
+ .smp_secondary_init = versatile_secondary_init,
+ .smp_boot_secondary = versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = realview_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+
+#include <asm/mcpm.h>
+#include <asm/smp_scu.h>
+#include <asm/mach/map.h>
+
+#include "platsmp.h"
+#include "vexpress.h"
+
+bool __init vexpress_smp_init_ops(void)
+{
+#ifdef CONFIG_MCPM
+ int cpu;
+ struct device_node *cpu_node, *cci_node;
+
+ /*
+ * The best way to detect a multi-cluster configuration
+ * is to detect if the kernel can take over CCI ports
+ * control. Loop over possible CPUs and check if CCI
+ * port control is available.
+ * Override the default vexpress_smp_ops if so.
+ */
+ for_each_possible_cpu(cpu) {
+ bool available;
+
+ cpu_node = of_get_cpu_node(cpu, NULL);
+ if (WARN(!cpu_node, "Missing cpu device node!"))
+ return false;
+
+ cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
+ available = cci_node && of_device_is_available(cci_node);
+ of_node_put(cci_node);
+ of_node_put(cpu_node);
+
+ if (!available)
+ return false;
+ }
+
+ mcpm_smp_set_ops();
+ return true;
+#else
+ return false;
+#endif
+}
+
+static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
+ { .compatible = "arm,cortex-a5-scu", },
+ { .compatible = "arm,cortex-a9-scu", },
+ {}
+};
+
+static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *scu = of_find_matching_node(NULL,
+ vexpress_smp_dt_scu_match);
+
+ if (scu)
+ scu_enable(of_iomap(scu, 0));
+
+ /*
+ * Write the address of secondary startup into the
+ * system-wide flags register. The boot monitor waits
+ * until it receives a soft interrupt, and then the
+ * secondary CPU branches to this address.
+ */
+ vexpress_flags_set(__pa_symbol(versatile_secondary_startup));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void vexpress_cpu_die(unsigned int cpu)
+{
+ versatile_immitation_cpu_die(cpu, 0x40);
+}
+#endif
+
+const struct smp_operations vexpress_smp_dt_ops __initconst = {
+ .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus,
+ .smp_secondary_init = versatile_secondary_init,
+ .smp_boot_secondary = versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = vexpress_cpu_die,
+#endif
+};
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This code is specific to the hardware found on ARM Realview and
+ * Versatile Express platforms where the CPUs are unable to be individually
+ * woken, and where there is no way to hot-unplug CPUs. Real platforms
+ * should not copy this code.
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+
+#include "platsmp.h"
+
+/*
+ * versatile_cpu_release controls the release of CPUs from the holding
+ * pen in headsmp.S, which exists because we are not always able to
+ * control the release of individual CPUs from the board firmware.
+ * Production platforms do not need this.
+ */
+volatile int versatile_cpu_release = -1;
+
+/*
+ * Write versatile_cpu_release in a way that is guaranteed to be visible to
+ * all observers, irrespective of whether they're taking part in coherency
+ * or not. This is necessary for the hotplug code to work reliably.
+ */
+static void versatile_write_cpu_release(int val)
+{
+ versatile_cpu_release = val;
+ smp_wmb();
+ sync_cache_w(&versatile_cpu_release);
+}
+
+/*
+ * versatile_lock exists to avoid running the loops_per_jiffy delay loop
+ * calibrations on the secondary CPU while the requesting CPU is using
+ * the limited-bandwidth bus - which affects the calibration value.
+ * Production platforms do not need this.
+ */
+static DEFINE_RAW_SPINLOCK(versatile_lock);
+
+void versatile_secondary_init(unsigned int cpu)
+{
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ versatile_write_cpu_release(-1);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ raw_spin_lock(&versatile_lock);
+ raw_spin_unlock(&versatile_lock);
+}
+
+int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+
+ /*
+ * Set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ raw_spin_lock(&versatile_lock);
+
+ /*
+ * This is really belt and braces; we hold unintended secondary
+ * CPUs in the holding pen until we're ready for them. However,
+ * since we haven't sent them a soft interrupt, they shouldn't
+ * be there.
+ */
+ versatile_write_cpu_release(cpu_logical_map(cpu));
+
+ /*
+ * Send the secondary CPU a soft interrupt, thereby causing
+ * the boot monitor to read the system wide flags register,
+ * and branch to the address found there.
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ smp_rmb();
+ if (versatile_cpu_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ raw_spin_unlock(&versatile_lock);
+
+ return versatile_cpu_release != -1 ? -ENOSYS : 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2011 ARM Ltd.
+ * All Rights Reserved
+ */
+extern volatile int versatile_cpu_release;
+
+extern void versatile_secondary_startup(void);
+extern void versatile_secondary_init(unsigned int cpu);
+extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle);
+void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
+
+static const char *const realview_dt_platform_compat[] __initconst = {
+ "arm,realview-eb",
+ "arm,realview-pb1176",
+ "arm,realview-pb11mp",
+ "arm,realview-pba8",
+ "arm,realview-pbx",
+ NULL,
+};
+
+DT_MACHINE_START(REALVIEW_DT, "ARM RealView Machine (Device Tree Support)")
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_256M,
+#endif
+ .dt_compat = realview_dt_platform_compat,
+ .l2c_aux_val = 0x0,
+ .l2c_aux_mask = ~0x0,
+MACHINE_END
--- /dev/null
+/*
+ * Versatile Express Serial Power Controller (SPC) support
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * Authors: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+ * Achin Gupta <achin.gupta@arm.com>
+ * Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+#include <linux/semaphore.h>
+
+#include <asm/cacheflush.h>
+
+#include "spc.h"
+
+#define SPCLOG "vexpress-spc: "
+
+#define PERF_LVL_A15 0x00
+#define PERF_REQ_A15 0x04
+#define PERF_LVL_A7 0x08
+#define PERF_REQ_A7 0x0c
+#define COMMS 0x10
+#define COMMS_REQ 0x14
+#define PWC_STATUS 0x18
+#define PWC_FLAG 0x1c
+
+/* SPC wake-up IRQs status and mask */
+#define WAKE_INT_MASK 0x24
+#define WAKE_INT_RAW 0x28
+#define WAKE_INT_STAT 0x2c
+/* SPC power down registers */
+#define A15_PWRDN_EN 0x30
+#define A7_PWRDN_EN 0x34
+/* SPC per-CPU mailboxes */
+#define A15_BX_ADDR0 0x68
+#define A7_BX_ADDR0 0x78
+
+/* SPC CPU/cluster reset statue */
+#define STANDBYWFI_STAT 0x3c
+#define STANDBYWFI_STAT_A15_CPU_MASK(cpu) (1 << (cpu))
+#define STANDBYWFI_STAT_A7_CPU_MASK(cpu) (1 << (3 + (cpu)))
+
+/* SPC system config interface registers */
+#define SYSCFG_WDATA 0x70
+#define SYSCFG_RDATA 0x74
+
+/* A15/A7 OPP virtual register base */
+#define A15_PERFVAL_BASE 0xC10
+#define A7_PERFVAL_BASE 0xC30
+
+/* Config interface control bits */
+#define SYSCFG_START BIT(31)
+#define SYSCFG_SCC (6 << 20)
+#define SYSCFG_STAT (14 << 20)
+
+/* wake-up interrupt masks */
+#define GBL_WAKEUP_INT_MSK (0x3 << 10)
+
+/* TC2 static dual-cluster configuration */
+#define MAX_CLUSTERS 2
+
+/*
+ * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
+ * operation, the operation could start just before jiffie is about
+ * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
+ */
+#define TIMEOUT_US 20000
+
+#define MAX_OPPS 8
+#define CA15_DVFS 0
+#define CA7_DVFS 1
+#define SPC_SYS_CFG 2
+#define STAT_COMPLETE(type) ((1 << 0) << (type << 2))
+#define STAT_ERR(type) ((1 << 1) << (type << 2))
+#define RESPONSE_MASK(type) (STAT_COMPLETE(type) | STAT_ERR(type))
+
+struct ve_spc_opp {
+ unsigned long freq;
+ unsigned long u_volt;
+};
+
+struct ve_spc_drvdata {
+ void __iomem *baseaddr;
+ /*
+ * A15s cluster identifier
+ * It corresponds to A15 processors MPIDR[15:8] bitfield
+ */
+ u32 a15_clusid;
+ uint32_t cur_rsp_mask;
+ uint32_t cur_rsp_stat;
+ struct semaphore sem;
+ struct completion done;
+ struct ve_spc_opp *opps[MAX_CLUSTERS];
+ int num_opps[MAX_CLUSTERS];
+};
+
+static struct ve_spc_drvdata *info;
+
+static inline bool cluster_is_a15(u32 cluster)
+{
+ return cluster == info->a15_clusid;
+}
+
+/**
+ * ve_spc_global_wakeup_irq()
+ *
+ * Function to set/clear global wakeup IRQs. Not protected by locking since
+ * it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @set: if true, global wake-up IRQs are set, if false they are cleared
+ */
+void ve_spc_global_wakeup_irq(bool set)
+{
+ u32 reg;
+
+ reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
+
+ if (set)
+ reg |= GBL_WAKEUP_INT_MSK;
+ else
+ reg &= ~GBL_WAKEUP_INT_MSK;
+
+ writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
+}
+
+/**
+ * ve_spc_cpu_wakeup_irq()
+ *
+ * Function to set/clear per-CPU wake-up IRQs. Not protected by locking since
+ * it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @cpu: mpidr[7:0] bitfield describing cpu affinity level
+ * @set: if true, wake-up IRQs are set, if false they are cleared
+ */
+void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set)
+{
+ u32 mask, reg;
+
+ if (cluster >= MAX_CLUSTERS)
+ return;
+
+ mask = BIT(cpu);
+
+ if (!cluster_is_a15(cluster))
+ mask <<= 4;
+
+ reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
+
+ if (set)
+ reg |= mask;
+ else
+ reg &= ~mask;
+
+ writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
+}
+
+/**
+ * ve_spc_set_resume_addr() - set the jump address used for warm boot
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @cpu: mpidr[7:0] bitfield describing cpu affinity level
+ * @addr: physical resume address
+ */
+void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr)
+{
+ void __iomem *baseaddr;
+
+ if (cluster >= MAX_CLUSTERS)
+ return;
+
+ if (cluster_is_a15(cluster))
+ baseaddr = info->baseaddr + A15_BX_ADDR0 + (cpu << 2);
+ else
+ baseaddr = info->baseaddr + A7_BX_ADDR0 + (cpu << 2);
+
+ writel_relaxed(addr, baseaddr);
+}
+
+/**
+ * ve_spc_powerdown()
+ *
+ * Function to enable/disable cluster powerdown. Not protected by locking
+ * since it might be used in code paths where normal cacheable locks are not
+ * working. Locking must be provided by the caller to ensure atomicity.
+ *
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ * @enable: if true enables powerdown, if false disables it
+ */
+void ve_spc_powerdown(u32 cluster, bool enable)
+{
+ u32 pwdrn_reg;
+
+ if (cluster >= MAX_CLUSTERS)
+ return;
+
+ pwdrn_reg = cluster_is_a15(cluster) ? A15_PWRDN_EN : A7_PWRDN_EN;
+ writel_relaxed(enable, info->baseaddr + pwdrn_reg);
+}
+
+static u32 standbywfi_cpu_mask(u32 cpu, u32 cluster)
+{
+ return cluster_is_a15(cluster) ?
+ STANDBYWFI_STAT_A15_CPU_MASK(cpu)
+ : STANDBYWFI_STAT_A7_CPU_MASK(cpu);
+}
+
+/**
+ * ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
+ *
+ * @cpu: mpidr[7:0] bitfield describing CPU affinity level within cluster
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ *
+ * @return: non-zero if and only if the specified CPU is in WFI
+ *
+ * Take care when interpreting the result of this function: a CPU might
+ * be in WFI temporarily due to idle, and is not necessarily safely
+ * parked.
+ */
+int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
+{
+ int ret;
+ u32 mask = standbywfi_cpu_mask(cpu, cluster);
+
+ if (cluster >= MAX_CLUSTERS)
+ return 1;
+
+ ret = readl_relaxed(info->baseaddr + STANDBYWFI_STAT);
+
+ pr_debug("%s: PCFGREG[0x%X] = 0x%08X, mask = 0x%X\n",
+ __func__, STANDBYWFI_STAT, ret, mask);
+
+ return ret & mask;
+}
+
+static int ve_spc_get_performance(int cluster, u32 *freq)
+{
+ struct ve_spc_opp *opps = info->opps[cluster];
+ u32 perf_cfg_reg = 0;
+ u32 perf;
+
+ perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7;
+
+ perf = readl_relaxed(info->baseaddr + perf_cfg_reg);
+ if (perf >= info->num_opps[cluster])
+ return -EINVAL;
+
+ opps += perf;
+ *freq = opps->freq;
+
+ return 0;
+}
+
+/* find closest match to given frequency in OPP table */
+static int ve_spc_round_performance(int cluster, u32 freq)
+{
+ int idx, max_opp = info->num_opps[cluster];
+ struct ve_spc_opp *opps = info->opps[cluster];
+ u32 fmin = 0, fmax = ~0, ftmp;
+
+ freq /= 1000; /* OPP entries in kHz */
+ for (idx = 0; idx < max_opp; idx++, opps++) {
+ ftmp = opps->freq;
+ if (ftmp >= freq) {
+ if (ftmp <= fmax)
+ fmax = ftmp;
+ } else {
+ if (ftmp >= fmin)
+ fmin = ftmp;
+ }
+ }
+ if (fmax != ~0)
+ return fmax * 1000;
+ else
+ return fmin * 1000;
+}
+
+static int ve_spc_find_performance_index(int cluster, u32 freq)
+{
+ int idx, max_opp = info->num_opps[cluster];
+ struct ve_spc_opp *opps = info->opps[cluster];
+
+ for (idx = 0; idx < max_opp; idx++, opps++)
+ if (opps->freq == freq)
+ break;
+ return (idx == max_opp) ? -EINVAL : idx;
+}
+
+static int ve_spc_waitforcompletion(int req_type)
+{
+ int ret = wait_for_completion_interruptible_timeout(
+ &info->done, usecs_to_jiffies(TIMEOUT_US));
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ else if (ret > 0)
+ ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO;
+ return ret;
+}
+
+static int ve_spc_set_performance(int cluster, u32 freq)
+{
+ u32 perf_cfg_reg;
+ int ret, perf, req_type;
+
+ if (cluster_is_a15(cluster)) {
+ req_type = CA15_DVFS;
+ perf_cfg_reg = PERF_LVL_A15;
+ } else {
+ req_type = CA7_DVFS;
+ perf_cfg_reg = PERF_LVL_A7;
+ }
+
+ perf = ve_spc_find_performance_index(cluster, freq);
+
+ if (perf < 0)
+ return perf;
+
+ if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
+ return -ETIME;
+
+ init_completion(&info->done);
+ info->cur_rsp_mask = RESPONSE_MASK(req_type);
+
+ writel(perf, info->baseaddr + perf_cfg_reg);
+ ret = ve_spc_waitforcompletion(req_type);
+
+ info->cur_rsp_mask = 0;
+ up(&info->sem);
+
+ return ret;
+}
+
+static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data)
+{
+ int ret;
+
+ if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
+ return -ETIME;
+
+ init_completion(&info->done);
+ info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG);
+
+ /* Set the control value */
+ writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS);
+ ret = ve_spc_waitforcompletion(SPC_SYS_CFG);
+
+ if (ret == 0)
+ *data = readl(info->baseaddr + SYSCFG_RDATA);
+
+ info->cur_rsp_mask = 0;
+ up(&info->sem);
+
+ return ret;
+}
+
+static irqreturn_t ve_spc_irq_handler(int irq, void *data)
+{
+ struct ve_spc_drvdata *drv_data = data;
+ uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS);
+
+ if (info->cur_rsp_mask & status) {
+ info->cur_rsp_stat = status;
+ complete(&drv_data->done);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * +--------------------------+
+ * | 31 20 | 19 0 |
+ * +--------------------------+
+ * | m_volt | freq(kHz) |
+ * +--------------------------+
+ */
+#define MULT_FACTOR 20
+#define VOLT_SHIFT 20
+#define FREQ_MASK (0xFFFFF)
+static int ve_spc_populate_opps(uint32_t cluster)
+{
+ uint32_t data = 0, off, ret, idx;
+ struct ve_spc_opp *opps;
+
+ opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL);
+ if (!opps)
+ return -ENOMEM;
+
+ info->opps[cluster] = opps;
+
+ off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE;
+ for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) {
+ ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
+ if (!ret) {
+ opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
+ opps->u_volt = (data >> VOLT_SHIFT) * 1000;
+ } else {
+ break;
+ }
+ }
+ info->num_opps[cluster] = idx;
+
+ return ret;
+}
+
+static int ve_init_opp_table(struct device *cpu_dev)
+{
+ int cluster;
+ int idx, ret = 0, max_opp;
+ struct ve_spc_opp *opps;
+
+ cluster = topology_physical_package_id(cpu_dev->id);
+ cluster = cluster < 0 ? 0 : cluster;
+
+ max_opp = info->num_opps[cluster];
+ opps = info->opps[cluster];
+
+ for (idx = 0; idx < max_opp; idx++, opps++) {
+ ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to add opp %lu %lu\n",
+ opps->freq, opps->u_volt);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
+{
+ int ret;
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->baseaddr = baseaddr;
+ info->a15_clusid = a15_clusid;
+
+ if (irq <= 0) {
+ pr_err(SPCLOG "Invalid IRQ %d\n", irq);
+ kfree(info);
+ return -EINVAL;
+ }
+
+ init_completion(&info->done);
+
+ readl_relaxed(info->baseaddr + PWC_STATUS);
+
+ ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH
+ | IRQF_ONESHOT, "vexpress-spc", info);
+ if (ret) {
+ pr_err(SPCLOG "IRQ %d request failed\n", irq);
+ kfree(info);
+ return -ENODEV;
+ }
+
+ sema_init(&info->sem, 1);
+ /*
+ * Multi-cluster systems may need this data when non-coherent, during
+ * cluster power-up/power-down. Make sure driver info reaches main
+ * memory.
+ */
+ sync_cache_w(info);
+ sync_cache_w(&info);
+
+ return 0;
+}
+
+struct clk_spc {
+ struct clk_hw hw;
+ int cluster;
+};
+
+#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw)
+static unsigned long spc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_spc *spc = to_clk_spc(hw);
+ u32 freq;
+
+ if (ve_spc_get_performance(spc->cluster, &freq))
+ return -EIO;
+
+ return freq * 1000;
+}
+
+static long spc_round_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long *parent_rate)
+{
+ struct clk_spc *spc = to_clk_spc(hw);
+
+ return ve_spc_round_performance(spc->cluster, drate);
+}
+
+static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_spc *spc = to_clk_spc(hw);
+
+ return ve_spc_set_performance(spc->cluster, rate / 1000);
+}
+
+static struct clk_ops clk_spc_ops = {
+ .recalc_rate = spc_recalc_rate,
+ .round_rate = spc_round_rate,
+ .set_rate = spc_set_rate,
+};
+
+static struct clk *ve_spc_clk_register(struct device *cpu_dev)
+{
+ struct clk_init_data init;
+ struct clk_spc *spc;
+
+ spc = kzalloc(sizeof(*spc), GFP_KERNEL);
+ if (!spc)
+ return ERR_PTR(-ENOMEM);
+
+ spc->hw.init = &init;
+ spc->cluster = topology_physical_package_id(cpu_dev->id);
+
+ spc->cluster = spc->cluster < 0 ? 0 : spc->cluster;
+
+ init.name = dev_name(cpu_dev);
+ init.ops = &clk_spc_ops;
+ init.flags = CLK_GET_RATE_NOCACHE;
+ init.num_parents = 0;
+
+ return devm_clk_register(cpu_dev, &spc->hw);
+}
+
+static int __init ve_spc_clk_init(void)
+{
+ int cpu, cluster;
+ struct clk *clk;
+ bool init_opp_table[MAX_CLUSTERS] = { false };
+
+ if (!info)
+ return 0; /* Continue only if SPC is initialised */
+
+ if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) {
+ pr_err("failed to build OPP table\n");
+ return -ENODEV;
+ }
+
+ for_each_possible_cpu(cpu) {
+ struct device *cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev) {
+ pr_warn("failed to get cpu%d device\n", cpu);
+ continue;
+ }
+ clk = ve_spc_clk_register(cpu_dev);
+ if (IS_ERR(clk)) {
+ pr_warn("failed to register cpu%d clock\n", cpu);
+ continue;
+ }
+ if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
+ pr_warn("failed to register cpu%d clock lookup\n", cpu);
+ continue;
+ }
+
+ cluster = topology_physical_package_id(cpu_dev->id);
+ if (init_opp_table[cluster])
+ continue;
+
+ if (ve_init_opp_table(cpu_dev))
+ pr_warn("failed to initialise cpu%d opp table\n", cpu);
+ else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
+ topology_core_cpumask(cpu_dev->id)))
+ pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
+ else
+ init_opp_table[cluster] = true;
+ }
+
+ platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
+ return 0;
+}
+device_initcall(ve_spc_clk_init);
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+
+#ifndef __SPC_H_
+#define __SPC_H_
+
+int __init ve_spc_init(void __iomem *base, u32 a15_clusid, int irq);
+void ve_spc_global_wakeup_irq(bool set);
+void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
+void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
+void ve_spc_powerdown(u32 cluster, bool enable);
+int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster);
+
+#endif
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Created by: Nicolas Pitre, October 2012
+ * Copyright: (C) 2012-2013 Linaro Limited
+ *
+ * Some portions of this file were originally written by Achin Gupta
+ * Copyright: (C) 2012 ARM Limited
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/errno.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/mcpm.h>
+#include <asm/proc-fns.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/cp15.h>
+
+#include <linux/arm-cci.h>
+
+#include "spc.h"
+
+/* SCC conf registers */
+#define RESET_CTRL 0x018
+#define RESET_A15_NCORERESET(cpu) (1 << (2 + (cpu)))
+#define RESET_A7_NCORERESET(cpu) (1 << (16 + (cpu)))
+
+#define A15_CONF 0x400
+#define A7_CONF 0x500
+#define SYS_INFO 0x700
+#define SPC_BASE 0xb00
+
+static void __iomem *scc;
+
+#define TC2_CLUSTERS 2
+#define TC2_MAX_CPUS_PER_CLUSTER 3
+
+static unsigned int tc2_nr_cpus[TC2_CLUSTERS];
+
+static int tc2_pm_cpu_powerup(unsigned int cpu, unsigned int cluster)
+{
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster])
+ return -EINVAL;
+ ve_spc_set_resume_addr(cluster, cpu,
+ __pa_symbol(mcpm_entry_point));
+ ve_spc_cpu_wakeup_irq(cluster, cpu, true);
+ return 0;
+}
+
+static int tc2_pm_cluster_powerup(unsigned int cluster)
+{
+ pr_debug("%s: cluster %u\n", __func__, cluster);
+ if (cluster >= TC2_CLUSTERS)
+ return -EINVAL;
+ ve_spc_powerdown(cluster, false);
+ return 0;
+}
+
+static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
+{
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+ ve_spc_cpu_wakeup_irq(cluster, cpu, true);
+ /*
+ * If the CPU is committed to power down, make sure
+ * the power controller will be in charge of waking it
+ * up upon IRQ, ie IRQ lines are cut from GIC CPU IF
+ * to the CPU by disabling the GIC CPU IF to prevent wfi
+ * from completing execution behind power controller back
+ */
+ gic_cpu_if_down(0);
+}
+
+static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster)
+{
+ pr_debug("%s: cluster %u\n", __func__, cluster);
+ BUG_ON(cluster >= TC2_CLUSTERS);
+ ve_spc_powerdown(cluster, true);
+ ve_spc_global_wakeup_irq(true);
+}
+
+static void tc2_pm_cpu_cache_disable(void)
+{
+ v7_exit_coherency_flush(louis);
+}
+
+static void tc2_pm_cluster_cache_disable(void)
+{
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+ /*
+ * On the Cortex-A15 we need to disable
+ * L2 prefetching before flushing the cache.
+ */
+ asm volatile(
+ "mcr p15, 1, %0, c15, c0, 3 \n\t"
+ "isb \n\t"
+ "dsb "
+ : : "r" (0x400) );
+ }
+
+ v7_exit_coherency_flush(all);
+ cci_disable_port_by_cpu(read_cpuid_mpidr());
+}
+
+static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster)
+{
+ u32 mask = cluster ?
+ RESET_A7_NCORERESET(cpu)
+ : RESET_A15_NCORERESET(cpu);
+
+ return !(readl_relaxed(scc + RESET_CTRL) & mask);
+}
+
+#define POLL_MSEC 10
+#define TIMEOUT_MSEC 1000
+
+static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
+{
+ unsigned tries;
+
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+
+ for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; ++tries) {
+ pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
+ __func__, cpu, cluster,
+ readl_relaxed(scc + RESET_CTRL));
+
+ /*
+ * We need the CPU to reach WFI, but the power
+ * controller may put the cluster in reset and
+ * power it off as soon as that happens, before
+ * we have a chance to see STANDBYWFI.
+ *
+ * So we need to check for both conditions:
+ */
+ if (tc2_core_in_reset(cpu, cluster) ||
+ ve_spc_cpu_in_wfi(cpu, cluster))
+ return 0; /* success: the CPU is halted */
+
+ /* Otherwise, wait and retry: */
+ msleep(POLL_MSEC);
+ }
+
+ return -ETIMEDOUT; /* timeout */
+}
+
+static void tc2_pm_cpu_suspend_prepare(unsigned int cpu, unsigned int cluster)
+{
+ ve_spc_set_resume_addr(cluster, cpu, __pa_symbol(mcpm_entry_point));
+}
+
+static void tc2_pm_cpu_is_up(unsigned int cpu, unsigned int cluster)
+{
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+ ve_spc_cpu_wakeup_irq(cluster, cpu, false);
+ ve_spc_set_resume_addr(cluster, cpu, 0);
+}
+
+static void tc2_pm_cluster_is_up(unsigned int cluster)
+{
+ pr_debug("%s: cluster %u\n", __func__, cluster);
+ BUG_ON(cluster >= TC2_CLUSTERS);
+ ve_spc_powerdown(cluster, false);
+ ve_spc_global_wakeup_irq(false);
+}
+
+static const struct mcpm_platform_ops tc2_pm_power_ops = {
+ .cpu_powerup = tc2_pm_cpu_powerup,
+ .cluster_powerup = tc2_pm_cluster_powerup,
+ .cpu_suspend_prepare = tc2_pm_cpu_suspend_prepare,
+ .cpu_powerdown_prepare = tc2_pm_cpu_powerdown_prepare,
+ .cluster_powerdown_prepare = tc2_pm_cluster_powerdown_prepare,
+ .cpu_cache_disable = tc2_pm_cpu_cache_disable,
+ .cluster_cache_disable = tc2_pm_cluster_cache_disable,
+ .wait_for_powerdown = tc2_pm_wait_for_powerdown,
+ .cpu_is_up = tc2_pm_cpu_is_up,
+ .cluster_is_up = tc2_pm_cluster_is_up,
+};
+
+/*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ */
+static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
+{
+ asm volatile (" \n"
+" cmp r0, #1 \n"
+" bxne lr \n"
+" b cci_enable_port_for_self ");
+}
+
+static int __init tc2_pm_init(void)
+{
+ unsigned int mpidr, cpu, cluster;
+ int ret, irq;
+ u32 a15_cluster_id, a7_cluster_id, sys_info;
+ struct device_node *np;
+
+ /*
+ * The power management-related features are hidden behind
+ * SCC registers. We need to extract runtime information like
+ * cluster ids and number of CPUs really available in clusters.
+ */
+ np = of_find_compatible_node(NULL, NULL,
+ "arm,vexpress-scc,v2p-ca15_a7");
+ scc = of_iomap(np, 0);
+ if (!scc)
+ return -ENODEV;
+
+ a15_cluster_id = readl_relaxed(scc + A15_CONF) & 0xf;
+ a7_cluster_id = readl_relaxed(scc + A7_CONF) & 0xf;
+ if (a15_cluster_id >= TC2_CLUSTERS || a7_cluster_id >= TC2_CLUSTERS)
+ return -EINVAL;
+
+ sys_info = readl_relaxed(scc + SYS_INFO);
+ tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf;
+ tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf;
+
+ irq = irq_of_parse_and_map(np, 0);
+
+ /*
+ * A subset of the SCC registers is also used to communicate
+ * with the SPC (power controller). We need to be able to
+ * drive it very early in the boot process to power up
+ * processors, so we initialize the SPC driver here.
+ */
+ ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq);
+ if (ret)
+ return ret;
+
+ if (!cci_probed())
+ return -ENODEV;
+
+ mpidr = read_cpuid_mpidr();
+ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) {
+ pr_err("%s: boot CPU is out of bound!\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = mcpm_platform_register(&tc2_pm_power_ops);
+ if (!ret) {
+ mcpm_sync_init(tc2_pm_power_up_setup);
+ /* test if we can (re)enable the CCI on our own */
+ BUG_ON(mcpm_loopback(tc2_pm_cluster_cache_disable) != 0);
+ pr_info("TC2 power management initialized\n");
+ }
+ return ret;
+}
+
+early_initcall(tc2_pm_init);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ */
+
+#include <asm/mach/arch.h>
+
+static const char *const mps2_compat[] __initconst = {
+ "arm,mps2",
+ NULL
+};
+
+DT_MACHINE_START(MPS2DT, "MPS2 (Device Tree Support)")
+ .dt_compat = mps2_compat,
+MACHINE_END
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/mach/arch.h>
+
+#include "vexpress.h"
+
+#define SYS_FLAGSSET 0x030
+#define SYS_FLAGSCLR 0x034
+
+void vexpress_flags_set(u32 data)
+{
+ static void __iomem *base;
+
+ if (!base) {
+ struct device_node *node = of_find_compatible_node(NULL, NULL,
+ "arm,vexpress-sysreg");
+
+ base = of_iomap(node, 0);
+ }
+
+ if (WARN_ON(!base))
+ return;
+
+ writel(~0, base + SYS_FLAGSCLR);
+ writel(data, base + SYS_FLAGSSET);
+}
+
+static const char * const v2m_dt_match[] __initconst = {
+ "arm,vexpress",
+ NULL,
+};
+
+DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
+ .dt_compat = v2m_dt_match,
+ .l2c_aux_val = 0x00400000,
+ .l2c_aux_mask = 0xfe0fffff,
+ .smp = smp_ops(vexpress_smp_dt_ops),
+ .smp_init = smp_init_ops(vexpress_smp_init_ops),
+MACHINE_END
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Versatile board support using the device tree
+ *
+ * Copyright (C) 2010 Secret Lab Technologies Ltd.
+ * Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
+ * Copyright (C) 2004 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+/* macro to get at MMIO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
+
+/*
+ * ------------------------------------------------------------------------
+ * Versatile Registers
+ * ------------------------------------------------------------------------
+ */
+#define VERSATILE_SYS_PCICTL_OFFSET 0x44
+#define VERSATILE_SYS_MCI_OFFSET 0x48
+
+/*
+ * VERSATILE peripheral addresses
+ */
+#define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
+#define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
+#define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
+
+/*
+ * System controller bit assignment
+ */
+#define VERSATILE_REFCLK 0
+#define VERSATILE_TIMCLK 1
+
+#define VERSATILE_TIMER1_EnSel 15
+#define VERSATILE_TIMER2_EnSel 17
+#define VERSATILE_TIMER3_EnSel 19
+#define VERSATILE_TIMER4_EnSel 21
+
+static void __iomem *versatile_sys_base;
+
+unsigned int mmc_status(struct device *dev)
+{
+ struct amba_device *adev = container_of(dev, struct amba_device, dev);
+ u32 mask;
+
+ if (adev->res.start == VERSATILE_MMCI0_BASE)
+ mask = 1;
+ else
+ mask = 2;
+
+ return readl(versatile_sys_base + VERSATILE_SYS_MCI_OFFSET) & mask;
+}
+
+static struct mmci_platform_data mmc0_plat_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+};
+
+static struct mmci_platform_data mmc1_plat_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+};
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
+ OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", &mmc0_plat_data),
+ OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", &mmc1_plat_data),
+ {}
+};
+
+static struct map_desc versatile_io_desc[] __initdata __maybe_unused = {
+ {
+ .virtual = IO_ADDRESS(VERSATILE_SCTL_BASE),
+ .pfn = __phys_to_pfn(VERSATILE_SCTL_BASE),
+ .length = SZ_4K * 9,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init versatile_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
+}
+
+static void __init versatile_init_early(void)
+{
+ u32 val;
+
+ /*
+ * set clock frequency:
+ * VERSATILE_REFCLK is 32KHz
+ * VERSATILE_TIMCLK is 1MHz
+ */
+ val = readl(__io_address(VERSATILE_SCTL_BASE));
+ writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
+ (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) |
+ (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
+ (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
+ __io_address(VERSATILE_SCTL_BASE));
+}
+
+static void __init versatile_dt_pci_init(void)
+{
+ u32 val;
+ struct device_node *np;
+ struct property *newprop;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,versatile-pci");
+ if (!np)
+ return;
+
+ /* Check if PCI backplane is detected */
+ val = readl(versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
+ if (val & 1) {
+ /*
+ * Enable PCI accesses. Note that the documentaton is
+ * inconsistent whether or not this is needed, but the old
+ * driver had it so we will keep it.
+ */
+ writel(1, versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
+ goto out_put_node;
+ }
+
+ newprop = kzalloc(sizeof(*newprop), GFP_KERNEL);
+ if (!newprop)
+ goto out_put_node;
+
+ newprop->name = kstrdup("status", GFP_KERNEL);
+ newprop->value = kstrdup("disabled", GFP_KERNEL);
+ newprop->length = sizeof("disabled");
+ of_update_property(np, newprop);
+
+ pr_info("Not plugged into PCI backplane!\n");
+
+out_put_node:
+ of_node_put(np);
+}
+
+static void __init versatile_dt_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,core-module-versatile");
+ if (np)
+ versatile_sys_base = of_iomap(np, 0);
+ WARN_ON(!versatile_sys_base);
+
+ versatile_dt_pci_init();
+
+ of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL);
+}
+
+static const char *const versatile_dt_match[] __initconst = {
+ "arm,versatile-ab",
+ "arm,versatile-pb",
+ NULL,
+};
+
+DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
+ .map_io = versatile_map_io,
+ .init_early = versatile_init_early,
+ .init_machine = versatile_dt_init,
+ .dt_compat = versatile_dt_match,
+MACHINE_END
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Versatile board support using the device tree
- *
- * Copyright (C) 2010 Secret Lab Technologies Ltd.
- * Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
- * Copyright (C) 2004 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/slab.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/mmci.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-/* macro to get at MMIO space when running virtually */
-#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
-#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
-
-/*
- * ------------------------------------------------------------------------
- * Versatile Registers
- * ------------------------------------------------------------------------
- */
-#define VERSATILE_SYS_PCICTL_OFFSET 0x44
-#define VERSATILE_SYS_MCI_OFFSET 0x48
-
-/*
- * VERSATILE peripheral addresses
- */
-#define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
-#define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
-#define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
-
-/*
- * System controller bit assignment
- */
-#define VERSATILE_REFCLK 0
-#define VERSATILE_TIMCLK 1
-
-#define VERSATILE_TIMER1_EnSel 15
-#define VERSATILE_TIMER2_EnSel 17
-#define VERSATILE_TIMER3_EnSel 19
-#define VERSATILE_TIMER4_EnSel 21
-
-static void __iomem *versatile_sys_base;
-
-unsigned int mmc_status(struct device *dev)
-{
- struct amba_device *adev = container_of(dev, struct amba_device, dev);
- u32 mask;
-
- if (adev->res.start == VERSATILE_MMCI0_BASE)
- mask = 1;
- else
- mask = 2;
-
- return readl(versatile_sys_base + VERSATILE_SYS_MCI_OFFSET) & mask;
-}
-
-static struct mmci_platform_data mmc0_plat_data = {
- .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .status = mmc_status,
-};
-
-static struct mmci_platform_data mmc1_plat_data = {
- .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .status = mmc_status,
-};
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate(). Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", &mmc0_plat_data),
- OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", &mmc1_plat_data),
- {}
-};
-
-static struct map_desc versatile_io_desc[] __initdata __maybe_unused = {
- {
- .virtual = IO_ADDRESS(VERSATILE_SCTL_BASE),
- .pfn = __phys_to_pfn(VERSATILE_SCTL_BASE),
- .length = SZ_4K * 9,
- .type = MT_DEVICE
- }
-};
-
-static void __init versatile_map_io(void)
-{
- debug_ll_io_init();
- iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
-}
-
-static void __init versatile_init_early(void)
-{
- u32 val;
-
- /*
- * set clock frequency:
- * VERSATILE_REFCLK is 32KHz
- * VERSATILE_TIMCLK is 1MHz
- */
- val = readl(__io_address(VERSATILE_SCTL_BASE));
- writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
- (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) |
- (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
- (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
- __io_address(VERSATILE_SCTL_BASE));
-}
-
-static void __init versatile_dt_pci_init(void)
-{
- u32 val;
- struct device_node *np;
- struct property *newprop;
-
- np = of_find_compatible_node(NULL, NULL, "arm,versatile-pci");
- if (!np)
- return;
-
- /* Check if PCI backplane is detected */
- val = readl(versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
- if (val & 1) {
- /*
- * Enable PCI accesses. Note that the documentaton is
- * inconsistent whether or not this is needed, but the old
- * driver had it so we will keep it.
- */
- writel(1, versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
- goto out_put_node;
- }
-
- newprop = kzalloc(sizeof(*newprop), GFP_KERNEL);
- if (!newprop)
- goto out_put_node;
-
- newprop->name = kstrdup("status", GFP_KERNEL);
- newprop->value = kstrdup("disabled", GFP_KERNEL);
- newprop->length = sizeof("disabled");
- of_update_property(np, newprop);
-
- pr_info("Not plugged into PCI backplane!\n");
-
-out_put_node:
- of_node_put(np);
-}
-
-static void __init versatile_dt_init(void)
-{
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL, "arm,core-module-versatile");
- if (np)
- versatile_sys_base = of_iomap(np, 0);
- WARN_ON(!versatile_sys_base);
-
- versatile_dt_pci_init();
-
- of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL);
-}
-
-static const char *const versatile_dt_match[] __initconst = {
- "arm,versatile-ab",
- "arm,versatile-pb",
- NULL,
-};
-
-DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
- .map_io = versatile_map_io,
- .init_early = versatile_init_early,
- .init_machine = versatile_dt_init,
- .dt_compat = versatile_dt_match,
-MACHINE_END
--- /dev/null
+bool vexpress_smp_init_ops(void);
+void vexpress_flags_set(u32 data);
+
+extern const struct smp_operations vexpress_smp_dt_ops;
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0
-menuconfig ARCH_VEXPRESS
- bool "ARM Ltd. Versatile Express family"
- depends on ARCH_MULTI_V7
- select ARCH_SUPPORTS_BIG_ENDIAN
- select ARM_AMBA
- select ARM_GIC
- select ARM_GLOBAL_TIMER
- select ARM_TIMER_SP804
- select GPIOLIB
- select HAVE_ARM_SCU if SMP
- select HAVE_ARM_TWD if SMP
- select HAVE_PATA_PLATFORM
- select CLK_ICST
- select NO_IOPORT_MAP
- select PLAT_VERSATILE
- select POWER_RESET
- select POWER_RESET_VEXPRESS
- select POWER_SUPPLY
- select REGULATOR if MMC_ARMMMCI
- select REGULATOR_FIXED_VOLTAGE if REGULATOR
- select VEXPRESS_CONFIG
- help
- This option enables support for systems using Cortex processor based
- ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
- for example:
-
- - CoreTile Express A5x2 (V2P-CA5s)
- - CoreTile Express A9x4 (V2P-CA9)
- - CoreTile Express A15x2 (V2P-CA15)
- - LogicTile Express 13MG (V2F-2XV6) with A5, A7, A9 or A15 SMMs
- (Soft Macrocell Models)
- - Versatile Express RTSMs (Models)
-
- You must boot using a Flattened Device Tree in order to use these
- platforms. The traditional (ATAGs) boot method is not usable on
- these boards with this option.
-
-if ARCH_VEXPRESS
-
-config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
- bool "Enable A5 and A9 only errata work-arounds"
- default y
- select ARM_ERRATA_643719 if SMP
- select ARM_ERRATA_720789
- select PL310_ERRATA_753970 if CACHE_L2X0
- help
- Provides common dependencies for Versatile Express platforms
- based on Cortex-A5 and Cortex-A9 processors. In order to
- build a working kernel, you must also enable relevant core
- tile support or Flattened Device Tree based support options.
-
-config ARCH_VEXPRESS_DCSCB
- bool "Dual Cluster System Control Block (DCSCB) support"
- depends on MCPM
- select ARM_CCI400_PORT_CTRL
- help
- Support for the Dual Cluster System Configuration Block (DCSCB).
- This is needed to provide CPU and cluster power management
- on RTSM implementing big.LITTLE.
-
-config ARCH_VEXPRESS_SPC
- bool "Versatile Express Serial Power Controller (SPC)"
- select PM_OPP
- help
- The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
- block called Serial Power Controller (SPC) that provides the interface
- between the dual cluster test-chip and the M3 microcontroller that
- carries out power management.
-
-config ARCH_VEXPRESS_TC2_PM
- bool "Versatile Express TC2 power management"
- depends on MCPM
- select ARM_CCI400_PORT_CTRL
- select ARCH_VEXPRESS_SPC
- select ARM_CPU_SUSPEND
- help
- Support for CPU and cluster power management on Versatile Express
- with a TC2 (A15x2 A7x3) big.LITTLE core tile.
-
-endif
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux kernel.
-#
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := \
- -I$(srctree)/arch/arm/plat-versatile/include
-
-obj-$(CONFIG_ARCH_VEXPRESS) := v2m.o
-obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o
-CFLAGS_dcscb.o += -march=armv7-a
-CFLAGS_REMOVE_dcscb.o = -pg
-obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o
-CFLAGS_REMOVE_spc.o = -pg
-obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o
-CFLAGS_tc2_pm.o += -march=armv7-a
-CFLAGS_REMOVE_tc2_pm.o = -pg
-obj-$(CONFIG_SMP) += platsmp.o
-
-obj-$(CONFIG_ARCH_MPS2) += v2m-mps2.o
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-# Empty file waiting for deletion once Makefile.boot isn't needed any more.
-# Patch waits for application at
-# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
+++ /dev/null
-bool vexpress_smp_init_ops(void);
-void vexpress_flags_set(u32 data);
-
-extern const struct smp_operations vexpress_smp_dt_ops;
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-vexpress/dcscb.c - Dual Cluster System Configuration Block
- *
- * Created by: Nicolas Pitre, May 2012
- * Copyright: (C) 2012-2013 Linaro Limited
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/of_address.h>
-#include <linux/vexpress.h>
-#include <linux/arm-cci.h>
-
-#include <asm/mcpm.h>
-#include <asm/proc-fns.h>
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/cp15.h>
-
-#include "core.h"
-
-#define RST_HOLD0 0x0
-#define RST_HOLD1 0x4
-#define SYS_SWRESET 0x8
-#define RST_STAT0 0xc
-#define RST_STAT1 0x10
-#define EAG_CFG_R 0x20
-#define EAG_CFG_W 0x24
-#define KFC_CFG_R 0x28
-#define KFC_CFG_W 0x2c
-#define DCS_CFG_R 0x30
-
-static void __iomem *dcscb_base;
-static int dcscb_allcpus_mask[2];
-
-static int dcscb_cpu_powerup(unsigned int cpu, unsigned int cluster)
-{
- unsigned int rst_hold, cpumask = (1 << cpu);
-
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- if (cluster >= 2 || !(cpumask & dcscb_allcpus_mask[cluster]))
- return -EINVAL;
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold &= ~(cpumask | (cpumask << 4));
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
- return 0;
-}
-
-static int dcscb_cluster_powerup(unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cluster %u\n", __func__, cluster);
- if (cluster >= 2)
- return -EINVAL;
-
- /* remove cluster reset and add individual CPU's reset */
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold &= ~(1 << 8);
- rst_hold |= dcscb_allcpus_mask[cluster];
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
- return 0;
-}
-
-static void dcscb_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- BUG_ON(cluster >= 2 || !((1 << cpu) & dcscb_allcpus_mask[cluster]));
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold |= (1 << cpu);
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-}
-
-static void dcscb_cluster_powerdown_prepare(unsigned int cluster)
-{
- unsigned int rst_hold;
-
- pr_debug("%s: cluster %u\n", __func__, cluster);
- BUG_ON(cluster >= 2);
-
- rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
- rst_hold |= (1 << 8);
- writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-}
-
-static void dcscb_cpu_cache_disable(void)
-{
- /* Disable and flush the local CPU cache. */
- v7_exit_coherency_flush(louis);
-}
-
-static void dcscb_cluster_cache_disable(void)
-{
- /* Flush all cache levels for this cluster. */
- v7_exit_coherency_flush(all);
-
- /*
- * A full outer cache flush could be needed at this point
- * on platforms with such a cache, depending on where the
- * outer cache sits. In some cases the notion of a "last
- * cluster standing" would need to be implemented if the
- * outer cache is shared across clusters. In any case, when
- * the outer cache needs flushing, there is no concurrent
- * access to the cache controller to worry about and no
- * special locking besides what is already provided by the
- * MCPM state machinery is needed.
- */
-
- /*
- * Disable cluster-level coherency by masking
- * incoming snoops and DVM messages:
- */
- cci_disable_port_by_cpu(read_cpuid_mpidr());
-}
-
-static const struct mcpm_platform_ops dcscb_power_ops = {
- .cpu_powerup = dcscb_cpu_powerup,
- .cluster_powerup = dcscb_cluster_powerup,
- .cpu_powerdown_prepare = dcscb_cpu_powerdown_prepare,
- .cluster_powerdown_prepare = dcscb_cluster_powerdown_prepare,
- .cpu_cache_disable = dcscb_cpu_cache_disable,
- .cluster_cache_disable = dcscb_cluster_cache_disable,
-};
-
-extern void dcscb_power_up_setup(unsigned int affinity_level);
-
-static int __init dcscb_init(void)
-{
- struct device_node *node;
- unsigned int cfg;
- int ret;
-
- if (!cci_probed())
- return -ENODEV;
-
- node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb");
- if (!node)
- return -ENODEV;
- dcscb_base = of_iomap(node, 0);
- if (!dcscb_base)
- return -EADDRNOTAVAIL;
- cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
- dcscb_allcpus_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
- dcscb_allcpus_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
-
- ret = mcpm_platform_register(&dcscb_power_ops);
- if (!ret)
- ret = mcpm_sync_init(dcscb_power_up_setup);
- if (ret) {
- iounmap(dcscb_base);
- return ret;
- }
-
- pr_info("VExpress DCSCB support installed\n");
-
- /*
- * Future entries into the kernel can now go
- * through the cluster entry vectors.
- */
- vexpress_flags_set(__pa_symbol(mcpm_entry_point));
-
- return 0;
-}
-
-early_initcall(dcscb_init);
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/include/asm/dcscb_setup.S
- *
- * Created by: Dave Martin, 2012-06-22
- * Copyright: (C) 2012-2013 Linaro Limited
- */
-
-#include <linux/linkage.h>
-
-
-ENTRY(dcscb_power_up_setup)
-
- cmp r0, #0 @ check affinity level
- beq 2f
-
-/*
- * Enable cluster-level coherency, in preparation for turning on the MMU.
- * The ACTLR SMP bit does not need to be set here, because cpu_resume()
- * already restores that.
- *
- * A15/A7 may not require explicit L2 invalidation on reset, dependent
- * on hardware integration decisions.
- * For now, this code assumes that L2 is either already invalidated,
- * or invalidation is not required.
- */
-
- b cci_enable_port_for_self
-
-2: @ Implementation-specific local CPU setup operations should go here,
- @ if any. In this case, there is nothing to do.
-
- bx lr
-
-ENDPROC(dcscb_power_up_setup)
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/mach-vexpress/platsmp.c
- *
- * Copyright (C) 2002 ARM Ltd.
- * All Rights Reserved
- */
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/vexpress.h>
-
-#include <asm/mcpm.h>
-#include <asm/smp_scu.h>
-#include <asm/mach/map.h>
-
-#include <plat/platsmp.h>
-
-#include "core.h"
-
-bool __init vexpress_smp_init_ops(void)
-{
-#ifdef CONFIG_MCPM
- int cpu;
- struct device_node *cpu_node, *cci_node;
-
- /*
- * The best way to detect a multi-cluster configuration
- * is to detect if the kernel can take over CCI ports
- * control. Loop over possible CPUs and check if CCI
- * port control is available.
- * Override the default vexpress_smp_ops if so.
- */
- for_each_possible_cpu(cpu) {
- bool available;
-
- cpu_node = of_get_cpu_node(cpu, NULL);
- if (WARN(!cpu_node, "Missing cpu device node!"))
- return false;
-
- cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
- available = cci_node && of_device_is_available(cci_node);
- of_node_put(cci_node);
- of_node_put(cpu_node);
-
- if (!available)
- return false;
- }
-
- mcpm_smp_set_ops();
- return true;
-#else
- return false;
-#endif
-}
-
-static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
- { .compatible = "arm,cortex-a5-scu", },
- { .compatible = "arm,cortex-a9-scu", },
- {}
-};
-
-static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)
-{
- struct device_node *scu = of_find_matching_node(NULL,
- vexpress_smp_dt_scu_match);
-
- if (scu)
- scu_enable(of_iomap(scu, 0));
-
- /*
- * Write the address of secondary startup into the
- * system-wide flags register. The boot monitor waits
- * until it receives a soft interrupt, and then the
- * secondary CPU branches to this address.
- */
- vexpress_flags_set(__pa_symbol(versatile_secondary_startup));
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-static void vexpress_cpu_die(unsigned int cpu)
-{
- versatile_immitation_cpu_die(cpu, 0x40);
-}
-#endif
-
-const struct smp_operations vexpress_smp_dt_ops __initconst = {
- .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus,
- .smp_secondary_init = versatile_secondary_init,
- .smp_boot_secondary = versatile_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
- .cpu_die = vexpress_cpu_die,
-#endif
-};
+++ /dev/null
-/*
- * Versatile Express Serial Power Controller (SPC) support
- *
- * Copyright (C) 2013 ARM Ltd.
- *
- * Authors: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
- * Achin Gupta <achin.gupta@arm.com>
- * Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/slab.h>
-#include <linux/semaphore.h>
-
-#include <asm/cacheflush.h>
-
-#include "spc.h"
-
-#define SPCLOG "vexpress-spc: "
-
-#define PERF_LVL_A15 0x00
-#define PERF_REQ_A15 0x04
-#define PERF_LVL_A7 0x08
-#define PERF_REQ_A7 0x0c
-#define COMMS 0x10
-#define COMMS_REQ 0x14
-#define PWC_STATUS 0x18
-#define PWC_FLAG 0x1c
-
-/* SPC wake-up IRQs status and mask */
-#define WAKE_INT_MASK 0x24
-#define WAKE_INT_RAW 0x28
-#define WAKE_INT_STAT 0x2c
-/* SPC power down registers */
-#define A15_PWRDN_EN 0x30
-#define A7_PWRDN_EN 0x34
-/* SPC per-CPU mailboxes */
-#define A15_BX_ADDR0 0x68
-#define A7_BX_ADDR0 0x78
-
-/* SPC CPU/cluster reset statue */
-#define STANDBYWFI_STAT 0x3c
-#define STANDBYWFI_STAT_A15_CPU_MASK(cpu) (1 << (cpu))
-#define STANDBYWFI_STAT_A7_CPU_MASK(cpu) (1 << (3 + (cpu)))
-
-/* SPC system config interface registers */
-#define SYSCFG_WDATA 0x70
-#define SYSCFG_RDATA 0x74
-
-/* A15/A7 OPP virtual register base */
-#define A15_PERFVAL_BASE 0xC10
-#define A7_PERFVAL_BASE 0xC30
-
-/* Config interface control bits */
-#define SYSCFG_START BIT(31)
-#define SYSCFG_SCC (6 << 20)
-#define SYSCFG_STAT (14 << 20)
-
-/* wake-up interrupt masks */
-#define GBL_WAKEUP_INT_MSK (0x3 << 10)
-
-/* TC2 static dual-cluster configuration */
-#define MAX_CLUSTERS 2
-
-/*
- * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS
- * operation, the operation could start just before jiffie is about
- * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz
- */
-#define TIMEOUT_US 20000
-
-#define MAX_OPPS 8
-#define CA15_DVFS 0
-#define CA7_DVFS 1
-#define SPC_SYS_CFG 2
-#define STAT_COMPLETE(type) ((1 << 0) << (type << 2))
-#define STAT_ERR(type) ((1 << 1) << (type << 2))
-#define RESPONSE_MASK(type) (STAT_COMPLETE(type) | STAT_ERR(type))
-
-struct ve_spc_opp {
- unsigned long freq;
- unsigned long u_volt;
-};
-
-struct ve_spc_drvdata {
- void __iomem *baseaddr;
- /*
- * A15s cluster identifier
- * It corresponds to A15 processors MPIDR[15:8] bitfield
- */
- u32 a15_clusid;
- uint32_t cur_rsp_mask;
- uint32_t cur_rsp_stat;
- struct semaphore sem;
- struct completion done;
- struct ve_spc_opp *opps[MAX_CLUSTERS];
- int num_opps[MAX_CLUSTERS];
-};
-
-static struct ve_spc_drvdata *info;
-
-static inline bool cluster_is_a15(u32 cluster)
-{
- return cluster == info->a15_clusid;
-}
-
-/**
- * ve_spc_global_wakeup_irq()
- *
- * Function to set/clear global wakeup IRQs. Not protected by locking since
- * it might be used in code paths where normal cacheable locks are not
- * working. Locking must be provided by the caller to ensure atomicity.
- *
- * @set: if true, global wake-up IRQs are set, if false they are cleared
- */
-void ve_spc_global_wakeup_irq(bool set)
-{
- u32 reg;
-
- reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
-
- if (set)
- reg |= GBL_WAKEUP_INT_MSK;
- else
- reg &= ~GBL_WAKEUP_INT_MSK;
-
- writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
-}
-
-/**
- * ve_spc_cpu_wakeup_irq()
- *
- * Function to set/clear per-CPU wake-up IRQs. Not protected by locking since
- * it might be used in code paths where normal cacheable locks are not
- * working. Locking must be provided by the caller to ensure atomicity.
- *
- * @cluster: mpidr[15:8] bitfield describing cluster affinity level
- * @cpu: mpidr[7:0] bitfield describing cpu affinity level
- * @set: if true, wake-up IRQs are set, if false they are cleared
- */
-void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set)
-{
- u32 mask, reg;
-
- if (cluster >= MAX_CLUSTERS)
- return;
-
- mask = BIT(cpu);
-
- if (!cluster_is_a15(cluster))
- mask <<= 4;
-
- reg = readl_relaxed(info->baseaddr + WAKE_INT_MASK);
-
- if (set)
- reg |= mask;
- else
- reg &= ~mask;
-
- writel_relaxed(reg, info->baseaddr + WAKE_INT_MASK);
-}
-
-/**
- * ve_spc_set_resume_addr() - set the jump address used for warm boot
- *
- * @cluster: mpidr[15:8] bitfield describing cluster affinity level
- * @cpu: mpidr[7:0] bitfield describing cpu affinity level
- * @addr: physical resume address
- */
-void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr)
-{
- void __iomem *baseaddr;
-
- if (cluster >= MAX_CLUSTERS)
- return;
-
- if (cluster_is_a15(cluster))
- baseaddr = info->baseaddr + A15_BX_ADDR0 + (cpu << 2);
- else
- baseaddr = info->baseaddr + A7_BX_ADDR0 + (cpu << 2);
-
- writel_relaxed(addr, baseaddr);
-}
-
-/**
- * ve_spc_powerdown()
- *
- * Function to enable/disable cluster powerdown. Not protected by locking
- * since it might be used in code paths where normal cacheable locks are not
- * working. Locking must be provided by the caller to ensure atomicity.
- *
- * @cluster: mpidr[15:8] bitfield describing cluster affinity level
- * @enable: if true enables powerdown, if false disables it
- */
-void ve_spc_powerdown(u32 cluster, bool enable)
-{
- u32 pwdrn_reg;
-
- if (cluster >= MAX_CLUSTERS)
- return;
-
- pwdrn_reg = cluster_is_a15(cluster) ? A15_PWRDN_EN : A7_PWRDN_EN;
- writel_relaxed(enable, info->baseaddr + pwdrn_reg);
-}
-
-static u32 standbywfi_cpu_mask(u32 cpu, u32 cluster)
-{
- return cluster_is_a15(cluster) ?
- STANDBYWFI_STAT_A15_CPU_MASK(cpu)
- : STANDBYWFI_STAT_A7_CPU_MASK(cpu);
-}
-
-/**
- * ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
- *
- * @cpu: mpidr[7:0] bitfield describing CPU affinity level within cluster
- * @cluster: mpidr[15:8] bitfield describing cluster affinity level
- *
- * @return: non-zero if and only if the specified CPU is in WFI
- *
- * Take care when interpreting the result of this function: a CPU might
- * be in WFI temporarily due to idle, and is not necessarily safely
- * parked.
- */
-int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
-{
- int ret;
- u32 mask = standbywfi_cpu_mask(cpu, cluster);
-
- if (cluster >= MAX_CLUSTERS)
- return 1;
-
- ret = readl_relaxed(info->baseaddr + STANDBYWFI_STAT);
-
- pr_debug("%s: PCFGREG[0x%X] = 0x%08X, mask = 0x%X\n",
- __func__, STANDBYWFI_STAT, ret, mask);
-
- return ret & mask;
-}
-
-static int ve_spc_get_performance(int cluster, u32 *freq)
-{
- struct ve_spc_opp *opps = info->opps[cluster];
- u32 perf_cfg_reg = 0;
- u32 perf;
-
- perf_cfg_reg = cluster_is_a15(cluster) ? PERF_LVL_A15 : PERF_LVL_A7;
-
- perf = readl_relaxed(info->baseaddr + perf_cfg_reg);
- if (perf >= info->num_opps[cluster])
- return -EINVAL;
-
- opps += perf;
- *freq = opps->freq;
-
- return 0;
-}
-
-/* find closest match to given frequency in OPP table */
-static int ve_spc_round_performance(int cluster, u32 freq)
-{
- int idx, max_opp = info->num_opps[cluster];
- struct ve_spc_opp *opps = info->opps[cluster];
- u32 fmin = 0, fmax = ~0, ftmp;
-
- freq /= 1000; /* OPP entries in kHz */
- for (idx = 0; idx < max_opp; idx++, opps++) {
- ftmp = opps->freq;
- if (ftmp >= freq) {
- if (ftmp <= fmax)
- fmax = ftmp;
- } else {
- if (ftmp >= fmin)
- fmin = ftmp;
- }
- }
- if (fmax != ~0)
- return fmax * 1000;
- else
- return fmin * 1000;
-}
-
-static int ve_spc_find_performance_index(int cluster, u32 freq)
-{
- int idx, max_opp = info->num_opps[cluster];
- struct ve_spc_opp *opps = info->opps[cluster];
-
- for (idx = 0; idx < max_opp; idx++, opps++)
- if (opps->freq == freq)
- break;
- return (idx == max_opp) ? -EINVAL : idx;
-}
-
-static int ve_spc_waitforcompletion(int req_type)
-{
- int ret = wait_for_completion_interruptible_timeout(
- &info->done, usecs_to_jiffies(TIMEOUT_US));
- if (ret == 0)
- ret = -ETIMEDOUT;
- else if (ret > 0)
- ret = info->cur_rsp_stat & STAT_COMPLETE(req_type) ? 0 : -EIO;
- return ret;
-}
-
-static int ve_spc_set_performance(int cluster, u32 freq)
-{
- u32 perf_cfg_reg;
- int ret, perf, req_type;
-
- if (cluster_is_a15(cluster)) {
- req_type = CA15_DVFS;
- perf_cfg_reg = PERF_LVL_A15;
- } else {
- req_type = CA7_DVFS;
- perf_cfg_reg = PERF_LVL_A7;
- }
-
- perf = ve_spc_find_performance_index(cluster, freq);
-
- if (perf < 0)
- return perf;
-
- if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
- return -ETIME;
-
- init_completion(&info->done);
- info->cur_rsp_mask = RESPONSE_MASK(req_type);
-
- writel(perf, info->baseaddr + perf_cfg_reg);
- ret = ve_spc_waitforcompletion(req_type);
-
- info->cur_rsp_mask = 0;
- up(&info->sem);
-
- return ret;
-}
-
-static int ve_spc_read_sys_cfg(int func, int offset, uint32_t *data)
-{
- int ret;
-
- if (down_timeout(&info->sem, usecs_to_jiffies(TIMEOUT_US)))
- return -ETIME;
-
- init_completion(&info->done);
- info->cur_rsp_mask = RESPONSE_MASK(SPC_SYS_CFG);
-
- /* Set the control value */
- writel(SYSCFG_START | func | offset >> 2, info->baseaddr + COMMS);
- ret = ve_spc_waitforcompletion(SPC_SYS_CFG);
-
- if (ret == 0)
- *data = readl(info->baseaddr + SYSCFG_RDATA);
-
- info->cur_rsp_mask = 0;
- up(&info->sem);
-
- return ret;
-}
-
-static irqreturn_t ve_spc_irq_handler(int irq, void *data)
-{
- struct ve_spc_drvdata *drv_data = data;
- uint32_t status = readl_relaxed(drv_data->baseaddr + PWC_STATUS);
-
- if (info->cur_rsp_mask & status) {
- info->cur_rsp_stat = status;
- complete(&drv_data->done);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * +--------------------------+
- * | 31 20 | 19 0 |
- * +--------------------------+
- * | m_volt | freq(kHz) |
- * +--------------------------+
- */
-#define MULT_FACTOR 20
-#define VOLT_SHIFT 20
-#define FREQ_MASK (0xFFFFF)
-static int ve_spc_populate_opps(uint32_t cluster)
-{
- uint32_t data = 0, off, ret, idx;
- struct ve_spc_opp *opps;
-
- opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL);
- if (!opps)
- return -ENOMEM;
-
- info->opps[cluster] = opps;
-
- off = cluster_is_a15(cluster) ? A15_PERFVAL_BASE : A7_PERFVAL_BASE;
- for (idx = 0; idx < MAX_OPPS; idx++, off += 4, opps++) {
- ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
- if (!ret) {
- opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
- opps->u_volt = (data >> VOLT_SHIFT) * 1000;
- } else {
- break;
- }
- }
- info->num_opps[cluster] = idx;
-
- return ret;
-}
-
-static int ve_init_opp_table(struct device *cpu_dev)
-{
- int cluster;
- int idx, ret = 0, max_opp;
- struct ve_spc_opp *opps;
-
- cluster = topology_physical_package_id(cpu_dev->id);
- cluster = cluster < 0 ? 0 : cluster;
-
- max_opp = info->num_opps[cluster];
- opps = info->opps[cluster];
-
- for (idx = 0; idx < max_opp; idx++, opps++) {
- ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
- if (ret) {
- dev_warn(cpu_dev, "failed to add opp %lu %lu\n",
- opps->freq, opps->u_volt);
- return ret;
- }
- }
- return ret;
-}
-
-int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
-{
- int ret;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- info->baseaddr = baseaddr;
- info->a15_clusid = a15_clusid;
-
- if (irq <= 0) {
- pr_err(SPCLOG "Invalid IRQ %d\n", irq);
- kfree(info);
- return -EINVAL;
- }
-
- init_completion(&info->done);
-
- readl_relaxed(info->baseaddr + PWC_STATUS);
-
- ret = request_irq(irq, ve_spc_irq_handler, IRQF_TRIGGER_HIGH
- | IRQF_ONESHOT, "vexpress-spc", info);
- if (ret) {
- pr_err(SPCLOG "IRQ %d request failed\n", irq);
- kfree(info);
- return -ENODEV;
- }
-
- sema_init(&info->sem, 1);
- /*
- * Multi-cluster systems may need this data when non-coherent, during
- * cluster power-up/power-down. Make sure driver info reaches main
- * memory.
- */
- sync_cache_w(info);
- sync_cache_w(&info);
-
- return 0;
-}
-
-struct clk_spc {
- struct clk_hw hw;
- int cluster;
-};
-
-#define to_clk_spc(spc) container_of(spc, struct clk_spc, hw)
-static unsigned long spc_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct clk_spc *spc = to_clk_spc(hw);
- u32 freq;
-
- if (ve_spc_get_performance(spc->cluster, &freq))
- return -EIO;
-
- return freq * 1000;
-}
-
-static long spc_round_rate(struct clk_hw *hw, unsigned long drate,
- unsigned long *parent_rate)
-{
- struct clk_spc *spc = to_clk_spc(hw);
-
- return ve_spc_round_performance(spc->cluster, drate);
-}
-
-static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_spc *spc = to_clk_spc(hw);
-
- return ve_spc_set_performance(spc->cluster, rate / 1000);
-}
-
-static struct clk_ops clk_spc_ops = {
- .recalc_rate = spc_recalc_rate,
- .round_rate = spc_round_rate,
- .set_rate = spc_set_rate,
-};
-
-static struct clk *ve_spc_clk_register(struct device *cpu_dev)
-{
- struct clk_init_data init;
- struct clk_spc *spc;
-
- spc = kzalloc(sizeof(*spc), GFP_KERNEL);
- if (!spc)
- return ERR_PTR(-ENOMEM);
-
- spc->hw.init = &init;
- spc->cluster = topology_physical_package_id(cpu_dev->id);
-
- spc->cluster = spc->cluster < 0 ? 0 : spc->cluster;
-
- init.name = dev_name(cpu_dev);
- init.ops = &clk_spc_ops;
- init.flags = CLK_GET_RATE_NOCACHE;
- init.num_parents = 0;
-
- return devm_clk_register(cpu_dev, &spc->hw);
-}
-
-static int __init ve_spc_clk_init(void)
-{
- int cpu, cluster;
- struct clk *clk;
- bool init_opp_table[MAX_CLUSTERS] = { false };
-
- if (!info)
- return 0; /* Continue only if SPC is initialised */
-
- if (ve_spc_populate_opps(0) || ve_spc_populate_opps(1)) {
- pr_err("failed to build OPP table\n");
- return -ENODEV;
- }
-
- for_each_possible_cpu(cpu) {
- struct device *cpu_dev = get_cpu_device(cpu);
- if (!cpu_dev) {
- pr_warn("failed to get cpu%d device\n", cpu);
- continue;
- }
- clk = ve_spc_clk_register(cpu_dev);
- if (IS_ERR(clk)) {
- pr_warn("failed to register cpu%d clock\n", cpu);
- continue;
- }
- if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
- pr_warn("failed to register cpu%d clock lookup\n", cpu);
- continue;
- }
-
- cluster = topology_physical_package_id(cpu_dev->id);
- if (init_opp_table[cluster])
- continue;
-
- if (ve_init_opp_table(cpu_dev))
- pr_warn("failed to initialise cpu%d opp table\n", cpu);
- else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
- topology_core_cpumask(cpu_dev->id)))
- pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
- else
- init_opp_table[cluster] = true;
- }
-
- platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
- return 0;
-}
-device_initcall(ve_spc_clk_init);
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-
-#ifndef __SPC_H_
-#define __SPC_H_
-
-int __init ve_spc_init(void __iomem *base, u32 a15_clusid, int irq);
-void ve_spc_global_wakeup_irq(bool set);
-void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
-void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
-void ve_spc_powerdown(u32 cluster, bool enable);
-int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster);
-
-#endif
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-vexpress/tc2_pm.c - TC2 power management support
- *
- * Created by: Nicolas Pitre, October 2012
- * Copyright: (C) 2012-2013 Linaro Limited
- *
- * Some portions of this file were originally written by Achin Gupta
- * Copyright: (C) 2012 ARM Limited
- */
-
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/errno.h>
-#include <linux/irqchip/arm-gic.h>
-
-#include <asm/mcpm.h>
-#include <asm/proc-fns.h>
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/cp15.h>
-
-#include <linux/arm-cci.h>
-
-#include "spc.h"
-
-/* SCC conf registers */
-#define RESET_CTRL 0x018
-#define RESET_A15_NCORERESET(cpu) (1 << (2 + (cpu)))
-#define RESET_A7_NCORERESET(cpu) (1 << (16 + (cpu)))
-
-#define A15_CONF 0x400
-#define A7_CONF 0x500
-#define SYS_INFO 0x700
-#define SPC_BASE 0xb00
-
-static void __iomem *scc;
-
-#define TC2_CLUSTERS 2
-#define TC2_MAX_CPUS_PER_CLUSTER 3
-
-static unsigned int tc2_nr_cpus[TC2_CLUSTERS];
-
-static int tc2_pm_cpu_powerup(unsigned int cpu, unsigned int cluster)
-{
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster])
- return -EINVAL;
- ve_spc_set_resume_addr(cluster, cpu,
- __pa_symbol(mcpm_entry_point));
- ve_spc_cpu_wakeup_irq(cluster, cpu, true);
- return 0;
-}
-
-static int tc2_pm_cluster_powerup(unsigned int cluster)
-{
- pr_debug("%s: cluster %u\n", __func__, cluster);
- if (cluster >= TC2_CLUSTERS)
- return -EINVAL;
- ve_spc_powerdown(cluster, false);
- return 0;
-}
-
-static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
-{
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
- ve_spc_cpu_wakeup_irq(cluster, cpu, true);
- /*
- * If the CPU is committed to power down, make sure
- * the power controller will be in charge of waking it
- * up upon IRQ, ie IRQ lines are cut from GIC CPU IF
- * to the CPU by disabling the GIC CPU IF to prevent wfi
- * from completing execution behind power controller back
- */
- gic_cpu_if_down(0);
-}
-
-static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster)
-{
- pr_debug("%s: cluster %u\n", __func__, cluster);
- BUG_ON(cluster >= TC2_CLUSTERS);
- ve_spc_powerdown(cluster, true);
- ve_spc_global_wakeup_irq(true);
-}
-
-static void tc2_pm_cpu_cache_disable(void)
-{
- v7_exit_coherency_flush(louis);
-}
-
-static void tc2_pm_cluster_cache_disable(void)
-{
- if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
- /*
- * On the Cortex-A15 we need to disable
- * L2 prefetching before flushing the cache.
- */
- asm volatile(
- "mcr p15, 1, %0, c15, c0, 3 \n\t"
- "isb \n\t"
- "dsb "
- : : "r" (0x400) );
- }
-
- v7_exit_coherency_flush(all);
- cci_disable_port_by_cpu(read_cpuid_mpidr());
-}
-
-static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster)
-{
- u32 mask = cluster ?
- RESET_A7_NCORERESET(cpu)
- : RESET_A15_NCORERESET(cpu);
-
- return !(readl_relaxed(scc + RESET_CTRL) & mask);
-}
-
-#define POLL_MSEC 10
-#define TIMEOUT_MSEC 1000
-
-static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
-{
- unsigned tries;
-
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
-
- for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; ++tries) {
- pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
- __func__, cpu, cluster,
- readl_relaxed(scc + RESET_CTRL));
-
- /*
- * We need the CPU to reach WFI, but the power
- * controller may put the cluster in reset and
- * power it off as soon as that happens, before
- * we have a chance to see STANDBYWFI.
- *
- * So we need to check for both conditions:
- */
- if (tc2_core_in_reset(cpu, cluster) ||
- ve_spc_cpu_in_wfi(cpu, cluster))
- return 0; /* success: the CPU is halted */
-
- /* Otherwise, wait and retry: */
- msleep(POLL_MSEC);
- }
-
- return -ETIMEDOUT; /* timeout */
-}
-
-static void tc2_pm_cpu_suspend_prepare(unsigned int cpu, unsigned int cluster)
-{
- ve_spc_set_resume_addr(cluster, cpu, __pa_symbol(mcpm_entry_point));
-}
-
-static void tc2_pm_cpu_is_up(unsigned int cpu, unsigned int cluster)
-{
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
- ve_spc_cpu_wakeup_irq(cluster, cpu, false);
- ve_spc_set_resume_addr(cluster, cpu, 0);
-}
-
-static void tc2_pm_cluster_is_up(unsigned int cluster)
-{
- pr_debug("%s: cluster %u\n", __func__, cluster);
- BUG_ON(cluster >= TC2_CLUSTERS);
- ve_spc_powerdown(cluster, false);
- ve_spc_global_wakeup_irq(false);
-}
-
-static const struct mcpm_platform_ops tc2_pm_power_ops = {
- .cpu_powerup = tc2_pm_cpu_powerup,
- .cluster_powerup = tc2_pm_cluster_powerup,
- .cpu_suspend_prepare = tc2_pm_cpu_suspend_prepare,
- .cpu_powerdown_prepare = tc2_pm_cpu_powerdown_prepare,
- .cluster_powerdown_prepare = tc2_pm_cluster_powerdown_prepare,
- .cpu_cache_disable = tc2_pm_cpu_cache_disable,
- .cluster_cache_disable = tc2_pm_cluster_cache_disable,
- .wait_for_powerdown = tc2_pm_wait_for_powerdown,
- .cpu_is_up = tc2_pm_cpu_is_up,
- .cluster_is_up = tc2_pm_cluster_is_up,
-};
-
-/*
- * Enable cluster-level coherency, in preparation for turning on the MMU.
- */
-static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
-{
- asm volatile (" \n"
-" cmp r0, #1 \n"
-" bxne lr \n"
-" b cci_enable_port_for_self ");
-}
-
-static int __init tc2_pm_init(void)
-{
- unsigned int mpidr, cpu, cluster;
- int ret, irq;
- u32 a15_cluster_id, a7_cluster_id, sys_info;
- struct device_node *np;
-
- /*
- * The power management-related features are hidden behind
- * SCC registers. We need to extract runtime information like
- * cluster ids and number of CPUs really available in clusters.
- */
- np = of_find_compatible_node(NULL, NULL,
- "arm,vexpress-scc,v2p-ca15_a7");
- scc = of_iomap(np, 0);
- if (!scc)
- return -ENODEV;
-
- a15_cluster_id = readl_relaxed(scc + A15_CONF) & 0xf;
- a7_cluster_id = readl_relaxed(scc + A7_CONF) & 0xf;
- if (a15_cluster_id >= TC2_CLUSTERS || a7_cluster_id >= TC2_CLUSTERS)
- return -EINVAL;
-
- sys_info = readl_relaxed(scc + SYS_INFO);
- tc2_nr_cpus[a15_cluster_id] = (sys_info >> 16) & 0xf;
- tc2_nr_cpus[a7_cluster_id] = (sys_info >> 20) & 0xf;
-
- irq = irq_of_parse_and_map(np, 0);
-
- /*
- * A subset of the SCC registers is also used to communicate
- * with the SPC (power controller). We need to be able to
- * drive it very early in the boot process to power up
- * processors, so we initialize the SPC driver here.
- */
- ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq);
- if (ret)
- return ret;
-
- if (!cci_probed())
- return -ENODEV;
-
- mpidr = read_cpuid_mpidr();
- cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
- pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
- if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) {
- pr_err("%s: boot CPU is out of bound!\n", __func__);
- return -EINVAL;
- }
-
- ret = mcpm_platform_register(&tc2_pm_power_ops);
- if (!ret) {
- mcpm_sync_init(tc2_pm_power_up_setup);
- /* test if we can (re)enable the CCI on our own */
- BUG_ON(mcpm_loopback(tc2_pm_cluster_cache_disable) != 0);
- pr_info("TC2 power management initialized\n");
- }
- return ret;
-}
-
-early_initcall(tc2_pm_init);
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 ARM Limited
- *
- * Author: Vladimir Murzin <vladimir.murzin@arm.com>
- */
-
-#include <asm/mach/arch.h>
-
-static const char *const mps2_compat[] __initconst = {
- "arm,mps2",
- NULL
-};
-
-DT_MACHINE_START(MPS2DT, "MPS2 (Device Tree Support)")
- .dt_compat = mps2_compat,
-MACHINE_END
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <asm/mach/arch.h>
-
-#include "core.h"
-
-#define SYS_FLAGSSET 0x030
-#define SYS_FLAGSCLR 0x034
-
-void vexpress_flags_set(u32 data)
-{
- static void __iomem *base;
-
- if (!base) {
- struct device_node *node = of_find_compatible_node(NULL, NULL,
- "arm,vexpress-sysreg");
-
- base = of_iomap(node, 0);
- }
-
- if (WARN_ON(!base))
- return;
-
- writel(~0, base + SYS_FLAGSCLR);
- writel(data, base + SYS_FLAGSSET);
-}
-
-static const char * const v2m_dt_match[] __initconst = {
- "arm,vexpress",
- NULL,
-};
-
-DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
- .dt_compat = v2m_dt_match,
- .l2c_aux_val = 0x00400000,
- .l2c_aux_mask = 0xfe0fffff,
- .smp = smp_ops(vexpress_smp_dt_ops),
- .smp_init = smp_init_ops(vexpress_smp_init_ops),
-MACHINE_END
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
-
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
-obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/arm/plat-versatile/headsmp.S
- *
- * Copyright (c) 2003 ARM Limited
- * All Rights Reserved
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/assembler.h>
-
-/*
- * Realview/Versatile Express specific entry point for secondary CPUs.
- * This provides a "holding pen" into which all secondary cores are held
- * until we're ready for them to initialise.
- */
-ENTRY(versatile_secondary_startup)
- ARM_BE8(setend be)
- mrc p15, 0, r0, c0, c0, 5
- bic r0, #0xff000000
- adr r4, 1f
- ldmia r4, {r5, r6}
- sub r4, r4, r5
- add r6, r6, r4
-pen: ldr r7, [r6]
- cmp r7, r0
- bne pen
-
- /*
- * we've been released from the holding pen: secondary_stack
- * should now contain the SVC stack for this core
- */
- b secondary_startup
-
- .align
-1: .long .
- .long versatile_cpu_release
-ENDPROC(versatile_secondary_startup)
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2002 ARM Ltd.
- * All Rights Reserved
- *
- * This hotplug implementation is _specific_ to the situation found on
- * ARM development platforms where there is _no_ possibility of actually
- * taking a CPU offline, resetting it, or otherwise. Real platforms must
- * NOT copy this code.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-
-#include <asm/smp_plat.h>
-#include <asm/cp15.h>
-
-#include <plat/platsmp.h>
-
-static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
-{
- unsigned int v;
-
- asm volatile(
- "mcr p15, 0, %1, c7, c5, 0\n"
- " mcr p15, 0, %1, c7, c10, 4\n"
- /*
- * Turn off coherency
- */
- " mrc p15, 0, %0, c1, c0, 1\n"
- " bic %0, %0, %3\n"
- " mcr p15, 0, %0, c1, c0, 1\n"
- " mrc p15, 0, %0, c1, c0, 0\n"
- " bic %0, %0, %2\n"
- " mcr p15, 0, %0, c1, c0, 0\n"
- : "=&r" (v)
- : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
- : "cc");
-}
-
-static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
-{
- unsigned int v;
-
- asm volatile(
- "mrc p15, 0, %0, c1, c0, 0\n"
- " orr %0, %0, %1\n"
- " mcr p15, 0, %0, c1, c0, 0\n"
- " mrc p15, 0, %0, c1, c0, 1\n"
- " orr %0, %0, %2\n"
- " mcr p15, 0, %0, c1, c0, 1\n"
- : "=&r" (v)
- : "Ir" (CR_C), "Ir" (actrl_mask)
- : "cc");
-}
-
-static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
-{
- /*
- * there is no power-control hardware on this platform, so all
- * we can do is put the core into WFI; this is safe as the calling
- * code will have already disabled interrupts.
- *
- * This code should not be used outside Versatile platforms.
- */
- for (;;) {
- wfi();
-
- if (versatile_cpu_release == cpu_logical_map(cpu)) {
- /*
- * OK, proper wakeup, we're done
- */
- break;
- }
-
- /*
- * Getting here, means that we have come out of WFI without
- * having been woken up - this shouldn't happen
- *
- * Just note it happening - when we're woken, we can report
- * its occurrence.
- */
- (*spurious)++;
- }
-}
-
-/*
- * platform-specific code to shutdown a CPU.
- * This code supports immitation-style CPU hotplug for Versatile/Realview/
- * Versatile Express platforms that are unable to do real CPU hotplug.
- */
-void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
-{
- int spurious = 0;
-
- versatile_immitation_enter_lowpower(actrl_mask);
- versatile_immitation_do_lowpower(cpu, &spurious);
- versatile_immitation_leave_lowpower(actrl_mask);
-
- if (spurious)
- pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/arm/plat-versatile/include/plat/platsmp.h
- *
- * Copyright (C) 2011 ARM Ltd.
- * All Rights Reserved
- */
-extern volatile int versatile_cpu_release;
-
-extern void versatile_secondary_startup(void);
-extern void versatile_secondary_init(unsigned int cpu);
-extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle);
-void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask);
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/arm/plat-versatile/platsmp.c
- *
- * Copyright (C) 2002 ARM Ltd.
- * All Rights Reserved
- *
- * This code is specific to the hardware found on ARM Realview and
- * Versatile Express platforms where the CPUs are unable to be individually
- * woken, and where there is no way to hot-unplug CPUs. Real platforms
- * should not copy this code.
- */
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
-
-#include <asm/cacheflush.h>
-#include <asm/smp_plat.h>
-
-#include <plat/platsmp.h>
-
-/*
- * versatile_cpu_release controls the release of CPUs from the holding
- * pen in headsmp.S, which exists because we are not always able to
- * control the release of individual CPUs from the board firmware.
- * Production platforms do not need this.
- */
-volatile int versatile_cpu_release = -1;
-
-/*
- * Write versatile_cpu_release in a way that is guaranteed to be visible to
- * all observers, irrespective of whether they're taking part in coherency
- * or not. This is necessary for the hotplug code to work reliably.
- */
-static void versatile_write_cpu_release(int val)
-{
- versatile_cpu_release = val;
- smp_wmb();
- sync_cache_w(&versatile_cpu_release);
-}
-
-/*
- * versatile_lock exists to avoid running the loops_per_jiffy delay loop
- * calibrations on the secondary CPU while the requesting CPU is using
- * the limited-bandwidth bus - which affects the calibration value.
- * Production platforms do not need this.
- */
-static DEFINE_RAW_SPINLOCK(versatile_lock);
-
-void versatile_secondary_init(unsigned int cpu)
-{
- /*
- * let the primary processor know we're out of the
- * pen, then head off into the C entry point
- */
- versatile_write_cpu_release(-1);
-
- /*
- * Synchronise with the boot thread.
- */
- raw_spin_lock(&versatile_lock);
- raw_spin_unlock(&versatile_lock);
-}
-
-int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
- unsigned long timeout;
-
- /*
- * Set synchronisation state between this boot processor
- * and the secondary one
- */
- raw_spin_lock(&versatile_lock);
-
- /*
- * This is really belt and braces; we hold unintended secondary
- * CPUs in the holding pen until we're ready for them. However,
- * since we haven't sent them a soft interrupt, they shouldn't
- * be there.
- */
- versatile_write_cpu_release(cpu_logical_map(cpu));
-
- /*
- * Send the secondary CPU a soft interrupt, thereby causing
- * the boot monitor to read the system wide flags register,
- * and branch to the address found there.
- */
- arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-
- timeout = jiffies + (1 * HZ);
- while (time_before(jiffies, timeout)) {
- smp_rmb();
- if (versatile_cpu_release == -1)
- break;
-
- udelay(10);
- }
-
- /*
- * now the secondary core is starting up let it run its
- * calibrations, then wait for it to finish
- */
- raw_spin_unlock(&versatile_lock);
-
- return versatile_cpu_release != -1 ? -ENOSYS : 0;
-}