diff options
63 files changed, 938 insertions, 1117 deletions
diff --git a/Documentation/arm/stm32/overview.txt b/Documentation/arm/stm32/overview.txt new file mode 100644 index 000000000000..09aed5588d7c --- /dev/null +++ b/Documentation/arm/stm32/overview.txt @@ -0,0 +1,32 @@ + STM32 ARM Linux Overview + ======================== + +Introduction +------------ + + The STMicroelectronics family of Cortex-M based MCUs are supported by the + 'STM32' platform of ARM Linux. Currently only the STM32F429 is supported. + + +Configuration +------------- + + A generic configuration is provided for STM32 family, and can be used as the + default by + make stm32_defconfig + +Layout +------ + + All the files for multiple machine families are located in the platform code + contained in arch/arm/mach-stm32 + + There is a generic board board-dt.c in the mach folder which support + Flattened Device Tree, which means, it works with any compatible board with + Device Trees. + + +Document Author +--------------- + + Maxime Coquelin <mcoquelin.stm32@gmail.com> diff --git a/Documentation/arm/stm32/stm32f429-overview.txt b/Documentation/arm/stm32/stm32f429-overview.txt new file mode 100644 index 000000000000..5206822bd8ef --- /dev/null +++ b/Documentation/arm/stm32/stm32f429-overview.txt @@ -0,0 +1,22 @@ + STM32F429 Overview + ================== + + Introduction + ------------ + The STM32F429 is a Cortex-M4 MCU aimed at various applications. + It features: + - ARM Cortex-M4 up to 180MHz with FPU + - 2MB internal Flash Memory + - External memory support through FMC controller (PSRAM, SDRAM, NOR, NAND) + - I2C, SPI, SAI, CAN, USB OTG, Ethernet controllers + - LCD controller & Camera interface + - Cryptographic processor + + Resources + --------- + Datasheet and reference manual are publicly available on ST website: + - http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN1806?ecmp=stm32f429-439_pron_pr-ces2014_nov2013 + + Document Author + --------------- + Maxime Coquelin <mcoquelin.stm32@gmail.com> diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 6aa331d11c5e..d6b794cef0b8 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -188,6 +188,7 @@ nodes to be present and contain the properties described below. # On ARM 32-bit systems this property is optional and can be one of: "allwinner,sun6i-a31" + "allwinner,sun8i-a23" "arm,psci" "brcm,brahma-b15" "marvell,armada-375-smp" diff --git a/MAINTAINERS b/MAINTAINERS index c5300741f933..2985fc0c85d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1189,6 +1189,12 @@ M: Lennert Buytenhek <kernel@wantstofly.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained +ARM/LPC18XX ARCHITECTURE +M: Joachim Eastwood <manabian@gmail.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +N: lpc18xx + ARM/MAGICIAN MACHINE SUPPORT M: Philipp Zabel <philipp.zabel@gmail.com> S: Maintained @@ -1485,6 +1491,14 @@ F: drivers/usb/host/ehci-st.c F: drivers/usb/host/ohci-st.c F: drivers/ata/ahci_st.c +ARM/STM32 ARCHITECTURE +M: Maxime Coquelin <mcoquelin.stm32@gmail.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcoquelin/stm32.git +N: stm32 +F: drivers/clocksource/armv7m_systick.c + ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT M: Lennert Buytenhek <kernel@wantstofly.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1531,6 +1545,13 @@ F: drivers/rtc/rtc-ab3100.c F: drivers/rtc/rtc-coh901331.c T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git +ARM/UNIPHIER ARCHITECTURE +M: Masahiro Yamada <yamada.masahiro@socionext.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-uniphier/ +N: uniphier + ARM/Ux500 ARM ARCHITECTURE M: Linus Walleij <linus.walleij@linaro.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1608,6 +1629,15 @@ S: Maintained F: arch/arm/mach-pxa/z2.c F: arch/arm/mach-pxa/include/mach/z2.h +ARM/ZTE ARCHITECTURE +M: Jun Nie <jun.nie@linaro.org> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-zx/ +F: drivers/clk/zte/ +F: Documentation/devicetree/bindings/arm/zte.txt +F: Documentation/devicetree/bindings/clock/zx296702-clk.txt + ARM/ZYNQ ARCHITECTURE M: Michal Simek <michal.simek@xilinx.com> R: Sören Brinkmann <soren.brinkmann@xilinx.com> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 45df48ba0b12..80a2a14df604 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -586,6 +586,26 @@ config ARCH_W90X900 <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller> +config ARCH_LPC18XX + bool "NXP LPC18xx/LPC43xx" + depends on !MMU + select ARCH_HAS_RESET_CONTROLLER + select ARCH_REQUIRE_GPIOLIB + select ARM_AMBA + select ARM_NVIC + select AUTO_ZRELADDR + select CLKSRC_LPC32XX + select COMMON_CLK + select CPU_V7M + select GENERIC_CLOCKEVENTS + select NO_IOPORT_MAP + select PINCTRL + select SPARSE_IRQ + select USE_OF + help + Support for NXP's LPC18xx Cortex-M3 and LPC43xx Cortex-M4 + high performance microcontrollers. + config ARCH_LPC32XX bool "NXP LPC32XX" select ARCH_REQUIRE_GPIOLIB @@ -606,6 +626,7 @@ config ARCH_PXA select ARCH_REQUIRE_GPIOLIB select ARM_CPU_SUSPEND if PM select AUTO_ZRELADDR + select COMMON_CLK select CLKDEV_LOOKUP select CLKSRC_MMIO select CLKSRC_OF @@ -757,6 +778,24 @@ config ARCH_OMAP1 help Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx) +config ARCH_STM32 + bool "STMicrolectronics STM32" + depends on !MMU + select ARCH_HAS_RESET_CONTROLLER + select ARM_NVIC + select ARMV7M_SYSTICK + select AUTO_ZRELADDR + select CLKSRC_OF + select COMMON_CLK + select CPU_V7M + select GENERIC_CLOCKEVENTS + select NO_IOPORT_MAP + select RESET_CONTROLLER + select SPARSE_IRQ + select USE_OF + help + Support for STMicroelectronics STM32 processors. + endchoice menu "Multiple platform selection" @@ -937,6 +976,8 @@ source "arch/arm/mach-tegra/Kconfig" source "arch/arm/mach-u300/Kconfig" +source "arch/arm/mach-uniphier/Kconfig" + source "arch/arm/mach-ux500/Kconfig" source "arch/arm/mach-versatile/Kconfig" @@ -948,6 +989,8 @@ source "arch/arm/mach-vt8500/Kconfig" source "arch/arm/mach-w90x900/Kconfig" +source "arch/arm/mach-zx/Kconfig" + source "arch/arm/mach-zynq/Kconfig" # Definitions to make life easier diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0c12ffb155a2..2ea7f564ad98 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -433,6 +433,14 @@ choice Say Y here if you want kernel low-level debugging support on KS8695. + config DEBUG_LPC18XX_UART0 + bool "Kernel low-level debugging via LPC18xx/43xx UART0" + depends on ARCH_LPC18XX + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on NXP LPC18xx/43xx UART0. + config DEBUG_MESON_UARTAO bool "Kernel low-level debugging via Meson6 UARTAO" depends on ARCH_MESON @@ -908,13 +916,22 @@ choice on SA-11x0 UART ports. The kernel will check for the first enabled UART in a sequence 3-1-2. - config DEBUG_SOCFPGA_UART + config DEBUG_SOCFPGA_UART0 + depends on ARCH_SOCFPGA + bool "Use SOCFPGA UART0 for low-level debug" + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on SOCFPGA(Cyclone 5 and Arria 5) based platforms. + + config DEBUG_SOCFPGA_UART1 depends on ARCH_SOCFPGA - bool "Use SOCFPGA UART for low-level debug" + bool "Use SOCFPGA UART1 for low-level debug" select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support - on SOCFPGA based platforms. + on SOCFPGA(Arria 10) based platforms. + config DEBUG_SUN9I_UART0 bool "Kernel low-level debugging messages via sun9i UART0" @@ -1157,6 +1174,18 @@ choice For more details about semihosting, please see chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd. + config DEBUG_ZTE_ZX + bool "Use ZTE ZX UART" + select DEBUG_UART_PL01X + depends on ARCH_ZX + help + Say Y here if you are enabling ZTE ZX296702 SOC and need + debug uart support. + + This option is preferred over the platform specific + options; the platform specific options are deprecated + and will be soon removed. + config DEBUG_LL_UART_8250 bool "Kernel low-level debugging via 8250 UART" help @@ -1337,6 +1366,7 @@ config DEBUG_UART_PHYS default 0x02531000 if DEBUG_KEYSTONE_UART1 default 0x03010fe0 if ARCH_RPC default 0x07000000 if DEBUG_SUN9I_UART0 + default 0x09405000 if DEBUG_ZTE_ZX default 0x10009000 if DEBUG_REALVIEW_STD_PORT || \ DEBUG_VEXPRESS_UART0_CA9 default 0x1010c000 if DEBUG_REALVIEW_PB1176_PORT @@ -1359,6 +1389,7 @@ config DEBUG_UART_PHYS default 0x20201000 if DEBUG_BCM2835 default 0x3e000000 if DEBUG_BCM_KONA_UART default 0x4000e400 if DEBUG_LL_UART_EFM32 + default 0x40081000 if DEBUG_LPC18XX_UART0 default 0x40090000 if ARCH_LPC32XX default 0x40100000 if DEBUG_PXA_UART1 default 0x42000000 if ARCH_GEMINI @@ -1407,7 +1438,8 @@ config DEBUG_UART_PHYS default 0xfd883000 if DEBUG_ALPINE_UART0 default 0xfe800000 if ARCH_IOP32X default 0xff690000 if DEBUG_RK32_UART2 - default 0xffc02000 if DEBUG_SOCFPGA_UART + default 0xffc02000 if DEBUG_SOCFPGA_UART0 + default 0xffc02100 if DEBUG_SOCFPGA_UART1 default 0xffd82340 if ARCH_IOP13XX default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0 default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2 @@ -1466,6 +1498,7 @@ config DEBUG_UART_VIRT default 0xfb009000 if DEBUG_REALVIEW_STD_PORT default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT default 0xfc40ab00 if DEBUG_BRCMSTB_UART + default 0xfc705000 if DEBUG_ZTE_ZX default 0xfcfe8600 if DEBUG_UART_BCM63XX default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX default 0xfd000000 if ARCH_SPEAR13XX @@ -1485,7 +1518,8 @@ config DEBUG_UART_VIRT default 0xfeb26000 if DEBUG_RK3X_UART1 default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 default 0xfeb31000 if DEBUG_KEYSTONE_UART1 - default 0xfec02000 if DEBUG_SOCFPGA_UART + default 0xfec02000 if DEBUG_SOCFPGA_UART0 + default 0xfec02100 if DEBUG_SOCFPGA_UART1 default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE default 0xfec10000 if DEBUG_SIRFATLAS7_UART0 @@ -1530,8 +1564,9 @@ config DEBUG_UART_8250_WORD bool "Use 32-bit accesses for 8250 UART" depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 depends on DEBUG_UART_8250_SHIFT >= 2 - default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \ - ARCH_KEYSTONE || DEBUG_ALPINE_UART0 || \ + default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART0 || \ + DEBUG_SOCFPGA_UART1 || ARCH_KEYSTONE || \ + DEBUG_ALPINE_UART0 || \ DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \ DEBUG_DAVINCI_DA8XX_UART2 || \ DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 || \ @@ -1562,7 +1597,7 @@ config UNCOMPRESS_INCLUDE string default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ PLAT_SAMSUNG || ARCH_EFM32 || \ - ARCH_SHMOBILE_LEGACY + ARCH_SHMOBILE_LEGACY || ARCH_LPC18XX default "mach/uncompress.h" config EARLY_PRINTK diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 985227cbbd1b..2a4fae7e9c44 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -167,6 +167,7 @@ machine-$(CONFIG_ARCH_IOP33X) += iop33x machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx machine-$(CONFIG_ARCH_KEYSTONE) += keystone machine-$(CONFIG_ARCH_KS8695) += ks8695 +machine-$(CONFIG_ARCH_LPC18XX) += lpc18xx machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx machine-$(CONFIG_ARCH_MESON) += meson machine-$(CONFIG_ARCH_MMP) += mmp @@ -196,14 +197,17 @@ machine-$(CONFIG_ARCH_SHMOBILE) += shmobile machine-$(CONFIG_ARCH_SIRF) += prima2 machine-$(CONFIG_ARCH_SOCFPGA) += socfpga machine-$(CONFIG_ARCH_STI) += sti +machine-$(CONFIG_ARCH_STM32) += stm32 machine-$(CONFIG_ARCH_SUNXI) += sunxi machine-$(CONFIG_ARCH_TEGRA) += tegra machine-$(CONFIG_ARCH_U300) += u300 machine-$(CONFIG_ARCH_U8500) += ux500 +machine-$(CONFIG_ARCH_UNIPHIER) += uniphier machine-$(CONFIG_ARCH_VERSATILE) += versatile machine-$(CONFIG_ARCH_VEXPRESS) += vexpress machine-$(CONFIG_ARCH_VT8500) += vt8500 machine-$(CONFIG_ARCH_W90X900) += w90x900 +machine-$(CONFIG_ARCH_ZX) += zx machine-$(CONFIG_ARCH_ZYNQ) += zynq machine-$(CONFIG_PLAT_SPEAR) += spear diff --git a/arch/arm/include/debug/8250.S b/arch/arm/include/debug/8250.S index 7a2baf913aa0..7f7446f6f806 100644 --- a/arch/arm/include/debug/8250.S +++ b/arch/arm/include/debug/8250.S @@ -16,11 +16,14 @@ #ifdef CONFIG_DEBUG_UART_8250_WORD .macro store, rd, rx:vararg + ARM_BE8(rev \rd, \rd) str \rd, \rx + ARM_BE8(rev \rd, \rd) .endm .macro load, rd, rx:vararg ldr \rd, \rx + ARM_BE8(rev \rd, \rd) .endm #else .macro store, rd, rx:vararg diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S index 92ef808a2337..f7d8323cefcc 100644 --- a/arch/arm/include/debug/pl01x.S +++ b/arch/arm/include/debug/pl01x.S @@ -12,6 +12,13 @@ */ #include <linux/amba/serial.h> +#ifdef CONFIG_DEBUG_ZTE_ZX +#undef UART01x_DR +#undef UART01x_FR +#define UART01x_DR 0x04 +#define UART01x_FR 0x14 +#endif + #ifdef CONFIG_DEBUG_UART_PHYS .macro addruart, rp, rv, tmp ldr \rp, =CONFIG_DEBUG_UART_PHYS diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c index 70f2f3925f0e..0f7b9eac3d15 100644 --- a/arch/arm/mach-bcm/board_bcm2835.c +++ b/arch/arm/mach-bcm/board_bcm2835.c @@ -12,7 +12,6 @@ * GNU General Public License for more details. */ -#include <linux/delay.h> #include <linux/init.h> #include <linux/irqchip.h> #include <linux/of_address.h> @@ -22,97 +21,10 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#define PM_RSTC 0x1c -#define PM_RSTS 0x20 -#define PM_WDOG 0x24 - -#define PM_PASSWORD 0x5a000000 -#define PM_RSTC_WRCFG_MASK 0x00000030 -#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -#define PM_RSTS_HADWRH_SET 0x00000040 - -#define BCM2835_PERIPH_PHYS 0x20000000 -#define BCM2835_PERIPH_VIRT 0xf0000000 -#define BCM2835_PERIPH_SIZE SZ_16M - -static void __iomem *wdt_regs; - -/* - * The machine restart method can be called from an atomic context so we won't - * be able to ioremap the regs then. - */ -static void bcm2835_setup_restart(void) -{ - struct device_node *np = of_find_compatible_node(NULL, NULL, - "brcm,bcm2835-pm-wdt"); - if (WARN(!np, "unable to setup watchdog restart")) - return; - - wdt_regs = of_iomap(np, 0); - WARN(!wdt_regs, "failed to remap watchdog regs"); -} - -static void bcm2835_restart(enum reboot_mode mode, const char *cmd) -{ - u32 val; - - if (!wdt_regs) - return; - - /* use a timeout of 10 ticks (~150us) */ - writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG); - val = readl_relaxed(wdt_regs + PM_RSTC); - val &= ~PM_RSTC_WRCFG_MASK; - val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; - writel_relaxed(val, wdt_regs + PM_RSTC); - - /* No sleeping, possibly atomic. */ - mdelay(1); -} - -/* - * We can't really power off, but if we do the normal reset scheme, and - * indicate to bootcode.bin not to reboot, then most of the chip will be - * powered off. - */ -static void bcm2835_power_off(void) -{ - u32 val; - - /* - * We set the watchdog hard reset bit here to distinguish this reset - * from the normal (full) reset. bootcode.bin will not reboot after a - * hard reset. - */ - val = readl_relaxed(wdt_regs + PM_RSTS); - val &= ~PM_RSTC_WRCFG_MASK; - val |= PM_PASSWORD | PM_RSTS_HADWRH_SET; - writel_relaxed(val, wdt_regs + PM_RSTS); - - /* Continue with normal reset mechanism */ - bcm2835_restart(REBOOT_HARD, ""); -} - -static struct map_desc io_map __initdata = { - .virtual = BCM2835_PERIPH_VIRT, - .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), - .length = BCM2835_PERIPH_SIZE, - .type = MT_DEVICE -}; - -static void __init bcm2835_map_io(void) -{ - iotable_init(&io_map, 1); -} - static void __init bcm2835_init(void) { int ret; - bcm2835_setup_restart(); - if (wdt_regs) - pm_power_off = bcm2835_power_off; - bcm2835_init_clocks(); ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, @@ -129,9 +41,6 @@ static const char * const bcm2835_compat[] = { }; DT_MACHINE_START(BCM2835, "BCM2835") - .map_io = bcm2835_map_io, - .init_irq = irqchip_init, .init_machine = bcm2835_init, - .restart = bcm2835_restart, .dt_compat = bcm2835_compat MACHINE_END diff --git a/arch/arm/mach-lpc18xx/Makefile b/arch/arm/mach-lpc18xx/Makefile new file mode 100644 index 000000000000..bd0b7b5d6e9d --- /dev/null +++ b/arch/arm/mach-lpc18xx/Makefile @@ -0,0 +1 @@ +obj-y += board-dt.o diff --git a/arch/arm/mach-lpc18xx/Makefile.boot b/arch/arm/mach-lpc18xx/Makefile.boot new file mode 100644 index 000000000000..eacfc3f5c33e --- /dev/null +++ b/arch/arm/mach-lpc18xx/Makefile.boot @@ -0,0 +1,3 @@ +# 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 . diff --git a/arch/arm/mach-lpc18xx/board-dt.c b/arch/arm/mach-lpc18xx/board-dt.c new file mode 100644 index 000000000000..fdcee78d1bc4 --- /dev/null +++ b/arch/arm/mach-lpc18xx/board-dt.c @@ -0,0 +1,22 @@ +/* + * Device Tree board file for NXP LPC18xx/43xx + * + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <asm/mach/arch.h> + +static const char *const lpc18xx_43xx_compat[] __initconst = { + "nxp,lpc1850", + "nxp,lpc4350", + "nxp,lpc4370", + NULL +}; + +DT_MACHINE_START(LPC18XXDT, "NXP LPC18xx/43xx (Device Tree)") + .dt_compat = lpc18xx_43xx_compat, +MACHINE_END diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 4087d334ecdf..2ceed407eda9 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -3,16 +3,15 @@ # # Common support (must be linked before board specific support) -obj-y += clock.o devices.o generic.o irq.o \ - reset.o +obj-y += devices.o generic.o irq.o reset.o obj-$(CONFIG_PM) += pm.o sleep.o standby.o # Generic drivers that other drivers may depend upon # SoC-specific code -obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o -obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o -obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o +obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o +obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa2xx.o pxa27x.o +obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o obj-$(CONFIG_CPU_PXA300) += pxa300.o obj-$(CONFIG_CPU_PXA320) += pxa320.o obj-$(CONFIG_CPU_PXA930) += pxa930.o diff --git a/arch/arm/mach-pxa/clock-pxa2xx.c b/arch/arm/mach-pxa/clock-pxa2xx.c deleted file mode 100644 index 9ee2ad6a0a07..000000000000 --- a/arch/arm/mach-pxa/clock-pxa2xx.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/clock-pxa2xx.c - * - * 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. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/syscore_ops.h> - -#include <mach/pxa2xx-regs.h> - -#include "clock.h" - -void clk_pxa2xx_cken_enable(struct clk *clk) -{ - CKEN |= 1 << clk->cken; -} - -void clk_pxa2xx_cken_disable(struct clk *clk) -{ - CKEN &= ~(1 << clk->cken); -} - -const struct clkops clk_pxa2xx_cken_ops = { - .enable = clk_pxa2xx_cken_enable, - .disable = clk_pxa2xx_cken_disable, -}; - -#ifdef CONFIG_PM -static uint32_t saved_cken; - -static int pxa2xx_clock_suspend(void) -{ - saved_cken = CKEN; - return 0; -} - -static void pxa2xx_clock_resume(void) -{ - CKEN = saved_cken; -} -#else -#define pxa2xx_clock_suspend NULL -#define pxa2xx_clock_resume NULL -#endif - -struct syscore_ops pxa2xx_clock_syscore_ops = { - .suspend = pxa2xx_clock_suspend, - .resume = pxa2xx_clock_resume, -}; diff --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c deleted file mode 100644 index d4e9499832dc..000000000000 --- a/arch/arm/mach-pxa/clock-pxa3xx.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/clock-pxa3xx.c - * - * 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. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/syscore_ops.h> - -#include <mach/smemc.h> -#include <mach/pxa3xx-regs.h> - -#include "clock.h" - -/* Crystal clock: 13MHz */ -#define BASE_CLK 13000000 - -/* Ring Oscillator Clock: 60MHz */ -#define RO_CLK 60000000 - -#define ACCR_D0CS (1 << 26) -#define ACCR_PCCE (1 << 11) - -/* crystal frequency to HSIO bus frequency multiplier (HSS) */ -static unsigned char hss_mult[4] = { 8, 12, 16, 24 }; - -/* - * Get the clock frequency as reflected by CCSR and the turbo flag. - * We assume these values have been applied via a fcs. - * If info is not 0 we also display the current settings. - */ -unsigned int pxa3xx_get_clk_frequency_khz(int info) -{ - unsigned long acsr, xclkcfg; - unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS; - - /* Read XCLKCFG register turbo bit */ - __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg)); - t = xclkcfg & 0x1; - - acsr = ACSR; - - xl = acsr & 0x1f; - xn = (acsr >> 8) & 0x7; - hss = (acsr >> 14) & 0x3; - - XL = xl * BASE_CLK; - XN = xn * XL; - - ro = acsr & ACCR_D0CS; - - CLK = (ro) ? RO_CLK : ((t) ? XN : XL); - HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK; - - if (info) { - pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n", - RO_CLK / 1000000, (RO_CLK % 1000000) / 10000, - (ro) ? "" : "in"); - pr_info("Run Mode clock: %d.%02dMHz (*%d)\n", - XL / 1000000, (XL % 1000000) / 10000, xl); - pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n", - XN / 1000000, (XN % 1000000) / 10000, xn, - (t) ? "" : "in"); - pr_info("HSIO bus clock: %d.%02dMHz\n", - HSS / 1000000, (HSS % 1000000) / 10000); - } - - return CLK / 1000; -} - -/* - * Return the current AC97 clock frequency. - */ -static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk) -{ - unsigned long rate = 312000000; - unsigned long ac97_div; - - ac97_div = AC97_DIV; - - /* This may loose precision for some rates but won't for the - * standard 24.576MHz. - */ - rate /= (ac97_div >> 12) & 0x7fff; - rate *= (ac97_div & 0xfff); - - return rate; -} - -/* - * Return the current HSIO bus clock frequency - */ -static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk) -{ - unsigned long acsr; - unsigned int hss, hsio_clk; - - acsr = ACSR; - - hss = (acsr >> 14) & 0x3; - hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK; - - return hsio_clk; -} - -/* crystal frequency to static memory controller multiplier (SMCFS) */ -static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, }; -static unsigned int df_clkdiv[4] = { 1, 2, 4, 1 }; - -static unsigned long clk_pxa3xx_smemc_getrate(struct clk *clk) -{ - unsigned long acsr = ACSR; - unsigned long memclkcfg = __raw_readl(MEMCLKCFG); - - return BASE_CLK * smcfs_mult[(acsr >> 23) & 0x7] / - df_clkdiv[(memclkcfg >> 16) & 0x3]; -} - -void clk_pxa3xx_cken_enable(struct clk *clk) -{ - unsigned long mask = 1ul << (clk->cken & 0x1f); - - if (clk->cken < 32) - CKENA |= mask; - else if (clk->cken < 64) - CKENB |= mask; - else - CKENC |= mask; -} - -void clk_pxa3xx_cken_disable(struct clk *clk) -{ - unsigned long mask = 1ul << (clk->cken & 0x1f); - - if (clk->cken < 32) - CKENA &= ~mask; - else if (clk->cken < 64) - CKENB &= ~mask; - else - CKENC &= ~mask; -} - -const struct clkops clk_pxa3xx_cken_ops = { - .enable = clk_pxa3xx_cken_enable, - .disable = clk_pxa3xx_cken_disable, -}; - -const struct clkops clk_pxa3xx_hsio_ops = { - .enable = clk_pxa3xx_cken_enable, - .disable = clk_pxa3xx_cken_disable, - .getrate = clk_pxa3xx_hsio_getrate, -}; - -const struct clkops clk_pxa3xx_ac97_ops = { - .enable = clk_pxa3xx_cken_enable, - .disable = clk_pxa3xx_cken_disable, - .getrate = clk_pxa3xx_ac97_getrate, -}; - -const struct clkops clk_pxa3xx_smemc_ops = { - .enable = clk_pxa3xx_cken_enable, - .disable = clk_pxa3xx_cken_disable, - .getrate = clk_pxa3xx_smemc_getrate, -}; - -static void clk_pout_enable(struct clk *clk) -{ - OSCC |= OSCC_PEN; -} - -static void clk_pout_disable(struct clk *clk) -{ - OSCC &= ~OSCC_PEN; -} - -const struct clkops clk_pxa3xx_pout_ops = { - .enable = clk_pout_enable, - .disable = clk_pout_disable, -}; - -#ifdef CONFIG_PM -static uint32_t cken[2]; -static uint32_t accr; - -static int pxa3xx_clock_suspend(void) -{ - cken[0] = CKENA; - cken[1] = CKENB; - accr = ACCR; - return 0; -} - -static void pxa3xx_clock_resume(void) -{ - ACCR = accr; - CKENA = cken[0]; - CKENB = cken[1]; -} -#else -#define pxa3xx_clock_suspend NULL -#define pxa3xx_clock_resume NULL -#endif - -struct syscore_ops pxa3xx_clock_syscore_ops = { - .suspend = pxa3xx_clock_suspend, - .resume = pxa3xx_clock_resume, -}; diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c deleted file mode 100644 index 4d466102a027..000000000000 --- a/arch/arm/mach-pxa/clock.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/clock.c - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/clkdev.h> - -#include "clock.h" - -static DEFINE_SPINLOCK(clocks_lock); - -int clk_enable(struct clk *clk) -{ - unsigned long flags; - - spin_lock_irqsave(&clocks_lock, flags); - if (clk->enabled++ == 0) - clk->ops->enable(clk); - spin_unlock_irqrestore(&clocks_lock, flags); - - if (clk->delay) - udelay(clk->delay); - - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - WARN_ON(clk->enabled == 0); - - spin_lock_irqsave(&clocks_lock, flags); - if (--clk->enabled == 0) - clk->ops->disable(clk); - spin_unlock_irqrestore(&clocks_lock, flags); -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - unsigned long rate; - - rate = clk->rate; - if (clk->ops->getrate) - rate = clk->ops->getrate(clk); - - return rate; -} -EXPORT_SYMBOL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - unsigned long flags; - int ret = -EINVAL; - - if (clk->ops->setrate) { - spin_lock_irqsave(&clocks_lock, flags); - ret = clk->ops->setrate(clk, rate); - spin_unlock_irqrestore(&clocks_lock, flags); - } - - return ret; -} -EXPORT_SYMBOL(clk_set_rate); - -void clk_dummy_enable(struct clk *clk) -{ -} - -void clk_dummy_disable(struct clk *clk) -{ -} - -const struct clkops clk_dummy_ops = { - .enable = clk_dummy_enable, - .disable = clk_dummy_disable, -}; - -struct clk clk_dummy = { - .ops = &clk_dummy_ops, -}; diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h deleted file mode 100644 index 1f65d32c8d5e..000000000000 --- a/arch/arm/mach-pxa/clock.h +++ /dev/null @@ -1,80 +0,0 @@ -#include <linux/clkdev.h> -#include <linux/syscore_ops.h> - -struct clkops { - void (*enable)(struct clk *); - void (*disable)(struct clk *); - unsigned long (*getrate)(struct clk *); - int (*setrate)(struct clk *, unsigned long); -}; - -struct clk { - const struct clkops *ops; - unsigned long rate; - unsigned int cken; - unsigned int delay; - unsigned int enabled; -}; - -void clk_dummy_enable(struct clk *); -void clk_dummy_disable(struct clk *); - -extern const struct clkops clk_dummy_ops; -extern struct clk clk_dummy; - -#define INIT_CLKREG(_clk,_devname,_conname) \ - { \ - .clk = _clk, \ - .dev_id = _devname, \ - .con_id = _conname, \ - } - -#define DEFINE_CK(_name, _cken, _ops) \ -struct clk clk_##_name = { \ - .ops = _ops, \ - .cken = CKEN_##_cken, \ - } - -#define DEFINE_CLK(_name, _ops, _rate, _delay) \ -struct clk clk_##_name = { \ - .ops = _ops, \ - .rate = _rate, \ - .delay = _delay, \ - } - -#define DEFINE_PXA2_CKEN(_name, _cken, _rate, _delay) \ -struct clk clk_##_name = { \ - .ops = &clk_pxa2xx_cken_ops, \ - .rate = _rate, \ - .cken = CKEN_##_cken, \ - .delay = _delay, \ - } - -extern const struct clkops clk_pxa2xx_cken_ops; - -void clk_pxa2xx_cken_enable(struct clk *clk); -void clk_pxa2xx_cken_disable(struct clk *clk); - -extern struct syscore_ops pxa2xx_clock_syscore_ops; - -#if defined(CONFIG_PXA3xx) -#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay) \ -struct clk clk_##_name = { \ - .ops = &clk_pxa3xx_cken_ops, \ - .rate = _rate, \ - .cken = CKEN_##_cken, \ - .delay = _delay, \ - } - -extern const struct clkops clk_pxa3xx_cken_ops; -extern const struct clkops clk_pxa3xx_hsio_ops; -extern const struct clkops clk_pxa3xx_ac97_ops; -extern const struct clkops clk_pxa3xx_pout_ops; -extern const struct clkops clk_pxa3xx_smemc_ops; - -extern void clk_pxa3xx_cken_enable(struct clk *); -extern void clk_pxa3xx_cken_disable(struct clk *); - -extern struct syscore_ops pxa3xx_clock_syscore_ops; - -#endif diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index cfb864173ce3..11863be59066 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/clk-provider.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/platform_device.h> @@ -39,7 +40,6 @@ #include "devices.h" #include "generic.h" -#include "clock.h" /* Only e800 has 128MB RAM */ void __init eseries_fixup(struct tag *tags, char **cmdline) @@ -125,27 +125,9 @@ struct resource eseries_tmio_resources[] = { }; /* Some e-series hardware cannot control the 32K clock */ -static void clk_32k_dummy(struct clk *clk) -{ -} - -static const struct clkops clk_32k_dummy_ops = { - .enable = clk_32k_dummy, - .disable = clk_32k_dummy, -}; - -static struct clk tmio_dummy_clk = { - .ops = &clk_32k_dummy_ops, - .rate = 32768, -}; - -static struct clk_lookup eseries_clkregs[] = { - INIT_CLKREG(&tmio_dummy_clk, NULL, "CLK_CK32K"), -}; - static void __init eseries_register_clks(void) { - clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs)); + clk_register_fixed_rate(NULL, "CLK_CK32K", NULL, CLK_IS_ROOT, 32768); } #ifdef CONFIG_MACH_E330 @@ -683,7 +665,7 @@ static unsigned long e750_pin_config[] __initdata = { /* PC Card */ GPIO8_GPIO, /* CD0 */ GPIO44_GPIO, /* CD1 */ - GPIO11_GPIO, /* IRQ0 */ + /* GPIO11_GPIO, IRQ0 */ GPIO6_GPIO, /* IRQ1 */ GPIO27_GPIO, /* RST0 */ GPIO24_GPIO, /* RST1 */ @@ -778,6 +760,9 @@ static unsigned long e800_pin_config[] __initdata = { GPIO29_AC97_SDATA_IN_0, GPIO30_AC97_SDATA_OUT, GPIO31_AC97_SYNC, + + /* tc6393xb */ + GPIO11_3_6MHz, }; static struct w100_gen_regs e800_lcd_regs = { diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 04b013fbc98f..ec510ecf8370 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -63,6 +63,12 @@ EXPORT_SYMBOL(get_clock_tick_rate); */ void __init pxa_timer_init(void) { + if (cpu_is_pxa25x()) + pxa25x_clocks_init(); + if (cpu_is_pxa27x()) + pxa27x_clocks_init(); + if (cpu_is_pxa3xx()) + pxa3xx_clocks_init(); pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000), get_clock_tick_rate()); } diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 7a9fa1aa4e41..0b1dbb54871a 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -26,17 +26,20 @@ extern void pxa_timer_init(void); #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) #define pxa25x_handle_irq icip_handle_irq +extern int __init pxa25x_clocks_init(void); extern void __init pxa25x_init_irq(void); extern void __init pxa25x_map_io(void); extern void __init pxa26x_init_irq(void); #define pxa27x_handle_irq ichp_handle_irq +extern int __init pxa27x_clocks_init(void); extern void __init pxa27x_dt_init_irq(void); extern unsigned pxa27x_get_clk_frequency_khz(int); extern void __init pxa27x_init_irq(void); extern void __init pxa27x_map_io(void); #define pxa3xx_handle_irq ichp_handle_irq +extern int __init pxa3xx_clocks_init(void); extern void __init pxa3xx_dt_init_irq(void); extern void __init pxa3xx_init_irq(void); extern void __init pxa3xx_map_io(void); diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 89a7c06570d3..98608c5575cb 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -138,7 +138,7 @@ static int pxa_irq_map(struct irq_domain *h, unsigned int virq, return 0; } -static struct irq_domain_ops pxa_irq_ops = { +static const struct irq_domain_ops pxa_irq_ops = { .map = pxa_irq_map, .xlate = irq_domain_xlate_onecell, }; diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 4ac9ab80d24b..2d4bf1fb7312 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -57,7 +57,6 @@ #include <mach/smemc.h> #include "generic.h" -#include "clock.h" #include "devices.h" static unsigned long lubbock_pin_config[] __initdata = { @@ -102,6 +101,9 @@ static unsigned long lubbock_pin_config[] __initdata = { GPIO6_MMC_CLK, GPIO8_MMC_CS0, + /* SA1111 chip */ + GPIO11_3_6MHz, + /* wakeup */ GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, }; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 66e4a2b6316e..23a90c62ec11 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -38,187 +38,11 @@ #include "generic.h" #include "devices.h" -#include "clock.h" /* * Various clock factors driven by the CCCR register. */ -/* Crystal Frequency to Memory Frequency Multiplier (L) */ -static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, }; - -/* Memory Frequency to Run Mode Frequency Multiplier (M) */ -static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 }; - -/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */ -/* Note: we store the value N * 2 here. */ -static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 }; - -/* Crystal clock */ -#define BASE_CLK 3686400 - -/* - * Get the clock frequency as reflected by CCCR and the turbo flag. - * We assume these values have been applied via a fcs. - * If info is not 0 we also display the current settings. - */ -unsigned int pxa25x_get_clk_frequency_khz(int info) -{ - unsigned long cccr, turbo; - unsigned int l, L, m, M, n2, N; - - cccr = CCCR; - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) ); - - l = L_clk_mult[(cccr >> 0) & 0x1f]; - m = M_clk_mult[(cccr >> 5) & 0x03]; - n2 = N2_clk_mult[(cccr >> 7) & 0x07]; - - L = l * BASE_CLK; - M = m * L; - N = n2 * M / 2; - - if(info) - { - L += 5000; - printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n", - L / 1000000, (L % 1000000) / 10000, l ); - M += 5000; - printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n", - M / 1000000, (M % 1000000) / 10000, m ); - N += 5000; - printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n", - N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5, - (turbo & 1) ? "" : "in" ); - } - - return (turbo & 1) ? (N/1000) : (M/1000); -} - -static unsigned long clk_pxa25x_mem_getrate(struct clk *clk) -{ - return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK; -} - -static const struct clkops clk_pxa25x_mem_ops = { - .enable = clk_dummy_enable, - .disable = clk_dummy_disable, - .getrate = clk_pxa25x_mem_getrate, -}; - -static const struct clkops clk_pxa25x_lcd_ops = { - .enable = clk_pxa2xx_cken_enable, - .disable = clk_pxa2xx_cken_disable, - .getrate = clk_pxa25x_mem_getrate, -}; - -static unsigned long gpio12_config_32k[] = { - GPIO12_32KHz, -}; - -static unsigned long gpio12_config_gpio[] = { - GPIO12_GPIO, -}; - -static void clk_gpio12_enable(struct clk *clk) -{ - pxa2xx_mfp_config(gpio12_config_32k, 1); -} - -static void clk_gpio12_disable(struct clk *clk) -{ - pxa2xx_mfp_config(gpio12_config_gpio, 1); -} - -static const struct clkops clk_pxa25x_gpio12_ops = { - .enable = clk_gpio12_enable, - .disable = clk_gpio12_disable, -}; - -static unsigned long gpio11_config_3m6[] = { - GPIO11_3_6MHz, -}; - -static unsigned long gpio11_config_gpio[] = { - GPIO11_GPIO, -}; - -static void clk_gpio11_enable(struct clk *clk) -{ - pxa2xx_mfp_config(gpio11_config_3m6, 1); -} - -static void clk_gpio11_disable(struct clk *clk) -{ - pxa2xx_mfp_config(gpio11_config_gpio, 1); -} - -static const struct clkops clk_pxa25x_gpio11_ops = { - .enable = clk_gpio11_enable, - .disable = clk_gpio11_disable, -}; - -/* - * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz) - * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz - * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly) - */ - -/* - * PXA 2xx clock declarations. - */ -static DEFINE_PXA2_CKEN(pxa25x_hwuart, HWUART, 14745600, 1); -static DEFINE_PXA2_CKEN(pxa25x_ffuart, FFUART, 14745600, 1); -static DEFINE_PXA2_CKEN(pxa25x_btuart, BTUART, 14745600, 1); -static DEFINE_PXA2_CKEN(pxa25x_stuart, STUART, 14745600, 1); -static DEFINE_PXA2_CKEN(pxa25x_usb, USB, 47923000, 5); -static DEFINE_PXA2_CKEN(pxa25x_mmc, MMC, 19169000, 0); -static DEFINE_PXA2_CKEN(pxa25x_i2c, I2C, 31949000, 0); -static DEFINE_PXA2_CKEN(pxa25x_ssp, SSP, 3686400, 0); -static DEFINE_PXA2_CKEN(pxa25x_nssp, NSSP, 3686400, 0); -static DEFINE_PXA2_CKEN(pxa25x_assp, ASSP, 3686400, 0); -static DEFINE_PXA2_CKEN(pxa25x_pwm0, PWM0, 3686400, 0); -static DEFINE_PXA2_CKEN(pxa25x_pwm1, PWM1, 3686400, 0); -static DEFINE_PXA2_CKEN(pxa25x_ac97, AC97, 24576000, 0); -static DEFINE_PXA2_CKEN(pxa25x_i2s, I2S, 14745600, 0); -static DEFINE_PXA2_CKEN(pxa25x_ficp, FICP, 47923000, 0); - -static DEFINE_CK(pxa25x_lcd, LCD, &clk_pxa25x_lcd_ops); -static DEFINE_CLK(pxa25x_gpio11, &clk_pxa25x_gpio11_ops, 3686400, 0); -static DEFINE_CLK(pxa25x_gpio12, &clk_pxa25x_gpio12_ops, 32768, 0); -static DEFINE_CLK(pxa25x_mem, &clk_pxa25x_mem_ops, 0, 0); - -static struct clk_lookup pxa25x_clkregs[] = { - INIT_CLKREG(&clk_pxa25x_lcd, "pxa2xx-fb", NULL), - INIT_CLKREG(&clk_pxa25x_ffuart, "pxa2xx-uart.0", NULL), - INIT_CLKREG(&clk_pxa25x_btuart, "pxa2xx-uart.1", NULL), - INIT_CLKREG(&clk_pxa25x_stuart, "pxa2xx-uart.2", NULL), - INIT_CLKREG(&clk_pxa25x_usb, "pxa25x-udc", NULL), - INIT_CLKREG(&clk_pxa25x_mmc, "pxa2xx-mci.0", NULL), - INIT_CLKREG(&clk_pxa25x_i2c, "pxa2xx-i2c.0", NULL), - INIT_CLKREG(&clk_pxa25x_ssp, "pxa25x-ssp.0", NULL), - INIT_CLKREG(&clk_pxa25x_nssp, "pxa25x-nssp.1", NULL), - INIT_CLKREG(&clk_pxa25x_assp, "pxa25x-nssp.2", NULL), - INIT_CLKREG(&clk_pxa25x_pwm0, "pxa25x-pwm.0", NULL), - INIT_CLKREG(&clk_pxa25x_pwm1, "pxa25x-pwm.1", NULL), - INIT_CLKREG(&clk_pxa25x_i2s, "pxa2xx-i2s", NULL), - INIT_CLKREG(&clk_pxa25x_stuart, "pxa2xx-ir", "UARTCLK"), - INIT_CLKREG(&clk_pxa25x_ficp, "pxa2xx-ir", "FICPCLK"), - INIT_CLKREG(&clk_pxa25x_ac97, NULL, "AC97CLK"), - INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"), - INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"), - INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL), -#ifdef CONFIG_CPU_PXA26x - INIT_CLKREG(&clk_dummy, "pxa26x-gpio", NULL), -#else - INIT_CLKREG(&clk_dummy, "pxa25x-gpio", NULL), -#endif - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), -}; - -static struct clk_lookup pxa25x_hwuart_clkreg = - INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL); - #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x @@ -374,8 +198,6 @@ static int __init pxa25x_init(void) reset_status = RCSR; - clkdev_add_table(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs)); - if ((ret = pxa_init_dma(IRQ_DMA, 16))) return ret; @@ -383,7 +205,6 @@ static int __init pxa25x_init(void) register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa2xx_mfp_syscore_ops); - register_syscore_ops(&pxa2xx_clock_syscore_ops); pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info); ret = platform_add_devices(pxa25x_devices, @@ -392,10 +213,6 @@ static int __init pxa25x_init(void) return ret; } - /* Only add HWUART for PXA255/26x; PXA210/250 do not have it. */ - if (cpu_is_pxa255()) - clkdev_add(&pxa25x_hwuart_clkreg); - return ret; } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index af423a48c2e3..b5abdeb5bb2d 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -37,7 +37,8 @@ #include "generic.h" #include "devices.h" -#include "clock.h" +#include <linux/clk-provider.h> +#include <linux/clkdev.h> void pxa27x_clear_otgph(void) { @@ -73,174 +74,6 @@ void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio) } EXPORT_SYMBOL_GPL(pxa27x_configure_ac97reset); -/* Crystal clock: 13MHz */ -#define BASE_CLK 13000000 - -/* - * Get the clock frequency as reflected by CCSR and the turbo flag. - * We assume these values have been applied via a fcs. - * If info is not 0 we also display the current settings. - */ -unsigned int pxa27x_get_clk_frequency_khz(int info) -{ - unsigned long ccsr, clkcfg; - unsigned int l, L, m, M, n2, N, S; - int cccr_a, t, ht, b; - - ccsr = CCSR; - cccr_a = CCCR & (1 << 25); - - /* Read clkcfg register: it has turbo, b, half-turbo (and f) */ - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) ); - t = clkcfg & (1 << 0); - ht = clkcfg & (1 << 2); - b = clkcfg & (1 << 3); - - l = ccsr & 0x1f; - n2 = (ccsr>>7) & 0xf; - m = (l <= 10) ? 1 : (l <= 20) ? 2 : 4; - - L = l * BASE_CLK; - N = (L * n2) / 2; - M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2)); - S = (b) ? L : (L/2); - - if (info) { - printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n", - L / 1000000, (L % 1000000) / 10000, l ); - printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n", - N / 1000000, (N % 1000000)/10000, n2 / 2, (n2 % 2)*5, - (t) ? "" : "in" ); - printk( KERN_INFO "Memory clock: %d.%02dMHz (/%d)\n", - M / 1000000, (M % 1000000) / 10000, m ); - printk( KERN_INFO "System bus clock: %d.%02dMHz \n", - S / 1000000, (S % 1000000) / 10000 ); - } - - return (t) ? (N/1000) : (L/1000); -} - -/* - * Return the current mem clock frequency as reflected by CCCR[A], B, and L - */ -static unsigned long clk_pxa27x_mem_getrate(struct clk *clk) -{ - unsigned long ccsr, clkcfg; - unsigned int l, L, m, M; - int cccr_a, b; - - ccsr = CCSR; - cccr_a = CCCR & (1 << 25); - - /* Read clkcfg register: it has turbo, b, half-turbo (and f) */ - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) ); - b = clkcfg & (1 << 3); - - l = ccsr & 0x1f; - m = (l <= 10) ? 1 : (l <= 20) ? 2 : 4; - - L = l * BASE_CLK; - M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2)); - - return M; -} - -static const struct clkops clk_pxa27x_mem_ops = { - .enable = clk_dummy_enable, - .disable = clk_dummy_disable, - .getrate = clk_pxa27x_mem_getrate, -}; - -/* - * Return the current LCD clock frequency in units of 10kHz as - */ -static unsigned int pxa27x_get_lcdclk_frequency_10khz(void) -{ - unsigned long ccsr; - unsigned int l, L, k, K; - - ccsr = CCSR; - - l = ccsr & 0x1f; - k = (l <= 7) ? 1 : (l <= 16) ? 2 : 4; - - L = l * BASE_CLK; - K = L / k; - - return (K / 10000); -} - -static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk) -{ - return pxa27x_get_lcdclk_frequency_10khz() * 10000; -} - -static const struct clkops clk_pxa27x_lcd_ops = { - .enable = clk_pxa2xx_cken_enable, - .disable = clk_pxa2xx_cken_disable, - .getrate = clk_pxa27x_lcd_getrate, -}; - -static DEFINE_PXA2_CKEN(pxa27x_ffuart, FFUART, 14857000, 1); -static DEFINE_PXA2_CKEN(pxa27x_btuart, BTUART, 14857000, 1); -static DEFINE_PXA2_CKEN(pxa27x_stuart, STUART, 14857000, 1); -static DEFINE_PXA2_CKEN(pxa27x_i2s, I2S, 14682000, 0); -static DEFINE_PXA2_CKEN(pxa27x_i2c, I2C, 32842000, 0); -static DEFINE_PXA2_CKEN(pxa27x_usb, USB, 48000000, 5); -static DEFINE_PXA2_CKEN(pxa27x_mmc, MMC, 19500000, 0); -static DEFINE_PXA2_CKEN(pxa27x_ficp, FICP, 48000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_keypad, KEYPAD, 32768, 0); -static DEFINE_PXA2_CKEN(pxa27x_ssp1, SSP1, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_ssp2, SSP2, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_ssp3, SSP3, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_pwm0, PWM0, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_pwm1, PWM1, 13000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_ac97, AC97, 24576000, 0); -static DEFINE_PXA2_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0); -static DEFINE_PXA2_CKEN(pxa27x_msl, MSL, 48000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_usim, USIM, 48000000, 0); -static DEFINE_PXA2_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0); -static DEFINE_PXA2_CKEN(pxa27x_im, IM, 0, 0); -static DEFINE_PXA2_CKEN(pxa27x_memc, MEMC, 0, 0); - -static DEFINE_CK(pxa27x_lcd, LCD, &clk_pxa27x_lcd_ops); -static DEFINE_CK(pxa27x_camera, CAMERA, &clk_pxa27x_lcd_ops); -static DEFINE_CLK(pxa27x_mem, &clk_pxa27x_mem_ops, 0, 0); - -static struct clk_lookup pxa27x_clkregs[] = { - INIT_CLKREG(&clk_pxa27x_lcd, "pxa2xx-fb", NULL), - INIT_CLKREG(&clk_pxa27x_camera, "pxa27x-camera.0", NULL), - INIT_CLKREG(&clk_pxa27x_ffuart, "pxa2xx-uart.0", NULL), - INIT_CLKREG(&clk_pxa27x_btuart, "pxa2xx-uart.1", NULL), - INIT_CLKREG(&clk_pxa27x_stuart, "pxa2xx-uart.2", NULL), - INIT_CLKREG(&clk_pxa27x_i2s, "pxa2xx-i2s", NULL), - INIT_CLKREG(&clk_pxa27x_i2c, "pxa2xx-i2c.0", NULL), - INIT_CLKREG(&clk_pxa27x_usb, "pxa27x-udc", NULL), - INIT_CLKREG(&clk_pxa27x_mmc, "pxa2xx-mci.0", NULL), - INIT_CLKREG(&clk_pxa27x_stuart, "pxa2xx-ir", "UARTCLK"), - INIT_CLKREG(&clk_pxa27x_ficp, "pxa2xx-ir", "FICPCLK"), - INIT_CLKREG(&clk_pxa27x_usbhost, "pxa27x-ohci", NULL), - INIT_CLKREG(&clk_pxa27x_pwri2c, "pxa2xx-i2c.1", NULL), - INIT_CLKREG(&clk_pxa27x_keypad, "pxa27x-keypad", NULL), - INIT_CLKREG(&clk_pxa27x_ssp1, "pxa27x-ssp.0", NULL), - INIT_CLKREG(&clk_pxa27x_ssp2, "pxa27x-ssp.1", NULL), - INIT_CLKREG(&clk_pxa27x_ssp3, "pxa27x-ssp.2", NULL), - INIT_CLKREG(&clk_pxa27x_pwm0, "pxa27x-pwm.0", NULL), - INIT_CLKREG(&clk_pxa27x_pwm1, "pxa27x-pwm.1", NULL), - INIT_CLKREG(&clk_pxa27x_ac97, NULL, "AC97CLK"), - INIT_CLKREG(&clk_pxa27x_ac97conf, NULL, "AC97CONFCLK"), - INIT_CLKREG(&clk_pxa27x_msl, NULL, "MSLCLK"), - INIT_CLKREG(&clk_pxa27x_usim, NULL, "USIMCLK"), - INIT_CLKREG(&clk_pxa27x_memstk, NULL, "MSTKCLK"), - INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"), - INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"), - INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL), - INIT_CLKREG(&clk_dummy, "pxa27x-gpio", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), -}; - #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x @@ -466,8 +299,6 @@ static int __init pxa27x_init(void) reset_status = RCSR; - clkdev_add_table(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs)); - if ((ret = pxa_init_dma(IRQ_DMA, 32))) return ret; @@ -475,10 +306,13 @@ static int __init pxa27x_init(void) register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa2xx_mfp_syscore_ops); - register_syscore_ops(&pxa2xx_clock_syscore_ops); - pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info); - ret = platform_add_devices(devices, ARRAY_SIZE(devices)); + if (!of_have_populated_dt()) { + pxa_register_device(&pxa27x_device_gpio, + &pxa27x_gpio_info); + ret = platform_add_devices(devices, + ARRAY_SIZE(devices)); + } } return ret; diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 17cbc0c7bdb8..28c5b5686638 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -22,7 +22,6 @@ #include "generic.h" #include "devices.h" -#include "clock.h" static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = { @@ -84,32 +83,15 @@ static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = { MFP_ADDR_END, }; -static DEFINE_PXA3_CKEN(common_nand, NAND, 156000000, 0); -static DEFINE_PXA3_CKEN(gcu, PXA300_GCU, 0, 0); - -static struct clk_lookup common_clkregs[] = { - INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL), - INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL), -}; - -static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0); - -static struct clk_lookup pxa310_clkregs[] = { - INIT_CLKREG(&clk_pxa310_mmc3, "pxa2xx-mci.2", NULL), -}; - static int __init pxa300_init(void) { if (cpu_is_pxa300() || cpu_is_pxa310()) { mfp_init_base(io_p2v(MFPR_BASE)); mfp_init_addr(pxa300_mfp_addr_map); - clkdev_add_table(ARRAY_AND_SIZE(common_clkregs)); } - if (cpu_is_pxa310()) { + if (cpu_is_pxa310()) mfp_init_addr(pxa310_mfp_addr_map); - clkdev_add_table(ARRAY_AND_SIZE(pxa310_clkregs)); - } return 0; } diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index 6dc99d4f2dc6..2f55bb4b9087 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -22,7 +22,6 @@ #include "generic.h" #include "devices.h" -#include "clock.h" static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { @@ -78,20 +77,11 @@ static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_END, }; -static DEFINE_PXA3_CKEN(pxa320_nand, NAND, 104000000, 0); -static DEFINE_PXA3_CKEN(gcu, PXA320_GCU, 0, 0); - -static struct clk_lookup pxa320_clkregs[] = { - INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL), - INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL), -}; - static int __init pxa320_init(void) { if (cpu_is_pxa320()) { mfp_init_base(io_p2v(MFPR_BASE)); mfp_init_addr(pxa320_mfp_addr_map); - clkdev_add_table(ARRAY_AND_SIZE(pxa320_clkregs)); } return 0; diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index edcbd9c0bcb2..bd4cbef15ccf 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -37,67 +37,11 @@ #include "generic.h" #include "devices.h" -#include "clock.h" #define PECR_IE(n) ((1 << ((n) * 2)) << 28) #define PECR_IS(n) ((1 << ((n) * 2)) << 29) extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int)); - -static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1); -static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1); -static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1); -static DEFINE_PXA3_CKEN(pxa3xx_i2c, I2C, 32842000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_udc, UDC, 48000000, 5); -static DEFINE_PXA3_CKEN(pxa3xx_usbh, USBH, 48000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_u2d, USB2, 48000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_keypad, KEYPAD, 32768, 0); -static DEFINE_PXA3_CKEN(pxa3xx_ssp1, SSP1, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_ssp2, SSP2, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_ssp3, SSP3, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_ssp4, SSP4, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_pwm0, PWM0, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM1, 13000000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0); -static DEFINE_PXA3_CKEN(pxa3xx_gpio, GPIO, 13000000, 0); - -static DEFINE_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops); -static DEFINE_CK(pxa3xx_smemc, SMC, &clk_pxa3xx_smemc_ops); -static DEFINE_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops); -static DEFINE_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops); -static DEFINE_CLK(pxa3xx_pout, &clk_pxa3xx_pout_ops, 13000000, 70); - -static struct clk_lookup pxa3xx_clkregs[] = { - INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"), - /* Power I2C clock is always on */ - INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL), - INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL), - INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"), - INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"), - INIT_CLKREG(&clk_pxa3xx_ffuart, "pxa2xx-uart.0", NULL), - INIT_CLKREG(&clk_pxa3xx_btuart, "pxa2xx-uart.1", NULL), - INIT_CLKREG(&clk_pxa3xx_stuart, "pxa2xx-uart.2", NULL), - INIT_CLKREG(&clk_pxa3xx_stuart, "pxa2xx-ir", "UARTCLK"), - INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL), - INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL), - INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL), - INIT_CLKREG(&clk_pxa3xx_u2d, "pxa3xx-u2d", NULL), - INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL), - INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa3xx-ssp.0", NULL), - INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa3xx-ssp.1", NULL), - INIT_CLKREG(&clk_pxa3xx_ssp3, "pxa3xx-ssp.2", NULL), - INIT_CLKREG(&clk_pxa3xx_ssp4, "pxa3xx-ssp.3", NULL), - INIT_CLKREG(&clk_pxa3xx_pwm0, "pxa27x-pwm.0", NULL), - INIT_CLKREG(&clk_pxa3xx_pwm1, "pxa27x-pwm.1", NULL), - INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL), - INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL), - INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL), - INIT_CLKREG(&clk_pxa3xx_gpio, "pxa3xx-gpio", NULL), - INIT_CLKREG(&clk_pxa3xx_gpio, "pxa93x-gpio", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), -}; - #ifdef CONFIG_PM #define ISRAM_START 0x5c000000 @@ -476,8 +420,6 @@ static int __init pxa3xx_init(void) */ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); - clkdev_add_table(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs)); - if ((ret = pxa_init_dma(IRQ_DMA, 32))) return ret; @@ -485,7 +427,6 @@ static int __init pxa3xx_init(void) register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa3xx_mfp_syscore_ops); - register_syscore_ops(&pxa3xx_clock_syscore_ops); if (of_have_populated_dt()) return 0; diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 6dc4f025e674..88f70c37ad0d 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -56,7 +56,6 @@ #include "generic.h" #include "devices.h" -#include "clock.h" /* common GPIO definitions */ diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 7780d1faa06f..93bf4ef44d2c 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -58,7 +58,6 @@ #include <asm/mach/sharpsl_param.h> #include "generic.h" -#include "clock.h" #include "devices.h" static unsigned long tosa_pin_config[] = { diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index b5f8d75d51a0..f420a1b200c2 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -1,5 +1,6 @@ config ARCH_SOCFPGA bool "Altera SOCFPGA family" if ARCH_MULTI_V7 + select ARCH_SUPPORTS_BIG_ENDIAN select ARM_AMBA select ARM_GIC select CACHE_L2X0 diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index a0f3b1cd497c..5913bbb50036 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -32,7 +32,6 @@ #define RSTMGR_MPUMODRST_CPU1 0x2 /* CPU1 Reset */ extern void socfpga_secondary_startup(void); -extern void __iomem *socfpga_scu_base_addr; extern void socfpga_init_clocks(void); extern void socfpga_sysmgr_init(void); diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S index f65ea0af4af3..a580dcdec526 100644 --- a/arch/arm/mach-socfpga/headsmp.S +++ b/arch/arm/mach-socfpga/headsmp.S @@ -10,6 +10,7 @@ #include <linux/linkage.h> #include <linux/init.h> #include <asm/memory.h> +#include <asm/assembler.h> .arch armv7-a @@ -18,12 +19,14 @@ ENTRY(secondary_trampoline) * Thus, we can just subtract the PAGE_OFFSET to get the physical * address of &cpu1start_addr. This would not work for platforms * where the physical memory does not start at 0x0. - */ + */ +ARM_BE8(setend be) adr r0, 1f ldmia r0, {r1, r2} sub r2, r2, #PAGE_OFFSET ldr r3, [r2] ldr r4, [r3] +ARM_BE8(rev r4, r4) bx r4 .align diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index c64d89b7c0ca..7886eaeb6723 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -54,32 +54,20 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) return 0; } -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. - */ -static void __init socfpga_smp_init_cpus(void) +static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) { - unsigned int i, ncores; - - ncores = scu_get_core_count(socfpga_scu_base_addr); - - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + struct device_node *np; + void __iomem *socfpga_scu_base_addr; - /* sanity check */ - if (ncores > num_possible_cpus()) { - pr_warn("socfpga: no. of cores (%d) greater than configured" - "maximum of %d - clipping\n", ncores, num_possible_cpus()); - ncores = num_possible_cpus(); + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (!np) { + pr_err("%s: missing scu\n", __func__); + return; } - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); -} - -static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) -{ + socfpga_scu_base_addr = of_iomap(np, 0); + if (!socfpga_scu_base_addr) + return; scu_enable(socfpga_scu_base_addr); } @@ -96,7 +84,6 @@ static void socfpga_cpu_die(unsigned int cpu) } struct smp_operations socfpga_smp_ops __initdata = { - .smp_init_cpus = socfpga_smp_init_cpus, .smp_prepare_cpus = socfpga_smp_prepare_cpus, .smp_boot_secondary = socfpga_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index f5e597c207b9..b63dec6e740c 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -27,43 +27,10 @@ #include "core.h" -void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); void __iomem *sys_manager_base_addr; void __iomem *rst_manager_base_addr; unsigned long socfpga_cpu1start_addr; -static struct map_desc scu_io_desc __initdata = { - .virtual = SOCFPGA_SCU_VIRT_BASE, - .pfn = 0, /* run-time */ - .length = SZ_8K, - .type = MT_DEVICE, -}; - -static struct map_desc uart_io_desc __initdata = { - .virtual = 0xfec02000, - .pfn = __phys_to_pfn(0xffc02000), - .length = SZ_8K, - .type = MT_DEVICE, -}; - -static void __init socfpga_scu_map_io(void) -{ - unsigned long base; - - /* Get SCU base */ - asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); - - scu_io_desc.pfn = __phys_to_pfn(base); - iotable_init(&scu_io_desc, 1); -} - -static void __init socfpga_map_io(void) -{ - socfpga_scu_map_io(); - iotable_init(&uart_io_desc, 1); - early_printk("Early printk initialized\n"); -} - void __init socfpga_sysmgr_init(void) { struct device_node *np; @@ -112,7 +79,6 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") .l2c_aux_val = 0, .l2c_aux_mask = ~0, .smp = smp_ops(socfpga_smp_ops), - .map_io = socfpga_map_io, .init_irq = socfpga_init_irq, .restart = socfpga_cyclone5_restart, .dt_compat = altera_dt_match, diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile new file mode 100644 index 000000000000..bd0b7b5d6e9d --- /dev/null +++ b/arch/arm/mach-stm32/Makefile @@ -0,0 +1 @@ +obj-y += board-dt.o diff --git a/arch/arm/mach-stm32/Makefile.boot b/arch/arm/mach-stm32/Makefile.boot new file mode 100644 index 000000000000..eacfc3f5c33e --- /dev/null +++ b/arch/arm/mach-stm32/Makefile.boot @@ -0,0 +1,3 @@ +# 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 . diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c new file mode 100644 index 000000000000..f2ad7723d034 --- /dev/null +++ b/arch/arm/mach-stm32/board-dt.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/kernel.h> +#include <asm/v7m.h> +#include <asm/mach/arch.h> + +static const char *const stm32_compat[] __initconst = { + "st,stm32f429", + NULL +}; + +DT_MACHINE_START(STM32DT, "STM32 (Device Tree Support)") + .dt_compat = stm32_compat, + .restart = armv7m_restart, +MACHINE_END diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index 587b0468efcc..e8483ec79d67 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -121,3 +121,72 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_boot_secondary = sun6i_smp_boot_secondary, }; CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); + +static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "allwinner,sun8i-a23-prcm"); + if (!node) { + pr_err("Missing A23 PRCM node in the device tree\n"); + return; + } + + prcm_membase = of_iomap(node, 0); + if (!prcm_membase) { + pr_err("Couldn't map A23 PRCM registers\n"); + return; + } + + node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a23-cpuconfig"); + if (!node) { + pr_err("Missing A23 CPU config node in the device tree\n"); + return; + } + + cpucfg_membase = of_iomap(node, 0); + if (!cpucfg_membase) + pr_err("Couldn't map A23 CPU config registers\n"); + +} + +static int sun8i_smp_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + u32 reg; + + if (!(prcm_membase && cpucfg_membase)) + return -EFAULT; + + spin_lock(&cpu_lock); + + /* Set CPU boot address */ + writel(virt_to_phys(secondary_startup), + cpucfg_membase + CPUCFG_PRIVATE0_REG); + + /* Assert the CPU core in reset */ + writel(0, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + /* Assert the L1 cache in reset */ + reg = readl(cpucfg_membase + CPUCFG_GEN_CTRL_REG); + writel(reg & ~BIT(cpu), cpucfg_membase + CPUCFG_GEN_CTRL_REG); + + /* Clear CPU power-off gating */ + reg = readl(prcm_membase + PRCM_CPU_PWROFF_REG); + writel(reg & ~BIT(cpu), prcm_membase + PRCM_CPU_PWROFF_REG); + mdelay(1); + + /* Deassert the CPU core reset */ + writel(3, cpucfg_membase + CPUCFG_CPU_RST_CTRL_REG(cpu)); + + spin_unlock(&cpu_lock); + + return 0; +} + +struct smp_operations sun8i_smp_ops __initdata = { + .smp_prepare_cpus = sun8i_smp_prepare_cpus, + .smp_boot_secondary = sun8i_smp_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(sun8i_a23_smp, "allwinner,sun8i-a23", &sun8i_smp_ops); diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index 88de2dce2e87..7469347b1749 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -34,6 +34,7 @@ #include "iomap.h" #include "irq.h" #include "pm.h" +#include "reset.h" #include "sleep.h" #ifdef CONFIG_PM_SLEEP @@ -70,15 +71,13 @@ static struct cpuidle_driver tegra_idle_driver = { #ifdef CONFIG_PM_SLEEP #ifdef CONFIG_SMP -static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); - static int tegra20_reset_sleeping_cpu_1(void) { int ret = 0; tegra_pen_lock(); - if (readl(pmc + PMC_SCRATCH41) == CPU_RESETTABLE) + if (readb(tegra20_cpu1_resettable_status) == CPU_RESETTABLE) tegra20_cpu_shutdown(1); else ret = -EINVAL; diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S index 71be4af5e975..e3070fdab80b 100644 --- a/arch/arm/mach-tegra/reset-handler.S +++ b/arch/arm/mach-tegra/reset-handler.S @@ -169,10 +169,10 @@ after_errata: cmp r6, #TEGRA20 bne 1f /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ - mov32 r5, TEGRA_PMC_BASE - mov r0, #0 + mov32 r5, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + mov r0, #CPU_NOT_RESETTABLE cmp r10, #0 - strne r0, [r5, #PMC_SCRATCH41] + strneb r0, [r5, #__tegra20_cpu1_resettable_status_offset] 1: #endif @@ -281,6 +281,10 @@ __tegra_cpu_reset_handler_data: .rept TEGRA_RESET_DATA_SIZE .long 0 .endr + .globl __tegra20_cpu1_resettable_status_offset + .equ __tegra20_cpu1_resettable_status_offset, \ + . - __tegra_cpu_reset_handler_start + .byte 0 .align L1_CACHE_SHIFT ENTRY(__tegra_cpu_reset_handler_end) diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h index 76a93434c6ee..29c3dec0126a 100644 --- a/arch/arm/mach-tegra/reset.h +++ b/arch/arm/mach-tegra/reset.h @@ -35,6 +35,7 @@ extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]; void __tegra_cpu_reset_handler_start(void); void __tegra_cpu_reset_handler(void); +void __tegra20_cpu1_resettable_status_offset(void); void __tegra_cpu_reset_handler_end(void); void tegra_secondary_startup(void); @@ -47,6 +48,9 @@ void tegra_secondary_startup(void); (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \ ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \ (u32)__tegra_cpu_reset_handler_start))) +#define tegra20_cpu1_resettable_status \ + (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \ + (u32)__tegra20_cpu1_resettable_status_offset)) #endif #define tegra_cpu_reset_handler_offset \ diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index be4bc5f853f5..e6b684e14322 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -97,9 +97,10 @@ ENDPROC(tegra20_hotplug_shutdown) ENTRY(tegra20_cpu_shutdown) cmp r0, #0 reteq lr @ must not be called for CPU 0 - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_RESETTABLE - str r12, [r1] + strb r12, [r1, r2] cpu_to_halt_reg r1, r0 ldr r3, =TEGRA_FLOW_CTRL_VIRT @@ -182,38 +183,41 @@ ENDPROC(tegra_pen_unlock) /* * tegra20_cpu_clear_resettable(void) * - * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when + * Called to clear the "resettable soon" flag in IRAM variable when * it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_clear_resettable) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_NOT_RESETTABLE - str r12, [r1] + strb r12, [r1, r2] ret lr ENDPROC(tegra20_cpu_clear_resettable) /* * tegra20_cpu_set_resettable_soon(void) * - * Called to set the "resettable soon" flag in PMC_SCRATCH41 when + * Called to set the "resettable soon" flag in IRAM variable when * it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_set_resettable_soon) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset mov r12, #CPU_RESETTABLE_SOON - str r12, [r1] + strb r12, [r1, r2] ret lr ENDPROC(tegra20_cpu_set_resettable_soon) /* * tegra20_cpu_is_resettable_soon(void) * - * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been + * Returns true if the "resettable soon" flag in IRAM variable has been * set because it is expected that the secondary CPU will be idle soon. */ ENTRY(tegra20_cpu_is_resettable_soon) - mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 - ldr r12, [r1] + mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT + ldr r2, =__tegra20_cpu1_resettable_status_offset + ldrb r12, [r1, r2] cmp r12, #CPU_RESETTABLE_SOON moveq r0, #1 movne r0, #0 @@ -256,9 +260,10 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) mov r0, #TEGRA_FLUSH_CACHE_LOUIS bl tegra_disable_clean_inv_dcache - mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT + ldr r4, =__tegra20_cpu1_resettable_status_offset mov r3, #CPU_RESETTABLE - str r3, [r0] + strb r3, [r0, r4] bl tegra_cpu_do_idle @@ -274,10 +279,10 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) bl tegra_pen_lock - mov32 r3, TEGRA_PMC_VIRT - add r0, r3, #PMC_SCRATCH41 + mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT + ldr r4, =__tegra20_cpu1_resettable_status_offset mov r3, #CPU_NOT_RESETTABLE - str r3, [r0] + strb r3, [r0, r4] bl tegra_pen_unlock diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 92d46ec1361a..0d59360d891d 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -18,6 +18,7 @@ #define __MACH_TEGRA_SLEEP_H #include "iomap.h" +#include "irammap.h" #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \ + IO_CPU_VIRT) @@ -29,6 +30,9 @@ + IO_APB_VIRT) #define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT) +#define TEGRA_IRAM_RESET_BASE_VIRT (IO_IRAM_VIRT + \ + TEGRA_IRAM_RESET_HANDLER_OFFSET) + /* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */ #define PMC_SCRATCH37 0x130 #define PMC_SCRATCH38 0x134 diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 861d88486dbe..2378fa560a21 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -163,6 +163,5 @@ DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)") .init_irq = tegra_dt_init_irq, .init_machine = tegra_dt_init, .init_late = tegra_dt_init_late, - .restart = tegra_pmc_restart, .dt_compat = tegra_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig new file mode 100644 index 000000000000..b640458fd757 --- /dev/null +++ b/arch/arm/mach-uniphier/Kconfig @@ -0,0 +1,11 @@ +config ARCH_UNIPHIER + bool "Socionext UniPhier SoCs" + depends on ARCH_MULTI_V7 + select ARM_AMBA + select ARM_GLOBAL_TIMER + select ARM_GIC + select HAVE_ARM_SCU + select HAVE_ARM_TWD if SMP + help + Support for UniPhier SoC family developed by Socionext Inc. + (formerly, System LSI Business Division of Panasonic Corporation) diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile new file mode 100644 index 000000000000..60bd2265f753 --- /dev/null +++ b/arch/arm/mach-uniphier/Makefile @@ -0,0 +1,2 @@ +obj-y := uniphier.o +obj-$(CONFIG_SMP) += platsmp.o diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c new file mode 100644 index 000000000000..5943e1cb7fe1 --- /dev/null +++ b/arch/arm/mach-uniphier/platsmp.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/sizes.h> +#include <linux/compiler.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <asm/smp.h> +#include <asm/smp_scu.h> + +static struct regmap *sbcm_regmap; + +static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus) +{ + static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; + unsigned long scu_base_phys = 0; + void __iomem *scu_base; + + sbcm_regmap = syscon_regmap_lookup_by_compatible( + "socionext,uniphier-system-bus-controller-misc"); + if (IS_ERR(sbcm_regmap)) { + pr_err("failed to regmap system-bus-controller-misc\n"); + goto err; + } + + if (scu_a9_has_base()) + scu_base_phys = scu_a9_get_base(); + + if (!scu_base_phys) { + pr_err("failed to get scu base\n"); + goto err; + } + + scu_base = ioremap(scu_base_phys, SZ_128); + if (!scu_base) { + pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys); + goto err; + } + + scu_enable(scu_base); + iounmap(scu_base); + + return; +err: + pr_warn("disabling SMP\n"); + init_cpu_present(&only_cpu_0); + sbcm_regmap = NULL; +} + +static void __naked uniphier_secondary_startup(void) +{ + asm("bl v7_invalidate_l1\n" + "b secondary_startup\n"); +}; + +static int uniphier_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + int ret; + + if (!sbcm_regmap) + return -ENODEV; + + ret = regmap_write(sbcm_regmap, 0x1208, + virt_to_phys(uniphier_secondary_startup)); + if (!ret) + asm("sev"); /* wake up secondary CPU */ + + return ret; +} + +struct smp_operations uniphier_smp_ops __initdata = { + .smp_prepare_cpus = uniphier_smp_prepare_cpus, + .smp_boot_secondary = uniphier_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp", + &uniphier_smp_ops); diff --git a/arch/arm/mach-uniphier/uniphier.c b/arch/arm/mach-uniphier/uniphier.c new file mode 100644 index 000000000000..9be10efacb7d --- /dev/null +++ b/arch/arm/mach-uniphier/uniphier.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <asm/mach/arch.h> + +static const char * const uniphier_dt_compat[] __initconst = { + "socionext,ph1-sld3", + "socionext,ph1-ld4", + "socionext,ph1-pro4", + "socionext,ph1-sld8", + "socionext,ph1-pro5", + "socionext,proxstream2", + "socionext,ph1-ld6b", + NULL, +}; + +DT_MACHINE_START(UNIPHIER, "Socionext UniPhier") + .dt_compat = uniphier_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-zx/Kconfig b/arch/arm/mach-zx/Kconfig new file mode 100644 index 000000000000..2a910dc0d15e --- /dev/null +++ b/arch/arm/mach-zx/Kconfig @@ -0,0 +1,18 @@ +menuconfig ARCH_ZX + bool "ZTE ZX family" if ARCH_MULTI_V7 + help + Support for ZTE ZX-based family of processors. TV + set-top-box processor is supported. More will be + added soon. + +if ARCH_ZX + +config SOC_ZX296702 + def_bool y + select ARM_GIC + select ARM_GLOBAL_TIMER + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + help + Support for ZTE ZX296702 SoC which is a dual core CortexA9MP +endif diff --git a/arch/arm/mach-zx/Makefile b/arch/arm/mach-zx/Makefile new file mode 100644 index 000000000000..7c2edf6e5f8b --- /dev/null +++ b/arch/arm/mach-zx/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SOC_ZX296702) += zx296702.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-zx/core.h b/arch/arm/mach-zx/core.h new file mode 100644 index 000000000000..3efe8e038ee4 --- /dev/null +++ b/arch/arm/mach-zx/core.h @@ -0,0 +1,19 @@ +/* + * Copyright 2014 Linaro Ltd. + * Copyright (C) 2014 ZTE Corporation. + * + * 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. + */ + +#ifndef __MACH_ZX_CORE_H +#define __MACH_ZX_CORE_H + +extern void zx_resume_jump(void); +extern size_t zx_suspend_iram_sz; +extern unsigned long zx_secondary_startup_pa; + +void zx_secondary_startup(void); + +#endif /* __MACH_ZX_CORE_H */ diff --git a/arch/arm/mach-zx/headsmp.S b/arch/arm/mach-zx/headsmp.S new file mode 100644 index 000000000000..c0fece0c3955 --- /dev/null +++ b/arch/arm/mach-zx/headsmp.S @@ -0,0 +1,32 @@ +/* + * Copyright 2014 Linaro Ltd. + * Copyright (C) 2014 ZTE Corporation. + * + * 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. + */ + +#include <linux/linkage.h> + + .align 3 + +/* It runs from physical address */ +ENTRY(zx_resume_jump) + adr r1, zx_secondary_startup_pa + ldr r0, [r1] + bx r0 +ENDPROC(zx_resume_jump) + +ENTRY(zx_secondary_startup_pa) + .word zx_secondary_startup_pa + +ENTRY(zx_suspend_iram_sz) + .word . - zx_resume_jump +ENDPROC(zx_secondary_startup_pa) + + +ENTRY(zx_secondary_startup) + bl v7_invalidate_l1 + b secondary_startup +ENDPROC(zx_secondary_startup) diff --git a/arch/arm/mach-zx/platsmp.c b/arch/arm/mach-zx/platsmp.c new file mode 100644 index 000000000000..a3693982d65d --- /dev/null +++ b/arch/arm/mach-zx/platsmp.c @@ -0,0 +1,189 @@ +/* + * Copyright 2014 Linaro Ltd. + * Copyright (C) 2014 ZTE Corporation. + * + * 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. + */ + +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/jiffies.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/cp15.h> +#include <asm/fncpy.h> +#include <asm/proc-fns.h> +#include <asm/smp_scu.h> +#include <asm/smp_plat.h> + +#include "core.h" + +#define AON_SYS_CTRL_RESERVED1 0xa8 + +#define BUS_MATRIX_REMAP_CONFIG 0x00 + +#define PCU_CPU0_CTRL 0x00 +#define PCU_CPU1_CTRL 0x04 +#define PCU_CPU1_ST 0x0c +#define PCU_GLOBAL_CTRL 0x14 +#define PCU_EXPEND_CONTROL 0x34 + +#define ZX_IRAM_BASE 0x00200000 + +static void __iomem *pcu_base; +static void __iomem *matrix_base; +static void __iomem *scu_base; + +void __init zx_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *np; + unsigned long base = 0; + void __iomem *aonsysctrl_base; + void __iomem *sys_iram; + + base = scu_a9_get_base(); + scu_base = ioremap(base, SZ_256); + if (!scu_base) { + pr_err("%s: failed to map scu\n", __func__); + return; + } + + scu_enable(scu_base); + + np = of_find_compatible_node(NULL, NULL, "zte,sysctrl"); + if (!np) { + pr_err("%s: failed to find sysctrl node\n", __func__); + return; + } + + aonsysctrl_base = of_iomap(np, 0); + if (!aonsysctrl_base) { + pr_err("%s: failed to map aonsysctrl\n", __func__); + of_node_put(np); + return; + } + + /* + * Write the address of secondary startup into the + * system-wide flags register. The BootMonitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + __raw_writel(virt_to_phys(zx_secondary_startup), + aonsysctrl_base + AON_SYS_CTRL_RESERVED1); + + iounmap(aonsysctrl_base); + of_node_put(np); + + np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu"); + pcu_base = of_iomap(np, 0); + of_node_put(np); + WARN_ON(!pcu_base); + + np = of_find_compatible_node(NULL, NULL, "zte,zx-bus-matrix"); + matrix_base = of_iomap(np, 0); + of_node_put(np); + WARN_ON(!matrix_base); + + /* Map the first 4 KB IRAM for suspend usage */ + sys_iram = __arm_ioremap_exec(ZX_IRAM_BASE, PAGE_SIZE, false); + zx_secondary_startup_pa = virt_to_phys(zx_secondary_startup); + fncpy(sys_iram, &zx_resume_jump, zx_suspend_iram_sz); +} + +static int zx_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + static bool first_boot = true; + + if (first_boot) { + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + first_boot = false; + return 0; + } + + /* Swap the base address mapping between IRAM and IROM */ + writel_relaxed(0x1, matrix_base + BUS_MATRIX_REMAP_CONFIG); + + /* Power on CPU1 */ + writel_relaxed(0x0, pcu_base + PCU_CPU1_CTRL); + + /* Wait for power on ack */ + while (readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x4) + cpu_relax(); + + /* Swap back the mapping of IRAM and IROM */ + writel_relaxed(0x0, matrix_base + BUS_MATRIX_REMAP_CONFIG); + + return 0; +} + +#ifdef CONFIG_HOTPLUG_CPU +static inline void cpu_enter_lowpower(void) +{ + 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" (0x40) + : "cc"); +} + +static int zx_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(2000); + + writel_relaxed(0x2, pcu_base + PCU_CPU1_CTRL); + + while ((readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x3) != 0x0) { + if (time_after(jiffies, timeout)) { + pr_err("*** cpu1 poweroff timeout\n"); + break; + } + } + return 1; +} + +static void zx_cpu_die(unsigned int cpu) +{ + scu_power_mode(scu_base, SCU_PM_POWEROFF); + cpu_enter_lowpower(); + + while (1) + cpu_do_idle(); +} +#endif + +static void zx_secondary_init(unsigned int cpu) +{ + scu_power_mode(scu_base, SCU_PM_NORMAL); +} + +struct smp_operations zx_smp_ops __initdata = { + .smp_prepare_cpus = zx_smp_prepare_cpus, + .smp_secondary_init = zx_secondary_init, + .smp_boot_secondary = zx_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = zx_cpu_kill, + .cpu_die = zx_cpu_die, +#endif +}; + +CPU_METHOD_OF_DECLARE(zx_smp, "zte,zx296702-smp", &zx_smp_ops); diff --git a/arch/arm/mach-zx/zx296702.c b/arch/arm/mach-zx/zx296702.c new file mode 100644 index 000000000000..60bb1a8e1bf1 --- /dev/null +++ b/arch/arm/mach-zx/zx296702.c @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Linaro Ltd. + * Copyright (C) 2014 ZTE Corporation. + * + * 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. + */ + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/of_address.h> +#include <linux/of_platform.h> + +static const char *zx296702_dt_compat[] __initconst = { + "zte,zx296702", + NULL, +}; + +DT_MACHINE_START(ZX, "ZTE ZX296702 (Device Tree)") + .dt_compat = zx296702_dt_compat, + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, +MACHINE_END diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 58ef2a700414..616d5840fc2e 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -190,11 +190,6 @@ static void __init zynq_irq_init(void) irqchip_init(); } -static void zynq_system_reset(enum reboot_mode mode, const char *cmd) -{ - zynq_slcr_system_reset(); -} - static const char * const zynq_dt_match[] = { "xlnx,zynq-7000", NULL @@ -212,5 +207,4 @@ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .init_time = zynq_timer_init, .dt_compat = zynq_dt_match, .reserve = zynq_memory_init, - .restart = zynq_system_reset, MACHINE_END diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 382c60e9aa16..f2f0bf2e7d14 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -21,7 +21,6 @@ void zynq_secondary_startup(void); extern int zynq_slcr_init(void); extern int zynq_early_slcr_init(void); -extern void zynq_slcr_system_reset(void); extern void zynq_slcr_cpu_stop(int cpu); extern void zynq_slcr_cpu_start(int cpu); extern bool zynq_slcr_cpu_state_read(int cpu); diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index c3c24fd8b306..26320ebf3493 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -15,6 +15,7 @@ */ #include <linux/io.h> +#include <linux/reboot.h> #include <linux/mfd/syscon.h> #include <linux/of_address.h> #include <linux/regmap.h> @@ -92,20 +93,21 @@ u32 zynq_slcr_get_device_id(void) } /** - * zynq_slcr_system_reset - Reset the entire system. + * zynq_slcr_system_restart - Restart the entire system. + * + * @nb: Pointer to restart notifier block (unused) + * @action: Reboot mode (unused) + * @data: Restart handler private data (unused) + * + * Return: 0 always */ -void zynq_slcr_system_reset(void) +static +int zynq_slcr_system_restart(struct notifier_block *nb, + unsigned long action, void *data) { u32 reboot; /* - * Unlock the SLCR then reset the system. - * Note that this seems to require raw i/o - * functions or there's a lockup? - */ - zynq_slcr_unlock(); - - /* * Clear 0x0F000000 bits of reboot status register to workaround * the FSBL not loading the bitstream after soft-reboot * This is a temporary solution until we know more. @@ -113,8 +115,14 @@ void zynq_slcr_system_reset(void) zynq_slcr_read(&reboot, SLCR_REBOOT_STATUS_OFFSET); zynq_slcr_write(reboot & 0xF0FFFFFF, SLCR_REBOOT_STATUS_OFFSET); zynq_slcr_write(1, SLCR_PS_RST_CTRL_OFFSET); + return 0; } +static struct notifier_block zynq_slcr_restart_nb = { + .notifier_call = zynq_slcr_system_restart, + .priority = 192, +}; + /** * zynq_slcr_cpu_start - Start cpu * @cpu: cpu number @@ -219,6 +227,8 @@ int __init zynq_early_slcr_init(void) /* unlock the SLCR so that registers can be changed */ zynq_slcr_unlock(); + register_restart_handler(&zynq_slcr_restart_nb); + pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); of_node_put(np); diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 5f9b54b024b9..9a31b77eed23 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -353,6 +353,34 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw) PARENTS(clk_pxa27x_memory) = { "osc_13mhz", "system_bus", "run" }; MUX_RO_RATE_RO_OPS(clk_pxa27x_memory, "memory"); +#define DUMMY_CLK(_con_id, _dev_id, _parent) \ + { .con_id = _con_id, .dev_id = _dev_id, .parent = _parent } +struct dummy_clk { + const char *con_id; + const char *dev_id; + const char *parent; +}; +static struct dummy_clk dummy_clks[] __initdata = { + DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"), + DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"), + DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"), +}; + +static void __init pxa27x_dummy_clocks_init(void) +{ + struct clk *clk; + struct dummy_clk *d; + const char *name; + int i; + + for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) { + d = &dummy_clks[i]; + name = d->dev_id ? d->dev_id : d->con_id; + clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1); + clk_register_clkdev(clk, d->con_id, d->dev_id); + } +} + static void __init pxa27x_base_clocks_init(void) { pxa27x_register_plls(); @@ -362,12 +390,12 @@ static void __init pxa27x_base_clocks_init(void) clk_register_clk_pxa27x_lcd_base(); } -static int __init pxa27x_clocks_init(void) +int __init pxa27x_clocks_init(void) { pxa27x_base_clocks_init(); + pxa27x_dummy_clocks_init(); return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks)); } -postcore_initcall(pxa27x_clocks_init); static void __init pxa27x_dt_clocks_init(struct device_node *np) { diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c index 5eff6f097f98..6acc2c44ee2c 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra20.c +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c @@ -59,6 +59,7 @@ static u32 tegra20_fuse_readl(const unsigned int offset) int ret; u32 val = 0; struct dma_async_tx_descriptor *dma_desc; + unsigned long time_left; mutex_lock(&apb_dma_lock); @@ -82,9 +83,10 @@ static u32 tegra20_fuse_readl(const unsigned int offset) dmaengine_submit(dma_desc); dma_async_issue_pending(apb_dma_chan); - ret = wait_for_completion_timeout(&apb_dma_wait, msecs_to_jiffies(50)); + time_left = wait_for_completion_timeout(&apb_dma_wait, + msecs_to_jiffies(50)); - if (WARN(ret == 0, "apb read dma timed out")) + if (WARN(time_left == 0, "apb read dma timed out")) dmaengine_terminate_all(apb_dma_chan); else val = *apb_buffer; diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index c956395cf46f..cc119d15dd16 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -377,13 +377,10 @@ int tegra_pmc_cpu_remove_clamping(int cpuid) } #endif /* CONFIG_SMP */ -/** - * tegra_pmc_restart() - reboot the system - * @mode: which mode to reboot in - * @cmd: reboot command - */ -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) +static int tegra_pmc_restart_notify(struct notifier_block *this, + unsigned long action, void *data) { + const char *cmd = data; u32 value; value = tegra_pmc_readl(PMC_SCRATCH0); @@ -405,8 +402,15 @@ void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) value = tegra_pmc_readl(0); value |= 0x10; tegra_pmc_writel(value, 0); + + return NOTIFY_DONE; } +static struct notifier_block tegra_pmc_restart_handler = { + .notifier_call = tegra_pmc_restart_notify, + .priority = 128, +}; + static int powergate_show(struct seq_file *s, void *data) { unsigned int i; @@ -837,6 +841,13 @@ static int tegra_pmc_probe(struct platform_device *pdev) return err; } + err = register_restart_handler(&tegra_pmc_restart_handler); + if (err) { + dev_err(&pdev->dev, "unable to register restart handler, %d\n", + err); + return err; + } + return 0; } diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 2b5a9bbf80b7..7116968dee12 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -13,20 +13,25 @@ * option) any later version. */ +#include <linux/delay.h> +#include <linux/reboot.h> #include <linux/types.h> #include <linux/module.h> #include <linux/io.h> #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/of_address.h> +#include <linux/of_platform.h> #define PM_RSTC 0x1c +#define PM_RSTS 0x20 #define PM_WDOG 0x24 #define PM_PASSWORD 0x5a000000 #define PM_WDOG_TIME_SET 0x000fffff #define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTS_HADWRH_SET 0x00000040 #define PM_RSTC_WRCFG_SET 0x00000030 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 #define PM_RSTC_RESET 0x00000102 @@ -37,6 +42,7 @@ struct bcm2835_wdt { void __iomem *base; spinlock_t lock; + struct notifier_block restart_handler; }; static unsigned int heartbeat; @@ -106,6 +112,53 @@ static struct watchdog_device bcm2835_wdt_wdd = { .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), }; +static int +bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) +{ + struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, + restart_handler); + u32 val; + + /* use a timeout of 10 ticks (~150us) */ + writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); + val = readl_relaxed(wdt->base + PM_RSTC); + val &= PM_RSTC_WRCFG_CLR; + val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; + writel_relaxed(val, wdt->base + PM_RSTC); + + /* No sleeping, possibly atomic. */ + mdelay(1); + + return 0; +} + +/* + * We can't really power off, but if we do the normal reset scheme, and + * indicate to bootcode.bin not to reboot, then most of the chip will be + * powered off. + */ +static void bcm2835_power_off(void) +{ + struct device_node *np = + of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); + struct platform_device *pdev = of_find_device_by_node(np); + struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); + u32 val; + + /* + * We set the watchdog hard reset bit here to distinguish this reset + * from the normal (full) reset. bootcode.bin will not reboot after a + * hard reset. + */ + val = readl_relaxed(wdt->base + PM_RSTS); + val &= PM_RSTC_WRCFG_CLR; + val |= PM_PASSWORD | PM_RSTS_HADWRH_SET; + writel_relaxed(val, wdt->base + PM_RSTS); + + /* Continue with normal reset mechanism */ + bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); +} + static int bcm2835_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -136,6 +189,12 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) return err; } + wdt->restart_handler.notifier_call = bcm2835_restart; + wdt->restart_handler.priority = 128; + register_restart_handler(&wdt->restart_handler); + if (pm_power_off == NULL) + pm_power_off = bcm2835_power_off; + dev_info(dev, "Broadcom BCM2835 watchdog timer"); return 0; } @@ -144,6 +203,9 @@ static int bcm2835_wdt_remove(struct platform_device *pdev) { struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); + unregister_restart_handler(&wdt->restart_handler); + if (pm_power_off == bcm2835_power_off) + pm_power_off = NULL; watchdog_unregister_device(&bcm2835_wdt_wdd); iounmap(wdt->base); diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index 65a93273e72f..f5c0de43a5fa 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h @@ -26,8 +26,6 @@ struct clk; struct reset_control; -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd); - #ifdef CONFIG_PM_SLEEP enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void); void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); |