diff options
author | Arnd Bergmann <arnd@arndb.de> | 2019-03-01 15:21:04 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2019-03-01 15:21:04 +0100 |
commit | c889e2a0b053703be7e7591c9a574975440e5502 (patch) | |
tree | 09810287d9ed4d57e133ba4184deebb0db14c283 | |
parent | ee036df9bd1d3ca8b138c6376792c0b72f96a903 (diff) | |
parent | 2781204594c2705868c1f9388f80ae6cdcdabd22 (diff) |
Merge branch 'milbeaut/newsoc' into arm/newsoc
Sugaya Taichi <sugaya.taichi@socionext.com> explains:
Here is the series of patches the initial support for SC2000(M10V) of
Milbeaut SoCs. "M10V" is the internal name of SC2000, so commonly used in
source code.
SC2000 is a SoC of the Milbeaut series. equipped with a DSP optimized for
computer vision. It also features advanced functionalities such as 360-degree,
real-time spherical stitching with multi cameras, image stabilization for
without mechanical gimbals, and rolling shutter correction. More detail is
below:
https://www.socionext.com/en/products/assp/milbeaut/SC2000.html
Specifications for developers are below:
- Quad-core 32bit Cortex-A7 on ARMv7-A architecture
- NEON support
- DSP
- GPU
- MAX 3GB DDR3
- Cortex-M0 for power control
- NAND Flash Interface
- SD UHS-I
- SD UHS-II
- SDIO
- USB2.0 HOST / Device
- USB3.0 HOST / Device
- PCI express Gen2
- Ethernet Engine
- I2C
- UART
- SPI
- PWM
Support is quite minimal for now, since it only includes timer, clock,
pictrl and serial controller drivers, so we can only boot to userspace
through initramfs. Support for the other peripherals will come eventually.
* milbeaut/newsoc:
ARM: multi_v7_defconfig: add ARCH_MILBEAUT and ARCH_MILBEAUT_M10V
ARM: configs: Add Milbeaut M10V defconfig
ARM: dts: milbeaut: Add device tree set for the Milbeaut M10V board
clocksource/drivers/timer-milbeaut: Introduce timer for Milbeaut SoCs
dt-bindings: timer: Add Milbeaut M10V timer description
ARM: milbeaut: Add basic support for Milbeaut m10v SoC
dt-bindings: Add documentation for Milbeaut SoCs
dt-bindings: arm: Add SMP enable-method for Milbeaut
dt-bindings: sram: milbeaut: Add binding for Milbeaut smp-sram
Link: https://lore.kernel.org/linux-arm-kernel/1551243056-10521-1-git-send-email-sugaya.taichi@socionext.com/
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | Documentation/devicetree/bindings/arm/cpus.yaml | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml | 22 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sram/milbeaut-smp-sram.txt | 24 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/timer/socionext,milbeaut-timer.txt | 17 | ||||
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/milbeaut-m10v-evb.dts | 32 | ||||
-rw-r--r-- | arch/arm/boot/dts/milbeaut-m10v.dtsi | 95 | ||||
-rw-r--r-- | arch/arm/configs/milbeaut_m10v_defconfig | 119 | ||||
-rw-r--r-- | arch/arm/configs/multi_v7_defconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-milbeaut/Kconfig | 20 | ||||
-rw-r--r-- | arch/arm/mach-milbeaut/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-milbeaut/platsmp.c | 143 | ||||
-rw-r--r-- | drivers/clocksource/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-milbeaut.c | 161 |
17 files changed, 651 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 298c17b327c6..365dcf384d73 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -228,6 +228,7 @@ patternProperties: - renesas,r9a06g032-smp - rockchip,rk3036-smp - rockchip,rk3066-smp + - socionext,milbeaut-m10v-smp - ste,dbx500-smp cpu-release-addr: diff --git a/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml b/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml new file mode 100644 index 000000000000..aae53fc3cb1e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/milbeaut.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Milbeaut platforms device tree bindings + +maintainers: + - Taichi Sugaya <sugaya.taichi@socionext.com> + - Takao Orito <orito.takao@socionext.com> + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - items: + - enum: + - socionext,milbeaut-m10v-evb + - const: socionext,sc2000a +... diff --git a/Documentation/devicetree/bindings/sram/milbeaut-smp-sram.txt b/Documentation/devicetree/bindings/sram/milbeaut-smp-sram.txt new file mode 100644 index 000000000000..194f6a3c1c1e --- /dev/null +++ b/Documentation/devicetree/bindings/sram/milbeaut-smp-sram.txt @@ -0,0 +1,24 @@ +Milbeaut SRAM for smp bringup + +Milbeaut SoCs use a part of the sram for the bringup of the secondary cores. +Once they get powered up in the bootloader, they stay at the specific part +of the sram. +Therefore the part needs to be added as the sub-node of mmio-sram. + +Required sub-node properties: +- compatible : should be "socionext,milbeaut-smp-sram" + +Example: + + sram: sram@0 { + compatible = "mmio-sram"; + reg = <0x0 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x10000>; + + smp-sram@f100 { + compatible = "socionext,milbeaut-smp-sram"; + reg = <0xf100 0x20>; + }; + }; diff --git a/Documentation/devicetree/bindings/timer/socionext,milbeaut-timer.txt b/Documentation/devicetree/bindings/timer/socionext,milbeaut-timer.txt new file mode 100644 index 000000000000..ac44c4b67530 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/socionext,milbeaut-timer.txt @@ -0,0 +1,17 @@ +Milbeaut SoCs Timer Controller + +Required properties: + +- compatible : should be "socionext,milbeaut-timer". +- reg : Specifies base physical address and size of the registers. +- interrupts : The interrupt of the first timer. +- clocks: phandle to the input clk. + +Example: + +timer { + compatible = "socionext,milbeaut-timer"; + reg = <0x1e000050 0x20> + interrupts = <0 91 4>; + clocks = <&clk 4>; +}; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 664e918e2624..c8cb75288953 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -750,6 +750,8 @@ source "arch/arm/mach-mediatek/Kconfig" source "arch/arm/mach-meson/Kconfig" +source "arch/arm/mach-milbeaut/Kconfig" + source "arch/arm/mach-mmp/Kconfig" source "arch/arm/mach-moxart/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9db3c584b2cb..00000e91ad65 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -190,6 +190,7 @@ machine-$(CONFIG_ARCH_MV78XX0) += mv78xx0 machine-$(CONFIG_ARCH_MVEBU) += mvebu machine-$(CONFIG_ARCH_MXC) += imx machine-$(CONFIG_ARCH_MEDIATEK) += mediatek +machine-$(CONFIG_ARCH_MILBEAUT) += milbeaut machine-$(CONFIG_ARCH_MXS) += mxs machine-$(CONFIG_ARCH_NETX) += netx machine-$(CONFIG_ARCH_NOMADIK) += nomadik diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index bd40148a15b2..f697d87e99aa 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1233,6 +1233,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt7623n-bananapi-bpi-r2.dtb \ mt8127-moose.dtb \ mt8135-evbp1.dtb +dtb-$(CONFIG_ARCH_MILBEAUT) += milbeaut-m10v-evb.dtb dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-ast2500-evb.dtb \ diff --git a/arch/arm/boot/dts/milbeaut-m10v-evb.dts b/arch/arm/boot/dts/milbeaut-m10v-evb.dts new file mode 100644 index 000000000000..614f60c6b0a2 --- /dev/null +++ b/arch/arm/boot/dts/milbeaut-m10v-evb.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Socionext Milbeaut M10V Evaluation Board */ +/dts-v1/; +#include "milbeaut-m10v.dtsi" + +/ { + model = "Socionext M10V EVB"; + compatible = "socionext,milbeaut-m10v-evb", "socionext,sc2000a"; + + aliases { + serial0 = &uart1; + }; + + chosen { + bootargs = "rootwait earlycon"; + stdout-path = "serial0:115200n8"; + }; + + clocks { + uclk40xi: uclk40xi { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <40000000>; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x80000000>; + }; + +}; diff --git a/arch/arm/boot/dts/milbeaut-m10v.dtsi b/arch/arm/boot/dts/milbeaut-m10v.dtsi new file mode 100644 index 000000000000..aa7c6caeb750 --- /dev/null +++ b/arch/arm/boot/dts/milbeaut-m10v.dtsi @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "socionext,sc2000a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "socionext,milbeaut-m10v-smp"; + cpu@f00 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf00>; + }; + cpu@f01 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf01>; + }; + cpu@f02 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf02>; + }; + cpu@f03 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf03>; + }; + }; + + timer { /* The Generic Timer */ + compatible = "arm,armv7-timer"; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 14 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 11 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 10 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + clock-frequency = <40000000>; + always-on; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-parent = <&gic>; + + gic: interrupt-controller@1d000000 { + compatible = "arm,cortex-a7-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x1d001000 0x1000>, + <0x1d002000 0x1000>; /* CPU I/f base and size */ + }; + + timer@1e000050 { /* 32-bit Reload Timers */ + compatible = "socionext,milbeaut-timer"; + reg = <0x1e000050 0x20>; + interrupts = <0 91 4>; + }; + + uart1: serial@1e700010 { /* PE4, PE5 */ + /* Enable this as ttyUSI0 */ + compatible = "socionext,milbeaut-usio-uart"; + reg = <0x1e700010 0x10>; + interrupts = <0 141 0x4>, <0 149 0x4>; + interrupt-names = "rx", "tx"; + }; + + }; + + sram@0 { + compatible = "mmio-sram"; + reg = <0x0 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x10000>; + smp-sram@f100 { + compatible = "socionext,milbeaut-smp-sram"; + reg = <0xf100 0x20>; + }; + }; +}; diff --git a/arch/arm/configs/milbeaut_m10v_defconfig b/arch/arm/configs/milbeaut_m10v_defconfig new file mode 100644 index 000000000000..7c07f9893a0f --- /dev/null +++ b/arch/arm/configs/milbeaut_m10v_defconfig @@ -0,0 +1,119 @@ +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_CGROUPS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_MILBEAUT=y +CONFIG_ARCH_MILBEAUT_M10V=y +CONFIG_ARM_THUMBEE=y +# CONFIG_VDSO is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_ARM_ERRATA_798181=y +CONFIG_SMP=y +# CONFIG_SMP_ON_UP is not set +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_NR_CPUS=16 +CONFIG_THUMB2_KERNEL=y +# CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11 is not set +# CONFIG_ARM_PATCH_IDIV is not set +CONFIG_HIGHMEM=y +CONFIG_FORCE_MAX_ZONEORDER=12 +CONFIG_SECCOMP=y +CONFIG_KEXEC=y +CONFIG_EFI=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPUFREQ_DT=y +CONFIG_QORIQ_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_EFI_VARS=m +CONFIG_EFI_CAPSULE_LOADER=m +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_NEON=m +CONFIG_CRYPTO_SHA1_ARM_CE=m +CONFIG_CRYPTO_SHA2_ARM_CE=m +CONFIG_CRYPTO_SHA512_ARM=m +CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRYPTO_AES_ARM_BS=m +CONFIG_CRYPTO_AES_ARM_CE=m +CONFIG_CRYPTO_GHASH_ARM_CE=m +CONFIG_CRYPTO_CRC32_ARM_CE=m +CONFIG_CRYPTO_CHACHA20_NEON=m +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_CMDLINE_PARTITION=y +CONFIG_CMA=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=64 +CONFIG_OF_OVERLAY=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_SRAM=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_MATRIXKMAP=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_HWMON is not set +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +# CONFIG_HID is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_SYNC_FILE=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_SOC_BRCMSTB=y +CONFIG_MEMORY=y +# CONFIG_ARM_PMU is not set +CONFIG_EXT4_FS=y +CONFIG_AUTOFS4_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_NTFS_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_KEYS=y +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_SEQIV=m +# CONFIG_CRYPTO_ECHAINIV is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_CCITT=m +CONFIG_CRC_ITU_T=m +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 5bee34a7ff2e..6753805e520d 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -54,6 +54,8 @@ CONFIG_SOC_VF610=y CONFIG_ARCH_KEYSTONE=y CONFIG_ARCH_MEDIATEK=y CONFIG_ARCH_MESON=y +CONFIG_ARCH_MILBEAUT=y +CONFIG_ARCH_MILBEAUT_M10V=y CONFIG_ARCH_MVEBU=y CONFIG_MACH_ARMADA_370=y CONFIG_MACH_ARMADA_375=y diff --git a/arch/arm/mach-milbeaut/Kconfig b/arch/arm/mach-milbeaut/Kconfig new file mode 100644 index 000000000000..6a576fd8521e --- /dev/null +++ b/arch/arm/mach-milbeaut/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +menuconfig ARCH_MILBEAUT + bool "Socionext Milbeaut SoCs" + depends on ARCH_MULTI_V7 + select ARM_GIC + help + This enables support for Socionext Milbeaut SoCs + +if ARCH_MILBEAUT + +config ARCH_MILBEAUT_M10V + bool "Milbeaut SC2000/M10V platform" + select ARM_ARCH_TIMER + select MILBEAUT_TIMER + select PINCTRL + select PINCTRL_MILBEAUT + help + Support for Socionext's MILBEAUT M10V based systems + +endif diff --git a/arch/arm/mach-milbeaut/Makefile b/arch/arm/mach-milbeaut/Makefile new file mode 100644 index 000000000000..ce5ea062047a --- /dev/null +++ b/arch/arm/mach-milbeaut/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SMP) += platsmp.o diff --git a/arch/arm/mach-milbeaut/platsmp.c b/arch/arm/mach-milbeaut/platsmp.c new file mode 100644 index 000000000000..591543c81399 --- /dev/null +++ b/arch/arm/mach-milbeaut/platsmp.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright: (C) 2018 Socionext Inc. + * Copyright: (C) 2015 Linaro Ltd. + */ + +#include <linux/cpu_pm.h> +#include <linux/irqchip/arm-gic.h> +#include <linux/of_address.h> +#include <linux/suspend.h> + +#include <asm/cacheflush.h> +#include <asm/cp15.h> +#include <asm/idmap.h> +#include <asm/smp_plat.h> +#include <asm/suspend.h> + +#define M10V_MAX_CPU 4 +#define KERNEL_UNBOOT_FLAG 0x12345678 + +static void __iomem *m10v_smp_base; + +static int m10v_boot_secondary(unsigned int l_cpu, struct task_struct *idle) +{ + unsigned int mpidr, cpu, cluster; + + if (!m10v_smp_base) + return -ENXIO; + + mpidr = cpu_logical_map(l_cpu); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + + if (cpu >= M10V_MAX_CPU) + return -EINVAL; + + pr_info("%s: cpu %u l_cpu %u cluster %u\n", + __func__, cpu, l_cpu, cluster); + + writel(__pa_symbol(secondary_startup), m10v_smp_base + cpu * 4); + arch_send_wakeup_ipi_mask(cpumask_of(l_cpu)); + + return 0; +} + +static void m10v_smp_init(unsigned int max_cpus) +{ + unsigned int mpidr, cpu, cluster; + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "socionext,milbeaut-smp-sram"); + if (!np) + return; + + m10v_smp_base = of_iomap(np, 0); + if (!m10v_smp_base) + return; + + mpidr = read_cpuid_mpidr(); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + pr_info("MCPM boot on cpu_%u cluster_%u\n", cpu, cluster); + + for (cpu = 0; cpu < M10V_MAX_CPU; cpu++) + writel(KERNEL_UNBOOT_FLAG, m10v_smp_base + cpu * 4); +} + +static void m10v_cpu_die(unsigned int l_cpu) +{ + gic_cpu_if_down(0); + v7_exit_coherency_flush(louis); + wfi(); +} + +static int m10v_cpu_kill(unsigned int l_cpu) +{ + unsigned int mpidr, cpu; + + mpidr = cpu_logical_map(l_cpu); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + + writel(KERNEL_UNBOOT_FLAG, m10v_smp_base + cpu * 4); + + return 1; +} + +static struct smp_operations m10v_smp_ops __initdata = { + .smp_prepare_cpus = m10v_smp_init, + .smp_boot_secondary = m10v_boot_secondary, + .cpu_die = m10v_cpu_die, + .cpu_kill = m10v_cpu_kill, +}; +CPU_METHOD_OF_DECLARE(m10v_smp, "socionext,milbeaut-m10v-smp", &m10v_smp_ops); + +static int m10v_pm_valid(suspend_state_t state) +{ + return (state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM); +} + +typedef void (*phys_reset_t)(unsigned long); +static phys_reset_t phys_reset; + +static int m10v_die(unsigned long arg) +{ + setup_mm_for_reboot(); + asm("wfi"); + /* Boot just like a secondary */ + phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); + phys_reset(virt_to_phys(cpu_resume)); + + return 0; +} + +static int m10v_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + asm("wfi"); + break; + case PM_SUSPEND_MEM: + cpu_pm_enter(); + cpu_suspend(0, m10v_die); + cpu_pm_exit(); + break; + } + return 0; +} + +static const struct platform_suspend_ops m10v_pm_ops = { + .valid = m10v_pm_valid, + .enter = m10v_pm_enter, +}; + +struct clk *m10v_clclk_register(struct device *cpu_dev); + +static int __init m10v_pm_init(void) +{ + if (of_machine_is_compatible("socionext,milbeaut-evb")) + suspend_set_ops(&m10v_pm_ops); + + return 0; +} +late_initcall(m10v_pm_init); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a9e26f6a81a1..9101b8fde93c 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -634,4 +634,13 @@ config GX6605S_TIMER help This option enables support for gx6605s SOC's timer. +config MILBEAUT_TIMER + bool "Milbeaut timer driver" if COMPILE_TEST + depends on OF + depends on ARM + select TIMER_OF + select CLKSRC_MMIO + help + Enables the support for Milbeaut timer driver. + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index cdd210ff89ea..6f2543bd5fdb 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER) += timer-owl.o +obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o obj-$(CONFIG_RDA_TIMER) += timer-rda.o diff --git a/drivers/clocksource/timer-milbeaut.c b/drivers/clocksource/timer-milbeaut.c new file mode 100644 index 000000000000..f2019a88e3ee --- /dev/null +++ b/drivers/clocksource/timer-milbeaut.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Socionext Inc. + */ + +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqreturn.h> +#include <linux/sched_clock.h> +#include "timer-of.h" + +#define MLB_TMR_TMCSR_OFS 0x0 +#define MLB_TMR_TMR_OFS 0x4 +#define MLB_TMR_TMRLR1_OFS 0x8 +#define MLB_TMR_TMRLR2_OFS 0xc +#define MLB_TMR_REGSZPCH 0x10 + +#define MLB_TMR_TMCSR_OUTL BIT(5) +#define MLB_TMR_TMCSR_RELD BIT(4) +#define MLB_TMR_TMCSR_INTE BIT(3) +#define MLB_TMR_TMCSR_UF BIT(2) +#define MLB_TMR_TMCSR_CNTE BIT(1) +#define MLB_TMR_TMCSR_TRG BIT(0) + +#define MLB_TMR_TMCSR_CSL_DIV2 0 +#define MLB_TMR_DIV_CNT 2 + +#define MLB_TMR_SRC_CH (1) +#define MLB_TMR_EVT_CH (0) + +#define MLB_TMR_SRC_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_SRC_CH) +#define MLB_TMR_EVT_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_EVT_CH) + +#define MLB_TMR_SRC_TMCSR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMCSR_OFS) +#define MLB_TMR_SRC_TMR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMR_OFS) +#define MLB_TMR_SRC_TMRLR1_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR1_OFS) +#define MLB_TMR_SRC_TMRLR2_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR2_OFS) + +#define MLB_TMR_EVT_TMCSR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMCSR_OFS) +#define MLB_TMR_EVT_TMR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMR_OFS) +#define MLB_TMR_EVT_TMRLR1_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR1_OFS) +#define MLB_TMR_EVT_TMRLR2_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR2_OFS) + +#define MLB_TIMER_RATING 500 + +static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *clk = dev_id; + struct timer_of *to = to_timer_of(clk); + u32 val; + + val = readl_relaxed(timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + val &= ~MLB_TMR_TMCSR_UF; + writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + + clk->event_handler(clk); + + return IRQ_HANDLED; +} + +static int mlb_set_state_periodic(struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + u32 val = MLB_TMR_TMCSR_CSL_DIV2; + + writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + + writel_relaxed(to->of_clk.period, timer_of_base(to) + + MLB_TMR_EVT_TMRLR1_OFS); + val |= MLB_TMR_TMCSR_RELD | MLB_TMR_TMCSR_CNTE | + MLB_TMR_TMCSR_TRG | MLB_TMR_TMCSR_INTE; + writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + return 0; +} + +static int mlb_set_state_oneshot(struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + u32 val = MLB_TMR_TMCSR_CSL_DIV2; + + writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + return 0; +} + +static int mlb_clkevt_next_event(unsigned long event, + struct clock_event_device *clk) +{ + struct timer_of *to = to_timer_of(clk); + + writel_relaxed(event, timer_of_base(to) + MLB_TMR_EVT_TMRLR1_OFS); + writel_relaxed(MLB_TMR_TMCSR_CSL_DIV2 | + MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_INTE | + MLB_TMR_TMCSR_TRG, timer_of_base(to) + + MLB_TMR_EVT_TMCSR_OFS); + return 0; +} + +static int mlb_config_clock_source(struct timer_of *to) +{ + writel_relaxed(0, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS); + writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMR_OFS); + writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR1_OFS); + writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR2_OFS); + writel_relaxed(BIT(4) | BIT(1) | BIT(0), timer_of_base(to) + + MLB_TMR_SRC_TMCSR_OFS); + return 0; +} + +static int mlb_config_clock_event(struct timer_of *to) +{ + writel_relaxed(0, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); + return 0; +} + +static struct timer_of to = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, + + .clkevt = { + .name = "mlb-clkevt", + .rating = MLB_TIMER_RATING, + .cpumask = cpu_possible_mask, + .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_ONESHOT, + .set_state_oneshot = mlb_set_state_oneshot, + .set_state_periodic = mlb_set_state_periodic, + .set_next_event = mlb_clkevt_next_event, + }, + + .of_irq = { + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = mlb_timer_interrupt, + }, +}; + +static u64 notrace mlb_timer_sched_read(void) +{ + return ~readl_relaxed(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS); +} + +static int __init mlb_timer_init(struct device_node *node) +{ + int ret; + unsigned long rate; + + ret = timer_of_init(node, &to); + if (ret) + return ret; + + rate = timer_of_rate(&to) / MLB_TMR_DIV_CNT; + mlb_config_clock_source(&to); + clocksource_mmio_init(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS, + node->name, rate, MLB_TIMER_RATING, 32, + clocksource_mmio_readl_down); + sched_clock_register(mlb_timer_sched_read, 32, rate); + mlb_config_clock_event(&to); + clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), 15, + 0xffffffff); + return 0; +} +TIMER_OF_DECLARE(mlb_peritimer, "socionext,milbeaut-timer", + mlb_timer_init); |