diff options
225 files changed, 6675 insertions, 2075 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/Documentation/devicetree/bindings/arm/exynos/power_domain.txt b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt index 5da38c5ed476..e151057d92f0 100644 --- a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt +++ b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt @@ -19,9 +19,10 @@ Optional Properties: domains. - clock-names: The following clocks can be specified: - oscclk: Oscillator clock. - - pclkN, clkN: Pairs of parent of input clock and input clock to the - devices in this power domain. Maximum of 4 pairs (N = 0 to 3) - are supported currently. + - clkN: Input clocks to the devices in this power domain. These clocks + will be reparented to oscclk before swithing power domain off. + Their original parent will be brought back after turning on + the domain. Maximum of 4 clocks (N = 0 to 3) are supported. - asbN: Clocks required by asynchronous bridges (ASB) present in the power domain. These clock should be enabled during power domain on/off operations. diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt index a5462b6b3c30..2a3ba73f0c5c 100644 --- a/Documentation/devicetree/bindings/arm/fsl.txt +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -81,12 +81,15 @@ Freescale Vybrid Platform Device Tree Bindings For the Vybrid SoC familiy all variants with DDR controller are supported, which is the VF5xx and VF6xx series. Out of historical reasons, in most places the kernel uses vf610 to refer to the whole familiy. +The compatible string "fsl,vf610m4" is used for the secondary Cortex-M4 +core support. Required root node compatible property (one of them): - compatible = "fsl,vf500"; - compatible = "fsl,vf510"; - compatible = "fsl,vf600"; - compatible = "fsl,vf610"; + - compatible = "fsl,vf610m4"; Freescale LS1021A Platform Device Tree Bindings ------------------------------------------------ diff --git a/Documentation/devicetree/bindings/arm/zte.txt b/Documentation/devicetree/bindings/arm/zte.txt new file mode 100644 index 000000000000..3ff5c9e85c1c --- /dev/null +++ b/Documentation/devicetree/bindings/arm/zte.txt @@ -0,0 +1,15 @@ +ZTE platforms device tree bindings +--------------------------------------- + +- ZX296702 board: + Required root node properties: + - compatible = "zte,zx296702-ad1", "zte,zx296702" + +System management required properties: + - compatible = "zte,sysctrl" + +Low power management required properties: + - compatible = "zte,zx296702-pcu" + +Bus matrix required properties: + - compatible = "zte,zx-bus-matrix" diff --git a/Documentation/devicetree/bindings/clock/zx296702-clk.txt b/Documentation/devicetree/bindings/clock/zx296702-clk.txt new file mode 100644 index 000000000000..750442b65505 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/zx296702-clk.txt @@ -0,0 +1,35 @@ +Device Tree Clock bindings for ZTE zx296702 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be one of the following: + "zte,zx296702-topcrm-clk": + zx296702 top clock selection, divider and gating + + "zte,zx296702-lsp0crpm-clk" and + "zte,zx296702-lsp1crpm-clk": + zx296702 device level clock selection and gating + +- reg: Address and length of the register set + +The clock consumer should specify the desired clock by having the clock +ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296702-clock.h +for the full list of zx296702 clock IDs. + + +topclk: topcrm@0x09800000 { + compatible = "zte,zx296702-topcrm-clk"; + reg = <0x09800000 0x1000>; + #clock-cells = <1>; +}; + +uart0: serial@0x09405000 { + compatible = "zte,zx296702-uart"; + reg = <0x09405000 0x1000>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&lsp1clk ZX296702_UART0_PCLK>; + status = "disabled"; +}; diff --git a/Documentation/devicetree/bindings/serial/pl011.txt b/Documentation/devicetree/bindings/serial/pl011.txt index ba3ecb8cb5a1..cbae3d9a0278 100644 --- a/Documentation/devicetree/bindings/serial/pl011.txt +++ b/Documentation/devicetree/bindings/serial/pl011.txt @@ -1,7 +1,7 @@ * ARM AMBA Primecell PL011 serial UART Required properties: -- compatible: must be "arm,primecell", "arm,pl011" +- compatible: must be "arm,primecell", "arm,pl011", "zte,zx296702-uart" - reg: exactly one register range with length 0x1000 - interrupts: exactly one interrupt specifier diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 80339192c93e..717ffd5a3563 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -211,3 +211,4 @@ xillybus Xillybus Ltd. xlnx Xilinx zyxel ZyXEL Communications Corp. zarlink Zarlink Semiconductor +zte ZTE Corp. diff --git a/MAINTAINERS b/MAINTAINERS index d8afd2953678..beed98105695 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1035,7 +1035,7 @@ F: arch/arm/include/asm/hardware/dec21285.h F: arch/arm/mach-footbridge/ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE -M: Shawn Guo <shawn.guo@linaro.org> +M: Shawn Guo <shawnguo@kernel.org> M: Sascha Hauer <kernel@pengutronix.de> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -1044,9 +1044,11 @@ F: arch/arm/mach-imx/ F: arch/arm/mach-mxs/ F: arch/arm/boot/dts/imx* F: arch/arm/configs/imx*_defconfig +F: drivers/clk/imx/ +F: include/soc/imx/ ARM/FREESCALE VYBRID ARM ARCHITECTURE -M: Shawn Guo <shawn.guo@linaro.org> +M: Shawn Guo <shawnguo@kernel.org> M: Sascha Hauer <kernel@pengutronix.de> R: Stefan Agner <stefan@agner.ch> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1189,6 +1191,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 @@ -1385,6 +1393,7 @@ L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/s3c* F: arch/arm/boot/dts/exynos* +F: arch/arm64/boot/dts/exynos/ F: arch/arm/plat-samsung/ F: arch/arm/mach-s3c24*/ F: arch/arm/mach-s3c64xx/ @@ -1494,6 +1503,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) @@ -1540,6 +1557,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) @@ -1617,6 +1641,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> @@ -2193,6 +2226,7 @@ S: Maintained F: arch/arm/mach-bcm/*brcmstb* F: arch/arm/boot/dts/bcm7*.dts* F: drivers/bus/brcmstb_gisb.c +N: brcmstb BROADCOM BMIPS MIPS ARCHITECTURE M: Kevin Cernekee <cernekee@gmail.com> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 45df48ba0b12..72c4273de003 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -329,6 +329,20 @@ config ARCH_MULTIPLATFORM select SPARSE_IRQ select USE_OF +config ARM_SINGLE_ARMV7M + bool "ARMv7-M based platforms (Cortex-M0/M3/M4)" + depends on !MMU + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_NVIC + select AUTO_ZRELADDR + select CLKSRC_OF + select COMMON_CLK + select CPU_V7M + select GENERIC_CLOCKEVENTS + select NO_IOPORT_MAP + select SPARSE_IRQ + select USE_OF + config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARCH_WANT_OPTIONAL_GPIOLIB @@ -398,24 +412,6 @@ config ARCH_EBSA110 Ethernet interface, two PCMCIA sockets, two serial ports and a parallel port. -config ARCH_EFM32 - bool "Energy Micro efm32" - depends on !MMU - select ARCH_REQUIRE_GPIOLIB - select ARM_NVIC - select AUTO_ZRELADDR - select CLKSRC_OF - select COMMON_CLK - select CPU_V7M - select GENERIC_CLOCKEVENTS - select NO_DMA - select NO_IOPORT_MAP - select SPARSE_IRQ - select USE_OF - help - Support for Energy Micro's (now Silicon Labs) efm32 Giant Gecko - processors. - config ARCH_EP93XX bool "EP93xx-based" select ARCH_HAS_HOLES_MEMORYMODEL @@ -606,6 +602,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 @@ -752,8 +749,10 @@ config ARCH_OMAP1 select GENERIC_IRQ_CHIP select HAVE_IDE select IRQ_DOMAIN + select MULTI_IRQ_HANDLER select NEED_MACH_IO_H if PCCARD select NEED_MACH_MEMORY_H + select SPARSE_IRQ help Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx) @@ -937,6 +936,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,8 +949,40 @@ source "arch/arm/mach-vt8500/Kconfig" source "arch/arm/mach-w90x900/Kconfig" +source "arch/arm/mach-zx/Kconfig" + source "arch/arm/mach-zynq/Kconfig" +# ARMv7-M architecture +config ARCH_EFM32 + bool "Energy Micro efm32" + depends on ARM_SINGLE_ARMV7M + select ARCH_REQUIRE_GPIOLIB + help + Support for Energy Micro's (now Silicon Labs) efm32 Giant Gecko + processors. + +config ARCH_LPC18XX + bool "NXP LPC18xx/LPC43xx" + depends on ARM_SINGLE_ARMV7M + select ARCH_HAS_RESET_CONTROLLER + select ARM_AMBA + select CLKSRC_LPC32XX + select PINCTRL + help + Support for NXP's LPC18xx Cortex-M3 and LPC43xx Cortex-M4 + high performance microcontrollers. + +config ARCH_STM32 + bool "STMicrolectronics STM32" + depends on ARM_SINGLE_ARMV7M + select ARCH_HAS_RESET_CONTROLLER + select ARMV7M_SYSTICK + select CLKSRC_STM32 + select RESET_CONTROLLER + help + Support for STMicroelectronics STM32 processors. + # Definitions to make life easier config ARCH_ACORN bool @@ -1477,7 +1510,8 @@ config ARM_PSCI # selected platforms. config ARCH_NR_GPIO int - default 1024 if ARCH_SHMOBILE || ARCH_TEGRA || ARCH_ZYNQ + default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \ + ARCH_ZYNQ default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \ SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210 default 416 if ARCH_SUNXI diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0c12ffb155a2..a6b5d0e35968 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -410,6 +410,13 @@ choice Say Y here if you want kernel low-level debugging support on i.MX6SX. + config DEBUG_IMX7D_UART + bool "i.MX7D Debug UART" + depends on SOC_IMX7D + help + Say Y here if you want kernel low-level debugging support + on i.MX7D. + config DEBUG_KEYSTONE_UART0 bool "Kernel low-level debugging on KEYSTONE2 using UART0" depends on ARCH_KEYSTONE @@ -433,6 +440,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 +923,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 +1181,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 @@ -1231,7 +1267,8 @@ config DEBUG_IMX_UART_PORT DEBUG_IMX53_UART || \ DEBUG_IMX6Q_UART || \ DEBUG_IMX6SL_UART || \ - DEBUG_IMX6SX_UART + DEBUG_IMX6SX_UART || \ + DEBUG_IMX7D_UART default 1 depends on ARCH_MXC help @@ -1281,7 +1318,8 @@ config DEBUG_LL_INCLUDE DEBUG_IMX53_UART ||\ DEBUG_IMX6Q_UART || \ DEBUG_IMX6SL_UART || \ - DEBUG_IMX6SX_UART + DEBUG_IMX6SX_UART || \ + DEBUG_IMX7D_UART default "debug/ks8695.S" if DEBUG_KS8695_UART default "debug/msm.S" if DEBUG_QCOM_UARTDM default "debug/netx.S" if DEBUG_NETX_UART @@ -1337,6 +1375,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 +1398,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 +1447,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 +1507,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 +1527,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 +1573,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 || \ @@ -1544,7 +1588,7 @@ config DEBUG_UART_8250_FLOW_CONTROL config DEBUG_UNCOMPRESS bool - depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG + depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ (!DEBUG_TEGRA_UART || !ZBOOT_ROM) help @@ -1561,7 +1605,7 @@ config DEBUG_UNCOMPRESS config UNCOMPRESS_INCLUDE string default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \ - PLAT_SAMSUNG || ARCH_EFM32 || \ + PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \ ARCH_SHMOBILE_LEGACY default "mach/uncompress.h" 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/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 992736b5229b..c52002c802f8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -660,6 +660,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt6592-evb.dtb \ mt8127-moose.dtb \ mt8135-evbp1.dtb +dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb endif always := $(dtb-y) diff --git a/arch/arm/boot/dts/zx296702-ad1.dts b/arch/arm/boot/dts/zx296702-ad1.dts new file mode 100644 index 000000000000..081f980cfbe6 --- /dev/null +++ b/arch/arm/boot/dts/zx296702-ad1.dts @@ -0,0 +1,48 @@ + +/dts-v1/; + +#include "zx296702.dtsi" + +/ { + model = "ZTE ZX296702 AD1 Board"; + compatible = "zte,zx296702-ad1", "zte,zx296702"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + memory { + reg = <0x50000000 0x20000000>; + }; +}; + +&mmc0 { + num-slots = <1>; + supports-highspeed; + non-removable; + disable-wp; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <4>; + }; +}; + +&mmc1 { + num-slots = <1>; + supports-highspeed; + non-removable; + disable-wp; + status = "okay"; + + slot@0 { + reg = <0>; + bus-width = <8>; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/zx296702.dtsi b/arch/arm/boot/dts/zx296702.dtsi new file mode 100644 index 000000000000..d45c8fcd7ab4 --- /dev/null +++ b/arch/arm/boot/dts/zx296702.dtsi @@ -0,0 +1,139 @@ + +#include "skeleton.dtsi" +#include <dt-bindings/clock/zx296702-clock.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "zte,zx296702-smp"; + + cpu@0 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + next-level-cache = <&l2cc>; + reg = <0>; + }; + + cpu@1 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + next-level-cache = <&l2cc>; + reg = <1>; + }; + }; + + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&intc>; + ranges; + + matrix: bus-matrix@400000 { + compatible = "zte,zx-bus-matrix"; + reg = <0x00400000 0x1000>; + }; + + intc: interrupt-controller@00801000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + interrupt-controller; + reg = <0x00801000 0x1000>, + <0x00800100 0x100>; + }; + + global_timer: timer@008000200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0x00800200 0x20>; + interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&intc>; + clocks = <&topclk ZX296702_A9_PERIPHCLK>; + }; + + l2cc: l2-cache-controller@0x00c00000 { + compatible = "arm,pl310-cache"; + reg = <0x00c00000 0x1000>; + cache-unified; + cache-level = <2>; + arm,data-latency = <1 1 1>; + arm,tag-latency = <1 1 1>; + arm,double-linefill = <1>; + arm,double-linefill-incr = <0>; + }; + + pcu: pcu@0xa0008000 { + compatible = "zte,zx296702-pcu"; + reg = <0xa0008000 0x1000>; + }; + + topclk: topclk@0x09800000 { + compatible = "zte,zx296702-topcrm-clk"; + reg = <0x09800000 0x1000>; + #clock-cells = <1>; + }; + + lsp1clk: lsp1clk@0x09400000 { + compatible = "zte,zx296702-lsp1crpm-clk"; + reg = <0x09400000 0x1000>; + #clock-cells = <1>; + }; + + lsp0clk: lsp0clk@0x0b000000 { + compatible = "zte,zx296702-lsp0crpm-clk"; + reg = <0x0b000000 0x1000>; + #clock-cells = <1>; + }; + + uart0: serial@0x09405000 { + compatible = "zte,zx296702-uart"; + reg = <0x09405000 0x1000>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&lsp1clk ZX296702_UART0_WCLK>; + status = "disabled"; + }; + + uart1: serial@0x09406000 { + compatible = "zte,zx296702-uart"; + reg = <0x09406000 0x1000>; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&lsp1clk ZX296702_UART1_WCLK>; + status = "disabled"; + }; + + mmc0: mmc@0x09408000 { + compatible = "snps,dw-mshc"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x09408000 0x1000>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + fifo-depth = <32>; + clocks = <&lsp1clk ZX296702_SDMMC0_PCLK>, + <&lsp1clk ZX296702_SDMMC0_WCLK>; + clock-names = "biu", "ciu"; + status = "disabled"; + }; + + mmc1: mmc@0x0b003000 { + compatible = "snps,dw-mshc"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0b003000 0x1000>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + fifo-depth = <32>; + clocks = <&lsp0clk ZX296702_SDMMC1_PCLK>, + <&lsp0clk ZX296702_SDMMC1_WCLK>; + clock-names = "biu", "ciu"; + status = "disabled"; + }; + + sysctrl: sysctrl@0xa0007000 { + compatible = "zte,sysctrl", "syscon"; + reg = <0xa0007000 0x1000>; + }; + }; +}; diff --git a/arch/arm/configs/efm32_defconfig b/arch/arm/configs/efm32_defconfig index c4c17e3a8e1a..e969f7884deb 100644 --- a/arch/arm/configs/efm32_defconfig +++ b/arch/arm/configs/efm32_defconfig @@ -16,6 +16,7 @@ CONFIG_EMBEDDED=y # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set # CONFIG_MMU is not set +CONFIG_ARM_SINGLE_ARMV7M=y CONFIG_ARCH_EFM32=y CONFIG_SET_MEM_PARAM=y CONFIG_DRAM_BASE=0x88000000 diff --git a/arch/arm/configs/zx_defconfig b/arch/arm/configs/zx_defconfig new file mode 100644 index 000000000000..b200bb0fecdd --- /dev/null +++ b/arch/arm/configs/zx_defconfig @@ -0,0 +1,129 @@ +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_PERF_EVENTS=y +CONFIG_SLAB=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_ZX=y +CONFIG_SOC_ZX296702=y +# CONFIG_SWP_EMULATE is not set +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_SMP=y +CONFIG_VMSPLIT_2G=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_KSM=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HIBERNATION=y +CONFIG_PM_RUNTIME=y +CONFIG_PM_DEBUG=y +CONFIG_SUSPEND_TIME=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyAMA0,115200 debug earlyprintk root=/dev/ram rw rootwait" +#CONFIG_NET is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=192 +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_UID_STAT=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_NETDEVICES=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIO=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SPI=y +CONFIG_LOGO=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_CONSOLE_POLL=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_BLOCK_MINORS=16 +CONFIG_MMC_DW=y +CONFIG_MMC_DW_IDMAC=y +CONFIG_EXT2_FS=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_DEBUG=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +#CONFIG_NFS_FS is not set +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=4096 +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_PANIC_TIMEOUT=5 +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_FTRACE is not set +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_STACKTRACE=y +CONFIG_DEBUG_ZTE_ZX=y +CONFIG_EARLY_PRINTK=y +CONFIG_CRYPTO_LZO=y +CONFIG_GPIOLIB=y diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h index 89aefe10d66b..34c1d96ef46d 100644 --- a/arch/arm/include/asm/firmware.h +++ b/arch/arm/include/asm/firmware.h @@ -34,6 +34,10 @@ struct firmware_ops { */ int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); /* + * Gets boot address of specified physical CPU + */ + int (*get_cpu_boot_addr)(int cpu, unsigned long *boot_addr); + /* * Boots specified physical CPU */ int (*cpu_boot)(int cpu); diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h index ee5f3084243c..22e414056a8c 100644 --- a/arch/arm/include/asm/vfp.h +++ b/arch/arm/include/asm/vfp.h @@ -5,6 +5,9 @@ * First, the standard VFP set. */ +#ifndef __ASM_VFP_H +#define __ASM_VFP_H + #define FPSID cr0 #define FPSCR cr1 #define MVFR1 cr6 @@ -87,3 +90,9 @@ #define VFPOPDESC_UNUSED_BIT (24) #define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT) #define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK)) + +#ifndef __ASSEMBLY__ +void vfp_disable(void); +#endif + +#endif /* __ASM_VFP_H */ 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/efm32.S b/arch/arm/include/debug/efm32.S index 2265a199280c..660fa1e4b77b 100644 --- a/arch/arm/include/debug/efm32.S +++ b/arch/arm/include/debug/efm32.S @@ -16,7 +16,7 @@ #define UARTn_TXDATA 0x0034 - .macro addruart, rx, tmp + .macro addruart, rx, tmp, tmp2 ldr \rx, =(CONFIG_DEBUG_UART_PHYS) /* diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h index 032a316eb802..66f736f74684 100644 --- a/arch/arm/include/debug/imx-uart.h +++ b/arch/arm/include/debug/imx-uart.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. * * 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 @@ -90,6 +90,16 @@ #define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR #define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n) +#define IMX7D_UART1_BASE_ADDR 0x30860000 +#define IMX7D_UART2_BASE_ADDR 0x30890000 +#define IMX7D_UART3_BASE_ADDR 0x30880000 +#define IMX7D_UART4_BASE_ADDR 0x30a60000 +#define IMX7D_UART5_BASE_ADDR 0x30a70000 +#define IMX7D_UART6_BASE_ADDR 0x30a80000 +#define IMX7D_UART7_BASE_ADDR 0x30a90000 +#define IMX7D_UART_BASE_ADDR(n) IMX7D_UART##n##_BASE_ADDR +#define IMX7D_UART_BASE(n) IMX7D_UART_BASE_ADDR(n) + #define IMX_DEBUG_UART_BASE(soc) soc##_UART_BASE(CONFIG_DEBUG_IMX_UART_PORT) #ifdef CONFIG_DEBUG_IMX1_UART @@ -114,6 +124,9 @@ #define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL) #elif defined(CONFIG_DEBUG_IMX6SX_UART) #define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX) +#elif defined(CONFIG_DEBUG_IMX7D_UART) +#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D) + #endif #endif /* __DEBUG_IMX_UART_H */ 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/kernel/debug.S b/arch/arm/kernel/debug.S index 78c91b5f97d4..ea9646cc2a0e 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -35,7 +35,7 @@ #else /* !CONFIG_MMU */ .macro addruart_current, rx, tmp1, tmp2 - addruart \rx, \tmp1 + addruart \rx, \tmp1, \tmp2 .endm #endif /* CONFIG_MMU */ diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 8b11f44bb36e..e9184feffc4e 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -19,6 +19,7 @@ config ARCH_BCM_IPROC select ARCH_REQUIRE_GPIOLIB select ARM_AMBA select PINCTRL + select MTD_NAND_BRCMNAND help This enables support for systems based on Broadcom IPROC architected SoCs. The IPROC complex contains one or more ARM CPUs along with common @@ -144,6 +145,7 @@ config ARCH_BRCMSTB select BRCMSTB_GISB_ARB select BRCMSTB_L2_IRQ select BCM7120_L2_IRQ + select ARCH_WANT_OPTIONAL_GPIOLIB help Say Y if you intend to run the kernel on a Broadcom ARM-based STB chipset. diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 54d274da7ccb..4fb0da458e91 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -38,7 +38,12 @@ obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o # BCM63XXx -obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o +ifeq ($(CONFIG_ARCH_BCM_63XX),y) +CFLAGS_bcm63xx_headsmp.o += -march=armv7-a +obj-y += bcm63xx.o +obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_headsmp.o \ + bcm63xx_pmb.o +endif ifeq ($(CONFIG_ARCH_BRCMSTB),y) CFLAGS_platsmp-brcmstb.o += -march=armv7-a diff --git a/arch/arm/mach-bcm/bcm63xx_headsmp.S b/arch/arm/mach-bcm/bcm63xx_headsmp.S new file mode 100644 index 000000000000..c7af397c7f14 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_headsmp.S @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015, Broadcom Corporation + * All Rights Reserved + * + * 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> +#include <linux/init.h> +#include <asm/assembler.h> + +ENTRY(bcm63138_secondary_startup) + ARM_BE8(setend be) + /* + * L1 cache does have unpredictable contents at power-up clean its + * contents without flushing + */ + bl v7_invalidate_l1 + nop + + b secondary_startup +ENDPROC(bcm63138_secondary_startup) diff --git a/arch/arm/mach-bcm/bcm63xx_pmb.c b/arch/arm/mach-bcm/bcm63xx_pmb.c new file mode 100644 index 000000000000..de061ec5a479 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_pmb.c @@ -0,0 +1,221 @@ +/* + * Broadcom BCM63138 PMB initialization for secondary CPU(s) + * + * Copyright (C) 2015 Broadcom Corporation + * Author: Florian Fainelli <f.fainelli@gmail.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. + */ +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/spinlock.h> +#include <linux/reset/bcm63xx_pmb.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include "bcm63xx_smp.h" + +/* ARM Control register definitions */ +#define CORE_PWR_CTRL_SHIFT 0 +#define CORE_PWR_CTRL_MASK 0x3 +#define PLL_PWR_ON BIT(8) +#define PLL_LDO_PWR_ON BIT(9) +#define PLL_CLAMP_ON BIT(10) +#define CPU_RESET_N(x) BIT(13 + (x)) +#define NEON_RESET_N BIT(15) +#define PWR_CTRL_STATUS_SHIFT 28 +#define PWR_CTRL_STATUS_MASK 0x3 +#define PWR_DOWN_SHIFT 30 +#define PWR_DOWN_MASK 0x3 + +/* CPU Power control register definitions */ +#define MEM_PWR_OK BIT(0) +#define MEM_PWR_ON BIT(1) +#define MEM_CLAMP_ON BIT(2) +#define MEM_PWR_OK_STATUS BIT(4) +#define MEM_PWR_ON_STATUS BIT(5) +#define MEM_PDA_SHIFT 8 +#define MEM_PDA_MASK 0xf +#define MEM_PDA_CPU_MASK 0x1 +#define MEM_PDA_NEON_MASK 0xf +#define CLAMP_ON BIT(15) +#define PWR_OK_SHIFT 16 +#define PWR_OK_MASK 0xf +#define PWR_ON_SHIFT 20 +#define PWR_CPU_MASK 0x03 +#define PWR_NEON_MASK 0x01 +#define PWR_ON_MASK 0xf +#define PWR_OK_STATUS_SHIFT 24 +#define PWR_OK_STATUS_MASK 0xf +#define PWR_ON_STATUS_SHIFT 28 +#define PWR_ON_STATUS_MASK 0xf + +#define ARM_CONTROL 0x30 +#define ARM_PWR_CONTROL_BASE 0x34 +#define ARM_PWR_CONTROL(x) (ARM_PWR_CONTROL_BASE + (x) * 0x4) +#define ARM_NEON_L2 0x3c + +/* Perform a value write, then spin until the value shifted by + * shift is seen, masked with mask and is different from cond. + */ +static int bpcm_wr_rd_mask(void __iomem *master, + unsigned int addr, u32 off, u32 *val, + u32 shift, u32 mask, u32 cond) +{ + int ret; + + ret = bpcm_wr(master, addr, off, *val); + if (ret) + return ret; + + do { + ret = bpcm_rd(master, addr, off, val); + if (ret) + return ret; + + cpu_relax(); + } while (((*val >> shift) & mask) != cond); + + return ret; +} + +/* Global lock to serialize accesses to the PMB registers while we + * are bringing up the secondary CPU + */ +static DEFINE_SPINLOCK(pmb_lock); + +static int bcm63xx_pmb_get_resources(struct device_node *dn, + void __iomem **base, + unsigned int *cpu, + unsigned int *addr) +{ + struct device_node *pmb_dn; + struct of_phandle_args args; + int ret; + + ret = of_property_read_u32(dn, "reg", cpu); + if (ret) { + pr_err("CPU is missing a reg node\n"); + return ret; + } + + ret = of_parse_phandle_with_args(dn, "resets", "#reset-cells", + 0, &args); + if (ret) { + pr_err("CPU is missing a resets phandle\n"); + return ret; + } + + pmb_dn = args.np; + if (args.args_count != 2) { + pr_err("reset-controller does not conform to reset-cells\n"); + return -EINVAL; + } + + *base = of_iomap(args.np, 0); + if (!*base) { + pr_err("failed remapping PMB register\n"); + return -ENOMEM; + } + + /* We do not need the number of zones */ + *addr = args.args[0]; + + return 0; +} + +int bcm63xx_pmb_power_on_cpu(struct device_node *dn) +{ + void __iomem *base; + unsigned int cpu, addr; + unsigned long flags; + u32 val, ctrl; + int ret; + + ret = bcm63xx_pmb_get_resources(dn, &base, &cpu, &addr); + if (ret) + return ret; + + /* We would not know how to enable a third and greater CPU */ + WARN_ON(cpu > 1); + + spin_lock_irqsave(&pmb_lock, flags); + + /* Check if the CPU is already on and save the ARM_CONTROL register + * value since we will use it later for CPU de-assert once done with + * the CPU-specific power sequence + */ + ret = bpcm_rd(base, addr, ARM_CONTROL, &ctrl); + if (ret) + goto out; + + if (ctrl & CPU_RESET_N(cpu)) { + pr_info("PMB: CPU%d is already powered on\n", cpu); + ret = 0; + goto out; + } + + /* Power on PLL */ + ret = bpcm_rd(base, addr, ARM_PWR_CONTROL(cpu), &val); + if (ret) + goto out; + + val |= (PWR_CPU_MASK << PWR_ON_SHIFT); + + ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, + PWR_ON_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK); + if (ret) + goto out; + + val |= (PWR_CPU_MASK << PWR_OK_SHIFT); + + ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, + PWR_OK_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK); + if (ret) + goto out; + + val &= ~CLAMP_ON; + + ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); + if (ret) + goto out; + + /* Power on CPU<N> RAM */ + val &= ~(MEM_PDA_MASK << MEM_PDA_SHIFT); + + ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); + if (ret) + goto out; + + val |= MEM_PWR_ON; + + ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, + 0, MEM_PWR_ON_STATUS, MEM_PWR_ON_STATUS); + if (ret) + goto out; + + val |= MEM_PWR_OK; + + ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, + 0, MEM_PWR_OK_STATUS, MEM_PWR_OK_STATUS); + if (ret) + goto out; + + val &= ~MEM_CLAMP_ON; + + ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); + if (ret) + goto out; + + /* De-assert CPU reset */ + ctrl |= CPU_RESET_N(cpu); + + ret = bpcm_wr(base, addr, ARM_CONTROL, ctrl); +out: + spin_unlock_irqrestore(&pmb_lock, flags); + iounmap(base); + return ret; +} diff --git a/arch/arm/mach-bcm/bcm63xx_smp.c b/arch/arm/mach-bcm/bcm63xx_smp.c new file mode 100644 index 000000000000..3f014f18cea5 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_smp.c @@ -0,0 +1,169 @@ +/* + * Broadcom BCM63138 DSL SoCs SMP support code + * + * Copyright (C) 2015, Broadcom Corporation + * + * Licensed under the terms of the GPLv2 + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include <asm/cacheflush.h> +#include <asm/smp_scu.h> +#include <asm/smp_plat.h> +#include <asm/vfp.h> + +#include "bcm63xx_smp.h" + +/* Size of mapped Cortex A9 SCU address space */ +#define CORTEX_A9_SCU_SIZE 0x58 + +/* + * Enable the Cortex A9 Snoop Control Unit + * + * By the time this is called we already know there are multiple + * cores present. We assume we're running on a Cortex A9 processor, + * so any trouble getting the base address register or getting the + * SCU base is a problem. + * + * Return 0 if successful or an error code otherwise. + */ +static int __init scu_a9_enable(void) +{ + unsigned long config_base; + void __iomem *scu_base; + unsigned int i, ncores; + + if (!scu_a9_has_base()) { + pr_err("no configuration base address register!\n"); + return -ENXIO; + } + + /* Config base address register value is zero for uniprocessor */ + config_base = scu_a9_get_base(); + if (!config_base) { + pr_err("hardware reports only one core\n"); + return -ENOENT; + } + + scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); + if (!scu_base) { + pr_err("failed to remap config base (%lu/%u) for SCU\n", + config_base, CORTEX_A9_SCU_SIZE); + return -ENOMEM; + } + + scu_enable(scu_base); + + ncores = scu_base ? scu_get_core_count(scu_base) : 1; + + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + + /* The BCM63138 SoC has two Cortex-A9 CPUs, CPU0 features a complete + * and fully functional VFP unit that can be used, but CPU1 does not. + * Since we will not be able to trap kernel-mode NEON to force + * migration to CPU0, just do not advertise VFP support at all. + * + * This will make vfp_init bail out and do not attempt to use VFP at + * all, for kernel-mode NEON, we do not want to introduce any + * conditionals in hot-paths, so we just restrict the system to UP. + */ +#ifdef CONFIG_VFP + if (ncores > 1) { + pr_warn("SMP: secondary CPUs lack VFP unit, disabling VFP\n"); + vfp_disable(); + +#ifdef CONFIG_KERNEL_MODE_NEON + WARN(1, "SMP: kernel-mode NEON enabled, restricting to UP\n"); + ncores = 1; +#endif + } +#endif + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); + + iounmap(scu_base); /* That's the last we'll need of this */ + + return 0; +} + +static const struct of_device_id bcm63138_bootlut_ids[] = { + { .compatible = "brcm,bcm63138-bootlut", }, + { /* sentinel */ }, +}; + +#define BOOTLUT_RESET_VECT 0x20 + +static int bcm63138_smp_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + void __iomem *bootlut_base; + struct device_node *dn; + int ret = 0; + u32 val; + + dn = of_find_matching_node(NULL, bcm63138_bootlut_ids); + if (!dn) { + pr_err("SMP: unable to find bcm63138 boot LUT node\n"); + return -ENODEV; + } + + bootlut_base = of_iomap(dn, 0); + of_node_put(dn); + + if (!bootlut_base) { + pr_err("SMP: unable to remap boot LUT base register\n"); + return -ENOMEM; + } + + /* Locate the secondary CPU node */ + dn = of_get_cpu_node(cpu_logical_map(cpu), NULL); + if (!dn) { + pr_err("SMP: failed to locate secondary CPU%d node\n", cpu); + ret = -ENODEV; + goto out; + } + + /* Write the secondary init routine to the BootLUT reset vector */ + val = virt_to_phys(bcm63138_secondary_startup); + writel_relaxed(val, bootlut_base + BOOTLUT_RESET_VECT); + + /* Power up the core, will jump straight to its reset vector when we + * return + */ + ret = bcm63xx_pmb_power_on_cpu(dn); + if (ret) + goto out; +out: + iounmap(bootlut_base); + + return ret; +} + +static void __init bcm63138_smp_prepare_cpus(unsigned int max_cpus) +{ + int ret; + + ret = scu_a9_enable(); + if (ret) { + pr_warn("SMP: Cortex-A9 SCU setup failed\n"); + return; + } +} + +struct smp_operations bcm63138_smp_ops __initdata = { + .smp_prepare_cpus = bcm63138_smp_prepare_cpus, + .smp_boot_secondary = bcm63138_smp_boot_secondary, +}; + +CPU_METHOD_OF_DECLARE(bcm63138_smp, "brcm,bcm63138", &bcm63138_smp_ops); diff --git a/arch/arm/mach-bcm/bcm63xx_smp.h b/arch/arm/mach-bcm/bcm63xx_smp.h new file mode 100644 index 000000000000..50b76044536e --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_smp.h @@ -0,0 +1,9 @@ +#ifndef __BCM63XX_SMP_H +#define __BCM63XX_SMP_H + +struct device_node; + +extern void bcm63138_secondary_startup(void); +extern int bcm63xx_pmb_power_on_cpu(struct device_node *dn); + +#endif /* __BCM63XX_SMP_H */ diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c index e9bcbdbce555..7aef92720eb4 100644 --- a/arch/arm/mach-bcm/bcm_5301x.c +++ b/arch/arm/mach-bcm/bcm_5301x.c @@ -18,15 +18,16 @@ static bool first_fault = true; static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - if (fsr == 0x1c06 && first_fault) { + if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) { first_fault = false; /* - * These faults with code 0x1c06 happens for no good reason, - * possibly left over from the CFE boot loader. + * These faults with codes 0x1406 (BCM4709) or 0x1c06 happens + * for no good reason, possibly left over from the CFE boot + * loader. */ pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", - addr, fsr); + addr, fsr); /* Returning non-zero causes fault display and panic */ return 0; 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-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 36f22c1a31fe..3c950f5864f3 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -20,9 +20,14 @@ #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/i2c-gpio.h> +#include <linux/mmc/host.h> +#include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> +#include <linux/platform_data/video-ep93xx.h> +#include <linux/platform_data/spi-ep93xx.h> +#include <linux/gpio.h> #include <mach/hardware.h> -#include <linux/platform_data/video-ep93xx.h> #include <mach/gpio-ep93xx.h> #include <asm/mach-types.h> @@ -40,6 +45,132 @@ static struct ep93xxfb_mach_info __initdata simone_fb_info = { .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, }; +/* + * GPIO lines used for MMC card detection. + */ +#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 + +/* + * Up to v1.3, the Sim.One used SFRMOUT as SD card chip select, but this goes + * low between multi-message command blocks. From v1.4, it uses a GPIO instead. + * v1.3 parts will still work, since the signal on SFRMOUT is automatic. + */ +#define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO1 + +/* + * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal, + * you can leave these empty and pass NULL as .controller_data. + */ + +static int simone_mmc_spi_setup(struct spi_device *spi) +{ + unsigned int gpio = MMC_CHIP_SELECT_GPIO; + int err; + + err = gpio_request(gpio, spi->modalias); + if (err) + return err; + + err = gpio_direction_output(gpio, 1); + if (err) { + gpio_free(gpio); + return err; + } + + return 0; +} + +static void simone_mmc_spi_cleanup(struct spi_device *spi) +{ + unsigned int gpio = MMC_CHIP_SELECT_GPIO; + + gpio_set_value(gpio, 1); + gpio_direction_input(gpio); + gpio_free(gpio); +} + +static void simone_mmc_spi_cs_control(struct spi_device *spi, int value) +{ + gpio_set_value(MMC_CHIP_SELECT_GPIO, value); +} + +static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = { + .setup = simone_mmc_spi_setup, + .cleanup = simone_mmc_spi_cleanup, + .cs_control = simone_mmc_spi_cs_control, +}; + +/* + * MMC card detection GPIO setup. + */ + +static int simone_mmc_spi_init(struct device *dev, + irqreturn_t (*irq_handler)(int, void *), void *mmc) +{ + unsigned int gpio = MMC_CARD_DETECT_GPIO; + int irq, err; + + err = gpio_request(gpio, dev_name(dev)); + if (err) + return err; + + err = gpio_direction_input(gpio); + if (err) + goto fail; + + irq = gpio_to_irq(gpio); + if (irq < 0) + goto fail; + + err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING, + "MMC card detect", mmc); + if (err) + goto fail; + + printk(KERN_INFO "%s: using irq %d for MMC card detection\n", + dev_name(dev), irq); + + return 0; +fail: + gpio_free(gpio); + return err; +} + +static void simone_mmc_spi_exit(struct device *dev, void *mmc) +{ + unsigned int gpio = MMC_CARD_DETECT_GPIO; + + free_irq(gpio_to_irq(gpio), mmc); + gpio_free(gpio); +} + +static struct mmc_spi_platform_data simone_mmc_spi_data = { + .init = simone_mmc_spi_init, + .exit = simone_mmc_spi_exit, + .detect_delay = 500, + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + +static struct spi_board_info simone_spi_devices[] __initdata = { + { + .modalias = "mmc_spi", + .controller_data = &simone_mmc_spi_ops, + .platform_data = &simone_mmc_spi_data, + /* + * We use 10 MHz even though the maximum is 3.7 MHz. The driver + * will limit it automatically to max. frequency. + */ + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_3, + }, +}; + +static struct ep93xx_spi_info simone_spi_info __initdata = { + .num_chipselect = ARRAY_SIZE(simone_spi_devices), +}; + static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { .sda_pin = EP93XX_GPIO_LINE_EEDAT, .sda_is_open_drain = 0, @@ -74,6 +205,8 @@ static void __init simone_init_machine(void) ep93xx_register_fb(&simone_fb_info); ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, ARRAY_SIZE(simone_i2c_board_info)); + ep93xx_register_spi(&simone_spi_info, simone_spi_devices, + ARRAY_SIZE(simone_spi_devices)); simone_register_audio(); } diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 5f5cd562c593..e3a9256ed55f 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -163,7 +163,9 @@ extern void exynos_set_delayed_reset_assertion(bool enable); extern void s5p_init_cpu(void __iomem *cpuid_addr); extern unsigned int samsung_rev(void); -extern void __iomem *cpu_boot_reg_base(void); +extern void exynos_core_restart(u32 core_id); +extern int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr); +extern int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr); static inline void pmu_raw_writel(u32 val, u32 offset) { diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 5917a30eee33..4bd8b7653817 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -234,7 +234,8 @@ static void __init exynos_dt_machine_init(void) exynos_sysram_init(); #if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE) - if (of_machine_is_compatible("samsung,exynos4210")) + if (of_machine_is_compatible("samsung,exynos4210") || + of_machine_is_compatible("samsung,exynos3250")) exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data; #endif if (of_machine_is_compatible("samsung,exynos4210") || diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 1bd35763f12e..245f6dec1ded 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -49,6 +49,7 @@ static int exynos_do_idle(unsigned long mode) sysram_ns_base_addr + 0x24); __raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20); if (soc_is_exynos3250()) { + flush_cache_all(); exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE, SMC_POWERSTATE_IDLE, 0); exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER, @@ -104,6 +105,22 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) return 0; } +static int exynos_get_cpu_boot_addr(int cpu, unsigned long *boot_addr) +{ + void __iomem *boot_reg; + + if (!sysram_ns_base_addr) + return -ENODEV; + + boot_reg = sysram_ns_base_addr + 0x1c; + + if (soc_is_exynos4412()) + boot_reg += 4 * cpu; + + *boot_addr = __raw_readl(boot_reg); + return 0; +} + static int exynos_cpu_suspend(unsigned long arg) { flush_cache_all(); @@ -138,6 +155,7 @@ static int exynos_resume(void) static const struct firmware_ops exynos_firmware_ops = { .do_idle = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL, .set_cpu_boot_addr = exynos_set_cpu_boot_addr, + .get_cpu_boot_addr = exynos_get_cpu_boot_addr, .cpu_boot = exynos_cpu_boot, .suspend = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL, .resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL, diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index a825bca2a2b6..58e05a2eae57 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -169,7 +169,7 @@ int exynos_cluster_power_state(int cluster) S5P_CORE_LOCAL_PWR_EN); } -void __iomem *cpu_boot_reg_base(void) +static void __iomem *cpu_boot_reg_base(void) { if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) return pmu_base_addr + S5P_INFORM5; @@ -195,7 +195,7 @@ static inline void __iomem *cpu_boot_reg(int cpu) * * Currently this is needed only when booting secondary CPU on Exynos3250. */ -static void exynos_core_restart(u32 core_id) +void exynos_core_restart(u32 core_id) { u32 val; @@ -210,7 +210,6 @@ static void exynos_core_restart(u32 core_id) val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG; pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id)); - pr_info("CPU%u: Software reset\n", core_id); pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET); } @@ -248,6 +247,56 @@ static void exynos_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } +int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr) +{ + int ret; + + /* + * Try to set boot address using firmware first + * and fall back to boot register if it fails. + */ + ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr); + if (ret && ret != -ENOSYS) + goto fail; + if (ret == -ENOSYS) { + void __iomem *boot_reg = cpu_boot_reg(core_id); + + if (IS_ERR(boot_reg)) { + ret = PTR_ERR(boot_reg); + goto fail; + } + __raw_writel(boot_addr, boot_reg); + ret = 0; + } +fail: + return ret; +} + +int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr) +{ + int ret; + + /* + * Try to get boot address using firmware first + * and fall back to boot register if it fails. + */ + ret = call_firmware_op(get_cpu_boot_addr, core_id, boot_addr); + if (ret && ret != -ENOSYS) + goto fail; + if (ret == -ENOSYS) { + void __iomem *boot_reg = cpu_boot_reg(core_id); + + if (IS_ERR(boot_reg)) { + ret = PTR_ERR(boot_reg); + goto fail; + } + *boot_addr = __raw_readl(boot_reg); + ret = 0; + } +fail: + return ret; +} + static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; @@ -307,22 +356,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) boot_addr = virt_to_phys(exynos4_secondary_startup); - /* - * Try to set boot address using firmware first - * and fall back to boot register if it fails. - */ - ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr); - if (ret && ret != -ENOSYS) + ret = exynos_set_boot_addr(core_id, boot_addr); + if (ret) goto fail; - if (ret == -ENOSYS) { - void __iomem *boot_reg = cpu_boot_reg(core_id); - - if (IS_ERR(boot_reg)) { - ret = PTR_ERR(boot_reg); - goto fail; - } - __raw_writel(boot_addr, boot_reg); - } call_firmware_op(cpu_boot, core_id); @@ -337,6 +373,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) udelay(10); } + if (pen_release != -1) + ret = -ETIMEDOUT; + /* * now the secondary core is starting up let it run its * calibrations, then wait for it to finish @@ -407,16 +446,9 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); boot_addr = virt_to_phys(exynos4_secondary_startup); - ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr); - if (ret && ret != -ENOSYS) + ret = exynos_set_boot_addr(core_id, boot_addr); + if (ret) break; - if (ret == -ENOSYS) { - void __iomem *boot_reg = cpu_boot_reg(core_id); - - if (IS_ERR(boot_reg)) - break; - __raw_writel(boot_addr, boot_reg); - } } } diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index cc75ab448be3..9c1506b499bc 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -22,6 +22,7 @@ #include <asm/firmware.h> #include <asm/smp_scu.h> #include <asm/suspend.h> +#include <asm/cacheflush.h> #include <mach/map.h> @@ -209,6 +210,8 @@ static int exynos_cpu0_enter_aftr(void) * sequence, let's wait for one of these to happen */ while (exynos_cpu_power_state(1)) { + unsigned long boot_addr; + /* * The other cpu may skip idle and boot back * up again @@ -221,7 +224,11 @@ static int exynos_cpu0_enter_aftr(void) * boot back up again, getting stuck in the * boot rom code */ - if (__raw_readl(cpu_boot_reg_base()) == 0) + ret = exynos_get_boot_addr(1, &boot_addr); + if (ret) + goto fail; + ret = -1; + if (boot_addr == 0) goto abort; cpu_relax(); @@ -233,11 +240,14 @@ static int exynos_cpu0_enter_aftr(void) abort: if (cpu_online(1)) { + unsigned long boot_addr = virt_to_phys(exynos_cpu_resume); + /* * Set the boot vector to something non-zero */ - __raw_writel(virt_to_phys(exynos_cpu_resume), - cpu_boot_reg_base()); + ret = exynos_set_boot_addr(1, boot_addr); + if (ret) + goto fail; dsb(); /* @@ -247,22 +257,42 @@ abort: while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN) cpu_relax(); + if (soc_is_exynos3250()) { + while (!pmu_raw_readl(S5P_PMU_SPARE2) && + !atomic_read(&cpu1_wakeup)) + cpu_relax(); + + if (!atomic_read(&cpu1_wakeup)) + exynos_core_restart(1); + } + while (!atomic_read(&cpu1_wakeup)) { + smp_rmb(); + /* * Poke cpu1 out of the boot rom */ - __raw_writel(virt_to_phys(exynos_cpu_resume), - cpu_boot_reg_base()); - arch_send_wakeup_ipi_mask(cpumask_of(1)); + ret = exynos_set_boot_addr(1, boot_addr); + if (ret) + goto fail; + + call_firmware_op(cpu_boot, 1); + + if (soc_is_exynos3250()) + dsb_sev(); + else + arch_send_wakeup_ipi_mask(cpumask_of(1)); } } - +fail: return ret; } static int exynos_wfi_finisher(unsigned long flags) { + if (soc_is_exynos3250()) + flush_cache_all(); cpu_do_idle(); return -1; @@ -283,6 +313,9 @@ static int exynos_cpu1_powerdown(void) */ exynos_cpu_power_down(1); + if (soc_is_exynos3250()) + pmu_raw_writel(0, S5P_PMU_SPARE2); + ret = cpu_suspend(0, exynos_wfi_finisher); cpu_pm_exit(); @@ -299,7 +332,9 @@ cpu1_aborted: static void exynos_pre_enter_aftr(void) { - __raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base()); + unsigned long boot_addr = virt_to_phys(exynos_cpu_resume); + + (void)exynos_set_boot_addr(1, boot_addr); } static void exynos_post_enter_aftr(void) diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index a9686535f9ed..6001f1c9d136 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -62,6 +62,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { if (IS_ERR(pd->clk[i])) break; + pd->pclk[i] = clk_get_parent(pd->clk[i]); if (clk_set_parent(pd->clk[i], pd->oscclk)) pr_err("%s: error setting oscclk as parent to clock %d\n", pd->name, i); @@ -90,6 +91,9 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { if (IS_ERR(pd->clk[i])) break; + + if (IS_ERR(pd->clk[i])) + continue; /* Skip on first power up */ if (clk_set_parent(pd->clk[i], pd->pclk[i])) pr_err("%s: error setting parent to clock%d\n", pd->name, i); @@ -117,27 +121,37 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain) static __init int exynos4_pm_init_power_domain(void) { - struct platform_device *pdev; struct device_node *np; for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") { struct exynos_pm_domain *pd; int on, i; - struct device *dev; - - pdev = of_find_device_by_node(np); - dev = &pdev->dev; pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) { pr_err("%s: failed to allocate memory for domain\n", __func__); + of_node_put(np); + return -ENOMEM; + } + pd->pd.name = kstrdup_const(strrchr(np->full_name, '/') + 1, + GFP_KERNEL); + if (!pd->pd.name) { + kfree(pd); + of_node_put(np); return -ENOMEM; } - pd->pd.name = kstrdup(dev_name(dev), GFP_KERNEL); pd->name = pd->pd.name; pd->base = of_iomap(np, 0); + if (!pd->base) { + pr_warn("%s: failed to map memory\n", __func__); + kfree(pd->pd.name); + kfree(pd); + of_node_put(np); + continue; + } + pd->pd.power_off = exynos_pd_power_off; pd->pd.power_on = exynos_pd_power_on; @@ -145,12 +159,12 @@ static __init int exynos4_pm_init_power_domain(void) char clk_name[8]; snprintf(clk_name, sizeof(clk_name), "asb%d", i); - pd->asb_clk[i] = clk_get(dev, clk_name); + pd->asb_clk[i] = of_clk_get_by_name(np, clk_name); if (IS_ERR(pd->asb_clk[i])) break; } - pd->oscclk = clk_get(dev, "oscclk"); + pd->oscclk = of_clk_get_by_name(np, "oscclk"); if (IS_ERR(pd->oscclk)) goto no_clk; @@ -158,16 +172,14 @@ static __init int exynos4_pm_init_power_domain(void) char clk_name[8]; snprintf(clk_name, sizeof(clk_name), "clk%d", i); - pd->clk[i] = clk_get(dev, clk_name); + pd->clk[i] = of_clk_get_by_name(np, clk_name); if (IS_ERR(pd->clk[i])) break; - snprintf(clk_name, sizeof(clk_name), "pclk%d", i); - pd->pclk[i] = clk_get(dev, clk_name); - if (IS_ERR(pd->pclk[i])) { - clk_put(pd->clk[i]); - pd->clk[i] = ERR_PTR(-EINVAL); - break; - } + /* + * Skip setting parent on first power up. + * The parent at this time may not be useful at all. + */ + pd->pclk[i] = ERR_PTR(-EINVAL); } if (IS_ERR(pd->clk[0])) @@ -189,15 +201,15 @@ no_clk: args.args_count = 0; child_domain = of_genpd_get_from_provider(&args); if (IS_ERR(child_domain)) - continue; + goto next_pd; if (of_parse_phandle_with_args(np, "power-domains", "#power-domain-cells", 0, &args) != 0) - continue; + goto next_pd; parent_domain = of_genpd_get_from_provider(&args); if (IS_ERR(parent_domain)) - continue; + goto next_pd; if (pm_genpd_add_subdomain(parent_domain, child_domain)) pr_warn("%s failed to add subdomain: %s\n", @@ -205,9 +217,10 @@ no_clk: else pr_info("%s has as child subdomain: %s.\n", parent_domain->name, child_domain->name); +next_pd: of_node_put(np); } return 0; } -arch_initcall(exynos4_pm_init_power_domain); +core_initcall(exynos4_pm_init_power_domain); diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index c15761ca2f18..e812c1c85624 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -681,7 +681,7 @@ static unsigned int const exynos5420_list_disable_pmu_reg[] = { EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG, }; -static void exynos5_power_off(void) +static void exynos_power_off(void) { unsigned int tmp; @@ -872,8 +872,6 @@ static void exynos5420_pmu_init(void) EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI); pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER); - - pm_power_off = exynos5_power_off; pr_info("EXYNOS5420 PMU initialized\n"); } @@ -984,6 +982,8 @@ static int exynos_pmu_probe(struct platform_device *pdev) if (ret) dev_warn(dev, "can't register restart handler err=%d\n", ret); + pm_power_off = exynos_power_off; + dev_dbg(dev, "Exynos PMU Driver probe done\n"); return 0; } diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 7d23ce04cad5..96866d03d281 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -223,7 +223,7 @@ static int exynos_pmu_domain_alloc(struct irq_domain *domain, return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args); } -static struct irq_domain_ops exynos_pmu_domain_ops = { +static const struct irq_domain_ops exynos_pmu_domain_ops = { .xlate = exynos_pmu_domain_xlate, .alloc = exynos_pmu_domain_alloc, .free = irq_domain_free_irqs_common, diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 388232ce92fc..573536f1bb73 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -1,8 +1,8 @@ menuconfig ARCH_MXC - bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 + bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 || ARM_SINGLE_ARMV7M select ARCH_REQUIRE_GPIOLIB select ARM_CPU_SUSPEND if PM - select CLKSRC_MMIO + select CLKSRC_IMX_GPT select GENERIC_IRQ_CHIP select PINCTRL select PM_OPP if PM @@ -462,10 +462,10 @@ config MACH_VPR200 endif -if ARCH_MULTI_V5 - comment "Device tree only" +if ARCH_MULTI_V5 + config SOC_IMX25 bool "i.MX25 support" select ARCH_MXC_IOMUX_V3 @@ -478,7 +478,7 @@ endif if ARCH_MULTI_V7 -comment "Device tree only" +comment "Cortex-A platforms" config SOC_IMX5 bool @@ -548,10 +548,33 @@ config SOC_IMX6SX help This enables support for Freescale i.MX6 SoloX processor. +config SOC_IMX7D + bool "i.MX7 Dual support" + select PINCTRL_IMX7D + select ARM_GIC + select HAVE_IMX_ANATOP + select HAVE_IMX_MMDC + help + This enables support for Freescale i.MX7 Dual processor. + +config SOC_LS1021A + bool "Freescale LS1021A support" + select ARM_GIC + select HAVE_ARM_ARCH_TIMER + select PCI_DOMAINS if PCI + select ZONE_DMA if ARM_LPAE + help + This enables support for Freescale LS1021A processor. + +endif + +comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms" + +if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M + config SOC_VF610 bool "Vybrid Family VF610 support" - select IRQ_DOMAIN_HIERARCHY - select ARM_GIC + select ARM_GIC if ARCH_MULTI_V7 select PINCTRL_VF610 select PL310_ERRATA_769419 if CACHE_L2X0 select SMP_ON_UP if SMP @@ -565,7 +588,7 @@ choice default VF_USE_ARM_GLOBAL_TIMER config VF_USE_ARM_GLOBAL_TIMER - bool "Use ARM Global Timer" + bool "Use ARM Global Timer" if ARCH_MULTI_V7 select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK help @@ -579,16 +602,6 @@ choice endchoice -config SOC_LS1021A - bool "Freescale LS1021A support" - select ARM_GIC - select HAVE_ARM_ARCH_TIMER - select PCI_DOMAINS if PCI - select ZONE_DMA if ARM_LPAE - - help - This enables support for Freescale LS1021A processor. - endif source "arch/arm/mach-imx/devices/Kconfig" diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index eed609834ffb..37c502ac9595 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -1,23 +1,18 @@ -obj-y := time.o cpu.o system.o irq-common.o +obj-y := cpu.o system.o irq-common.o -obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o -obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o +obj-$(CONFIG_SOC_IMX1) += mm-imx1.o +obj-$(CONFIG_SOC_IMX21) += mm-imx21.o -obj-$(CONFIG_SOC_IMX25) += clk-imx25.o cpu-imx25.o mach-imx25.o +obj-$(CONFIG_SOC_IMX25) += cpu-imx25.o mach-imx25.o obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o -obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o +obj-$(CONFIG_SOC_IMX27) += mm-imx27.o ehci-imx27.o -obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o -obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o +obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o +obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o ehci-imx35.o pm-imx3.o imx5-pm-$(CONFIG_PM) += pm-imx5.o -obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y) - -obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \ - clk-pfd.o clk-busy.o clk.o \ - clk-fixup-div.o clk-fixup-mux.o \ - clk-gate-exclusive.o +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o $(imx5-pm-y) obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o @@ -85,13 +80,15 @@ AFLAGS_headsmp.o :=-Wa,-march=armv7-a obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o endif -obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o -obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o -obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o +obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o +obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o +obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o +obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o ifeq ($(CONFIG_SUSPEND),y) AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o +obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o endif obj-$(CONFIG_SOC_IMX6) += pm-imx6.o @@ -99,7 +96,7 @@ obj-$(CONFIG_SOC_IMX50) += mach-imx50.o obj-$(CONFIG_SOC_IMX51) += mach-imx51.o obj-$(CONFIG_SOC_IMX53) += mach-imx53.o -obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o +obj-$(CONFIG_SOC_VF610) += mach-vf610.o obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/arch/arm/mach-imx/Makefile.boot diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index 7f262fe4ba77..231bb250c571 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Freescale Semiconductor, Inc. + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License @@ -28,6 +28,7 @@ #define ANADIG_USB2_CHRG_DETECT 0x210 #define ANADIG_DIGPROG 0x260 #define ANADIG_DIGPROG_IMX6SL 0x280 +#define ANADIG_DIGPROG_IMX7D 0x800 #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000 #define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8 @@ -121,6 +122,8 @@ void __init imx_init_revision_from_anatop(void) WARN_ON(!anatop_base); if (of_device_is_compatible(np, "fsl,imx6sl-anatop")) offset = ANADIG_DIGPROG_IMX6SL; + if (of_device_is_compatible(np, "fsl,imx7d-anatop")) + offset = ANADIG_DIGPROG_IMX7D; digprog = readl_relaxed(anatop_base + offset); iounmap(anatop_base); diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 0f04e30b726d..21e4e8697a58 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -44,7 +44,6 @@ void imx27_soc_init(void); void imx31_soc_init(void); void imx35_soc_init(void); void epit_timer_init(void __iomem *base, int irq); -void mxc_timer_init(void __iomem *, int); int mx1_clocks_init(unsigned long fref); int mx21_clocks_init(unsigned long lref, unsigned long fref); int mx27_clocks_init(unsigned long fref); @@ -56,13 +55,10 @@ struct platform_device *mxc_register_gpio(char *name, int id, void mxc_set_cpu_type(unsigned int type); void mxc_restart(enum reboot_mode, const char *); void mxc_arch_reset_init(void __iomem *); -int mx51_revision(void); -int mx53_revision(void); void imx_set_aips(void __iomem *); void imx_aips_allow_unprivileged_access(const char *compat); int mxc_device_init(void); void imx_set_soc_revision(unsigned int rev); -unsigned int imx_get_soc_revision(void); void imx_init_revision_from_anatop(void); struct device *imx_soc_device_init(void); void imx6_enable_rbc(bool enable); @@ -87,7 +83,6 @@ enum mx3_cpu_pwr_mode { }; void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode); -void imx_print_silicon_rev(const char *cpu, int srev); void imx_enable_cpu(int cpu, bool enable); void imx_set_cpu_jump(int cpu, void *jump_addr); @@ -111,7 +106,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq); void imx_anatop_init(void); void imx_anatop_pre_suspend(void); void imx_anatop_post_resume(void); -int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); +int imx6_set_lpm(enum mxc_cpu_pwr_mode mode); void imx6q_set_int_mem_clk_lpm(bool enable); void imx6sl_set_wait_clk(bool enter); int imx_mmdc_get_ddr_type(void); @@ -121,26 +116,28 @@ int imx_cpu_kill(unsigned int cpu); #ifdef CONFIG_SUSPEND void v7_cpu_resume(void); +void imx53_suspend(void __iomem *ocram_vbase); +extern const u32 imx53_suspend_sz; void imx6_suspend(void __iomem *ocram_vbase); #else static inline void v7_cpu_resume(void) {} +static inline void imx53_suspend(void __iomem *ocram_vbase) {} +static const u32 imx53_suspend_sz; static inline void imx6_suspend(void __iomem *ocram_vbase) {} #endif +void imx6_pm_ccm_init(const char *ccm_compat); void imx6q_pm_init(void); void imx6dl_pm_init(void); void imx6sl_pm_init(void); void imx6sx_pm_init(void); -void imx6q_pm_set_ccm_base(void __iomem *base); #ifdef CONFIG_PM void imx51_pm_init(void); void imx53_pm_init(void); -void imx5_pm_set_ccm_base(void __iomem *base); #else static inline void imx51_pm_init(void) {} static inline void imx53_pm_init(void) {} -static inline void imx5_pm_set_ccm_base(void __iomem *base) {} #endif #ifdef CONFIG_NEON diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index df42c14ff749..a7fa92a7b1d7 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -130,6 +130,9 @@ struct device * __init imx_soc_device_init(void) case MXC_CPU_IMX6Q: soc_id = "i.MX6Q"; break; + case MXC_CPU_IMX7D: + soc_id = "i.MX7D"; + break; default: soc_id = "Unknown"; } diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c index 8e21ccc1eda2..353bb8774112 100644 --- a/arch/arm/mach-imx/cpuidle-imx6q.c +++ b/arch/arm/mach-imx/cpuidle-imx6q.c @@ -27,9 +27,9 @@ static int imx6q_enter_wait(struct cpuidle_device *dev, */ if (!spin_trylock(&master_lock)) goto idle; - imx6q_set_lpm(WAIT_UNCLOCKED); + imx6_set_lpm(WAIT_UNCLOCKED); cpu_do_idle(); - imx6q_set_lpm(WAIT_CLOCKED); + imx6_set_lpm(WAIT_CLOCKED); spin_unlock(&master_lock); goto done; } diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c index 5742a9fd1ef2..8d866fb674a8 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sl.c +++ b/arch/arm/mach-imx/cpuidle-imx6sl.c @@ -16,7 +16,7 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - imx6q_set_lpm(WAIT_UNCLOCKED); + imx6_set_lpm(WAIT_UNCLOCKED); /* * Software workaround for ERR005311, see function * description for details. @@ -24,7 +24,7 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev, imx6sl_set_wait_clk(true); cpu_do_idle(); imx6sl_set_wait_clk(false); - imx6q_set_lpm(WAIT_CLOCKED); + imx6_set_lpm(WAIT_CLOCKED); return index; } diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c index 2c9f1a8bf245..3c6672b3796b 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sx.c +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -25,7 +25,7 @@ static int imx6sx_idle_finish(unsigned long val) static int imx6sx_enter_wait(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - imx6q_set_lpm(WAIT_UNCLOCKED); + imx6_set_lpm(WAIT_UNCLOCKED); switch (index) { case 1: @@ -50,7 +50,7 @@ static int imx6sx_enter_wait(struct cpuidle_device *dev, break; } - imx6q_set_lpm(WAIT_CLOCKED); + imx6_set_lpm(WAIT_CLOCKED); return index; } diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 0ea77ed25b25..80bad29d609a 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -227,7 +227,7 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain, return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args); } -static struct irq_domain_ops imx_gpc_domain_ops = { +static const struct irq_domain_ops imx_gpc_domain_ops = { .xlate = imx_gpc_domain_xlate, .alloc = imx_gpc_domain_alloc, .free = irq_domain_free_irqs_common, diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h index 76af2c03c241..d737f95ebb07 100644 --- a/arch/arm/mach-imx/hardware.h +++ b/arch/arm/mach-imx/hardware.h @@ -22,6 +22,7 @@ #ifndef __ASSEMBLY__ #include <asm/io.h> +#include <soc/imx/revision.h> #endif #include <asm/sizes.h> diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c index d6a30753ca7c..6dd22cabf4d3 100644 --- a/arch/arm/mach-imx/iomux-imx31.c +++ b/arch/arm/mach-imx/iomux-imx31.c @@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(gpio_mux_lock); #define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3) -static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG]; +static DECLARE_BITMAP(mxc_pin_alloc_map, NB_PORTS * 32); /* * set the mode for a IOMUX pin. */ diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 3ab61549ce0f..9602cc12d2f1 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -393,6 +393,7 @@ static void __init imx6q_init_irq(void) imx_init_l2cache(); imx_src_init(); irqchip_init(); + imx6_pm_ccm_init("fsl,imx6q-ccm"); } static const char * const imx6q_dt_compat[] __initconst = { diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index 12a1b098fc6a..300326373166 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -66,6 +66,7 @@ static void __init imx6sl_init_irq(void) imx_init_l2cache(); imx_src_init(); irqchip_init(); + imx6_pm_ccm_init("fsl,imx6sl-ccm"); } static const char * const imx6sl_dt_compat[] __initconst = { diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index f17b7004c24b..6a0b0614de29 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -86,6 +86,7 @@ static void __init imx6sx_init_irq(void) imx_init_l2cache(); imx_src_init(); irqchip_init(); + imx6_pm_ccm_init("fsl,imx6sx-ccm"); } static void __init imx6sx_init_late(void) diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c new file mode 100644 index 000000000000..4d4a19099a43 --- /dev/null +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * + * 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/irqchip.h> +#include <linux/of_platform.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include "common.h" + +static void __init imx7d_init_machine(void) +{ + struct device *parent; + + parent = imx_soc_device_init(); + if (parent == NULL) + pr_warn("failed to initialize soc device\n"); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + imx_anatop_init(); +} + +static void __init imx7d_init_irq(void) +{ + imx_init_revision_from_anatop(); + imx_src_init(); + irqchip_init(); +} + +static const char *imx7d_dt_compat[] __initconst = { + "fsl,imx7d", + NULL, +}; + +DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)") + .init_irq = imx7d_init_irq, + .init_machine = imx7d_init_machine, + .dt_compat = imx7d_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index 2e7c75b66fe0..b20f6c14eda5 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -17,6 +17,7 @@ static const char * const vf610_dt_compat[] __initconst = { "fsl,vf510", "fsl,vf600", "fsl,vf610", + "fsl,vf610m4", NULL, }; diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c index 0411f0664c15..db9621c718ec 100644 --- a/arch/arm/mach-imx/mmdc.c +++ b/arch/arm/mach-imx/mmdc.c @@ -17,6 +17,8 @@ #include <linux/of_address.h> #include <linux/of_device.h> +#include "common.h" + #define MMDC_MAPSR 0x404 #define BP_MMDC_MAPSR_PSD 0 #define BP_MMDC_MAPSR_PSS 4 diff --git a/arch/arm/mach-imx/mx27.h b/arch/arm/mach-imx/mx27.h index 8a65f192e7f3..f96bb2642677 100644 --- a/arch/arm/mach-imx/mx27.h +++ b/arch/arm/mach-imx/mx27.h @@ -231,8 +231,4 @@ #define MX27_DMA_REQ_SDHC3 36 #define MX27_DMA_REQ_NFC 37 -#ifndef __ASSEMBLY__ -extern int mx27_revision(void); -#endif - #endif /* ifndef __MACH_MX27_H__ */ diff --git a/arch/arm/mach-imx/mx3x.h b/arch/arm/mach-imx/mx3x.h index 96fb4fbc8ad7..6fec6114c2f1 100644 --- a/arch/arm/mach-imx/mx3x.h +++ b/arch/arm/mach-imx/mx3x.h @@ -185,11 +185,4 @@ #define MX3x_PROD_SIGNATURE 0x1 /* For MX31 */ -/* Mandatory defines used globally */ - -#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) -extern int mx35_revision(void); -extern int mx31_revision(void); -#endif - #endif /* ifndef __MACH_MX3x_H__ */ diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index 4c1343df2ba4..c4436d4fd6fd 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2007, 2010-2015 Freescale Semiconductor, Inc. * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) * * This program is free software; you can redistribute it and/or @@ -38,22 +38,7 @@ #define MXC_CPU_IMX6DL 0x61 #define MXC_CPU_IMX6SX 0x62 #define MXC_CPU_IMX6Q 0x63 - -#define IMX_CHIP_REVISION_1_0 0x10 -#define IMX_CHIP_REVISION_1_1 0x11 -#define IMX_CHIP_REVISION_1_2 0x12 -#define IMX_CHIP_REVISION_1_3 0x13 -#define IMX_CHIP_REVISION_1_4 0x14 -#define IMX_CHIP_REVISION_1_5 0x15 -#define IMX_CHIP_REVISION_2_0 0x20 -#define IMX_CHIP_REVISION_2_1 0x21 -#define IMX_CHIP_REVISION_2_2 0x22 -#define IMX_CHIP_REVISION_2_3 0x23 -#define IMX_CHIP_REVISION_3_0 0x30 -#define IMX_CHIP_REVISION_3_1 0x31 -#define IMX_CHIP_REVISION_3_2 0x32 -#define IMX_CHIP_REVISION_3_3 0x33 -#define IMX_CHIP_REVISION_UNKNOWN 0xff +#define MXC_CPU_IMX7D 0x72 #define IMX_DDR_TYPE_LPDDR2 1 @@ -185,6 +170,11 @@ static inline bool cpu_is_imx6q(void) return __mxc_cpu_type == MXC_CPU_IMX6Q; } +static inline bool cpu_is_imx7d(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX7D; +} + struct cpu_op { u32 cpu_rate; }; diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index f1f80ab73e69..0309ccda36a9 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -13,7 +13,14 @@ #include <linux/io.h> #include <linux/err.h> #include <linux/export.h> + +#include <linux/genalloc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> + #include <asm/cacheflush.h> +#include <asm/fncpy.h> #include <asm/system_misc.h> #include <asm/tlbflush.h> @@ -49,29 +56,91 @@ */ #define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF +struct imx5_suspend_io_state { + u32 offset; + u32 clear; + u32 set; + u32 saved_value; +}; + struct imx5_pm_data { + phys_addr_t ccm_addr; phys_addr_t cortex_addr; phys_addr_t gpc_addr; + phys_addr_t m4if_addr; + phys_addr_t iomuxc_addr; + void (*suspend_asm)(void __iomem *ocram_vbase); + const u32 *suspend_asm_sz; + const struct imx5_suspend_io_state *suspend_io_config; + int suspend_io_count; +}; + +static const struct imx5_suspend_io_state imx53_suspend_io_config[] = { +#define MX53_DSE_HIGHZ_MASK (0x7 << 19) + {.offset = 0x584, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM0 */ + {.offset = 0x594, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM1 */ + {.offset = 0x560, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM2 */ + {.offset = 0x554, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM3 */ + {.offset = 0x574, .clear = MX53_DSE_HIGHZ_MASK}, /* CAS */ + {.offset = 0x588, .clear = MX53_DSE_HIGHZ_MASK}, /* RAS */ + {.offset = 0x578, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_0 */ + {.offset = 0x570, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_1 */ + + {.offset = 0x580, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT0 */ + {.offset = 0x564, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT1 */ + {.offset = 0x57c, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS0 */ + {.offset = 0x590, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS1 */ + {.offset = 0x568, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS2 */ + {.offset = 0x558, .clear = MX53_DSE_HIGHZ_MASK}, /* SDSQ3 */ + {.offset = 0x6f0, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_ADDS */ + {.offset = 0x718, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_BODS */ + {.offset = 0x71c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B1DS */ + {.offset = 0x728, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B2DS */ + {.offset = 0x72c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B3DS */ + + /* Controls the CKE signal which is required to leave self refresh */ + {.offset = 0x720, .clear = MX53_DSE_HIGHZ_MASK, .set = 1 << 19}, /* CTLDS */ }; static const struct imx5_pm_data imx51_pm_data __initconst = { + .ccm_addr = 0x73fd4000, .cortex_addr = 0x83fa0000, .gpc_addr = 0x73fd8000, }; static const struct imx5_pm_data imx53_pm_data __initconst = { + .ccm_addr = 0x53fd4000, .cortex_addr = 0x63fa0000, .gpc_addr = 0x53fd8000, + .m4if_addr = 0x63fd8000, + .iomuxc_addr = 0x53fa8000, + .suspend_asm = &imx53_suspend, + .suspend_asm_sz = &imx53_suspend_sz, + .suspend_io_config = imx53_suspend_io_config, + .suspend_io_count = ARRAY_SIZE(imx53_suspend_io_config), }; +#define MX5_MAX_SUSPEND_IOSTATE ARRAY_SIZE(imx53_suspend_io_config) + +/* + * This structure is for passing necessary data for low level ocram + * suspend code(arch/arm/mach-imx/suspend-imx53.S), if this struct + * definition is changed, the offset definition in that file + * must be also changed accordingly otherwise, the suspend to ocram + * function will be broken! + */ +struct imx5_cpu_suspend_info { + void __iomem *m4if_base; + void __iomem *iomuxc_base; + u32 io_count; + struct imx5_suspend_io_state io_state[MX5_MAX_SUSPEND_IOSTATE]; +} __aligned(8); + static void __iomem *ccm_base; static void __iomem *cortex_base; static void __iomem *gpc_base; - -void __init imx5_pm_set_ccm_base(void __iomem *base) -{ - ccm_base = base; -} +static void __iomem *suspend_ocram_base; +static void (*imx5_suspend_in_ocram_fn)(void __iomem *ocram_vbase); /* * set cpu low power mode before WFI instruction. This function is called @@ -161,8 +230,15 @@ static int mx5_suspend_enter(suspend_state_t state) /*clear the EMPGC0/1 bits */ __raw_writel(0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR); __raw_writel(0, gpc_base + MXC_SRPG_EMPGC1_SRPGCR); + + if (imx5_suspend_in_ocram_fn) + imx5_suspend_in_ocram_fn(suspend_ocram_base); + else + cpu_do_idle(); + + } else { + cpu_do_idle(); } - cpu_do_idle(); /* return registers to default idle state */ mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); @@ -194,6 +270,111 @@ static void imx5_pm_idle(void) imx5_cpu_do_idle(); } +static int __init imx_suspend_alloc_ocram( + size_t size, + void __iomem **virt_out, + phys_addr_t *phys_out) +{ + struct device_node *node; + struct platform_device *pdev; + struct gen_pool *ocram_pool; + unsigned long ocram_base; + void __iomem *virt; + phys_addr_t phys; + int ret = 0; + + /* Copied from imx6: TODO factorize */ + node = of_find_compatible_node(NULL, NULL, "mmio-sram"); + if (!node) { + pr_warn("%s: failed to find ocram node!\n", __func__); + return -ENODEV; + } + + pdev = of_find_device_by_node(node); + if (!pdev) { + pr_warn("%s: failed to find ocram device!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_pool = dev_get_gen_pool(&pdev->dev); + if (!ocram_pool) { + pr_warn("%s: ocram pool unavailable!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_base = gen_pool_alloc(ocram_pool, size); + if (!ocram_base) { + pr_warn("%s: unable to alloc ocram!\n", __func__); + ret = -ENOMEM; + goto put_node; + } + + phys = gen_pool_virt_to_phys(ocram_pool, ocram_base); + virt = __arm_ioremap_exec(phys, size, false); + if (phys_out) + *phys_out = phys; + if (virt_out) + *virt_out = virt; + +put_node: + of_node_put(node); + + return ret; +} + +static int __init imx5_suspend_init(const struct imx5_pm_data *soc_data) +{ + struct imx5_cpu_suspend_info *suspend_info; + int ret; + /* Need this to avoid compile error due to const typeof in fncpy.h */ + void (*suspend_asm)(void __iomem *) = soc_data->suspend_asm; + + if (!suspend_asm) + return 0; + + if (!soc_data->suspend_asm_sz || !*soc_data->suspend_asm_sz) + return -EINVAL; + + ret = imx_suspend_alloc_ocram( + *soc_data->suspend_asm_sz + sizeof(*suspend_info), + &suspend_ocram_base, NULL); + if (ret) + return ret; + + suspend_info = suspend_ocram_base; + + suspend_info->io_count = soc_data->suspend_io_count; + memcpy(suspend_info->io_state, soc_data->suspend_io_config, + sizeof(*suspend_info->io_state) * soc_data->suspend_io_count); + + suspend_info->m4if_base = ioremap(soc_data->m4if_addr, SZ_16K); + if (!suspend_info->m4if_base) { + ret = -ENOMEM; + goto failed_map_m4if; + } + + suspend_info->iomuxc_base = ioremap(soc_data->iomuxc_addr, SZ_16K); + if (!suspend_info->iomuxc_base) { + ret = -ENOMEM; + goto failed_map_iomuxc; + } + + imx5_suspend_in_ocram_fn = fncpy( + suspend_ocram_base + sizeof(*suspend_info), + suspend_asm, + *soc_data->suspend_asm_sz); + + return 0; + +failed_map_iomuxc: + iounmap(suspend_info->m4if_base); + +failed_map_m4if: + return ret; +} + static int __init imx5_pm_common_init(const struct imx5_pm_data *data) { int ret; @@ -208,6 +389,7 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data) arm_pm_idle = imx5_pm_idle; + ccm_base = ioremap(data->ccm_addr, SZ_16K); cortex_base = ioremap(data->cortex_addr, SZ_16K); gpc_base = ioremap(data->gpc_addr, SZ_16K); WARN_ON(!ccm_base || !cortex_base || !gpc_base); @@ -219,6 +401,11 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data) if (ret) pr_warn("%s: cpuidle init failed %d\n", __func__, ret); + ret = imx5_suspend_init(data); + if (ret) + pr_warn("%s: No DDR LPM support with suspend %d!\n", + __func__, ret); + suspend_set_ops(&mx5_suspend_ops); return 0; @@ -226,10 +413,12 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data) void __init imx51_pm_init(void) { - imx5_pm_common_init(&imx51_pm_data); + if (IS_ENABLED(CONFIG_SOC_IMX51)) + imx5_pm_common_init(&imx51_pm_data); } void __init imx53_pm_init(void) { - imx5_pm_common_init(&imx53_pm_data); + if (IS_ENABLED(CONFIG_SOC_IMX53)) + imx5_pm_common_init(&imx53_pm_data); } diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 6a7c6fc780cc..b01650d94f91 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -255,7 +255,7 @@ static void imx6q_enable_wb(bool enable) writel_relaxed(val, ccm_base + CCR); } -int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) +int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) { u32 val = readl_relaxed(ccm_base + CLPCR); @@ -340,7 +340,7 @@ static int imx6q_pm_enter(suspend_state_t state) { switch (state) { case PM_SUSPEND_STANDBY: - imx6q_set_lpm(STOP_POWER_ON); + imx6_set_lpm(STOP_POWER_ON); imx6q_set_int_mem_clk_lpm(true); imx_gpc_pre_suspend(false); if (cpu_is_imx6sl()) @@ -350,10 +350,10 @@ static int imx6q_pm_enter(suspend_state_t state) if (cpu_is_imx6sl()) imx6sl_set_wait_clk(false); imx_gpc_post_resume(); - imx6q_set_lpm(WAIT_CLOCKED); + imx6_set_lpm(WAIT_CLOCKED); break; case PM_SUSPEND_MEM: - imx6q_set_lpm(STOP_POWER_OFF); + imx6_set_lpm(STOP_POWER_OFF); imx6q_set_int_mem_clk_lpm(false); imx6q_enable_wb(true); /* @@ -373,7 +373,7 @@ static int imx6q_pm_enter(suspend_state_t state) imx6_enable_rbc(false); imx6q_enable_wb(false); imx6q_set_int_mem_clk_lpm(true); - imx6q_set_lpm(WAIT_CLOCKED); + imx6_set_lpm(WAIT_CLOCKED); break; default: return -EINVAL; @@ -392,11 +392,6 @@ static const struct platform_suspend_ops imx6q_pm_ops = { .valid = imx6q_pm_valid, }; -void __init imx6q_pm_set_ccm_base(void __iomem *base) -{ - ccm_base = base; -} - static int __init imx6_pm_get_base(struct imx6_pm_base *base, const char *compat) { @@ -482,8 +477,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) /* * ccm physical address is not used by asm code currently, - * so get ccm virtual address directly, as we already have - * it from ccm driver. + * so get ccm virtual address directly. */ pm_info->ccm_base.vbase = ccm_base; @@ -568,7 +562,7 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata /* * This is for SW workaround step #1 of ERR007265, see comments - * in imx6q_set_lpm for details of this errata. + * in imx6_set_lpm for details of this errata. * Force IOMUXC irq pending, so that the interrupt to GPC can be * used to deassert dsm_request signal when the signal gets * asserted unexpectedly. @@ -579,6 +573,24 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata IMX6Q_GPR1_GINT); } +void __init imx6_pm_ccm_init(const char *ccm_compat) +{ + struct device_node *np; + u32 val; + + np = of_find_compatible_node(NULL, NULL, ccm_compat); + ccm_base = of_iomap(np, 0); + BUG_ON(!ccm_base); + + /* + * Initialize CCM_CLPCR_LPM into RUN mode to avoid ARM core + * clock being shut down unexpectedly by WAIT mode. + */ + val = readl_relaxed(ccm_base + CLPCR); + val &= ~BM_CLPCR_LPM; + writel_relaxed(val, ccm_base + CLPCR); +} + void __init imx6q_pm_init(void) { imx6_pm_common_init(&imx6q_pm_data); diff --git a/arch/arm/mach-imx/suspend-imx53.S b/arch/arm/mach-imx/suspend-imx53.S new file mode 100644 index 000000000000..5ed078ad110a --- /dev/null +++ b/arch/arm/mach-imx/suspend-imx53.S @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. + */ +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/linkage.h> + +#define M4IF_MCR0_OFFSET (0x008C) +#define M4IF_MCR0_FDVFS (0x1 << 11) +#define M4IF_MCR0_FDVACK (0x1 << 27) + + .align 3 + +/* + * ==================== low level suspend ==================== + * + * On entry + * r0: pm_info structure address; + * + * suspend ocram space layout: + * ======================== high address ====================== + * . + * . + * . + * ^ + * ^ + * ^ + * imx53_suspend code + * PM_INFO structure(imx53_suspend_info) + * ======================== low address ======================= + */ + +/* Offsets of members of struct imx53_suspend_info */ +#define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0 +#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4 +#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8 +#define SUSPEND_INFO_MX53_IO_STATE_OFFSET 0xc + +ENTRY(imx53_suspend) + stmfd sp!, {r4,r5,r6,r7} + + /* Save pad config */ + ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET] + cmp r1, #0 + beq skip_pad_conf_1 + + add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET + ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET] + +1: + ldr r5, [r2], #12 /* IOMUXC register offset */ + ldr r6, [r3, r5] /* current value */ + str r6, [r2], #4 /* save area */ + subs r1, r1, #1 + bne 1b + +skip_pad_conf_1: + /* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */ + ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET] + ldr r2,[r1, #M4IF_MCR0_OFFSET] + orr r2, r2, #M4IF_MCR0_FDVFS + str r2,[r1, #M4IF_MCR0_OFFSET] + + /* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */ +wait_sr_ack: + ldr r2,[r1, #M4IF_MCR0_OFFSET] + ands r2, r2, #M4IF_MCR0_FDVACK + beq wait_sr_ack + + /* Set pad config */ + ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET] + cmp r1, #0 + beq skip_pad_conf_2 + + add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET + ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET] + +2: + ldr r5, [r2], #4 /* IOMUXC register offset */ + ldr r6, [r2], #4 /* clear */ + ldr r7, [r3, r5] + bic r7, r7, r6 + ldr r6, [r2], #8 /* set */ + orr r7, r7, r6 + str r7, [r3, r5] + subs r1, r1, #1 + bne 2b + +skip_pad_conf_2: + /* Zzz, enter stop mode */ + wfi + nop + nop + nop + nop + + /* Restore pad config */ + ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET] + cmp r1, #0 + beq skip_pad_conf_3 + + add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET + ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET] + +3: + ldr r5, [r2], #12 /* IOMUXC register offset */ + ldr r6, [r2], #4 /* saved value */ + str r6, [r3, r5] + subs r1, r1, #1 + bne 3b + +skip_pad_conf_3: + /* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */ + ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET] + ldr r2,[r1, #M4IF_MCR0_OFFSET] + bic r2, r2, #M4IF_MCR0_FDVFS + str r2,[r1, #M4IF_MCR0_OFFSET] + + /* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */ +wait_ar_ack: + ldr r2,[r1, #M4IF_MCR0_OFFSET] + ands r2, r2, #M4IF_MCR0_FDVACK + bne wait_ar_ack + + /* Restore registers */ + ldmfd sp!, {r4,r5,r6,r7} + mov pc, lr + +ENDPROC(imx53_suspend) + +ENTRY(imx53_suspend_sz) + .word . - imx53_suspend diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c deleted file mode 100644 index 15d18e198303..000000000000 --- a/arch/arm/mach-imx/time.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * linux/arch/arm/plat-mxc/time.c - * - * Copyright (C) 2000-2001 Deep Blue Solutions - * Copyright (C) 2002 Shane Nay (shane@minirl.com) - * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com) - * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/clockchips.h> -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/sched_clock.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> - -#include <asm/mach/time.h> - -#include "common.h" -#include "hardware.h" - -/* - * There are 2 versions of the timer hardware on Freescale MXC hardware. - * Version 1: MX1/MXL, MX21, MX27. - * Version 2: MX25, MX31, MX35, MX37, MX51 - */ - -/* defines common for all i.MX */ -#define MXC_TCTL 0x00 -#define MXC_TCTL_TEN (1 << 0) /* Enable module */ -#define MXC_TPRER 0x04 - -/* MX1, MX21, MX27 */ -#define MX1_2_TCTL_CLK_PCLK1 (1 << 1) -#define MX1_2_TCTL_IRQEN (1 << 4) -#define MX1_2_TCTL_FRR (1 << 8) -#define MX1_2_TCMP 0x08 -#define MX1_2_TCN 0x10 -#define MX1_2_TSTAT 0x14 - -/* MX21, MX27 */ -#define MX2_TSTAT_CAPT (1 << 1) -#define MX2_TSTAT_COMP (1 << 0) - -/* MX31, MX35, MX25, MX5, MX6 */ -#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ -#define V2_TCTL_CLK_IPG (1 << 6) -#define V2_TCTL_CLK_PER (2 << 6) -#define V2_TCTL_CLK_OSC_DIV8 (5 << 6) -#define V2_TCTL_FRR (1 << 9) -#define V2_TCTL_24MEN (1 << 10) -#define V2_TPRER_PRE24M 12 -#define V2_IR 0x0c -#define V2_TSTAT 0x08 -#define V2_TSTAT_OF1 (1 << 0) -#define V2_TCN 0x24 -#define V2_TCMP 0x10 - -#define V2_TIMER_RATE_OSC_DIV8 3000000 - -#define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) -#define timer_is_v2() (!timer_is_v1()) - -static struct clock_event_device clockevent_mxc; -static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED; - -static void __iomem *timer_base; - -static inline void gpt_irq_disable(void) -{ - unsigned int tmp; - - if (timer_is_v2()) - __raw_writel(0, timer_base + V2_IR); - else { - tmp = __raw_readl(timer_base + MXC_TCTL); - __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL); - } -} - -static inline void gpt_irq_enable(void) -{ - if (timer_is_v2()) - __raw_writel(1<<0, timer_base + V2_IR); - else { - __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN, - timer_base + MXC_TCTL); - } -} - -static void gpt_irq_acknowledge(void) -{ - if (timer_is_v1()) { - if (cpu_is_mx1()) - __raw_writel(0, timer_base + MX1_2_TSTAT); - else - __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, - timer_base + MX1_2_TSTAT); - } else if (timer_is_v2()) - __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT); -} - -static void __iomem *sched_clock_reg; - -static u64 notrace mxc_read_sched_clock(void) -{ - return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; -} - -static struct delay_timer imx_delay_timer; - -static unsigned long imx_read_current_timer(void) -{ - return __raw_readl(sched_clock_reg); -} - -static int __init mxc_clocksource_init(struct clk *timer_clk) -{ - unsigned int c = clk_get_rate(timer_clk); - void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN); - - imx_delay_timer.read_current_timer = &imx_read_current_timer; - imx_delay_timer.freq = c; - register_current_timer_delay(&imx_delay_timer); - - sched_clock_reg = reg; - - sched_clock_register(mxc_read_sched_clock, 32, c); - return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, - clocksource_mmio_readl_up); -} - -/* clock event */ - -static int mx1_2_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long tcmp; - - tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt; - - __raw_writel(tcmp, timer_base + MX1_2_TCMP); - - return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ? - -ETIME : 0; -} - -static int v2_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long tcmp; - - tcmp = __raw_readl(timer_base + V2_TCN) + evt; - - __raw_writel(tcmp, timer_base + V2_TCMP); - - return evt < 0x7fffffff && - (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ? - -ETIME : 0; -} - -#ifdef DEBUG -static const char *clock_event_mode_label[] = { - [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", - [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", - [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", - [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED", - [CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME", -}; -#endif /* DEBUG */ - -static void mxc_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned long flags; - - /* - * The timer interrupt generation is disabled at least - * for enough time to call mxc_set_next_event() - */ - local_irq_save(flags); - - /* Disable interrupt in GPT module */ - gpt_irq_disable(); - - if (mode != clockevent_mode) { - /* Set event time into far-far future */ - if (timer_is_v2()) - __raw_writel(__raw_readl(timer_base + V2_TCN) - 3, - timer_base + V2_TCMP); - else - __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3, - timer_base + MX1_2_TCMP); - - /* Clear pending interrupt */ - gpt_irq_acknowledge(); - } - -#ifdef DEBUG - printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n", - clock_event_mode_label[clockevent_mode], - clock_event_mode_label[mode]); -#endif /* DEBUG */ - - /* Remember timer mode */ - clockevent_mode = mode; - local_irq_restore(flags); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - printk(KERN_ERR"mxc_set_mode: Periodic mode is not " - "supported for i.MX\n"); - break; - case CLOCK_EVT_MODE_ONESHOT: - /* - * Do not put overhead of interrupt enable/disable into - * mxc_set_next_event(), the core has about 4 minutes - * to call mxc_set_next_event() or shutdown clock after - * mode switching - */ - local_irq_save(flags); - gpt_irq_enable(); - local_irq_restore(flags); - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_RESUME: - /* Left event sources disabled, no more interrupts appear */ - break; - } -} - -/* - * IRQ handler for the timer - */ -static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &clockevent_mxc; - uint32_t tstat; - - if (timer_is_v2()) - tstat = __raw_readl(timer_base + V2_TSTAT); - else - tstat = __raw_readl(timer_base + MX1_2_TSTAT); - - gpt_irq_acknowledge(); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction mxc_timer_irq = { - .name = "i.MX Timer Tick", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = mxc_timer_interrupt, -}; - -static struct clock_event_device clockevent_mxc = { - .name = "mxc_timer1", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = mxc_set_mode, - .set_next_event = mx1_2_set_next_event, - .rating = 200, -}; - -static int __init mxc_clockevent_init(struct clk *timer_clk) -{ - if (timer_is_v2()) - clockevent_mxc.set_next_event = v2_set_next_event; - - clockevent_mxc.cpumask = cpumask_of(0); - clockevents_config_and_register(&clockevent_mxc, - clk_get_rate(timer_clk), - 0xff, 0xfffffffe); - - return 0; -} - -static void __init _mxc_timer_init(int irq, - struct clk *clk_per, struct clk *clk_ipg) -{ - uint32_t tctl_val; - - if (IS_ERR(clk_per)) { - pr_err("i.MX timer: unable to get clk\n"); - return; - } - - if (!IS_ERR(clk_ipg)) - clk_prepare_enable(clk_ipg); - - clk_prepare_enable(clk_per); - - /* - * Initialise to a known state (all timers off, and timing reset) - */ - - __raw_writel(0, timer_base + MXC_TCTL); - __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ - - if (timer_is_v2()) { - tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; - if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) { - tctl_val |= V2_TCTL_CLK_OSC_DIV8; - if (cpu_is_imx6dl() || cpu_is_imx6sx()) { - /* 24 / 8 = 3 MHz */ - __raw_writel(7 << V2_TPRER_PRE24M, - timer_base + MXC_TPRER); - tctl_val |= V2_TCTL_24MEN; - } - } else { - tctl_val |= V2_TCTL_CLK_PER; - } - } else { - tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; - } - - __raw_writel(tctl_val, timer_base + MXC_TCTL); - - /* init and register the timer to the framework */ - mxc_clocksource_init(clk_per); - mxc_clockevent_init(clk_per); - - /* Make irqs happen */ - setup_irq(irq, &mxc_timer_irq); -} - -void __init mxc_timer_init(void __iomem *base, int irq) -{ - struct clk *clk_per = clk_get_sys("imx-gpt.0", "per"); - struct clk *clk_ipg = clk_get_sys("imx-gpt.0", "ipg"); - - timer_base = base; - - _mxc_timer_init(irq, clk_per, clk_ipg); -} - -static void __init mxc_timer_init_dt(struct device_node *np) -{ - struct clk *clk_per, *clk_ipg; - int irq; - - if (timer_base) - return; - - timer_base = of_iomap(np, 0); - WARN_ON(!timer_base); - irq = irq_of_parse_and_map(np, 0); - - clk_ipg = of_clk_get_by_name(np, "ipg"); - - /* Try osc_per first, and fall back to per otherwise */ - clk_per = of_clk_get_by_name(np, "osc_per"); - if (IS_ERR(clk_per)) - clk_per = of_clk_get_by_name(np, "per"); - - _mxc_timer_init(irq, clk_per, clk_ipg); -} -CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx50_timer, "fsl,imx50-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx51_timer, "fsl,imx51-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx53_timer, "fsl,imx53-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx6q_timer, "fsl,imx6q-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx6sl_timer, "fsl,imx6sl-gpt", mxc_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(mx6sx_timer, "fsl,imx6sx-gpt", mxc_timer_init_dt); 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-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S index 3d1e1c250a1a..5d7fb596bf4a 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S +++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S @@ -17,11 +17,10 @@ #include <asm/assembler.h> #include <mach/board-ams-delta.h> - -#include <mach/irqs.h> #include <mach/ams-delta-fiq.h> #include "iomap.h" +#include "soc.h" /* * GPIO related definitions, copied from arch/arm/plat-omap/gpio.c. diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 2aab761ee68d..a95499ea8706 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -626,6 +626,7 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)") .map_io = ams_delta_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = ams_delta_init, .init_late = ams_delta_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index 702d58039cc1..0fb51d22c8b5 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -362,6 +362,7 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample") .map_io = omap_fsample_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_fsample_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index e1d9171774bc..9708629f8c5f 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -82,6 +82,7 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") .map_io = omap16xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_generic_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 5b45d266d83e..8340d684d8b6 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -426,6 +426,7 @@ MACHINE_START(OMAP_H2, "TI-H2") .map_io = omap16xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = h2_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index 17d77914d769..43aab63cbc39 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -16,6 +16,7 @@ #include <linux/i2c/tps65010.h> +#include "common.h" #include "board-h3.h" #include "mmc.h" diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index bfed4f928663..086ff34e072b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -452,6 +452,7 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") .map_io = omap16xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = h3_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index 35a2379b986f..9525ef9bc6c0 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -601,6 +601,7 @@ MACHINE_START(HERALD, "HTC Herald") .map_io = htcherald_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = htcherald_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index c49ce83cc1eb..ed4e045c2ad8 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -456,6 +456,7 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") .map_io = innovator_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = innovator_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 85089d821982..9f6c7af3a4e7 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -294,6 +294,7 @@ MACHINE_START(NOKIA770, "Nokia 770") .map_io = omap16xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_nokia770_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 7436d4cf6596..0efd165b8227 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -610,6 +610,7 @@ MACHINE_START(OMAP_OSK, "TI-OSK") .map_io = omap16xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = osk_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 3b8e98f4353c..1142ae431fe0 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -235,6 +235,7 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") .map_io = omap15xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_palmte_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index ca501208825f..54a547a96950 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -282,6 +282,7 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T") .map_io = omap15xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_palmtt_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index 470e12d67360..87ec04ae40dd 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -297,6 +297,7 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71") .map_io = omap15xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_palmz71_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 8b2f7127f716..3d76f05407f0 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -324,6 +324,7 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") .map_io = omap_perseus2_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_perseus2_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 29e526235dc2..939991ea33d5 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -343,6 +343,7 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1") .map_io = omap15xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = omap_sx1_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 4677a9ccb3cb..e960687d0cb1 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -288,6 +288,7 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") .map_io = omap15xx_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, + .handle_irq = omap1_handle_irq, .init_machine = voiceblue_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h index 732f8ee2fcd2..65bb6e8085de 100644 --- a/arch/arm/mach-omap1/common.h +++ b/arch/arm/mach-omap1/common.h @@ -30,10 +30,14 @@ #include <linux/i2c-omap.h> #include <linux/reboot.h> +#include <asm/exception.h> + #include <plat/i2c.h> #include <mach/irqs.h> +#include "soc.h" + #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) void omap7xx_map_io(void); #else @@ -73,6 +77,7 @@ static inline int omap_serial_wakeup_init(void) void omap1_init_early(void); void omap1_init_irq(void); +void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs); void omap1_init_late(void); void omap1_restart(enum reboot_mode, const char *); @@ -91,8 +96,6 @@ static inline int __init omap_32k_timer_init(void) } #endif -extern u32 omap_irq_flags; - #ifdef CONFIG_ARCH_OMAP16XX extern int ocpi_enable(void); #else diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 4be601b638d7..7b02ed218a42 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -28,7 +28,7 @@ #include <linux/omap-dma.h> #include <mach/tc.h> -#include <mach/irqs.h> +#include "soc.h" #define OMAP1_DMA_BASE (0xfffed800) #define OMAP1_LOGICAL_DMA_CH_COUNT 17 diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 6e6ec93dcbb3..5b7a29b294d4 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -21,6 +21,8 @@ #include <mach/irqs.h> +#include "soc.h" + #define OMAP1610_GPIO1_BASE 0xfffbe400 #define OMAP1610_GPIO2_BASE 0xfffbec00 #define OMAP1610_GPIO3_BASE 0xfffbb400 diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 4612d2506a2d..0e5f68de23bf 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -21,6 +21,8 @@ #include <mach/irqs.h> +#include "soc.h" + #define OMAP7XX_GPIO1_BASE 0xfffbc000 #define OMAP7XX_GPIO2_BASE 0xfffbc800 #define OMAP7XX_GPIO3_BASE 0xfffbd000 diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c index 7f5761cffd2e..82887d645a6a 100644 --- a/arch/arm/mach-omap1/i2c.c +++ b/arch/arm/mach-omap1/i2c.c @@ -27,7 +27,6 @@ #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 -#define OMAP1_INT_I2C (32 + 4) static const char name[] = "omap_i2c"; @@ -67,7 +66,7 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata, res[0].start = OMAP1_I2C_BASE; res[0].end = res[0].start + OMAP_I2C_SIZE; res[0].flags = IORESOURCE_MEM; - res[1].start = OMAP1_INT_I2C; + res[1].start = INT_I2C; res[1].flags = IORESOURCE_IRQ; pdev->resource = res; diff --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S deleted file mode 100644 index 78a8c6c24764..000000000000 --- a/arch/arm/mach-omap1/include/mach/entry-macro.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/arm/mach-omap1/include/mach/entry-macro.S - * - * Low-level IRQ helper macros for OMAP-based platforms - * - * Copyright (C) 2009 Texas Instruments - * - * 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 <mach/hardware.h> -#include <mach/irqs.h> - - .macro get_irqnr_preamble, base, tmp - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =OMAP1_IO_ADDRESS(OMAP_IH1_BASE) - ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET] - ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET] - mov \irqstat, #0xffffffff - bic \tmp, \irqstat, \tmp - tst \irqnr, \tmp - beq 1510f - - ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET] - ldr \tmp, =omap_irq_flags @ irq flags address - ldr \tmp, [\tmp, #0] @ irq flags value - cmp \irqnr, #0 - ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] - cmpeq \irqnr, \tmp - ldreq \base, =OMAP1_IO_ADDRESS(OMAP_IH2_BASE) - ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] - addeqs \irqnr, \irqnr, #32 -1510: - .endm - diff --git a/arch/arm/mach-omap1/include/mach/irqs.h b/arch/arm/mach-omap1/include/mach/irqs.h index 729992d7d26a..9050085271bc 100644 --- a/arch/arm/mach-omap1/include/mach/irqs.h +++ b/arch/arm/mach-omap1/include/mach/irqs.h @@ -34,84 +34,84 @@ * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below * */ -#define INT_CAMERA 1 -#define INT_FIQ 3 -#define INT_RTDX 6 -#define INT_DSP_MMU_ABORT 7 -#define INT_HOST 8 -#define INT_ABORT 9 -#define INT_BRIDGE_PRIV 13 -#define INT_GPIO_BANK1 14 -#define INT_UART3 15 -#define INT_TIMER3 16 -#define INT_DMA_CH0_6 19 -#define INT_DMA_CH1_7 20 -#define INT_DMA_CH2_8 21 -#define INT_DMA_CH3 22 -#define INT_DMA_CH4 23 -#define INT_DMA_CH5 24 -#define INT_TIMER1 26 -#define INT_WD_TIMER 27 -#define INT_BRIDGE_PUB 28 -#define INT_TIMER2 30 -#define INT_LCD_CTRL 31 +#define INT_CAMERA (NR_IRQS_LEGACY + 1) +#define INT_FIQ (NR_IRQS_LEGACY + 3) +#define INT_RTDX (NR_IRQS_LEGACY + 6) +#define INT_DSP_MMU_ABORT (NR_IRQS_LEGACY + 7) +#define INT_HOST (NR_IRQS_LEGACY + 8) +#define INT_ABORT (NR_IRQS_LEGACY + 9) +#define INT_BRIDGE_PRIV (NR_IRQS_LEGACY + 13) +#define INT_GPIO_BANK1 (NR_IRQS_LEGACY + 14) +#define INT_UART3 (NR_IRQS_LEGACY + 15) +#define INT_TIMER3 (NR_IRQS_LEGACY + 16) +#define INT_DMA_CH0_6 (NR_IRQS_LEGACY + 19) +#define INT_DMA_CH1_7 (NR_IRQS_LEGACY + 20) +#define INT_DMA_CH2_8 (NR_IRQS_LEGACY + 21) +#define INT_DMA_CH3 (NR_IRQS_LEGACY + 22) +#define INT_DMA_CH4 (NR_IRQS_LEGACY + 23) +#define INT_DMA_CH5 (NR_IRQS_LEGACY + 24) +#define INT_TIMER1 (NR_IRQS_LEGACY + 26) +#define INT_WD_TIMER (NR_IRQS_LEGACY + 27) +#define INT_BRIDGE_PUB (NR_IRQS_LEGACY + 28) +#define INT_TIMER2 (NR_IRQS_LEGACY + 30) +#define INT_LCD_CTRL (NR_IRQS_LEGACY + 31) /* * OMAP-1510 specific IRQ numbers for interrupt handler 1 */ -#define INT_1510_IH2_IRQ 0 -#define INT_1510_RES2 2 -#define INT_1510_SPI_TX 4 -#define INT_1510_SPI_RX 5 -#define INT_1510_DSP_MAILBOX1 10 -#define INT_1510_DSP_MAILBOX2 11 -#define INT_1510_RES12 12 -#define INT_1510_LB_MMU 17 -#define INT_1510_RES18 18 -#define INT_1510_LOCAL_BUS 29 +#define INT_1510_IH2_IRQ (NR_IRQS_LEGACY + 0) +#define INT_1510_RES2 (NR_IRQS_LEGACY + 2) +#define INT_1510_SPI_TX (NR_IRQS_LEGACY + 4) +#define INT_1510_SPI_RX (NR_IRQS_LEGACY + 5) +#define INT_1510_DSP_MAILBOX1 (NR_IRQS_LEGACY + 10) +#define INT_1510_DSP_MAILBOX2 (NR_IRQS_LEGACY + 11) +#define INT_1510_RES12 (NR_IRQS_LEGACY + 12) +#define INT_1510_LB_MMU (NR_IRQS_LEGACY + 17) +#define INT_1510_RES18 (NR_IRQS_LEGACY + 18) +#define INT_1510_LOCAL_BUS (NR_IRQS_LEGACY + 29) /* * OMAP-1610 specific IRQ numbers for interrupt handler 1 */ #define INT_1610_IH2_IRQ INT_1510_IH2_IRQ -#define INT_1610_IH2_FIQ 2 -#define INT_1610_McBSP2_TX 4 -#define INT_1610_McBSP2_RX 5 -#define INT_1610_DSP_MAILBOX1 10 -#define INT_1610_DSP_MAILBOX2 11 -#define INT_1610_LCD_LINE 12 -#define INT_1610_GPTIMER1 17 -#define INT_1610_GPTIMER2 18 -#define INT_1610_SSR_FIFO_0 29 +#define INT_1610_IH2_FIQ (NR_IRQS_LEGACY + 2) +#define INT_1610_McBSP2_TX (NR_IRQS_LEGACY + 4) +#define INT_1610_McBSP2_RX (NR_IRQS_LEGACY + 5) +#define INT_1610_DSP_MAILBOX1 (NR_IRQS_LEGACY + 10) +#define INT_1610_DSP_MAILBOX2 (NR_IRQS_LEGACY + 11) +#define INT_1610_LCD_LINE (NR_IRQS_LEGACY + 12) +#define INT_1610_GPTIMER1 (NR_IRQS_LEGACY + 17) +#define INT_1610_GPTIMER2 (NR_IRQS_LEGACY + 18) +#define INT_1610_SSR_FIFO_0 (NR_IRQS_LEGACY + 29) /* * OMAP-7xx specific IRQ numbers for interrupt handler 1 */ -#define INT_7XX_IH2_FIQ 0 -#define INT_7XX_IH2_IRQ 1 -#define INT_7XX_USB_NON_ISO 2 -#define INT_7XX_USB_ISO 3 -#define INT_7XX_ICR 4 -#define INT_7XX_EAC 5 -#define INT_7XX_GPIO_BANK1 6 -#define INT_7XX_GPIO_BANK2 7 -#define INT_7XX_GPIO_BANK3 8 -#define INT_7XX_McBSP2TX 10 -#define INT_7XX_McBSP2RX 11 -#define INT_7XX_McBSP2RX_OVF 12 -#define INT_7XX_LCD_LINE 14 -#define INT_7XX_GSM_PROTECT 15 -#define INT_7XX_TIMER3 16 -#define INT_7XX_GPIO_BANK5 17 -#define INT_7XX_GPIO_BANK6 18 -#define INT_7XX_SPGIO_WR 29 +#define INT_7XX_IH2_FIQ (NR_IRQS_LEGACY + 0) +#define INT_7XX_IH2_IRQ (NR_IRQS_LEGACY + 1) +#define INT_7XX_USB_NON_ISO (NR_IRQS_LEGACY + 2) +#define INT_7XX_USB_ISO (NR_IRQS_LEGACY + 3) +#define INT_7XX_ICR (NR_IRQS_LEGACY + 4) +#define INT_7XX_EAC (NR_IRQS_LEGACY + 5) +#define INT_7XX_GPIO_BANK1 (NR_IRQS_LEGACY + 6) +#define INT_7XX_GPIO_BANK2 (NR_IRQS_LEGACY + 7) +#define INT_7XX_GPIO_BANK3 (NR_IRQS_LEGACY + 8) +#define INT_7XX_McBSP2TX (NR_IRQS_LEGACY + 10) +#define INT_7XX_McBSP2RX (NR_IRQS_LEGACY + 11) +#define INT_7XX_McBSP2RX_OVF (NR_IRQS_LEGACY + 12) +#define INT_7XX_LCD_LINE (NR_IRQS_LEGACY + 14) +#define INT_7XX_GSM_PROTECT (NR_IRQS_LEGACY + 15) +#define INT_7XX_TIMER3 (NR_IRQS_LEGACY + 16) +#define INT_7XX_GPIO_BANK5 (NR_IRQS_LEGACY + 17) +#define INT_7XX_GPIO_BANK6 (NR_IRQS_LEGACY + 18) +#define INT_7XX_SPGIO_WR (NR_IRQS_LEGACY + 29) /* * IRQ numbers for interrupt handler 2 * * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below */ -#define IH2_BASE 32 +#define IH2_BASE (NR_IRQS_LEGACY + 32) #define INT_KEYBOARD (1 + IH2_BASE) #define INT_uWireTX (2 + IH2_BASE) @@ -255,11 +255,7 @@ #endif #define OMAP_FPGA_IRQ_END (OMAP_FPGA_IRQ_BASE + OMAP_FPGA_NR_IRQS) -#define NR_IRQS OMAP_FPGA_IRQ_END - -#define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) - -#include <mach/hardware.h> +#define OMAP_IRQ_BIT(irq) (1 << ((irq - NR_IRQS_LEGACY) % 32)) #ifdef CONFIG_FIQ #define FIQ_START 1024 diff --git a/arch/arm/mach-omap1/include/mach/memory.h b/arch/arm/mach-omap1/include/mach/memory.h index 058a4f7d44c5..d43ff0f1cbf8 100644 --- a/arch/arm/mach-omap1/include/mach/memory.h +++ b/arch/arm/mach-omap1/include/mach/memory.h @@ -5,6 +5,9 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H +/* REVISIT: omap1 legacy drivers still rely on this */ +#include <mach/soc.h> + /* * Bus address is physical address, except for OMAP-1510 Local Bus. * OMAP-1510 bus address is translated into a Local Bus address if the @@ -14,7 +17,6 @@ * because of the strncmp(). */ #if defined(CONFIG_ARCH_OMAP15XX) && !defined(__ASSEMBLER__) -#include <mach/soc.h> /* * OMAP-1510 Local Bus address offset diff --git a/arch/arm/mach-omap1/include/mach/serial.h b/arch/arm/mach-omap1/include/mach/serial.h index 2ce6a2db470b..4700e384c3d9 100644 --- a/arch/arm/mach-omap1/include/mach/serial.h +++ b/arch/arm/mach-omap1/include/mach/serial.h @@ -27,11 +27,6 @@ */ #define OMAP_UART_INFO_OFS 0x3ffc -/* OMAP1 serial ports */ -#define OMAP1_UART1_BASE 0xfffb0000 -#define OMAP1_UART2_BASE 0xfffb0800 -#define OMAP1_UART3_BASE 0xfffb9800 - #define OMAP_PORT_SHIFT 2 #define OMAP7XX_PORT_SHIFT 0 diff --git a/arch/arm/mach-omap1/include/mach/soc.h b/arch/arm/mach-omap1/include/mach/soc.h index 612bd1cc257c..3d935570eb3b 100644 --- a/arch/arm/mach-omap1/include/mach/soc.h +++ b/arch/arm/mach-omap1/include/mach/soc.h @@ -28,6 +28,10 @@ #ifndef __ASM_ARCH_OMAP_CPU_H #define __ASM_ARCH_OMAP_CPU_H +#include <asm/irq.h> +#include <mach/hardware.h> +#include <mach/irqs.h> + #ifndef __ASSEMBLY__ #include <linux/bitops.h> diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index a8a533df24e1..f4d346fda9da 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -43,6 +43,7 @@ #include <linux/io.h> #include <asm/irq.h> +#include <asm/exception.h> #include <asm/mach/irq.h> #include "soc.h" @@ -56,66 +57,41 @@ struct omap_irq_bank { unsigned long base_reg; + void __iomem *va; unsigned long trigger_map; unsigned long wake_enable; }; -u32 omap_irq_flags; +static u32 omap_l2_irq; static unsigned int irq_bank_count; static struct omap_irq_bank *irq_banks; +static struct irq_domain *domain; -static inline void irq_bank_writel(unsigned long value, int bank, int offset) -{ - omap_writel(value, irq_banks[bank].base_reg + offset); -} - -static void omap_ack_irq(struct irq_data *d) +static inline unsigned int irq_bank_readl(int bank, int offset) { - if (d->irq > 31) - omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET); - - omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET); + return readl_relaxed(irq_banks[bank].va + offset); } - -static void omap_mask_irq(struct irq_data *d) +static inline void irq_bank_writel(unsigned long value, int bank, int offset) { - int bank = IRQ_BANK(d->irq); - u32 l; - - l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); - l |= 1 << IRQ_BIT(d->irq); - omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); + writel_relaxed(value, irq_banks[bank].va + offset); } -static void omap_unmask_irq(struct irq_data *d) +static void omap_ack_irq(int irq) { - int bank = IRQ_BANK(d->irq); - u32 l; + if (irq > 31) + writel_relaxed(0x1, irq_banks[1].va + IRQ_CONTROL_REG_OFFSET); - l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); - l &= ~(1 << IRQ_BIT(d->irq)); - omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); + writel_relaxed(0x1, irq_banks[0].va + IRQ_CONTROL_REG_OFFSET); } static void omap_mask_ack_irq(struct irq_data *d) { - omap_mask_irq(d); - omap_ack_irq(d); -} - -static int omap_wake_irq(struct irq_data *d, unsigned int enable) -{ - int bank = IRQ_BANK(d->irq); - - if (enable) - irq_banks[bank].wake_enable |= IRQ_BIT(d->irq); - else - irq_banks[bank].wake_enable &= ~IRQ_BIT(d->irq); + struct irq_chip_type *ct = irq_data_get_chip_type(d); - return 0; + ct->chip.irq_mask(d); + omap_ack_irq(d->irq); } - /* * Allows tuning the IRQ type and priority * @@ -165,46 +141,105 @@ static struct omap_irq_bank omap1610_irq_banks[] = { }; #endif -static struct irq_chip omap_irq_chip = { - .name = "MPU", - .irq_ack = omap_mask_ack_irq, - .irq_mask = omap_mask_irq, - .irq_unmask = omap_unmask_irq, - .irq_set_wake = omap_wake_irq, -}; +asmlinkage void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs) +{ + void __iomem *l1 = irq_banks[0].va; + void __iomem *l2 = irq_banks[1].va; + u32 irqnr; + + do { + irqnr = readl_relaxed(l1 + IRQ_ITR_REG_OFFSET); + irqnr &= ~(readl_relaxed(l1 + IRQ_MIR_REG_OFFSET) & 0xffffffff); + if (!irqnr) + break; + + irqnr = readl_relaxed(l1 + IRQ_SIR_FIQ_REG_OFFSET); + if (irqnr) + goto irq; + + irqnr = readl_relaxed(l1 + IRQ_SIR_IRQ_REG_OFFSET); + if (irqnr == omap_l2_irq) { + irqnr = readl_relaxed(l2 + IRQ_SIR_IRQ_REG_OFFSET); + if (irqnr) + irqnr += 32; + } +irq: + if (irqnr) + handle_domain_irq(domain, irqnr, regs); + else + break; + } while (irqnr); +} + +static __init void +omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("MPU", 1, irq_start, base, + handle_level_irq); + ct = gc->chip_types; + ct->chip.irq_ack = omap_mask_ack_irq; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_set_wake = irq_gc_set_wake; + ct->regs.mask = IRQ_MIR_REG_OFFSET; + irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); +} void __init omap1_init_irq(void) { - int i, j; + struct irq_chip_type *ct; + struct irq_data *d = NULL; + int i, j, irq_base; + unsigned long nr_irqs; #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) if (cpu_is_omap7xx()) { - omap_irq_flags = INT_7XX_IH2_IRQ; irq_banks = omap7xx_irq_banks; irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks); } #endif #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { - omap_irq_flags = INT_1510_IH2_IRQ; irq_banks = omap1510_irq_banks; irq_bank_count = ARRAY_SIZE(omap1510_irq_banks); } if (cpu_is_omap310()) { - omap_irq_flags = INT_1510_IH2_IRQ; irq_banks = omap310_irq_banks; irq_bank_count = ARRAY_SIZE(omap310_irq_banks); } #endif #if defined(CONFIG_ARCH_OMAP16XX) if (cpu_is_omap16xx()) { - omap_irq_flags = INT_1510_IH2_IRQ; irq_banks = omap1610_irq_banks; irq_bank_count = ARRAY_SIZE(omap1610_irq_banks); } #endif - printk("Total of %i interrupts in %i interrupt banks\n", - irq_bank_count * 32, irq_bank_count); + + for (i = 0; i < irq_bank_count; i++) { + irq_banks[i].va = ioremap(irq_banks[i].base_reg, 0xff); + if (WARN_ON(!irq_banks[i].va)) + return; + } + + nr_irqs = irq_bank_count * 32; + + irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); + if (irq_base < 0) { + pr_warn("Couldn't allocate IRQ numbers\n"); + irq_base = 0; + } + omap_l2_irq = cpu_is_omap7xx() ? irq_base + 1 : irq_base; + omap_l2_irq -= NR_IRQS_LEGACY; + + domain = irq_domain_add_legacy(NULL, nr_irqs, irq_base, 0, + &irq_domain_simple_ops, NULL); + + pr_info("Total of %lu interrupts in %i interrupt banks\n", + nr_irqs, irq_bank_count); /* Mask and clear all interrupts */ for (i = 0; i < irq_bank_count; i++) { @@ -227,19 +262,15 @@ void __init omap1_init_irq(void) irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j); omap_irq_set_cfg(j, 0, 0, irq_trigger); - - irq_set_chip_and_handler(j, &omap_irq_chip, - handle_level_irq); set_irq_flags(j, IRQF_VALID); } + omap_alloc_gc(irq_banks[i].va, irq_base + i * 32, 32); } /* Unmask level 2 handler */ - - if (cpu_is_omap7xx()) - omap_unmask_irq(irq_get_irq_data(INT_7XX_IH2_IRQ)); - else if (cpu_is_omap15xx()) - omap_unmask_irq(irq_get_irq_data(INT_1510_IH2_IRQ)); - else if (cpu_is_omap16xx()) - omap_unmask_irq(irq_get_irq_data(INT_1610_IH2_IRQ)); + d = irq_get_irq_data(irq_find_mapping(domain, omap_l2_irq)); + if (d) { + ct = irq_data_get_chip_type(d); + ct->chip.irq_unmask(d); + } } diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index 667ce5027f63..599490a596a7 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c @@ -36,7 +36,7 @@ static struct omap_mux_cfg arch_mux_cfg; #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) -static struct pin_config __initdata_or_module omap7xx_pins[] = { +static struct pin_config omap7xx_pins[] = { MUX_CFG_7XX("E2_7XX_KBR0", 12, 21, 0, 20, 1, 0) MUX_CFG_7XX("J7_7XX_KBR1", 12, 25, 0, 24, 1, 0) MUX_CFG_7XX("E1_7XX_KBR2", 12, 29, 0, 28, 1, 0) @@ -82,7 +82,7 @@ MUX_CFG_7XX("UART_7XX_2", 8, 1, 6, 0, 0, 0) #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */ #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -static struct pin_config __initdata_or_module omap1xxx_pins[] = { +static struct pin_config omap1xxx_pins[] = { /* * description mux mode mux pull pull pull pu_pd pu dbg * reg offset mode reg bit ena reg @@ -343,7 +343,7 @@ MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0) #define OMAP1XXX_PINS_SZ 0 #endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */ -static int __init_or_module omap1_cfg_reg(const struct pin_config *cfg) +static int omap1_cfg_reg(const struct pin_config *cfg) { static DEFINE_SPINLOCK(mux_spin_lock); unsigned long flags; @@ -469,7 +469,7 @@ int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg) /* * Sets the Omap MUX and PULL_DWN registers based on the table */ -int __init_or_module omap_cfg_reg(const unsigned long index) +int omap_cfg_reg(const unsigned long index) { struct pin_config *reg; diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index dd94567c3628..ee5460b8ec2e 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -62,6 +62,7 @@ #include "iomap.h" #include "clock.h" #include "pm.h" +#include "soc.h" #include "sram.h" static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index d1ac08016f0b..a65bd0c44296 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -25,6 +25,7 @@ #include <mach/mux.h> #include "pm.h" +#include "soc.h" static struct clk * uart1_ck; static struct clk * uart2_ck; diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c index bde7a35e5000..06c5ba7574a5 100644 --- a/arch/arm/mach-omap1/timer.c +++ b/arch/arm/mach-omap1/timer.c @@ -27,10 +27,10 @@ #include <linux/platform_device.h> #include <linux/platform_data/dmtimer-omap.h> -#include <mach/irqs.h> - #include <plat/dmtimer.h> +#include "soc.h" + #define OMAP1610_GPTIMER1_BASE 0xfffb1400 #define OMAP1610_GPTIMER2_BASE 0xfffb1c00 #define OMAP1610_GPTIMER3_BASE 0xfffb2400 diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 166b18f515a2..4a7303cf563e 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -224,13 +224,13 @@ static int _omap_device_notifier_call(struct notifier_block *nb, */ static int _omap_device_enable_hwmods(struct omap_device *od) { + int ret = 0; int i; for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_enable(od->hwmods[i]); + ret |= omap_hwmod_enable(od->hwmods[i]); - /* XXX pass along return value here? */ - return 0; + return ret; } /** @@ -241,13 +241,13 @@ static int _omap_device_enable_hwmods(struct omap_device *od) */ static int _omap_device_idle_hwmods(struct omap_device *od) { + int ret = 0; int i; for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_idle(od->hwmods[i]); + ret |= omap_hwmod_idle(od->hwmods[i]); - /* XXX pass along return value here? */ - return 0; + return ret; } /* Public functions for use by core code */ @@ -595,18 +595,20 @@ static int _od_runtime_suspend(struct device *dev) int ret; ret = pm_generic_runtime_suspend(dev); + if (ret) + return ret; - if (!ret) - omap_device_idle(pdev); - - return ret; + return omap_device_idle(pdev); } static int _od_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + int ret; - omap_device_enable(pdev); + ret = omap_device_enable(pdev); + if (ret) + return ret; return pm_generic_runtime_resume(dev); } @@ -743,7 +745,8 @@ int omap_device_enable(struct platform_device *pdev) ret = _omap_device_enable_hwmods(od); - od->_state = OMAP_DEVICE_STATE_ENABLED; + if (ret == 0) + od->_state = OMAP_DEVICE_STATE_ENABLED; return ret; } @@ -773,7 +776,8 @@ int omap_device_idle(struct platform_device *pdev) ret = _omap_device_idle_hwmods(od); - od->_state = OMAP_DEVICE_STATE_IDLE; + if (ret == 0) + od->_state = OMAP_DEVICE_STATE_IDLE; return ret; } diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 752969ff9de0..d78c12e7cb5e 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3318,16 +3318,17 @@ int omap_hwmod_enable(struct omap_hwmod *oh) */ int omap_hwmod_idle(struct omap_hwmod *oh) { + int r; unsigned long flags; if (!oh) return -EINVAL; spin_lock_irqsave(&oh->_lock, flags); - _idle(oh); + r = _idle(oh); spin_unlock_irqrestore(&oh->_lock, flags); - return 0; + return r; } /** @@ -3340,16 +3341,17 @@ int omap_hwmod_idle(struct omap_hwmod *oh) */ int omap_hwmod_shutdown(struct omap_hwmod *oh) { + int r; unsigned long flags; if (!oh) return -EINVAL; spin_lock_irqsave(&oh->_lock, flags); - _shutdown(oh); + r = _shutdown(oh); spin_unlock_irqrestore(&oh->_lock, flags); - return 0; + return r; } /* diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 9611c91d9b82..b5d27ec81610 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -109,6 +109,12 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3; #define DEBUG_OMAPUART_FLAGS (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET) +#ifdef CONFIG_OMAP_GPMC_DEBUG +#define DEBUG_OMAP_GPMC_HWMOD_FLAGS HWMOD_INIT_NO_RESET +#else +#define DEBUG_OMAP_GPMC_HWMOD_FLAGS 0 +#endif + #if defined(CONFIG_DEBUG_OMAP2UART1) #undef DEBUG_OMAP2UART1_FLAGS #define DEBUG_OMAP2UART1_FLAGS DEBUG_OMAPUART_FLAGS diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 8821b9d6bae4..6dcfd03ced8f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -762,16 +762,8 @@ struct omap_hwmod omap2xxx_gpmc_hwmod = { .name = "gpmc", .class = &omap2xxx_gpmc_hwmod_class, .main_clk = "gpmc_fck", - /* - * XXX HWMOD_INIT_NO_RESET should not be needed for this IP - * block. It is not being added due to any known bugs with - * resetting the GPMC IP block, but rather because any timings - * set by the bootloader are not being correctly programmed by - * the kernel from the board file or DT data. - * HWMOD_INIT_NO_RESET should be removed ASAP. - */ - .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET | - HWMOD_NO_IDLEST), + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = HWMOD_NO_IDLEST | DEBUG_OMAP_GPMC_HWMOD_FLAGS, .prcm = { .omap2 = { .prcm_reg_id = 3, diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h index 130332c0534d..7f737965f543 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h @@ -145,6 +145,7 @@ extern struct omap_hwmod am33xx_uart5_hwmod; extern struct omap_hwmod am33xx_uart6_hwmod; extern struct omap_hwmod am33xx_wd_timer1_hwmod; +extern struct omap_hwmod_class am33xx_emif_hwmod_class; extern struct omap_hwmod_class am33xx_l4_hwmod_class; extern struct omap_hwmod_class am33xx_wkup_m3_hwmod_class; extern struct omap_hwmod_class am33xx_control_hwmod_class; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index cabc5695b504..907a452b78ea 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -203,6 +203,19 @@ struct omap_hwmod am33xx_prcm_hwmod = { }; /* + * 'emif' class + * instance(s): emif + */ +static struct omap_hwmod_class_sysconfig am33xx_emif_sysc = { + .rev_offs = 0x0000, +}; + +struct omap_hwmod_class am33xx_emif_hwmod_class = { + .name = "emif", + .sysc = &am33xx_emif_sysc, +}; + +/* * 'aes0' class */ static struct omap_hwmod_class_sysconfig am33xx_aes0_sysc = { @@ -668,7 +681,8 @@ struct omap_hwmod am33xx_gpmc_hwmod = { .name = "gpmc", .class = &am33xx_gpmc_hwmod_class, .clkdm_name = "l3s_clkdm", - .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS, .main_clk = "l3s_gclk", .prcm = { .omap4 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 0cf7b563dcd1..cc0791d9125b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -34,19 +34,6 @@ * IP blocks */ -/* - * 'emif' class - * instance(s): emif - */ -static struct omap_hwmod_class_sysconfig am33xx_emif_sysc = { - .rev_offs = 0x0000, -}; - -static struct omap_hwmod_class am33xx_emif_hwmod_class = { - .name = "emif", - .sysc = &am33xx_emif_sysc, -}; - /* emif */ static struct omap_hwmod am33xx_emif_hwmod = { .name = "emif", diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 4e8e93c398db..dc55f8dedf2c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -2169,16 +2169,8 @@ static struct omap_hwmod omap3xxx_gpmc_hwmod = { .clkdm_name = "core_l3_clkdm", .mpu_irqs = omap3xxx_gpmc_irqs, .main_clk = "gpmc_fck", - /* - * XXX HWMOD_INIT_NO_RESET should not be needed for this IP - * block. It is not being added due to any known bugs with - * resetting the GPMC IP block, but rather because any timings - * set by the bootloader are not being correctly programmed by - * the kernel from the board file or DT data. - * HWMOD_INIT_NO_RESET should be removed ASAP. - */ - .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET | - HWMOD_NO_IDLEST), + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = HWMOD_NO_IDLEST | DEBUG_OMAP_GPMC_HWMOD_FLAGS, }; /* @@ -3744,29 +3736,54 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { /* GP-only hwmod links */ static struct omap_hwmod_ocp_if *omap34xx_gp_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_sec__timer12, - &omap3xxx_l4_core__sham, - &omap3xxx_l4_core__aes, NULL }; static struct omap_hwmod_ocp_if *omap36xx_gp_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_sec__timer12, - &omap3xxx_l4_core__sham, - &omap3xxx_l4_core__aes, NULL }; static struct omap_hwmod_ocp_if *am35xx_gp_hwmod_ocp_ifs[] __initdata = { &omap3xxx_l4_sec__timer12, - /* - * Apparently the SHA/MD5 and AES accelerator IP blocks are - * only present on some AM35xx chips, and no one knows which - * ones. See - * http://www.spinics.net/lists/arm-kernel/msg215466.html So - * if you need these IP blocks on an AM35xx, try uncommenting - * the following lines. - */ + NULL +}; + +/* crypto hwmod links */ +static struct omap_hwmod_ocp_if *omap34xx_sham_hwmod_ocp_ifs[] __initdata = { + &omap3xxx_l4_core__sham, + NULL +}; + +static struct omap_hwmod_ocp_if *omap34xx_aes_hwmod_ocp_ifs[] __initdata = { + &omap3xxx_l4_core__aes, + NULL +}; + +static struct omap_hwmod_ocp_if *omap36xx_sham_hwmod_ocp_ifs[] __initdata = { + &omap3xxx_l4_core__sham, + NULL +}; + +static struct omap_hwmod_ocp_if *omap36xx_aes_hwmod_ocp_ifs[] __initdata = { + &omap3xxx_l4_core__aes, + NULL +}; + +/* + * Apparently the SHA/MD5 and AES accelerator IP blocks are + * only present on some AM35xx chips, and no one knows which + * ones. See + * http://www.spinics.net/lists/arm-kernel/msg215466.html So + * if you need these IP blocks on an AM35xx, try uncommenting + * the following lines. + */ +static struct omap_hwmod_ocp_if *am35xx_sham_hwmod_ocp_ifs[] __initdata = { /* &omap3xxx_l4_core__sham, */ + NULL +}; + +static struct omap_hwmod_ocp_if *am35xx_aes_hwmod_ocp_ifs[] __initdata = { /* &omap3xxx_l4_core__aes, */ NULL }; @@ -3868,10 +3885,41 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = { NULL }; +/** + * omap3xxx_hwmod_is_hs_ip_block_usable - is a security IP block accessible? + * @bus: struct device_node * for the top-level OMAP DT data + * @dev_name: device name used in the DT file + * + * Determine whether a "secure" IP block @dev_name is usable by Linux. + * There doesn't appear to be a 100% reliable way to determine this, + * so we rely on heuristics. If @bus is null, meaning there's no DT + * data, then we only assume the IP block is accessible if the OMAP is + * fused as a 'general-purpose' SoC. If however DT data is present, + * test to see if the IP block is described in the DT data and set to + * 'status = "okay"'. If so then we assume the ODM has configured the + * OMAP firewalls to allow access to the IP block. + * + * Return: 0 if device named @dev_name is not likely to be accessible, + * or 1 if it is likely to be accessible. + */ +static int __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus, + const char *dev_name) +{ + if (!bus) + return (omap_type() == OMAP2_DEVICE_TYPE_GP) ? 1 : 0; + + if (of_device_is_available(of_find_node_by_name(bus, dev_name))) + return 1; + + return 0; +} + int __init omap3xxx_hwmod_init(void) { int r; - struct omap_hwmod_ocp_if **h = NULL, **h_gp = NULL; + struct omap_hwmod_ocp_if **h = NULL, **h_gp = NULL, **h_sham = NULL; + struct omap_hwmod_ocp_if **h_aes = NULL; + struct device_node *bus = NULL; unsigned int rev; omap_hwmod_init(); @@ -3893,13 +3941,19 @@ int __init omap3xxx_hwmod_init(void) rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) { h = omap34xx_hwmod_ocp_ifs; h_gp = omap34xx_gp_hwmod_ocp_ifs; + h_sham = omap34xx_sham_hwmod_ocp_ifs; + h_aes = omap34xx_aes_hwmod_ocp_ifs; } else if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) { h = am35xx_hwmod_ocp_ifs; h_gp = am35xx_gp_hwmod_ocp_ifs; + h_sham = am35xx_sham_hwmod_ocp_ifs; + h_aes = am35xx_aes_hwmod_ocp_ifs; } else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2) { h = omap36xx_hwmod_ocp_ifs; h_gp = omap36xx_gp_hwmod_ocp_ifs; + h_sham = omap36xx_sham_hwmod_ocp_ifs; + h_aes = omap36xx_aes_hwmod_ocp_ifs; } else { WARN(1, "OMAP3 hwmod family init: unknown chip type\n"); return -EINVAL; @@ -3916,6 +3970,25 @@ int __init omap3xxx_hwmod_init(void) return r; } + /* + * Register crypto hwmod links only if they are not disabled in DT. + * If DT information is missing, enable them only for GP devices. + */ + + if (of_have_populated_dt()) + bus = of_find_node_by_name(NULL, "ocp"); + + if (h_sham && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "sham")) { + r = omap_hwmod_register_links(h_sham); + if (r < 0) + return r; + } + + if (h_aes && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "aes")) { + r = omap_hwmod_register_links(h_aes); + if (r < 0) + return r; + } /* * Register hwmod links specific to certain ES levels of a diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 17e8004fc20f..215d5efa0dba 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -24,6 +24,20 @@ /* IP blocks */ +static struct omap_hwmod am43xx_emif_hwmod = { + .name = "emif", + .class = &am33xx_emif_hwmod_class, + .clkdm_name = "emif_clkdm", + .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "dpll_ddr_m2_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + static struct omap_hwmod am43xx_l4_hs_hwmod = { .name = "l4_hs", .class = &am33xx_l4_hwmod_class, @@ -583,6 +597,13 @@ static struct omap_hwmod am43xx_vpfe1_hwmod = { }; /* Interfaces */ +static struct omap_hwmod_ocp_if am43xx_l3_main__emif = { + .master = &am33xx_l3_main_hwmod, + .slave = &am43xx_emif_hwmod, + .clk = "dpll_core_m4_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = { .master = &am33xx_l3_main_hwmod, .slave = &am43xx_l4_hs_hwmod, @@ -918,6 +939,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__l3_instr, &am33xx_l3_main__gfx, &am33xx_l3_s__l3_main, + &am43xx_l3_main__emif, &am33xx_pruss__l3_main, &am43xx_wkup_m3__l4_wkup, &am33xx_gfx__l3_main, diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f5e68a782025..43eebf2c59e2 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1188,15 +1188,8 @@ static struct omap_hwmod omap44xx_gpmc_hwmod = { .name = "gpmc", .class = &omap44xx_gpmc_hwmod_class, .clkdm_name = "l3_2_clkdm", - /* - * XXX HWMOD_INIT_NO_RESET should not be needed for this IP - * block. It is not being added due to any known bugs with - * resetting the GPMC IP block, but rather because any timings - * set by the bootloader are not being correctly programmed by - * the kernel from the board file or DT data. - * HWMOD_INIT_NO_RESET should be removed ASAP. - */ - .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS, .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET, diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 0e64c2fac0b5..a0411f32e8b1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -819,8 +819,8 @@ static struct omap_hwmod dra7xx_gpmc_hwmod = { .name = "gpmc", .class = &dra7xx_gpmc_hwmod_class, .clkdm_name = "l3main1_clkdm", - .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET | - HWMOD_SWSUP_SIDLE), + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = HWMOD_SWSUP_SIDLE | DEBUG_OMAP_GPMC_HWMOD_FLAGS, .main_clk = "l3_iclk_div", .prcm = { .omap4 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c index cab1eb61ac96..c92413769144 100644 --- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c @@ -478,6 +478,8 @@ static struct omap_hwmod dm81xx_gpmc_hwmod = { .clkdm_name = "alwon_l3s_clkdm", .class = &dm81xx_gpmc_hwmod_class, .main_clk = "sysclk6_ck", + /* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */ + .flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS, .prcm = { .omap4 = { .clkctrl_offs = DM816X_CM_ALWON_GPMC_CLKCTRL, diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h index d0261996db6d..7eebc27fa892 100644 --- a/arch/arm/mach-omap2/prcm43xx.h +++ b/arch/arm/mach-omap2/prcm43xx.h @@ -146,4 +146,6 @@ #define AM43XX_CM_PER_HDQ1W_CLKCTRL_OFFSET 0x04a0 #define AM43XX_CM_PER_VPFE0_CLKCTRL_OFFSET 0x0068 #define AM43XX_CM_PER_VPFE1_CLKCTRL_OFFSET 0x0070 +#define AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET 0x0720 + #endif 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-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 0fb484221c90..45006479d461 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -139,7 +139,7 @@ config MACH_ARMADILLO800EVA select ARCH_REQUIRE_GPIOLIB select REGULATOR_FIXED_VOLTAGE if REGULATOR select SMSC_PHY if SH_ETH - select SND_SOC_WM8978 if SND_SIMPLE_CARD + select SND_SOC_WM8978 if SND_SIMPLE_CARD && I2C select USE_OF config MACH_BOCKW @@ -148,7 +148,7 @@ config MACH_BOCKW select ARCH_REQUIRE_GPIOLIB select REGULATOR_FIXED_VOLTAGE if REGULATOR select SND_SOC_AK4554 if SND_SIMPLE_CARD - select SND_SOC_AK4642 if SND_SIMPLE_CARD + select SND_SOC_AK4642 if SND_SIMPLE_CARD && I2C select USE_OF config MACH_BOCKW_REFERENCE diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index b5f8d75d51a0..90efdeb56be5 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -1,5 +1,6 @@ -config ARCH_SOCFPGA +menuconfig ARCH_SOCFPGA bool "Altera SOCFPGA family" if ARCH_MULTI_V7 + select ARCH_SUPPORTS_BIG_ENDIAN select ARM_AMBA select ARM_GIC select CACHE_L2X0 @@ -8,3 +9,11 @@ config ARCH_SOCFPGA select HAVE_ARM_SCU select HAVE_ARM_TWD if SMP select MFD_SYSCON + +if ARCH_SOCFPGA +config SOCFPGA_SUSPEND + bool "Suspend to RAM on SOCFPGA" + help + Select this if you want to enable Suspend-to-RAM on SOCFPGA + platforms. +endif diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 6dd7a93a90fe..b8f9e238e4ab 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -4,3 +4,4 @@ obj-y := socfpga.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o +obj-$(CONFIG_SOCFPGA_SUSPEND) += pm.o self-refresh.o diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index 767c09e954a0..7259c3732702 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -1,6 +1,6 @@ /* * Copyright 2012 Pavel Machek <pavel@denx.de> - * Copyright (C) 2012 Altera Corporation + * Copyright (C) 2012-2015 Altera Corporation * * 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 @@ -25,21 +25,24 @@ #define SOCFPGA_RSTMGR_MODPERRST 0x14 #define SOCFPGA_RSTMGR_BRGMODRST 0x1c +#define SOCFPGA_A10_RSTMGR_MODMPURST 0x20 + /* System Manager bits */ #define RSTMGR_CTRL_SWCOLDRSTREQ 0x1 /* Cold Reset */ #define RSTMGR_CTRL_SWWARMRSTREQ 0x2 /* Warm Reset */ #define RSTMGR_MPUMODRST_CPU1 0x2 /* CPU1 Reset */ -extern void __iomem *socfpga_scu_base_addr; - extern void socfpga_init_clocks(void); extern void socfpga_sysmgr_init(void); extern void __iomem *sys_manager_base_addr; extern void __iomem *rst_manager_base_addr; +extern void __iomem *sdr_ctl_base_addr; + +u32 socfpga_sdram_self_refresh(u32 sdr_base); +extern unsigned int socfpga_sdram_self_refresh_sz; -extern struct smp_operations socfpga_smp_ops; extern char secondary_trampoline, secondary_trampoline_end; extern unsigned long socfpga_cpu1start_addr; diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S index 5bb016427107..5d94b7a2fb10 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 79c5336c569f..c6f1df89f9af 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -54,32 +54,43 @@ 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 int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle) { - unsigned int i, ncores; + int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; - ncores = scu_get_core_count(socfpga_scu_base_addr); + if (socfpga_cpu1start_addr) { + writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr + + SOCFPGA_A10_RSTMGR_MODMPURST); + memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + writel(virt_to_phys(secondary_startup), + sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff)); - /* 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(); + flush_cache_all(); + smp_wmb(); + outer_clean_range(0, trampoline_size); + + /* This will release CPU #1 out of reset. */ + writel(0, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_MODMPURST); } - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + return 0; } static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) { + struct device_node *np; + void __iomem *socfpga_scu_base_addr; + + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (!np) { + pr_err("%s: missing scu\n", __func__); + return; + } + + socfpga_scu_base_addr = of_iomap(np, 0); + if (!socfpga_scu_base_addr) + return; scu_enable(socfpga_scu_base_addr); } @@ -95,11 +106,21 @@ static void socfpga_cpu_die(unsigned int cpu) cpu_do_idle(); } -struct smp_operations socfpga_smp_ops __initdata = { - .smp_init_cpus = socfpga_smp_init_cpus, +static struct smp_operations socfpga_smp_ops __initdata = { .smp_prepare_cpus = socfpga_smp_prepare_cpus, .smp_boot_secondary = socfpga_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = socfpga_cpu_die, #endif }; + +static struct smp_operations socfpga_a10_smp_ops __initdata = { + .smp_prepare_cpus = socfpga_smp_prepare_cpus, + .smp_boot_secondary = socfpga_a10_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = socfpga_cpu_die, +#endif +}; + +CPU_METHOD_OF_DECLARE(socfpga_smp, "altr,socfpga-smp", &socfpga_smp_ops); +CPU_METHOD_OF_DECLARE(socfpga_a10_smp, "altr,socfpga-a10-smp", &socfpga_a10_smp_ops); diff --git a/arch/arm/mach-socfpga/pm.c b/arch/arm/mach-socfpga/pm.c new file mode 100644 index 000000000000..1ed89fc2b7a8 --- /dev/null +++ b/arch/arm/mach-socfpga/pm.c @@ -0,0 +1,149 @@ +/* + * arch/arm/mach-socfpga/pm.c + * + * Copyright (C) 2014-2015 Altera Corporation. All rights reserved. + * + * with code from pm-imx6.c + * Copyright 2011-2014 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/bitops.h> +#include <linux/genalloc.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/of_platform.h> +#include <linux/suspend.h> +#include <asm/suspend.h> +#include <asm/fncpy.h> +#include "core.h" + +/* Pointer to function copied to ocram */ +static u32 (*socfpga_sdram_self_refresh_in_ocram)(u32 sdr_base); + +static int socfpga_setup_ocram_self_refresh(void) +{ + struct platform_device *pdev; + phys_addr_t ocram_pbase; + struct device_node *np; + struct gen_pool *ocram_pool; + unsigned long ocram_base; + void __iomem *suspend_ocram_base; + int ret = 0; + + np = of_find_compatible_node(NULL, NULL, "mmio-sram"); + if (!np) { + pr_err("%s: Unable to find mmio-sram in dtb\n", __func__); + return -ENODEV; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_warn("%s: failed to find ocram device!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_pool = dev_get_gen_pool(&pdev->dev); + if (!ocram_pool) { + pr_warn("%s: ocram pool unavailable!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_base = gen_pool_alloc(ocram_pool, socfpga_sdram_self_refresh_sz); + if (!ocram_base) { + pr_warn("%s: unable to alloc ocram!\n", __func__); + ret = -ENOMEM; + goto put_node; + } + + ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base); + + suspend_ocram_base = __arm_ioremap_exec(ocram_pbase, + socfpga_sdram_self_refresh_sz, + false); + if (!suspend_ocram_base) { + pr_warn("%s: __arm_ioremap_exec failed!\n", __func__); + ret = -ENOMEM; + goto put_node; + } + + /* Copy the code that puts DDR in self refresh to ocram */ + socfpga_sdram_self_refresh_in_ocram = + (void *)fncpy(suspend_ocram_base, + &socfpga_sdram_self_refresh, + socfpga_sdram_self_refresh_sz); + + WARN(!socfpga_sdram_self_refresh_in_ocram, + "could not copy function to ocram"); + if (!socfpga_sdram_self_refresh_in_ocram) + ret = -EFAULT; + +put_node: + of_node_put(np); + + return ret; +} + +static int socfpga_pm_suspend(unsigned long arg) +{ + u32 ret; + + if (!sdr_ctl_base_addr) + return -EFAULT; + + ret = socfpga_sdram_self_refresh_in_ocram((u32)sdr_ctl_base_addr); + + pr_debug("%s self-refresh loops request=%d exit=%d\n", __func__, + ret & 0xffff, (ret >> 16) & 0xffff); + + return 0; +} + +static int socfpga_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + outer_disable(); + cpu_suspend(0, socfpga_pm_suspend); + outer_resume(); + break; + default: + return -EINVAL; + } + return 0; +} + +static const struct platform_suspend_ops socfpga_pm_ops = { + .valid = suspend_valid_only_mem, + .enter = socfpga_pm_enter, +}; + +static int __init socfpga_pm_init(void) +{ + int ret; + + ret = socfpga_setup_ocram_self_refresh(); + if (ret) + return ret; + + suspend_set_ops(&socfpga_pm_ops); + pr_info("SoCFPGA initialized for DDR self-refresh during suspend.\n"); + + return 0; +} +arch_initcall(socfpga_pm_init); diff --git a/arch/arm/mach-socfpga/self-refresh.S b/arch/arm/mach-socfpga/self-refresh.S new file mode 100644 index 000000000000..f2d7f883e33d --- /dev/null +++ b/arch/arm/mach-socfpga/self-refresh.S @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2014-2015 Altera Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + +#define MAX_LOOP_COUNT 1000 + +/* Register offset */ +#define SDR_CTRLGRP_LOWPWREQ_ADDR 0x54 +#define SDR_CTRLGRP_LOWPWRACK_ADDR 0x58 + +/* Bitfield positions */ +#define SELFRSHREQ_POS 3 +#define SELFRSHREQ_MASK 0x8 + +#define SELFRFSHACK_POS 1 +#define SELFRFSHACK_MASK 0x2 + + /* + * This code assumes that when the bootloader configured + * the sdram controller for the DDR on the board it + * configured the following fields depending on the DDR + * vendor/configuration: + * + * sdr.ctrlcfg.lowpwreq.selfrfshmask + * sdr.ctrlcfg.lowpwrtiming.clkdisablecycles + * sdr.ctrlcfg.dramtiming4.selfrfshexit + */ + + .arch armv7-a + .text + .align 3 + + /* + * socfpga_sdram_self_refresh + * + * r0 : sdr_ctl_base_addr + * r1 : temp storage of return value + * r2 : temp storage of register values + * r3 : loop counter + * + * return value: lower 16 bits: loop count going into self refresh + * upper 16 bits: loop count exiting self refresh + */ +ENTRY(socfpga_sdram_self_refresh) + /* Enable dynamic clock gating in the Power Control Register. */ + mrc p15, 0, r2, c15, c0, 0 + orr r2, r2, #1 + mcr p15, 0, r2, c15, c0, 0 + + /* Enable self refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 1 */ + ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR] + orr r2, r2, #SELFRSHREQ_MASK + str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR] + + /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 1 or hit max loops */ + mov r3, #0 +while_ack_0: + ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR] + and r2, r2, #SELFRFSHACK_MASK + cmp r2, #SELFRFSHACK_MASK + beq ack_1 + + add r3, #1 + cmp r3, #MAX_LOOP_COUNT + bne while_ack_0 + +ack_1: + mov r1, r3 + + /* + * Execute an ISB instruction to ensure that all of the + * CP15 register changes have been committed. + */ + isb + + /* + * Execute a barrier instruction to ensure that all cache, + * TLB and branch predictor maintenance operations issued + * by any CPU in the cluster have completed. + */ + dsb + dmb + + wfi + + /* Disable self-refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 0 */ + ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR] + bic r2, r2, #SELFRSHREQ_MASK + str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR] + + /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 0 or hit max loops */ + mov r3, #0 +while_ack_1: + ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR] + and r2, r2, #SELFRFSHACK_MASK + cmp r2, #SELFRFSHACK_MASK + bne ack_0 + + add r3, #1 + cmp r3, #MAX_LOOP_COUNT + bne while_ack_1 + +ack_0: + /* + * Prepare return value: + * Shift loop count for exiting self refresh into upper 16 bits. + * Leave loop count for requesting self refresh in lower 16 bits. + */ + mov r3, r3, lsl #16 + add r1, r1, r3 + + /* Disable dynamic clock gating in the Power Control Register. */ + mrc p15, 0, r2, c15, c0, 0 + bic r2, r2, #1 + mcr p15, 0, r2, c15, c0, 0 + + mov r0, r1 @ return value + bx lr @ return + +ENDPROC(socfpga_sdram_self_refresh) +ENTRY(socfpga_sdram_self_refresh_sz) + .word . - socfpga_sdram_self_refresh diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index f5e597c207b9..19643a756c48 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Altera Corporation + * Copyright (C) 2012-2015 Altera Corporation * * 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 @@ -27,43 +27,11 @@ #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; +void __iomem *sdr_ctl_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; @@ -82,6 +50,9 @@ void __init socfpga_sysmgr_init(void) np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); rst_manager_base_addr = of_iomap(np, 0); + + np = of_find_compatible_node(NULL, NULL, "altr,sdr-ctl"); + sdr_ctl_base_addr = of_iomap(np, 0); } static void __init socfpga_init_irq(void) @@ -111,8 +82,6 @@ static const char *altera_dt_match[] = { 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 0aee0129f8d7..9c479c7925b8 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); #ifdef CONFIG_PM_SLEEP @@ -46,6 +47,9 @@ void __tegra_cpu_reset_handler_end(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..a1aa4028389f --- /dev/null +++ b/arch/arm/mach-zx/headsmp.S @@ -0,0 +1,33 @@ +/* + * 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 + .arm + +/* 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 7038cae95ddc..79cda2e5fa4e 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -19,7 +19,6 @@ 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/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 6416e03b4482..1e460b4ee3b9 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -38,6 +38,10 @@ #include <linux/omap-dma.h> +#ifdef CONFIG_ARCH_OMAP1 +#include <mach/soc.h> +#endif + /* * MAX_LOGICAL_DMA_CH_COUNT: the maximum number of logical DMA * channels that an instance of the SDMA IP block can support. Used diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index e2be70df06c6..efa6e85619ad 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -389,7 +389,7 @@ static int s3c_adc_probe(struct platform_device *pdev) if (ret) return ret; - clk_enable(adc->clk); + clk_prepare_enable(adc->clk); tmp = adc->prescale | S3C2410_ADCCON_PRSCEN; @@ -413,7 +413,7 @@ static int s3c_adc_remove(struct platform_device *pdev) { struct adc_device *adc = platform_get_drvdata(pdev); - clk_disable(adc->clk); + clk_disable_unprepare(adc->clk); regulator_disable(adc->vdd); return 0; @@ -475,7 +475,7 @@ static int s3c_adc_resume(struct device *dev) #define s3c_adc_resume NULL #endif -static struct platform_device_id s3c_adc_driver_ids[] = { +static const struct platform_device_id s3c_adc_driver_ids[] = { { .name = "s3c24xx-adc", .driver_data = TYPE_ADCV1, diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f6e4d56eda00..2a61e4b04600 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -445,6 +445,19 @@ static void vfp_enable(void *unused) set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); } +/* Called by platforms on which we want to disable VFP because it may not be + * present on all CPUs within a SMP complex. Needs to be called prior to + * vfp_init(). + */ +void vfp_disable(void) +{ + if (VFP_arch) { + pr_debug("%s: should be called prior to vfp_init\n", __func__); + return; + } + VFP_arch = 1; +} + #ifdef CONFIG_CPU_PM static int vfp_pm_suspend(void) { diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7796af4b1d6f..cb8fa34e1a6c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -181,6 +181,11 @@ config ARCH_FSL_LS2085A help This enables support for Freescale LS2085A SOC. +config ARCH_HISI + bool "Hisilicon SoC Family" + help + This enables support for Hisilicon ARMv8 SoC family + config ARCH_MEDIATEK bool "Mediatek MT65xx & MT81xx ARMv8 SoC" select ARM_GIC diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 2ed7449d9273..1d293ea16f46 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -33,6 +33,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_IOSCHED_DEADLINE is not set CONFIG_ARCH_EXYNOS7=y CONFIG_ARCH_FSL_LS2085A=y +CONFIG_ARCH_HISI=y CONFIG_ARCH_MEDIATEK=y CONFIG_ARCH_SEATTLE=y CONFIG_ARCH_TEGRA=y diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 738612c45266..f364fa4d24eb 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -91,6 +91,7 @@ static const int gisb_offsets_bcm7445[] = { struct brcmstb_gisb_arb_device { void __iomem *base; const int *gisb_offsets; + bool big_endian; struct mutex lock; struct list_head next; u32 valid_mask; @@ -108,7 +109,10 @@ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg) if (offset == -1) return 1; - return ioread32(gdev->base + offset); + if (gdev->big_endian) + return ioread32be(gdev->base + offset); + else + return ioread32(gdev->base + offset); } static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg) @@ -117,7 +121,11 @@ static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg) if (offset == -1) return; - iowrite32(val, gdev->base + reg); + + if (gdev->big_endian) + iowrite32be(val, gdev->base + reg); + else + iowrite32(val, gdev->base + reg); } static ssize_t gisb_arb_get_timeout(struct device *dev, @@ -296,6 +304,7 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) return -EINVAL; } gdev->gisb_offsets = of_id->data; + gdev->big_endian = of_device_is_big_endian(dn); err = devm_request_irq(&pdev->dev, timeout_irq, brcmstb_gisb_timeout_handler, 0, pdev->name, diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3d00c25382c5..4dcbdd36f24e 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ obj-$(CONFIG_ARCH_HIP04) += hisilicon/ obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ +obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ @@ -72,4 +73,5 @@ obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_X86) += x86/ +obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile new file mode 100644 index 000000000000..75fae169ce8f --- /dev/null +++ b/drivers/clk/imx/Makefile @@ -0,0 +1,26 @@ + +obj-y += \ + clk.o \ + clk-busy.o \ + clk-cpu.o \ + clk-fixup-div.o \ + clk-fixup-mux.o \ + clk-gate-exclusive.o \ + clk-gate2.o \ + clk-pllv1.o \ + clk-pllv2.o \ + clk-pllv3.o \ + clk-pfd.o + +obj-$(CONFIG_SOC_IMX1) += clk-imx1.o +obj-$(CONFIG_SOC_IMX21) += clk-imx21.o +obj-$(CONFIG_SOC_IMX25) += clk-imx25.o +obj-$(CONFIG_SOC_IMX27) += clk-imx27.o +obj-$(CONFIG_SOC_IMX31) += clk-imx31.o +obj-$(CONFIG_SOC_IMX35) += clk-imx35.o +obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o +obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o +obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o +obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o +obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o +obj-$(CONFIG_SOC_VF610) += clk-vf610.o diff --git a/arch/arm/mach-imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index 4bb1bc419b79..4bb1bc419b79 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c diff --git a/arch/arm/mach-imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c index aa1c345e2a19..9d46eac87f45 100644 --- a/arch/arm/mach-imx/clk-cpu.c +++ b/drivers/clk/imx/clk-cpu.c @@ -12,6 +12,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/slab.h> +#include "clk.h" struct clk_cpu { struct clk_hw hw; diff --git a/arch/arm/mach-imx/clk-fixup-div.c b/drivers/clk/imx/clk-fixup-div.c index 21db020b1f2d..21db020b1f2d 100644 --- a/arch/arm/mach-imx/clk-fixup-div.c +++ b/drivers/clk/imx/clk-fixup-div.c diff --git a/arch/arm/mach-imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c index 0d40b35c557c..0d40b35c557c 100644 --- a/arch/arm/mach-imx/clk-fixup-mux.c +++ b/drivers/clk/imx/clk-fixup-mux.c diff --git a/arch/arm/mach-imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c index c12f5f2e04dc..c12f5f2e04dc 100644 --- a/arch/arm/mach-imx/clk-gate-exclusive.c +++ b/drivers/clk/imx/clk-gate-exclusive.c diff --git a/arch/arm/mach-imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 8935bff99fe7..8935bff99fe7 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c diff --git a/arch/arm/mach-imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c index 37c307a8d896..c2647fa19f28 100644 --- a/arch/arm/mach-imx/clk-imx1.c +++ b/drivers/clk/imx/clk-imx1.c @@ -23,10 +23,14 @@ #include <linux/of.h> #include <linux/of_address.h> #include <dt-bindings/clock/imx1-clock.h> +#include <soc/imx/timer.h> +#include <asm/irq.h> #include "clk.h" -#include "common.h" -#include "hardware.h" + +#define MX1_CCM_BASE_ADDR 0x0021b000 +#define MX1_TIM1_BASE_ADDR 0x00220000 +#define MX1_TIM1_INT (NR_IRQS_LEGACY + 59) static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", }; static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", @@ -50,9 +54,9 @@ static void __init _mx1_clocks_init(unsigned long fref) clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17); clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1); clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks)); - clk[IMX1_CLK_MPLL] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0); + clk[IMX1_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "mpll", "clk32_premult", CCM_MPCTL0); clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); - clk[IMX1_CLK_SPLL] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0); + clk[IMX1_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "spll", "prem", CCM_SPCTL0); clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1); clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1); @@ -75,7 +79,8 @@ static void __init _mx1_clocks_init(unsigned long fref) int __init mx1_clocks_init(unsigned long fref) { - ccm = MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR); + ccm = ioremap(MX1_CCM_BASE_ADDR, SZ_4K); + BUG_ON(!ccm); _mx1_clocks_init(fref); @@ -98,7 +103,7 @@ int __init mx1_clocks_init(unsigned long fref) clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0"); clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0"); - mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT); + mxc_timer_init(MX1_TIM1_BASE_ADDR, MX1_TIM1_INT, GPT_TYPE_IMX1); return 0; } diff --git a/arch/arm/mach-imx/clk-imx21.c b/drivers/clk/imx/clk-imx21.c index 4b4c75339aa6..dba987e3b89f 100644 --- a/arch/arm/mach-imx/clk-imx21.c +++ b/drivers/clk/imx/clk-imx21.c @@ -15,10 +15,14 @@ #include <linux/of.h> #include <linux/of_address.h> #include <dt-bindings/clock/imx21-clock.h> +#include <soc/imx/timer.h> +#include <asm/irq.h> #include "clk.h" -#include "common.h" -#include "hardware.h" + +#define MX21_CCM_BASE_ADDR 0x10027000 +#define MX21_GPT1_BASE_ADDR 0x10003000 +#define MX21_INT_GPT1 (NR_IRQS_LEGACY + 26) static void __iomem *ccm __initdata; @@ -63,9 +67,9 @@ static void __init _mx21_clocks_init(unsigned long lref, unsigned long href) clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3); clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3); - clk[IMX21_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0); + clk[IMX21_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "mpll", "mpll_sel", CCM_MPCTL0); - clk[IMX21_CLK_SPLL] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0); + clk[IMX21_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "spll", "spll_sel", CCM_SPCTL0); clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4); clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); @@ -153,7 +157,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href) clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0"); clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0"); - mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1); + mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1, GPT_TYPE_IMX21); return 0; } diff --git a/arch/arm/mach-imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c index 9c2633a9de9f..ec1a4c1dacf1 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/drivers/clk/imx/clk-imx25.c @@ -28,8 +28,6 @@ #include <linux/of_irq.h> #include "clk.h" -#include "common.h" -#include "hardware.h" #define CCM_MPCTL 0x00 #define CCM_UPCTL 0x04 @@ -95,8 +93,8 @@ static int __init __mx25_clocks_init(unsigned long osc_rate, clk[dummy] = imx_clk_fixed("dummy", 0); clk[osc] = imx_clk_fixed("osc", osc_rate); - clk[mpll] = imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL)); - clk[upll] = imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL)); + clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL)); + clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL)); clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4); clk[cpu_sel] = imx_clk_mux("cpu_sel", ccm(CCM_CCTL), 14, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); clk[cpu] = imx_clk_divider("cpu", "cpu_sel", ccm(CCM_CCTL), 30, 2); diff --git a/arch/arm/mach-imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c index ab6349ec23b9..d9d50d54ef2a 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/drivers/clk/imx/clk-imx27.c @@ -5,10 +5,15 @@ #include <linux/of.h> #include <linux/of_address.h> #include <dt-bindings/clock/imx27-clock.h> +#include <soc/imx/revision.h> +#include <soc/imx/timer.h> +#include <asm/irq.h> #include "clk.h" -#include "common.h" -#include "hardware.h" + +#define MX27_CCM_BASE_ADDR 0x10027000 +#define MX27_GPT1_BASE_ADDR 0x10003000 +#define MX27_INT_GPT1 (NR_IRQS_LEGACY + 26) static void __iomem *ccm __initdata; @@ -54,8 +59,8 @@ static void __init _mx27_clocks_init(unsigned long fref) clk[IMX27_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3); clk[IMX27_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks)); clk[IMX27_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks)); - clk[IMX27_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0); - clk[IMX27_CLK_SPLL] = imx_clk_pllv1("spll", "ckih_gate", CCM_SPCTL0); + clk[IMX27_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "mpll", "mpll_sel", CCM_MPCTL0); + clk[IMX27_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "spll", "ckih_gate", CCM_SPCTL0); clk[IMX27_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); clk[IMX27_CLK_MPLL_MAIN2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3); @@ -229,7 +234,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0"); clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0"); - mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1); + mxc_timer_init(MX27_GPT1_BASE_ADDR, MX27_INT_GPT1, GPT_TYPE_IMX21); return 0; } diff --git a/arch/arm/mach-imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index 286ef422cebc..fe66c40b7be2 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -21,12 +21,26 @@ #include <linux/io.h> #include <linux/err.h> #include <linux/of.h> +#include <soc/imx/revision.h> +#include <soc/imx/timer.h> +#include <asm/irq.h> #include "clk.h" -#include "common.h" -#include "crmregs-imx3.h" -#include "hardware.h" -#include "mx31.h" + +#define MX31_CCM_BASE_ADDR 0x53f80000 +#define MX31_GPT1_BASE_ADDR 0x53f90000 +#define MX31_INT_GPT (NR_IRQS_LEGACY + 29) + +#define MXC_CCM_CCMR 0x00 +#define MXC_CCM_PDR0 0x04 +#define MXC_CCM_PDR1 0x08 +#define MXC_CCM_MPCTL 0x10 +#define MXC_CCM_UPCTL 0x14 +#define MXC_CCM_SRPCTL 0x18 +#define MXC_CCM_CGR0 0x20 +#define MXC_CCM_CGR1 0x24 +#define MXC_CCM_CGR2 0x28 +#define MXC_CCM_PMCR0 0x5c static const char *mcu_main_sel[] = { "spll", "mpll", }; static const char *per_sel[] = { "per_div", "ipg", }; @@ -50,15 +64,18 @@ static struct clk_onecell_data clk_data; int __init mx31_clocks_init(unsigned long fref) { - void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR); + void __iomem *base; struct device_node *np; + base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K); + BUG_ON(!base); + clk[dummy] = imx_clk_fixed("dummy", 0); clk[ckih] = imx_clk_fixed("ckih", fref); clk[ckil] = imx_clk_fixed("ckil", 32768); - clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL); - clk[spll] = imx_clk_pllv1("spll", "ckih", base + MXC_CCM_SRPCTL); - clk[upll] = imx_clk_pllv1("upll", "ckih", base + MXC_CCM_UPCTL); + clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "mpll", "ckih", base + MXC_CCM_MPCTL); + clk[spll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "spll", "ckih", base + MXC_CCM_SRPCTL); + clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "upll", "ckih", base + MXC_CCM_UPCTL); clk[mcu_main] = imx_clk_mux("mcu_main", base + MXC_CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel)); clk[hsp] = imx_clk_divider("hsp", "mcu_main", base + MXC_CCM_PDR0, 11, 3); clk[ahb] = imx_clk_divider("ahb", "mcu_main", base + MXC_CCM_PDR0, 3, 3); @@ -182,7 +199,7 @@ int __init mx31_clocks_init(unsigned long fref) mx31_revision(); clk_disable_unprepare(clk[iim_gate]); - mxc_timer_init(MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), MX31_INT_GPT); + mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31); return 0; } diff --git a/arch/arm/mach-imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c index a0d2b57fd376..69138ba3dec7 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/drivers/clk/imx/clk-imx35.c @@ -13,11 +13,26 @@ #include <linux/clkdev.h> #include <linux/of.h> #include <linux/err.h> +#include <soc/imx/revision.h> +#include <soc/imx/timer.h> +#include <asm/irq.h> -#include "crmregs-imx3.h" #include "clk.h" -#include "common.h" -#include "hardware.h" + +#define MX35_CCM_BASE_ADDR 0x53f80000 +#define MX35_GPT1_BASE_ADDR 0x53f90000 +#define MX35_INT_GPT (NR_IRQS_LEGACY + 29) + +#define MXC_CCM_PDR0 0x04 +#define MX35_CCM_PDR2 0x0c +#define MX35_CCM_PDR3 0x10 +#define MX35_CCM_PDR4 0x14 +#define MX35_CCM_MPCTL 0x1c +#define MX35_CCM_PPCTL 0x20 +#define MX35_CCM_CGR0 0x2c +#define MX35_CCM_CGR1 0x30 +#define MX35_CCM_CGR2 0x34 +#define MX35_CCM_CGR3 0x38 struct arm_ahb_div { unsigned char arm, ahb, sel; @@ -71,11 +86,14 @@ static struct clk *clk[clk_max]; int __init mx35_clocks_init(void) { - void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR); + void __iomem *base; u32 pdr0, consumer_sel, hsp_sel; struct arm_ahb_div *aad; unsigned char *hsp_div; + base = ioremap(MX35_CCM_BASE_ADDR, SZ_4K); + BUG_ON(!base); + pdr0 = __raw_readl(base + MXC_CCM_PDR0); consumer_sel = (pdr0 >> 16) & 0xf; aad = &clk_consumer[consumer_sel]; @@ -89,8 +107,8 @@ int __init mx35_clocks_init(void) } clk[ckih] = imx_clk_fixed("ckih", 24000000); - clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MX35_CCM_MPCTL); - clk[ppll] = imx_clk_pllv1("ppll", "ckih", base + MX35_CCM_PPCTL); + clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL); + clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL); clk[mpll] = imx_clk_fixed_factor("mpll_075", "mpll", 3, 4); @@ -276,11 +294,7 @@ int __init mx35_clocks_init(void) imx_print_silicon_rev("i.MX35", mx35_revision()); -#ifdef CONFIG_MXC_USE_EPIT - epit_timer_init(MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1); -#else - mxc_timer_init(MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); -#endif + mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31); return 0; } diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c index 0f7e536147cb..a7e4f394be0d 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/drivers/clk/imx/clk-imx51-imx53.c @@ -16,11 +16,10 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <soc/imx/revision.h> #include <dt-bindings/clock/imx5-clock.h> #include "clk.h" -#include "common.h" -#include "hardware.h" #define MX51_DPLL1_BASE 0x83f80000 #define MX51_DPLL2_BASE 0x83f84000 @@ -133,8 +132,6 @@ static struct clk_onecell_data clk_data; static void __init mx5_clocks_common_init(void __iomem *ccm_base) { - imx5_pm_set_ccm_base(ccm_base); - clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0); clk[IMX5_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); clk[IMX5_CLK_OSC] = imx_obtain_fixed_clock("osc", 0); diff --git a/arch/arm/mach-imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index 469a150bf98f..d046f8e43de8 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -19,11 +19,10 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <soc/imx/revision.h> #include <dt-bindings/clock/imx6qdl-clock.h> #include "clk.h" -#include "common.h" -#include "hardware.h" static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; @@ -121,6 +120,16 @@ static unsigned int share_count_ssi2; static unsigned int share_count_ssi3; static unsigned int share_count_mipi_core_cfg; +static inline int clk_on_imx6q(void) +{ + return of_machine_is_compatible("fsl,imx6q"); +} + +static inline int clk_on_imx6dl(void) +{ + return of_machine_is_compatible("fsl,imx6dl"); +} + static void __init imx6q_clocks_init(struct device_node *ccm_node) { struct device_node *np; @@ -141,7 +150,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) WARN_ON(!base); /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ - if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) { + if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) { post_div_table[1].div = 1; post_div_table[2].div = 1; video_div_table[1].div = 1; @@ -248,7 +257,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); clk[IMX6QDL_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20); - if (cpu_is_imx6dl()) { + if (clk_on_imx6dl()) { clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1); clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1); } @@ -262,8 +271,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) base = of_iomap(np, 0); WARN_ON(!base); - imx6q_pm_set_ccm_base(base); - /* name reg shift width parent_names num_parents */ clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); @@ -275,7 +282,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); clk[IMX6QDL_CLK_ASRC_SEL] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); clk[IMX6QDL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); - if (cpu_is_imx6q()) { + if (clk_on_imx6q()) { clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); } @@ -382,7 +389,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); clk[IMX6QDL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); clk[IMX6QDL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); - if (cpu_is_imx6dl()) + if (clk_on_imx6dl()) clk[IMX6DL_CLK_I2C4] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8); else clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); @@ -392,7 +399,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); - if (cpu_is_imx6dl()) + if (clk_on_imx6dl()) /* * The multiplexer and divider of imx6q clock gpu3d_shader get * redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl. @@ -420,7 +427,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_HSI_TX] = imx_clk_gate2_shared("hsi_tx", "hsi_tx_podf", base + 0x74, 16, &share_count_mipi_core_cfg); clk[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg); clk[IMX6QDL_CLK_MIPI_IPG] = imx_clk_gate2_shared("mipi_ipg", "ipg", base + 0x74, 16, &share_count_mipi_core_cfg); - if (cpu_is_imx6dl()) + if (clk_on_imx6dl()) /* * The multiplexer and divider of the imx6q clock gpu2d get * redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl. @@ -443,7 +450,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); clk[IMX6QDL_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); clk[IMX6QDL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); - clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); + clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4); clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14); @@ -470,7 +477,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) * The gpt_3m clock is not available on i.MX6Q TO1.0. Let's point it * to clock gpt_ipg_per to ease the gpt driver code. */ - if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) + if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) clk[IMX6QDL_CLK_GPT_3M] = clk[IMX6QDL_CLK_GPT_IPG_PER]; imx_check_clocks(clk, ARRAY_SIZE(clk)); @@ -482,7 +489,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL); if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || - cpu_is_imx6dl()) { + clk_on_imx6dl()) { clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]); } @@ -527,8 +534,5 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) /* All existing boards with PCIe use LVDS1 */ if (IS_ENABLED(CONFIG_PCI_IMX6)) clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]); - - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); } CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c index e982ebe10814..a0d4cf26cfa9 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/drivers/clk/imx/clk-imx6sl.c @@ -16,7 +16,6 @@ #include <dt-bindings/clock/imx6sl-clock.h> #include "clk.h" -#include "common.h" #define CCSR 0xc #define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2) @@ -288,9 +287,6 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) WARN_ON(!base); ccm_base = base; - /* Reuse imx6q pm code */ - imx6q_pm_set_ccm_base(base); - /* name reg shift width parent_names num_parents */ clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); @@ -443,8 +439,5 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL], clks[IMX6SL_CLK_PLL2_PFD2]); - - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); } CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index 87c5b0911ddd..5b95c2c2bf52 100644 --- a/arch/arm/mach-imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -21,7 +21,6 @@ #include <linux/types.h> #include "clk.h" -#include "common.h" #define CCDR 0x4 #define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16) @@ -268,8 +267,6 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) base = of_iomap(np, 0); WARN_ON(!base); - imx6q_pm_set_ccm_base(base); - /* name reg shift width parent_names num_parents */ clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); @@ -560,8 +557,5 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]); clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]); - - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); } CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c new file mode 100644 index 000000000000..71f3a94b472c --- /dev/null +++ b/drivers/clk/imx/clk-imx7d.c @@ -0,0 +1,860 @@ +/* + * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <dt-bindings/clock/imx7d-clock.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/types.h> + +#include "clk.h" + +static struct clk *clks[IMX7D_CLK_END]; +static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk", + "pll_enet_500m_clk", "pll_dram_main_clk", + "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_audio_main_clk", + "pll_usb_main_clk", }; + +static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_250m_clk", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_usb_main_clk", }; + +static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_125m_clk", "pll_sys_pfd2_135m_clk", + "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_usb_main_clk", }; + +static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_sys_pfd7_clk", }; + +static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk", + "pll_sys_pfd7_clk", "pll_audio_main_clk", "pll_video_main_clk", }; + +static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", + "pll_sys_main_240m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_sys_pfd4_clk", }; + +static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_sys_main_240m_clk", + "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", + "pll_audio_main_clk", }; + +static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk", + "pll_video_main_clk", }; + +static const char *dram_phym_sel[] = { "pll_dram_main_clk", + "dram_phym_alt_clk", }; + +static const char *dram_sel[] = { "pll_dram_main_clk", + "dram_alt_clk", }; + +static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk", + "pll_sys_main_clk", "pll_enet_500m_clk", + "pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_main_clk", + "pll_video_main_clk", }; + +static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk", + "pll_sys_main_clk", "pll_enet_500m_clk", + "pll_enet_250m_clk", "pll_sys_pfd0_392m_clk", + "pll_audio_main_clk", "pll_sys_pfd2_270m_clk", }; + +static const char *usb_hsic_sel[] = { "osc", "pll_sys_main_clk", + "pll_usb_main_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *pcie_ctrl_sel[] = { "osc", "pll_enet_250m_clk", + "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", + "pll_sys_pfd1_332m_clk", "pll_sys_pfd6_clk", }; + +static const char *pcie_phy_sel[] = { "osc", "pll_enet_100m_clk", + "pll_enet_500m_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_sys_pfd0_392m_clk", }; + +static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_sys_main_clk", "pll_sys_pfd5_clk", + "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main_clk", }; + +static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk", + "pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_video_main_clk", + "pll_usb_main_clk", }; + +static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk", + "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk", + "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_main_clk", }; + +static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk", + "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk", + "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_main_clk", }; + +static const char *mipi_dphy_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_pfd5_clk", "ref_1m_clk", "ext_clk_2", + "pll_video_main_clk", "ext_clk_3", }; + +static const char *sai1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; + +static const char *sai2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; + +static const char *sai3_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_3", }; + +static const char *spdif_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_main_clk", "pll_dram_533m_clk", "pll_video_main_clk", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_3_clk", }; + +static const char *enet1_ref_sel[] = { "osc", "pll_enet_125m_clk", + "pll_enet_50m_clk", "pll_enet_25m_clk", + "pll_sys_main_120m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "ext_clk_4", }; + +static const char *enet1_time_sel[] = { "osc", "pll_enet_100m_clk", + "pll_audio_main_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_video_main_clk", }; + +static const char *enet2_ref_sel[] = { "osc", "pll_enet_125m_clk", + "pll_enet_50m_clk", "pll_enet_25m_clk", + "pll_sys_main_120m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "ext_clk_4", }; + +static const char *enet2_time_sel[] = { "osc", "pll_enet_100m_clk", + "pll_audio_main_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_video_main_clk", }; + +static const char *enet_phy_ref_sel[] = { "osc", "pll_enet_25m_clk", + "pll_enet_50m_clk", "pll_enet_125m_clk", + "pll_dram_533m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_sys_pfd3_clk", }; + +static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_enet_125m_clk", + "pll_usb_main_clk", }; + +static const char *nand_sel[] = { "osc", "pll_sys_main_clk", + "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd3_clk", + "pll_enet_500m_clk", "pll_enet_250m_clk", + "pll_video_main_clk", }; + +static const char *qspi_sel[] = { "osc", "pll_sys_pfd4_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd3_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc1_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc2_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc3_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *can1_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_main_clk", + "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", + "ext_clk_4", }; + +static const char *can2_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_main_clk", + "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", + "ext_clk_3", }; + +static const char *i2c1_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c2_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c3_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c4_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *uart1_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart3_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart5_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart6_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart7_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *ecspi1_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi3_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main_clk", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *pwm1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *pwm2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *pwm3_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *pwm4_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *flextimer1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *flextimer2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_main_clk", + "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", }; + +static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_usb_main_clk", "pll_audio_main_clk", "pll_enet_125m_clk", + "pll_sys_pfd7_clk", }; + +static const char *sim2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_usb_main_clk", "pll_video_main_clk", "pll_enet_125m_clk", + "pll_sys_pfd7_clk", }; + +static const char *gpt1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", + "ref_1m_clk", "pll_audio_main_clk", "ext_clk_1", }; + +static const char *gpt2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", + "ref_1m_clk", "pll_audio_main_clk", "ext_clk_2", }; + +static const char *gpt3_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", + "ref_1m_clk", "pll_audio_main_clk", "ext_clk_3", }; + +static const char *gpt4_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk", + "ref_1m_clk", "pll_audio_main_clk", "ext_clk_4", }; + +static const char *trace_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "ext_clk_2", + "ext_clk_3", }; + +static const char *wdog_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "ref_1m_clk", + "pll_sys_pfd1_166m_clk", }; + +static const char *csi_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_usb_main_clk", }; + +static const char *audio_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_audio_main_clk", "pll_video_main_clk", + "pll_usb_main_clk", }; + +static const char *wrclk_sel[] = { "osc", "pll_enet_40m_clk", + "pll_dram_533m_clk", "pll_usb_main_clk", + "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", + "pll_enet_500m_clk", "pll_sys_pfd7_clk", }; + +static const char *clko1_sel[] = { "osc", "pll_sys_main_clk", + "pll_sys_main_240m_clk", "pll_sys_pfd0_196m_clk", "pll_sys_pfd3_clk", + "pll_enet_500m_clk", "pll_dram_533m_clk", "ref_1m_clk", }; + +static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", + "pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", }; + +static const char *lvds1_sel[] = { "pll_arm_main_clk", + "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", + "pll_audio_main_clk", "pll_video_main_clk", "pll_enet_500m_clk", + "pll_enet_250m_clk", "pll_enet_125m_clk", "pll_enet_100m_clk", + "pll_enet_50m_clk", "pll_enet_40m_clk", "pll_enet_25m_clk", + "pll_dram_main_clk", }; + +static const char *pll_bypass_src_sel[] = { "osc", "dummy", }; +static const char *pll_arm_bypass_sel[] = { "pll_arm_main", "pll_arm_main_src", }; +static const char *pll_dram_bypass_sel[] = { "pll_dram_main", "pll_dram_main_src", }; +static const char *pll_sys_bypass_sel[] = { "pll_sys_main", "pll_sys_main_src", }; +static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src", }; +static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", }; +static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", }; + +static struct clk_onecell_data clk_data; + +static void __init imx7d_clocks_init(struct device_node *ccm_node) +{ + struct device_node *np; + void __iomem *base; + int i; + + clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); + clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); + base = of_iomap(np, 0); + WARN_ON(!base); + + clks[IMX7D_PLL_ARM_MAIN_SRC] = imx_clk_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + clks[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + clks[IMX7D_PLL_SYS_MAIN_SRC] = imx_clk_mux("pll_sys_main_src", base + 0xb0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + clks[IMX7D_PLL_ENET_MAIN_SRC] = imx_clk_mux("pll_enet_main_src", base + 0xe0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + clks[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); + + clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "pll_arm_main_src", base + 0x60, 0x7f); + clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f); + clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "pll_sys_main_src", base + 0xb0, 0x1); + clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "pll_enet_main_src", base + 0xe0, 0x0); + clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "pll_audio_main_src", base + 0xf0, 0x7f); + clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "pll_video_main_src", base + 0x130, 0x7f); + + clks[IMX7D_PLL_ARM_MAIN_BYPASS] = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT); + clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT); + clks[IMX7D_PLL_SYS_MAIN_BYPASS] = imx_clk_mux_flags("pll_sys_main_bypass", base + 0xb0, 16, 1, pll_sys_bypass_sel, ARRAY_SIZE(pll_sys_bypass_sel), CLK_SET_RATE_PARENT); + clks[IMX7D_PLL_ENET_MAIN_BYPASS] = imx_clk_mux_flags("pll_enet_main_bypass", base + 0xe0, 16, 1, pll_enet_bypass_sel, ARRAY_SIZE(pll_enet_bypass_sel), CLK_SET_RATE_PARENT); + clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT); + clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT); + + clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]); + clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]); + clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]); + clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]); + clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]); + clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]); + + clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13); + clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_main_bypass", base + 0x70, 13); + clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13); + clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13); + clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13); + + clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0); + clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1); + clks[IMX7D_PLL_SYS_PFD2_270M_CLK] = imx_clk_pfd("pll_sys_pfd2_270m_clk", "pll_sys_main_clk", base + 0xc0, 2); + + clks[IMX7D_PLL_SYS_PFD3_CLK] = imx_clk_pfd("pll_sys_pfd3_clk", "pll_sys_main_clk", base + 0xc0, 3); + clks[IMX7D_PLL_SYS_PFD4_CLK] = imx_clk_pfd("pll_sys_pfd4_clk", "pll_sys_main_clk", base + 0xd0, 0); + clks[IMX7D_PLL_SYS_PFD5_CLK] = imx_clk_pfd("pll_sys_pfd5_clk", "pll_sys_main_clk", base + 0xd0, 1); + clks[IMX7D_PLL_SYS_PFD6_CLK] = imx_clk_pfd("pll_sys_pfd6_clk", "pll_sys_main_clk", base + 0xd0, 2); + clks[IMX7D_PLL_SYS_PFD7_CLK] = imx_clk_pfd("pll_sys_pfd7_clk", "pll_sys_main_clk", base + 0xd0, 3); + + clks[IMX7D_PLL_SYS_MAIN_480M] = imx_clk_fixed_factor("pll_sys_main_480m", "pll_sys_main_clk", 1, 1); + clks[IMX7D_PLL_SYS_MAIN_240M] = imx_clk_fixed_factor("pll_sys_main_240m", "pll_sys_main_clk", 1, 2); + clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4); + clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2); + + clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4); + clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5); + clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6); + clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12); + + clks[IMX7D_PLL_SYS_PFD0_196M] = imx_clk_fixed_factor("pll_sys_pfd0_196m", "pll_sys_pfd0_392m_clk", 1, 2); + clks[IMX7D_PLL_SYS_PFD1_166M] = imx_clk_fixed_factor("pll_sys_pfd1_166m", "pll_sys_pfd1_332m_clk", 1, 2); + clks[IMX7D_PLL_SYS_PFD2_135M] = imx_clk_fixed_factor("pll_sys_pfd2_135m", "pll_sys_pfd2_270m_clk", 1, 2); + + clks[IMX7D_PLL_SYS_PFD0_196M_CLK] = imx_clk_gate_dis("pll_sys_pfd0_196m_clk", "pll_sys_pfd0_196m", base + 0xb0, 26); + clks[IMX7D_PLL_SYS_PFD1_166M_CLK] = imx_clk_gate_dis("pll_sys_pfd1_166m_clk", "pll_sys_pfd1_166m", base + 0xb0, 27); + clks[IMX7D_PLL_SYS_PFD2_135M_CLK] = imx_clk_gate_dis("pll_sys_pfd2_135m_clk", "pll_sys_pfd2_135m", base + 0xb0, 28); + + clks[IMX7D_PLL_ENET_MAIN_CLK] = imx_clk_fixed_factor("pll_enet_main_clk", "pll_enet_main_bypass", 1, 1); + clks[IMX7D_PLL_ENET_MAIN_500M] = imx_clk_fixed_factor("pll_enet_500m", "pll_enet_main_clk", 1, 2); + clks[IMX7D_PLL_ENET_MAIN_250M] = imx_clk_fixed_factor("pll_enet_250m", "pll_enet_main_clk", 1, 4); + clks[IMX7D_PLL_ENET_MAIN_125M] = imx_clk_fixed_factor("pll_enet_125m", "pll_enet_main_clk", 1, 8); + clks[IMX7D_PLL_ENET_MAIN_100M] = imx_clk_fixed_factor("pll_enet_100m", "pll_enet_main_clk", 1, 10); + clks[IMX7D_PLL_ENET_MAIN_50M] = imx_clk_fixed_factor("pll_enet_50m", "pll_enet_main_clk", 1, 20); + clks[IMX7D_PLL_ENET_MAIN_40M] = imx_clk_fixed_factor("pll_enet_40m", "pll_enet_main_clk", 1, 25); + clks[IMX7D_PLL_ENET_MAIN_25M] = imx_clk_fixed_factor("pll_enet_25m", "pll_enet_main_clk", 1, 40); + + clks[IMX7D_PLL_ENET_MAIN_500M_CLK] = imx_clk_gate("pll_enet_500m_clk", "pll_enet_500m", base + 0xe0, 12); + clks[IMX7D_PLL_ENET_MAIN_250M_CLK] = imx_clk_gate("pll_enet_250m_clk", "pll_enet_250m", base + 0xe0, 11); + clks[IMX7D_PLL_ENET_MAIN_125M_CLK] = imx_clk_gate("pll_enet_125m_clk", "pll_enet_125m", base + 0xe0, 10); + clks[IMX7D_PLL_ENET_MAIN_100M_CLK] = imx_clk_gate("pll_enet_100m_clk", "pll_enet_100m", base + 0xe0, 9); + clks[IMX7D_PLL_ENET_MAIN_50M_CLK] = imx_clk_gate("pll_enet_50m_clk", "pll_enet_50m", base + 0xe0, 8); + clks[IMX7D_PLL_ENET_MAIN_40M_CLK] = imx_clk_gate("pll_enet_40m_clk", "pll_enet_40m", base + 0xe0, 7); + clks[IMX7D_PLL_ENET_MAIN_25M_CLK] = imx_clk_gate("pll_enet_25m_clk", "pll_enet_25m", base + 0xe0, 6); + + clks[IMX7D_LVDS1_OUT_SEL] = imx_clk_mux("lvds1_sel", base + 0x170, 0, 5, lvds1_sel, ARRAY_SIZE(lvds1_sel)); + clks[IMX7D_LVDS1_OUT_CLK] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x170, 5, BIT(6)); + + np = ccm_node; + base = of_iomap(np, 0); + WARN_ON(!base); + + clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); + clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); + clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); + clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); + clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); + clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); + clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel)); + clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel)); + clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel)); + clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel)); + clks[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_mux("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); + clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel)); + clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel)); + clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel)); + clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel)); + clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel)); + clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel)); + clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel)); + clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel)); + clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel)); + clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel)); + clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel)); + clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel)); + clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel)); + clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel)); + clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel)); + clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel)); + clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel)); + clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel)); + clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel)); + clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel)); + clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel)); + clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel)); + clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel)); + clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel)); + clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel)); + clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel)); + clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel)); + clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel)); + clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel)); + clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel)); + clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel)); + clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel)); + clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel)); + clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel)); + clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel)); + clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel)); + clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel)); + clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel)); + clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel)); + clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel)); + clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel)); + clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel)); + clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel)); + clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel)); + clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel)); + clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel)); + clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel)); + clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel)); + clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel)); + clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel)); + clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel)); + clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel)); + clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel)); + clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel)); + clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel)); + clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel)); + clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel)); + clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel)); + clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel)); + + clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); + clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); + clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); + clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate("axi_cg", "axi_src", base + 0x8800, 28); + clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); + clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28); + clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate("ahb_cg", "ahb_src", base + 0x9000, 28); + clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate("dram_phym_cg", "dram_phym_src", base + 0x9800, 28); + clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate("dram_cg", "dram_src", base + 0x9880, 28); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28); + clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate("dram_alt_cg", "dram_alt_src", base + 0xa080, 28); + clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28); + clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28); + clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28); + clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28); + clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28); + clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28); + clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28); + clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28); + clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate("sai1_cg", "sai1_src", base + 0xa500, 28); + clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate("sai2_cg", "sai2_src", base + 0xa580, 28); + clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate("sai3_cg", "sai3_src", base + 0xa600, 28); + clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate("spdif_cg", "spdif_src", base + 0xa680, 28); + clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28); + clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate("enet1_time_cg", "enet1_time_src", base + 0xa780, 28); + clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28); + clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate("enet2_time_cg", "enet2_time_src", base + 0xa880, 28); + clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28); + clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate("eim_cg", "eim_src", base + 0xa980, 28); + clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate("nand_cg", "nand_src", base + 0xaa00, 28); + clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate("qspi_cg", "qspi_src", base + 0xaa80, 28); + clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate("usdhc1_cg", "usdhc1_src", base + 0xab00, 28); + clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate("usdhc2_cg", "usdhc2_src", base + 0xab80, 28); + clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate("usdhc3_cg", "usdhc3_src", base + 0xac00, 28); + clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate("can1_cg", "can1_src", base + 0xac80, 28); + clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate("can2_cg", "can2_src", base + 0xad00, 28); + clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate("i2c1_cg", "i2c1_src", base + 0xad80, 28); + clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate("i2c2_cg", "i2c2_src", base + 0xae00, 28); + clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate("i2c3_cg", "i2c3_src", base + 0xae80, 28); + clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate("i2c4_cg", "i2c4_src", base + 0xaf00, 28); + clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate("uart1_cg", "uart1_src", base + 0xaf80, 28); + clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate("uart2_cg", "uart2_src", base + 0xb000, 28); + clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate("uart3_cg", "uart3_src", base + 0xb080, 28); + clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate("uart4_cg", "uart4_src", base + 0xb100, 28); + clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate("uart5_cg", "uart5_src", base + 0xb180, 28); + clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate("uart6_cg", "uart6_src", base + 0xb200, 28); + clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate("uart7_cg", "uart7_src", base + 0xb280, 28); + clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate("ecspi1_cg", "ecspi1_src", base + 0xb300, 28); + clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate("ecspi2_cg", "ecspi2_src", base + 0xb380, 28); + clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate("ecspi3_cg", "ecspi3_src", base + 0xb400, 28); + clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate("ecspi4_cg", "ecspi4_src", base + 0xb480, 28); + clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate("pwm1_cg", "pwm1_src", base + 0xb500, 28); + clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate("pwm2_cg", "pwm2_src", base + 0xb580, 28); + clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate("pwm3_cg", "pwm3_src", base + 0xb600, 28); + clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate("pwm4_cg", "pwm4_src", base + 0xb680, 28); + clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate("flextimer1_cg", "flextimer1_src", base + 0xb700, 28); + clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate("flextimer2_cg", "flextimer2_src", base + 0xb780, 28); + clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate("sim1_cg", "sim1_src", base + 0xb800, 28); + clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate("sim2_cg", "sim2_src", base + 0xb880, 28); + clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate("gpt1_cg", "gpt1_src", base + 0xb900, 28); + clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate("gpt2_cg", "gpt2_src", base + 0xb980, 28); + clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate("gpt3_cg", "gpt3_src", base + 0xbA00, 28); + clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate("gpt4_cg", "gpt4_src", base + 0xbA80, 28); + clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate("trace_cg", "trace_src", base + 0xbb00, 28); + clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate("wdog_cg", "wdog_src", base + 0xbb80, 28); + clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28); + clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28); + clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate("wrclk_cg", "wrclk_src", base + 0xbd00, 28); + clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate("clko1_cg", "clko1_src", base + 0xbd80, 28); + clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate("clko2_cg", "clko2_src", base + 0xbe00, 28); + + clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider("axi_pre_div", "axi_cg", base + 0x8800, 16, 3); + clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3); + clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3); + clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3); + clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3); + clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3); + clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3); + clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3); + clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3); + clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3); + clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3); + clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3); + clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3); + clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3); + clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3); + clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3); + clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3); + clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3); + clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3); + clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3); + clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3); + clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3); + clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3); + clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider("eim_pre_div", "eim_cg", base + 0xa980, 16, 3); + clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3); + clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3); + clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3); + clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3); + clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3); + clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider("can1_pre_div", "can1_cg", base + 0xac80, 16, 3); + clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider("can2_pre_div", "can2_cg", base + 0xad00, 16, 3); + clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3); + clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3); + clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3); + clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3); + clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3); + clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3); + clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3); + clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3); + clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3); + clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3); + clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3); + clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3); + clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3); + clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3); + clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3); + clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3); + clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3); + clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3); + clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3); + clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3); + clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3); + clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3); + clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3); + clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3); + clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3); + clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3); + clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3); + clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3); + clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3); + clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3); + clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3); + clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3); + clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3); + clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3); + + clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); + clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); + clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); + clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); + clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); + clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); + clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6); + clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6); + clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider("dram_post_div", "dram_cg", base + 0x9880, 0, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); + clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); + clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6); + clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6); + clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6); + clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6); + clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6); + clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6); + clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6); + clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6); + clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6); + clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6); + clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6); + clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6); + clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6); + clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6); + clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6); + clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6); + clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6); + clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6); + clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6); + clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6); + clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6); + clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6); + clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6); + clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6); + clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6); + clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6); + clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6); + clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6); + clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6); + clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6); + clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6); + clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6); + clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6); + clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6); + clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6); + clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6); + clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6); + clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6); + clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6); + clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6); + clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6); + clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6); + clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6); + clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6); + clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6); + clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6); + clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6); + clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6); + clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6); + clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6); + clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6); + clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6); + clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6); + clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6); + clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6); + clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6); + clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6); + clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); + clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); + + clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); + clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate2("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); + clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate2("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); + clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); + clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate2("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); + clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate2("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); + clks[IMX7D_OCRAM_CLK] = imx_clk_gate2("ocram_clk", "axi_post_div", base + 0x4110, 0); + clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate2("ocram_s_clk", "ahb_post_div", base + 0x4120, 0); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate2("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0); + clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate2("ahb_root_clk", "ahb_post_div", base + 0x4200, 0); + clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2("dram_root_clk", "dram_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); + clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate2("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); + clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate2("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); + clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate2("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); + clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate2("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); + clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate2("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0); + clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate2("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0); + clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate2("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0); + clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate2("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0); + clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0); + clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0); + clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0); + clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate2("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0); + clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate2("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0); + clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0); + clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate2("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0); + clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0); + clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate2("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0); + clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate2("eim_root_clk", "eim_post_div", base + 0x4160, 0); + clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate2("nand_root_clk", "nand_post_div", base + 0x4140, 0); + clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate2("qspi_root_clk", "qspi_post_div", base + 0x4150, 0); + clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate2("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0); + clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate2("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0); + clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate2("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0); + clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate2("can1_root_clk", "can1_post_div", base + 0x4740, 0); + clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate2("can2_root_clk", "can2_post_div", base + 0x4750, 0); + clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate2("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0); + clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate2("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0); + clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate2("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0); + clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate2("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0); + clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate2("uart1_root_clk", "uart1_post_div", base + 0x4940, 0); + clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate2("uart2_root_clk", "uart2_post_div", base + 0x4950, 0); + clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate2("uart3_root_clk", "uart3_post_div", base + 0x4960, 0); + clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate2("uart4_root_clk", "uart4_post_div", base + 0x4970, 0); + clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate2("uart5_root_clk", "uart5_post_div", base + 0x4980, 0); + clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate2("uart6_root_clk", "uart6_post_div", base + 0x4990, 0); + clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate2("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0); + clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate2("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0); + clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate2("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0); + clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate2("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0); + clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate2("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0); + clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate2("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0); + clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate2("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0); + clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate2("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0); + clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate2("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0); + clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate2("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0); + clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate2("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0); + clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate2("sim1_root_clk", "sim1_post_div", base + 0x4900, 0); + clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate2("sim2_root_clk", "sim2_post_div", base + 0x4910, 0); + clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate2("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0); + clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate2("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0); + clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate2("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0); + clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate2("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0); + clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate2("trace_root_clk", "trace_post_div", base + 0x4300, 0); + clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate2("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0); + clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate2("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0); + clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate2("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0); + clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate2("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); + clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); + clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); + clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); + + clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); + + for (i = 0; i < ARRAY_SIZE(clks); i++) + if (IS_ERR(clks[i])) + pr_err("i.MX7D clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + /* TO BE FIXED LATER + * Enable all clock to bring up imx7, otherwise system will be halt and block + * the other part upstream Because imx7d clock design changed, clock framework + * need do a little modify. + * Dong Aisheng is working on this. After that, this part need be changed. + */ + for (i = 0; i < IMX7D_CLK_END; i++) + clk_prepare_enable(clks[i]); + + /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ + clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); + + /* + * init enet clock source: + * AXI clock source is 250MHz + * Phy refrence clock is 25MHz + * 1588 time clock source is 100MHz + */ + clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]); + clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]); + clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); + clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); + + /* set uart module clock's parent clock source that must be great then 80MHz */ + clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); + +} +CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init); diff --git a/arch/arm/mach-imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c index 0b0f6f66ec56..0b0f6f66ec56 100644 --- a/arch/arm/mach-imx/clk-pfd.c +++ b/drivers/clk/imx/clk-pfd.c diff --git a/arch/arm/mach-imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c index d21d14ca46c1..c34ad8a611dd 100644 --- a/arch/arm/mach-imx/clk-pllv1.c +++ b/drivers/clk/imx/clk-pllv1.c @@ -6,8 +6,6 @@ #include <linux/err.h> #include "clk.h" -#include "common.h" -#include "hardware.h" /** * pll v1 @@ -26,13 +24,29 @@ struct clk_pllv1 { struct clk_hw hw; void __iomem *base; + enum imx_pllv1_type type; }; #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk)) -static inline bool mfn_is_negative(unsigned int mfn) +static inline bool is_imx1_pllv1(struct clk_pllv1 *pll) { - return !cpu_is_mx1() && !cpu_is_mx21() && (mfn & MFN_SIGN); + return pll->type == IMX_PLLV1_IMX1; +} + +static inline bool is_imx21_pllv1(struct clk_pllv1 *pll) +{ + return pll->type == IMX_PLLV1_IMX21; +} + +static inline bool is_imx27_pllv1(struct clk_pllv1 *pll) +{ + return pll->type == IMX_PLLV1_IMX27; +} + +static inline bool mfn_is_negative(struct clk_pllv1 *pll, unsigned int mfn) +{ + return !is_imx1_pllv1(pll) && !is_imx21_pllv1(pll) && (mfn & MFN_SIGN); } static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, @@ -71,8 +85,8 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, * 2's complements number. * On i.MX27 the bit 9 is the sign bit. */ - if (mfn_is_negative(mfn)) { - if (cpu_is_mx27()) + if (mfn_is_negative(pll, mfn)) { + if (is_imx27_pllv1(pll)) mfn_abs = mfn & MFN_MASK; else mfn_abs = BIT(MFN_BITS) - mfn; @@ -85,7 +99,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, do_div(ll, mfd + 1); - if (mfn_is_negative(mfn)) + if (mfn_is_negative(pll, mfn)) ll = -ll; ll = (rate * mfi) + ll; @@ -97,8 +111,8 @@ static struct clk_ops clk_pllv1_ops = { .recalc_rate = clk_pllv1_recalc_rate, }; -struct clk *imx_clk_pllv1(const char *name, const char *parent, - void __iomem *base) +struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name, + const char *parent, void __iomem *base) { struct clk_pllv1 *pll; struct clk *clk; @@ -109,6 +123,7 @@ struct clk *imx_clk_pllv1(const char *name, const char *parent, return ERR_PTR(-ENOMEM); pll->base = base; + pll->type = type; init.name = name; init.ops = &clk_pllv1_ops; diff --git a/arch/arm/mach-imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c index 20889d59b44d..20889d59b44d 100644 --- a/arch/arm/mach-imx/clk-pllv2.c +++ b/drivers/clk/imx/clk-pllv2.c diff --git a/arch/arm/mach-imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 641ebc508920..f0d15fb9d783 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -24,12 +24,14 @@ #define BM_PLL_POWER (0x1 << 12) #define BM_PLL_LOCK (0x1 << 31) +#define IMX7_ENET_PLL_POWER (0x1 << 5) /** * struct clk_pllv3 - IMX PLL clock version 3 * @clk_hw: clock source * @base: base address of PLL registers * @powerup_set: set POWER bit to power up the PLL + * @powerdown: pll powerdown offset bit * @div_mask: mask of divider bits * @div_shift: shift of divider bits * @@ -40,6 +42,7 @@ struct clk_pllv3 { struct clk_hw hw; void __iomem *base; bool powerup_set; + u32 powerdown; u32 div_mask; u32 div_shift; }; @@ -49,7 +52,7 @@ struct clk_pllv3 { static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) { unsigned long timeout = jiffies + msecs_to_jiffies(10); - u32 val = readl_relaxed(pll->base) & BM_PLL_POWER; + u32 val = readl_relaxed(pll->base) & pll->powerdown; /* No need to wait for lock when pll is not powered up */ if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) @@ -215,7 +218,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long max_rate = parent_rate * 54; u32 div; u32 mfn, mfd = 1000000; - s64 temp64; + u64 temp64; if (rate > max_rate) rate = max_rate; @@ -239,7 +242,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long max_rate = parent_rate * 54; u32 val, div; u32 mfn, mfd = 1000000; - s64 temp64; + u64 temp64; if (rate < min_rate || rate > max_rate) return -EINVAL; @@ -293,6 +296,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, if (!pll) return ERR_PTR(-ENOMEM); + pll->powerdown = BM_PLL_POWER; + switch (type) { case IMX_PLLV3_SYS: ops = &clk_pllv3_sys_ops; @@ -306,6 +311,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, case IMX_PLLV3_AV: ops = &clk_pllv3_av_ops; break; + case IMX_PLLV3_ENET_IMX7: + pll->powerdown = IMX7_ENET_PLL_POWER; case IMX_PLLV3_ENET: ops = &clk_pllv3_enet_ops; break; diff --git a/arch/arm/mach-imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 61876ed6e11e..bff45ead7389 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -118,6 +118,7 @@ static struct clk_onecell_data clk_data; static unsigned int const clks_init_on[] __initconst = { VF610_CLK_SYS_BUS, VF610_CLK_DDR_SEL, + VF610_CLK_DAP, }; static struct clk * __init vf610_get_fixed_clock( @@ -272,6 +273,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); + clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(6)); + clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(7)); clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(12)); clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(13)); @@ -383,6 +386,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2)); clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7)); + clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24); imx_check_clocks(clk, ARRAY_SIZE(clk)); diff --git a/arch/arm/mach-imx/clk.c b/drivers/clk/imx/clk.c index df12b5307175..df12b5307175 100644 --- a/arch/arm/mach-imx/clk.c +++ b/drivers/clk/imx/clk.c diff --git a/arch/arm/mach-imx/clk.h b/drivers/clk/imx/clk.h index 6a07903a28bc..1049b0c7d818 100644 --- a/arch/arm/mach-imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -10,8 +10,17 @@ void imx_check_clocks(struct clk *clks[], unsigned int count); extern void imx_cscmr1_fixup(u32 *val); -struct clk *imx_clk_pllv1(const char *name, const char *parent, - void __iomem *base); +enum imx_pllv1_type { + IMX_PLLV1_IMX1, + IMX_PLLV1_IMX21, + IMX_PLLV1_IMX25, + IMX_PLLV1_IMX27, + IMX_PLLV1_IMX31, + IMX_PLLV1_IMX35, +}; + +struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name, + const char *parent, void __iomem *base); struct clk *imx_clk_pllv2(const char *name, const char *parent, void __iomem *base); @@ -23,6 +32,7 @@ enum imx_pllv3_type { IMX_PLLV3_USB_VF610, IMX_PLLV3_AV, IMX_PLLV3_ENET, + IMX_PLLV3_ENET_IMX7, }; struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, 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/clk/zte/Makefile b/drivers/clk/zte/Makefile new file mode 100644 index 000000000000..95b707c18108 --- /dev/null +++ b/drivers/clk/zte/Makefile @@ -0,0 +1,2 @@ +obj-y := clk-pll.o +obj-$(CONFIG_SOC_ZX296702) += clk-zx296702.o diff --git a/drivers/clk/zte/clk-pll.c b/drivers/clk/zte/clk-pll.c new file mode 100644 index 000000000000..c3b221ae6cd7 --- /dev/null +++ b/drivers/clk/zte/clk-pll.c @@ -0,0 +1,172 @@ +/* + * 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/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include "clk.h" + +#define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw) + +#define CFG0_CFG1_OFFSET 4 +#define LOCK_FLAG BIT(30) +#define POWER_DOWN BIT(31) + +static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate) +{ + const struct zx_pll_config *config = zx_pll->lookup_table; + int i; + + for (i = 0; i < zx_pll->count; i++) { + if (config[i].rate > rate) + return i > 0 ? i - 1 : 0; + + if (config[i].rate == rate) + return i; + } + + return i - 1; +} + +static int hw_to_idx(struct clk_zx_pll *zx_pll) +{ + const struct zx_pll_config *config = zx_pll->lookup_table; + u32 hw_cfg0, hw_cfg1; + int i; + + hw_cfg0 = readl_relaxed(zx_pll->reg_base); + hw_cfg1 = readl_relaxed(zx_pll->reg_base + CFG0_CFG1_OFFSET); + + /* For matching the value in lookup table */ + hw_cfg0 &= ~LOCK_FLAG; + hw_cfg0 |= POWER_DOWN; + + for (i = 0; i < zx_pll->count; i++) { + if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1) + return i; + } + + return -EINVAL; +} + +static unsigned long zx_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + int idx; + + idx = hw_to_idx(zx_pll); + if (unlikely(idx == -EINVAL)) + return 0; + + return zx_pll->lookup_table[idx].rate; +} + +static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + int idx; + + idx = rate_to_idx(zx_pll, rate); + + return zx_pll->lookup_table[idx].rate; +} + +static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + /* Assume current cpu is not running on current PLL */ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + const struct zx_pll_config *config; + int idx; + + idx = rate_to_idx(zx_pll, rate); + config = &zx_pll->lookup_table[idx]; + + writel_relaxed(config->cfg0, zx_pll->reg_base); + writel_relaxed(config->cfg1, zx_pll->reg_base + CFG0_CFG1_OFFSET); + + return 0; +} + +static int zx_pll_enable(struct clk_hw *hw) +{ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + u32 reg; + + reg = readl_relaxed(zx_pll->reg_base); + writel_relaxed(reg & ~POWER_DOWN, zx_pll->reg_base); + + return readl_relaxed_poll_timeout(zx_pll->reg_base, reg, + reg & LOCK_FLAG, 0, 100); +} + +static void zx_pll_disable(struct clk_hw *hw) +{ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + u32 reg; + + reg = readl_relaxed(zx_pll->reg_base); + writel_relaxed(reg | POWER_DOWN, zx_pll->reg_base); +} + +static int zx_pll_is_enabled(struct clk_hw *hw) +{ + struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); + u32 reg; + + reg = readl_relaxed(zx_pll->reg_base); + + return !(reg & POWER_DOWN); +} + +static const struct clk_ops zx_pll_ops = { + .recalc_rate = zx_pll_recalc_rate, + .round_rate = zx_pll_round_rate, + .set_rate = zx_pll_set_rate, + .enable = zx_pll_enable, + .disable = zx_pll_disable, + .is_enabled = zx_pll_is_enabled, +}; + +struct clk *clk_register_zx_pll(const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg_base, + const struct zx_pll_config *lookup_table, int count, spinlock_t *lock) +{ + struct clk_zx_pll *zx_pll; + struct clk *clk; + struct clk_init_data init; + + zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL); + if (!zx_pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &zx_pll_ops; + init.flags = flags; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + + zx_pll->reg_base = reg_base; + zx_pll->lookup_table = lookup_table; + zx_pll->count = count; + zx_pll->lock = lock; + zx_pll->hw.init = &init; + + clk = clk_register(NULL, &zx_pll->hw); + if (IS_ERR(clk)) + kfree(zx_pll); + + return clk; +} diff --git a/drivers/clk/zte/clk-zx296702.c b/drivers/clk/zte/clk-zx296702.c new file mode 100644 index 000000000000..929d033594af --- /dev/null +++ b/drivers/clk/zte/clk-zx296702.c @@ -0,0 +1,657 @@ +/* + * 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/clk-provider.h> +#include <linux/of_address.h> +#include <dt-bindings/clock/zx296702-clock.h> +#include "clk.h" + +static DEFINE_SPINLOCK(reg_lock); + +static void __iomem *topcrm_base; +static void __iomem *lsp0crpm_base; +static void __iomem *lsp1crpm_base; + +static struct clk *topclk[ZX296702_TOPCLK_END]; +static struct clk *lsp0clk[ZX296702_LSP0CLK_END]; +static struct clk *lsp1clk[ZX296702_LSP1CLK_END]; + +static struct clk_onecell_data topclk_data; +static struct clk_onecell_data lsp0clk_data; +static struct clk_onecell_data lsp1clk_data; + +#define CLK_MUX (topcrm_base + 0x04) +#define CLK_DIV (topcrm_base + 0x08) +#define CLK_EN0 (topcrm_base + 0x0c) +#define CLK_EN1 (topcrm_base + 0x10) +#define VOU_LOCAL_CLKEN (topcrm_base + 0x68) +#define VOU_LOCAL_CLKSEL (topcrm_base + 0x70) +#define VOU_LOCAL_DIV2_SET (topcrm_base + 0x74) +#define CLK_MUX1 (topcrm_base + 0x8c) + +#define CLK_SDMMC1 (lsp0crpm_base + 0x0c) + +#define CLK_UART0 (lsp1crpm_base + 0x20) +#define CLK_UART1 (lsp1crpm_base + 0x24) +#define CLK_SDMMC0 (lsp1crpm_base + 0x2c) + +static const struct zx_pll_config pll_a9_config[] = { + { .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 }, + { .rate = 800000000, .cfg0 = 0x80040691, .cfg1 = 0x04aaaaaa }, + { .rate = 900000000, .cfg0 = 0x80040791, .cfg1 = 0x04000000 }, + { .rate = 1000000000, .cfg0 = 0x80040851, .cfg1 = 0x04555555 }, + { .rate = 1100000000, .cfg0 = 0x80040911, .cfg1 = 0x04aaaaaa }, + { .rate = 1200000000, .cfg0 = 0x80040a11, .cfg1 = 0x04000000 }, +}; + +static const struct clk_div_table main_hlk_div[] = { + { .val = 1, .div = 2, }, + { .val = 3, .div = 4, }, + { /* sentinel */ } +}; + +static const struct clk_div_table a9_as1_aclk_divider[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 3, .div = 4, }, + { /* sentinel */ } +}; + +static const struct clk_div_table sec_wclk_divider[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 3, .div = 4, }, + { .val = 5, .div = 6, }, + { .val = 7, .div = 8, }, + { /* sentinel */ } +}; + +static const char * matrix_aclk_sel[] = { + "pll_mm0_198M", + "osc", + "clk_148M5", + "pll_lsp_104M", +}; + +static const char * a9_wclk_sel[] = { + "pll_a9", + "osc", + "clk_500", + "clk_250", +}; + +static const char * a9_as1_aclk_sel[] = { + "clk_250", + "osc", + "pll_mm0_396M", + "pll_mac_333M", +}; + +static const char * a9_trace_clkin_sel[] = { + "clk_74M25", + "pll_mm1_108M", + "clk_125", + "clk_148M5", +}; + +static const char * decppu_aclk_sel[] = { + "clk_250", + "pll_mm0_198M", + "pll_lsp_104M", + "pll_audio_294M912", +}; + +static const char * vou_main_wclk_sel[] = { + "clk_148M5", + "clk_74M25", + "clk_27", + "pll_mm1_54M", +}; + +static const char * vou_scaler_wclk_sel[] = { + "clk_250", + "pll_mac_333M", + "pll_audio_294M912", + "pll_mm0_198M", +}; + +static const char * r2d_wclk_sel[] = { + "pll_audio_294M912", + "pll_mac_333M", + "pll_a9_350M", + "pll_mm0_396M", +}; + +static const char * ddr_wclk_sel[] = { + "pll_mac_333M", + "pll_ddr_266M", + "pll_audio_294M912", + "pll_mm0_198M", +}; + +static const char * nand_wclk_sel[] = { + "pll_lsp_104M", + "osc", +}; + +static const char * lsp_26_wclk_sel[] = { + "pll_lsp_26M", + "osc", +}; + +static const char * vl0_sel[] = { + "vou_main_channel_div", + "vou_aux_channel_div", +}; + +static const char * hdmi_sel[] = { + "vou_main_channel_wclk", + "vou_aux_channel_wclk", +}; + +static const char * sdmmc0_wclk_sel[] = { + "lsp1_104M_wclk", + "lsp1_26M_wclk", +}; + +static const char * sdmmc1_wclk_sel[] = { + "lsp0_104M_wclk", + "lsp0_26M_wclk", +}; + +static const char * uart_wclk_sel[] = { + "lsp1_104M_wclk", + "lsp1_26M_wclk", +}; + +static inline struct clk *zx_divtbl(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, + const struct clk_div_table *table) +{ + return clk_register_divider_table(NULL, name, parent, 0, reg, shift, + width, 0, table, ®_lock); +} + +static inline struct clk *zx_div(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width) +{ + return clk_register_divider(NULL, name, parent, 0, + reg, shift, width, 0, ®_lock); +} + +static inline struct clk *zx_mux(const char *name, const char **parents, + int num_parents, void __iomem *reg, u8 shift, u8 width) +{ + return clk_register_mux(NULL, name, parents, num_parents, + 0, reg, shift, width, 0, ®_lock); +} + +static inline struct clk *zx_gate(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED, + reg, shift, 0, ®_lock); +} + +static void __init zx296702_top_clocks_init(struct device_node *np) +{ + struct clk **clk = topclk; + int i; + + topcrm_base = of_iomap(np, 0); + WARN_ON(!topcrm_base); + + clk[ZX296702_OSC] = + clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, + 30000000); + clk[ZX296702_PLL_A9] = + clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base + + 0x01c, pll_a9_config, + ARRAY_SIZE(pll_a9_config), ®_lock); + + /* TODO: pll_a9_350M look like changeble follow a9 pll */ + clk[ZX296702_PLL_A9_350M] = + clk_register_fixed_rate(NULL, "pll_a9_350M", "osc", 0, + 350000000); + clk[ZX296702_PLL_MAC_1000M] = + clk_register_fixed_rate(NULL, "pll_mac_1000M", "osc", 0, + 1000000000); + clk[ZX296702_PLL_MAC_333M] = + clk_register_fixed_rate(NULL, "pll_mac_333M", "osc", 0, + 333000000); + clk[ZX296702_PLL_MM0_1188M] = + clk_register_fixed_rate(NULL, "pll_mm0_1188M", "osc", 0, + 1188000000); + clk[ZX296702_PLL_MM0_396M] = + clk_register_fixed_rate(NULL, "pll_mm0_396M", "osc", 0, + 396000000); + clk[ZX296702_PLL_MM0_198M] = + clk_register_fixed_rate(NULL, "pll_mm0_198M", "osc", 0, + 198000000); + clk[ZX296702_PLL_MM1_108M] = + clk_register_fixed_rate(NULL, "pll_mm1_108M", "osc", 0, + 108000000); + clk[ZX296702_PLL_MM1_72M] = + clk_register_fixed_rate(NULL, "pll_mm1_72M", "osc", 0, + 72000000); + clk[ZX296702_PLL_MM1_54M] = + clk_register_fixed_rate(NULL, "pll_mm1_54M", "osc", 0, + 54000000); + clk[ZX296702_PLL_LSP_104M] = + clk_register_fixed_rate(NULL, "pll_lsp_104M", "osc", 0, + 104000000); + clk[ZX296702_PLL_LSP_26M] = + clk_register_fixed_rate(NULL, "pll_lsp_26M", "osc", 0, + 26000000); + clk[ZX296702_PLL_DDR_266M] = + clk_register_fixed_rate(NULL, "pll_ddr_266M", "osc", 0, + 266000000); + clk[ZX296702_PLL_AUDIO_294M912] = + clk_register_fixed_rate(NULL, "pll_audio_294M912", "osc", 0, + 294912000); + + /* bus clock */ + clk[ZX296702_MATRIX_ACLK] = + zx_mux("matrix_aclk", matrix_aclk_sel, + ARRAY_SIZE(matrix_aclk_sel), CLK_MUX, 2, 2); + clk[ZX296702_MAIN_HCLK] = + zx_divtbl("main_hclk", "matrix_aclk", CLK_DIV, 0, 2, + main_hlk_div); + clk[ZX296702_MAIN_PCLK] = + zx_divtbl("main_pclk", "matrix_aclk", CLK_DIV, 2, 2, + main_hlk_div); + + /* cpu clock */ + clk[ZX296702_CLK_500] = + clk_register_fixed_factor(NULL, "clk_500", "pll_mac_1000M", 0, + 1, 2); + clk[ZX296702_CLK_250] = + clk_register_fixed_factor(NULL, "clk_250", "pll_mac_1000M", 0, + 1, 4); + clk[ZX296702_CLK_125] = + clk_register_fixed_factor(NULL, "clk_125", "clk_250", 0, 1, 2); + clk[ZX296702_CLK_148M5] = + clk_register_fixed_factor(NULL, "clk_148M5", "pll_mm0_1188M", 0, + 1, 8); + clk[ZX296702_CLK_74M25] = + clk_register_fixed_factor(NULL, "clk_74M25", "pll_mm0_1188M", 0, + 1, 16); + clk[ZX296702_A9_WCLK] = + zx_mux("a9_wclk", a9_wclk_sel, ARRAY_SIZE(a9_wclk_sel), CLK_MUX, + 0, 2); + clk[ZX296702_A9_AS1_ACLK_MUX] = + zx_mux("a9_as1_aclk_mux", a9_as1_aclk_sel, + ARRAY_SIZE(a9_as1_aclk_sel), CLK_MUX, 4, 2); + clk[ZX296702_A9_TRACE_CLKIN_MUX] = + zx_mux("a9_trace_clkin_mux", a9_trace_clkin_sel, + ARRAY_SIZE(a9_trace_clkin_sel), CLK_MUX1, 0, 2); + clk[ZX296702_A9_AS1_ACLK_DIV] = + zx_divtbl("a9_as1_aclk_div", "a9_as1_aclk_mux", CLK_DIV, 4, 2, + a9_as1_aclk_divider); + + /* multi-media clock */ + clk[ZX296702_CLK_2] = + clk_register_fixed_factor(NULL, "clk_2", "pll_mm1_72M", 0, + 1, 36); + clk[ZX296702_CLK_27] = + clk_register_fixed_factor(NULL, "clk_27", "pll_mm1_54M", 0, + 1, 2); + clk[ZX296702_DECPPU_ACLK_MUX] = + zx_mux("decppu_aclk_mux", decppu_aclk_sel, + ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 6, 2); + clk[ZX296702_PPU_ACLK_MUX] = + zx_mux("ppu_aclk_mux", decppu_aclk_sel, + ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 8, 2); + clk[ZX296702_MALI400_ACLK_MUX] = + zx_mux("mali400_aclk_mux", decppu_aclk_sel, + ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 12, 2); + clk[ZX296702_VOU_ACLK_MUX] = + zx_mux("vou_aclk_mux", decppu_aclk_sel, + ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 10, 2); + clk[ZX296702_VOU_MAIN_WCLK_MUX] = + zx_mux("vou_main_wclk_mux", vou_main_wclk_sel, + ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 14, 2); + clk[ZX296702_VOU_AUX_WCLK_MUX] = + zx_mux("vou_aux_wclk_mux", vou_main_wclk_sel, + ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 16, 2); + clk[ZX296702_VOU_SCALER_WCLK_MUX] = + zx_mux("vou_scaler_wclk_mux", vou_scaler_wclk_sel, + ARRAY_SIZE(vou_scaler_wclk_sel), CLK_MUX, + 18, 2); + clk[ZX296702_R2D_ACLK_MUX] = + zx_mux("r2d_aclk_mux", decppu_aclk_sel, + ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 20, 2); + clk[ZX296702_R2D_WCLK_MUX] = + zx_mux("r2d_wclk_mux", r2d_wclk_sel, + ARRAY_SIZE(r2d_wclk_sel), CLK_MUX, 22, 2); + + /* other clock */ + clk[ZX296702_CLK_50] = + clk_register_fixed_factor(NULL, "clk_50", "pll_mac_1000M", + 0, 1, 20); + clk[ZX296702_CLK_25] = + clk_register_fixed_factor(NULL, "clk_25", "pll_mac_1000M", + 0, 1, 40); + clk[ZX296702_CLK_12] = + clk_register_fixed_factor(NULL, "clk_12", "pll_mm1_72M", + 0, 1, 6); + clk[ZX296702_CLK_16M384] = + clk_register_fixed_factor(NULL, "clk_16M384", + "pll_audio_294M912", 0, 1, 18); + clk[ZX296702_CLK_32K768] = + clk_register_fixed_factor(NULL, "clk_32K768", "clk_16M384", + 0, 1, 500); + clk[ZX296702_SEC_WCLK_DIV] = + zx_divtbl("sec_wclk_div", "pll_lsp_104M", CLK_DIV, 6, 3, + sec_wclk_divider); + clk[ZX296702_DDR_WCLK_MUX] = + zx_mux("ddr_wclk_mux", ddr_wclk_sel, + ARRAY_SIZE(ddr_wclk_sel), CLK_MUX, 24, 2); + clk[ZX296702_NAND_WCLK_MUX] = + zx_mux("nand_wclk_mux", nand_wclk_sel, + ARRAY_SIZE(nand_wclk_sel), CLK_MUX, 24, 2); + clk[ZX296702_LSP_26_WCLK_MUX] = + zx_mux("lsp_26_wclk_mux", lsp_26_wclk_sel, + ARRAY_SIZE(lsp_26_wclk_sel), CLK_MUX, 27, 1); + + /* gates */ + clk[ZX296702_A9_AS0_ACLK] = + zx_gate("a9_as0_aclk", "matrix_aclk", CLK_EN0, 0); + clk[ZX296702_A9_AS1_ACLK] = + zx_gate("a9_as1_aclk", "a9_as1_aclk_div", CLK_EN0, 1); + clk[ZX296702_A9_TRACE_CLKIN] = + zx_gate("a9_trace_clkin", "a9_trace_clkin_mux", CLK_EN0, 2); + clk[ZX296702_DECPPU_AXI_M_ACLK] = + zx_gate("decppu_axi_m_aclk", "decppu_aclk_mux", CLK_EN0, 3); + clk[ZX296702_DECPPU_AHB_S_HCLK] = + zx_gate("decppu_ahb_s_hclk", "main_hclk", CLK_EN0, 4); + clk[ZX296702_PPU_AXI_M_ACLK] = + zx_gate("ppu_axi_m_aclk", "ppu_aclk_mux", CLK_EN0, 5); + clk[ZX296702_PPU_AHB_S_HCLK] = + zx_gate("ppu_ahb_s_hclk", "main_hclk", CLK_EN0, 6); + clk[ZX296702_VOU_AXI_M_ACLK] = + zx_gate("vou_axi_m_aclk", "vou_aclk_mux", CLK_EN0, 7); + clk[ZX296702_VOU_APB_PCLK] = + zx_gate("vou_apb_pclk", "main_pclk", CLK_EN0, 8); + clk[ZX296702_VOU_MAIN_CHANNEL_WCLK] = + zx_gate("vou_main_channel_wclk", "vou_main_wclk_mux", + CLK_EN0, 9); + clk[ZX296702_VOU_AUX_CHANNEL_WCLK] = + zx_gate("vou_aux_channel_wclk", "vou_aux_wclk_mux", + CLK_EN0, 10); + clk[ZX296702_VOU_HDMI_OSCLK_CEC] = + zx_gate("vou_hdmi_osclk_cec", "clk_2", CLK_EN0, 11); + clk[ZX296702_VOU_SCALER_WCLK] = + zx_gate("vou_scaler_wclk", "vou_scaler_wclk_mux", CLK_EN0, 12); + clk[ZX296702_MALI400_AXI_M_ACLK] = + zx_gate("mali400_axi_m_aclk", "mali400_aclk_mux", CLK_EN0, 13); + clk[ZX296702_MALI400_APB_PCLK] = + zx_gate("mali400_apb_pclk", "main_pclk", CLK_EN0, 14); + clk[ZX296702_R2D_WCLK] = + zx_gate("r2d_wclk", "r2d_wclk_mux", CLK_EN0, 15); + clk[ZX296702_R2D_AXI_M_ACLK] = + zx_gate("r2d_axi_m_aclk", "r2d_aclk_mux", CLK_EN0, 16); + clk[ZX296702_R2D_AHB_HCLK] = + zx_gate("r2d_ahb_hclk", "main_hclk", CLK_EN0, 17); + clk[ZX296702_DDR3_AXI_S0_ACLK] = + zx_gate("ddr3_axi_s0_aclk", "matrix_aclk", CLK_EN0, 18); + clk[ZX296702_DDR3_APB_PCLK] = + zx_gate("ddr3_apb_pclk", "main_pclk", CLK_EN0, 19); + clk[ZX296702_DDR3_WCLK] = + zx_gate("ddr3_wclk", "ddr_wclk_mux", CLK_EN0, 20); + clk[ZX296702_USB20_0_AHB_HCLK] = + zx_gate("usb20_0_ahb_hclk", "main_hclk", CLK_EN0, 21); + clk[ZX296702_USB20_0_EXTREFCLK] = + zx_gate("usb20_0_extrefclk", "clk_12", CLK_EN0, 22); + clk[ZX296702_USB20_1_AHB_HCLK] = + zx_gate("usb20_1_ahb_hclk", "main_hclk", CLK_EN0, 23); + clk[ZX296702_USB20_1_EXTREFCLK] = + zx_gate("usb20_1_extrefclk", "clk_12", CLK_EN0, 24); + clk[ZX296702_USB20_2_AHB_HCLK] = + zx_gate("usb20_2_ahb_hclk", "main_hclk", CLK_EN0, 25); + clk[ZX296702_USB20_2_EXTREFCLK] = + zx_gate("usb20_2_extrefclk", "clk_12", CLK_EN0, 26); + clk[ZX296702_GMAC_AXI_M_ACLK] = + zx_gate("gmac_axi_m_aclk", "matrix_aclk", CLK_EN0, 27); + clk[ZX296702_GMAC_APB_PCLK] = + zx_gate("gmac_apb_pclk", "main_pclk", CLK_EN0, 28); + clk[ZX296702_GMAC_125_CLKIN] = + zx_gate("gmac_125_clkin", "clk_125", CLK_EN0, 29); + clk[ZX296702_GMAC_RMII_CLKIN] = + zx_gate("gmac_rmii_clkin", "clk_50", CLK_EN0, 30); + clk[ZX296702_GMAC_25M_CLK] = + zx_gate("gmac_25M_clk", "clk_25", CLK_EN0, 31); + clk[ZX296702_NANDFLASH_AHB_HCLK] = + zx_gate("nandflash_ahb_hclk", "main_hclk", CLK_EN1, 0); + clk[ZX296702_NANDFLASH_WCLK] = + zx_gate("nandflash_wclk", "nand_wclk_mux", CLK_EN1, 1); + clk[ZX296702_LSP0_APB_PCLK] = + zx_gate("lsp0_apb_pclk", "main_pclk", CLK_EN1, 2); + clk[ZX296702_LSP0_AHB_HCLK] = + zx_gate("lsp0_ahb_hclk", "main_hclk", CLK_EN1, 3); + clk[ZX296702_LSP0_26M_WCLK] = + zx_gate("lsp0_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 4); + clk[ZX296702_LSP0_104M_WCLK] = + zx_gate("lsp0_104M_wclk", "pll_lsp_104M", CLK_EN1, 5); + clk[ZX296702_LSP0_16M384_WCLK] = + zx_gate("lsp0_16M384_wclk", "clk_16M384", CLK_EN1, 6); + clk[ZX296702_LSP1_APB_PCLK] = + zx_gate("lsp1_apb_pclk", "main_pclk", CLK_EN1, 7); + /* FIXME: wclk enable bit is bit8. We hack it as reserved 31 for + * UART does not work after parent clk is disabled/enabled */ + clk[ZX296702_LSP1_26M_WCLK] = + zx_gate("lsp1_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 31); + clk[ZX296702_LSP1_104M_WCLK] = + zx_gate("lsp1_104M_wclk", "pll_lsp_104M", CLK_EN1, 9); + clk[ZX296702_LSP1_32K_CLK] = + zx_gate("lsp1_32K_clk", "clk_32K768", CLK_EN1, 10); + clk[ZX296702_AON_HCLK] = + zx_gate("aon_hclk", "main_hclk", CLK_EN1, 11); + clk[ZX296702_SYS_CTRL_PCLK] = + zx_gate("sys_ctrl_pclk", "main_pclk", CLK_EN1, 12); + clk[ZX296702_DMA_PCLK] = + zx_gate("dma_pclk", "main_pclk", CLK_EN1, 13); + clk[ZX296702_DMA_ACLK] = + zx_gate("dma_aclk", "matrix_aclk", CLK_EN1, 14); + clk[ZX296702_SEC_HCLK] = + zx_gate("sec_hclk", "main_hclk", CLK_EN1, 15); + clk[ZX296702_AES_WCLK] = + zx_gate("aes_wclk", "sec_wclk_div", CLK_EN1, 16); + clk[ZX296702_DES_WCLK] = + zx_gate("des_wclk", "sec_wclk_div", CLK_EN1, 17); + clk[ZX296702_IRAM_ACLK] = + zx_gate("iram_aclk", "matrix_aclk", CLK_EN1, 18); + clk[ZX296702_IROM_ACLK] = + zx_gate("irom_aclk", "matrix_aclk", CLK_EN1, 19); + clk[ZX296702_BOOT_CTRL_HCLK] = + zx_gate("boot_ctrl_hclk", "main_hclk", CLK_EN1, 20); + clk[ZX296702_EFUSE_CLK_30] = + zx_gate("efuse_clk_30", "osc", CLK_EN1, 21); + + /* TODO: add VOU Local clocks */ + clk[ZX296702_VOU_MAIN_CHANNEL_DIV] = + zx_div("vou_main_channel_div", "vou_main_channel_wclk", + VOU_LOCAL_DIV2_SET, 1, 1); + clk[ZX296702_VOU_AUX_CHANNEL_DIV] = + zx_div("vou_aux_channel_div", "vou_aux_channel_wclk", + VOU_LOCAL_DIV2_SET, 0, 1); + clk[ZX296702_VOU_TV_ENC_HD_DIV] = + zx_div("vou_tv_enc_hd_div", "vou_tv_enc_hd_mux", + VOU_LOCAL_DIV2_SET, 3, 1); + clk[ZX296702_VOU_TV_ENC_SD_DIV] = + zx_div("vou_tv_enc_sd_div", "vou_tv_enc_sd_mux", + VOU_LOCAL_DIV2_SET, 2, 1); + clk[ZX296702_VL0_MUX] = + zx_mux("vl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 8, 1); + clk[ZX296702_VL1_MUX] = + zx_mux("vl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 9, 1); + clk[ZX296702_VL2_MUX] = + zx_mux("vl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 10, 1); + clk[ZX296702_GL0_MUX] = + zx_mux("gl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 5, 1); + clk[ZX296702_GL1_MUX] = + zx_mux("gl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 6, 1); + clk[ZX296702_GL2_MUX] = + zx_mux("gl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 7, 1); + clk[ZX296702_WB_MUX] = + zx_mux("wb_mux", vl0_sel, ARRAY_SIZE(vl0_sel), + VOU_LOCAL_CLKSEL, 11, 1); + clk[ZX296702_HDMI_MUX] = + zx_mux("hdmi_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), + VOU_LOCAL_CLKSEL, 4, 1); + clk[ZX296702_VOU_TV_ENC_HD_MUX] = + zx_mux("vou_tv_enc_hd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), + VOU_LOCAL_CLKSEL, 3, 1); + clk[ZX296702_VOU_TV_ENC_SD_MUX] = + zx_mux("vou_tv_enc_sd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), + VOU_LOCAL_CLKSEL, 2, 1); + clk[ZX296702_VL0_CLK] = + zx_gate("vl0_clk", "vl0_mux", VOU_LOCAL_CLKEN, 8); + clk[ZX296702_VL1_CLK] = + zx_gate("vl1_clk", "vl1_mux", VOU_LOCAL_CLKEN, 9); + clk[ZX296702_VL2_CLK] = + zx_gate("vl2_clk", "vl2_mux", VOU_LOCAL_CLKEN, 10); + clk[ZX296702_GL0_CLK] = + zx_gate("gl0_clk", "gl0_mux", VOU_LOCAL_CLKEN, 5); + clk[ZX296702_GL1_CLK] = + zx_gate("gl1_clk", "gl1_mux", VOU_LOCAL_CLKEN, 6); + clk[ZX296702_GL2_CLK] = + zx_gate("gl2_clk", "gl2_mux", VOU_LOCAL_CLKEN, 7); + clk[ZX296702_WB_CLK] = + zx_gate("wb_clk", "wb_mux", VOU_LOCAL_CLKEN, 11); + clk[ZX296702_CL_CLK] = + zx_gate("cl_clk", "vou_main_channel_div", VOU_LOCAL_CLKEN, 12); + clk[ZX296702_MAIN_MIX_CLK] = + zx_gate("main_mix_clk", "vou_main_channel_div", + VOU_LOCAL_CLKEN, 4); + clk[ZX296702_AUX_MIX_CLK] = + zx_gate("aux_mix_clk", "vou_aux_channel_div", + VOU_LOCAL_CLKEN, 3); + clk[ZX296702_HDMI_CLK] = + zx_gate("hdmi_clk", "hdmi_mux", VOU_LOCAL_CLKEN, 2); + clk[ZX296702_VOU_TV_ENC_HD_DAC_CLK] = + zx_gate("vou_tv_enc_hd_dac_clk", "vou_tv_enc_hd_div", + VOU_LOCAL_CLKEN, 1); + clk[ZX296702_VOU_TV_ENC_SD_DAC_CLK] = + zx_gate("vou_tv_enc_sd_dac_clk", "vou_tv_enc_sd_div", + VOU_LOCAL_CLKEN, 0); + + /* CA9 PERIPHCLK = a9_wclk / 2 */ + clk[ZX296702_A9_PERIPHCLK] = + clk_register_fixed_factor(NULL, "a9_periphclk", "a9_wclk", + 0, 1, 2); + + for (i = 0; i < ARRAY_SIZE(topclk); i++) { + if (IS_ERR(clk[i])) { + pr_err("zx296702 clk %d: register failed with %ld\n", + i, PTR_ERR(clk[i])); + return; + } + } + + topclk_data.clks = topclk; + topclk_data.clk_num = ARRAY_SIZE(topclk); + of_clk_add_provider(np, of_clk_src_onecell_get, &topclk_data); +} +CLK_OF_DECLARE(zx296702_top_clk, "zte,zx296702-topcrm-clk", + zx296702_top_clocks_init); + +static void __init zx296702_lsp0_clocks_init(struct device_node *np) +{ + struct clk **clk = lsp0clk; + int i; + + lsp0crpm_base = of_iomap(np, 0); + WARN_ON(!lsp0crpm_base); + + /* SDMMC1 */ + clk[ZX296702_SDMMC1_WCLK_MUX] = + zx_mux("sdmmc1_wclk_mux", sdmmc1_wclk_sel, + ARRAY_SIZE(sdmmc1_wclk_sel), CLK_SDMMC1, 4, 1); + clk[ZX296702_SDMMC1_WCLK_DIV] = + zx_div("sdmmc1_wclk_div", "sdmmc1_wclk_mux", CLK_SDMMC1, 12, 4); + clk[ZX296702_SDMMC1_WCLK] = + zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1); + clk[ZX296702_SDMMC1_PCLK] = + zx_gate("sdmmc1_pclk", "lsp1_apb_pclk", CLK_SDMMC1, 0); + + for (i = 0; i < ARRAY_SIZE(lsp0clk); i++) { + if (IS_ERR(clk[i])) { + pr_err("zx296702 clk %d: register failed with %ld\n", + i, PTR_ERR(clk[i])); + return; + } + } + + lsp0clk_data.clks = lsp0clk; + lsp0clk_data.clk_num = ARRAY_SIZE(lsp0clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &lsp0clk_data); +} +CLK_OF_DECLARE(zx296702_lsp0_clk, "zte,zx296702-lsp0crpm-clk", + zx296702_lsp0_clocks_init); + +static void __init zx296702_lsp1_clocks_init(struct device_node *np) +{ + struct clk **clk = lsp1clk; + int i; + + lsp1crpm_base = of_iomap(np, 0); + WARN_ON(!lsp1crpm_base); + + /* UART0 */ + clk[ZX296702_UART0_WCLK_MUX] = + zx_mux("uart0_wclk_mux", uart_wclk_sel, + ARRAY_SIZE(uart_wclk_sel), CLK_UART0, 4, 1); + /* FIXME: uart wclk enable bit is bit1 in. We hack it as reserved 31 for + * UART does not work after parent clk is disabled/enabled */ + clk[ZX296702_UART0_WCLK] = + zx_gate("uart0_wclk", "uart0_wclk_mux", CLK_UART0, 31); + clk[ZX296702_UART0_PCLK] = + zx_gate("uart0_pclk", "lsp1_apb_pclk", CLK_UART0, 0); + + /* UART1 */ + clk[ZX296702_UART1_WCLK_MUX] = + zx_mux("uart1_wclk_mux", uart_wclk_sel, + ARRAY_SIZE(uart_wclk_sel), CLK_UART1, 4, 1); + clk[ZX296702_UART1_WCLK] = + zx_gate("uart1_wclk", "uart1_wclk_mux", CLK_UART1, 1); + clk[ZX296702_UART1_PCLK] = + zx_gate("uart1_pclk", "lsp1_apb_pclk", CLK_UART1, 0); + + /* SDMMC0 */ + clk[ZX296702_SDMMC0_WCLK_MUX] = + zx_mux("sdmmc0_wclk_mux", sdmmc0_wclk_sel, + ARRAY_SIZE(sdmmc0_wclk_sel), CLK_SDMMC0, 4, 1); + clk[ZX296702_SDMMC0_WCLK_DIV] = + zx_div("sdmmc0_wclk_div", "sdmmc0_wclk_mux", CLK_SDMMC0, 12, 4); + clk[ZX296702_SDMMC0_WCLK] = + zx_gate("sdmmc0_wclk", "sdmmc0_wclk_div", CLK_SDMMC0, 1); + clk[ZX296702_SDMMC0_PCLK] = + zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0); + + for (i = 0; i < ARRAY_SIZE(lsp1clk); i++) { + if (IS_ERR(clk[i])) { + pr_err("zx296702 clk %d: register failed with %ld\n", + i, PTR_ERR(clk[i])); + return; + } + } + + lsp1clk_data.clks = lsp1clk; + lsp1clk_data.clk_num = ARRAY_SIZE(lsp1clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &lsp1clk_data); +} +CLK_OF_DECLARE(zx296702_lsp1_clk, "zte,zx296702-lsp1crpm-clk", + zx296702_lsp1_clocks_init); diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h new file mode 100644 index 000000000000..0914a82d0535 --- /dev/null +++ b/drivers/clk/zte/clk.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 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 __ZTE_CLK_H +#define __ZTE_CLK_H +#include <linux/clk-provider.h> +#include <linux/spinlock.h> + +struct zx_pll_config { + unsigned long rate; + u32 cfg0; + u32 cfg1; +}; + +struct clk_zx_pll { + struct clk_hw hw; + void __iomem *reg_base; + const struct zx_pll_config *lookup_table; /* order by rate asc */ + int count; + spinlock_t *lock; +}; + +struct clk *clk_register_zx_pll(const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg_base, + const struct zx_pll_config *lookup_table, int count, spinlock_t *lock); +#endif diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 51d7865fdddb..618102e5aa2a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -258,4 +258,10 @@ config CLKSRC_PXA help This enables OST0 support available on PXA and SA-11x0 platforms. + +config CLKSRC_IMX_GPT + bool "Clocksource using i.MX GPT" if COMPILE_TEST + depends on ARM && CLKDEV_LOOKUP + select CLKSRC_MMIO + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 5b85f6adb258..fce332cac646 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -51,4 +51,5 @@ obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o +obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c new file mode 100644 index 000000000000..879c78423546 --- /dev/null +++ b/drivers/clocksource/timer-imx-gpt.c @@ -0,0 +1,540 @@ +/* + * linux/arch/arm/plat-mxc/time.c + * + * Copyright (C) 2000-2001 Deep Blue Solutions + * Copyright (C) 2002 Shane Nay (shane@minirl.com) + * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com) + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/clockchips.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/sched_clock.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <soc/imx/timer.h> + +/* + * There are 4 versions of the timer hardware on Freescale MXC hardware. + * - MX1/MXL + * - MX21, MX27. + * - MX25, MX31, MX35, MX37, MX51, MX6Q(rev1.0) + * - MX6DL, MX6SX, MX6Q(rev1.1+) + */ + +/* defines common for all i.MX */ +#define MXC_TCTL 0x00 +#define MXC_TCTL_TEN (1 << 0) /* Enable module */ +#define MXC_TPRER 0x04 + +/* MX1, MX21, MX27 */ +#define MX1_2_TCTL_CLK_PCLK1 (1 << 1) +#define MX1_2_TCTL_IRQEN (1 << 4) +#define MX1_2_TCTL_FRR (1 << 8) +#define MX1_2_TCMP 0x08 +#define MX1_2_TCN 0x10 +#define MX1_2_TSTAT 0x14 + +/* MX21, MX27 */ +#define MX2_TSTAT_CAPT (1 << 1) +#define MX2_TSTAT_COMP (1 << 0) + +/* MX31, MX35, MX25, MX5, MX6 */ +#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ +#define V2_TCTL_CLK_IPG (1 << 6) +#define V2_TCTL_CLK_PER (2 << 6) +#define V2_TCTL_CLK_OSC_DIV8 (5 << 6) +#define V2_TCTL_FRR (1 << 9) +#define V2_TCTL_24MEN (1 << 10) +#define V2_TPRER_PRE24M 12 +#define V2_IR 0x0c +#define V2_TSTAT 0x08 +#define V2_TSTAT_OF1 (1 << 0) +#define V2_TCN 0x24 +#define V2_TCMP 0x10 + +#define V2_TIMER_RATE_OSC_DIV8 3000000 + +struct imx_timer { + enum imx_gpt_type type; + void __iomem *base; + int irq; + struct clk *clk_per; + struct clk *clk_ipg; + const struct imx_gpt_data *gpt; + struct clock_event_device ced; + enum clock_event_mode cem; + struct irqaction act; +}; + +struct imx_gpt_data { + int reg_tstat; + int reg_tcn; + int reg_tcmp; + void (*gpt_setup_tctl)(struct imx_timer *imxtm); + void (*gpt_irq_enable)(struct imx_timer *imxtm); + void (*gpt_irq_disable)(struct imx_timer *imxtm); + void (*gpt_irq_acknowledge)(struct imx_timer *imxtm); + int (*set_next_event)(unsigned long evt, + struct clock_event_device *ced); +}; + +static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced) +{ + return container_of(ced, struct imx_timer, ced); +} + +static void imx1_gpt_irq_disable(struct imx_timer *imxtm) +{ + unsigned int tmp; + + tmp = readl_relaxed(imxtm->base + MXC_TCTL); + writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); +} +#define imx21_gpt_irq_disable imx1_gpt_irq_disable + +static void imx31_gpt_irq_disable(struct imx_timer *imxtm) +{ + writel_relaxed(0, imxtm->base + V2_IR); +} +#define imx6dl_gpt_irq_disable imx31_gpt_irq_disable + +static void imx1_gpt_irq_enable(struct imx_timer *imxtm) +{ + unsigned int tmp; + + tmp = readl_relaxed(imxtm->base + MXC_TCTL); + writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); +} +#define imx21_gpt_irq_enable imx1_gpt_irq_enable + +static void imx31_gpt_irq_enable(struct imx_timer *imxtm) +{ + writel_relaxed(1<<0, imxtm->base + V2_IR); +} +#define imx6dl_gpt_irq_enable imx31_gpt_irq_enable + +static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm) +{ + writel_relaxed(0, imxtm->base + MX1_2_TSTAT); +} + +static void imx21_gpt_irq_acknowledge(struct imx_timer *imxtm) +{ + writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, + imxtm->base + MX1_2_TSTAT); +} + +static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm) +{ + writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT); +} +#define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge + +static void __iomem *sched_clock_reg; + +static u64 notrace mxc_read_sched_clock(void) +{ + return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0; +} + +static struct delay_timer imx_delay_timer; + +static unsigned long imx_read_current_timer(void) +{ + return readl_relaxed(sched_clock_reg); +} + +static int __init mxc_clocksource_init(struct imx_timer *imxtm) +{ + unsigned int c = clk_get_rate(imxtm->clk_per); + void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn; + + imx_delay_timer.read_current_timer = &imx_read_current_timer; + imx_delay_timer.freq = c; + register_current_timer_delay(&imx_delay_timer); + + sched_clock_reg = reg; + + sched_clock_register(mxc_read_sched_clock, 32, c); + return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, + clocksource_mmio_readl_up); +} + +/* clock event */ + +static int mx1_2_set_next_event(unsigned long evt, + struct clock_event_device *ced) +{ + struct imx_timer *imxtm = to_imx_timer(ced); + unsigned long tcmp; + + tcmp = readl_relaxed(imxtm->base + MX1_2_TCN) + evt; + + writel_relaxed(tcmp, imxtm->base + MX1_2_TCMP); + + return (int)(tcmp - readl_relaxed(imxtm->base + MX1_2_TCN)) < 0 ? + -ETIME : 0; +} + +static int v2_set_next_event(unsigned long evt, + struct clock_event_device *ced) +{ + struct imx_timer *imxtm = to_imx_timer(ced); + unsigned long tcmp; + + tcmp = readl_relaxed(imxtm->base + V2_TCN) + evt; + + writel_relaxed(tcmp, imxtm->base + V2_TCMP); + + return evt < 0x7fffffff && + (int)(tcmp - readl_relaxed(imxtm->base + V2_TCN)) < 0 ? + -ETIME : 0; +} + +#ifdef DEBUG +static const char *clock_event_mode_label[] = { + [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", + [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", + [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", + [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED", + [CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME", +}; +#endif /* DEBUG */ + +static void mxc_set_mode(enum clock_event_mode mode, + struct clock_event_device *ced) +{ + struct imx_timer *imxtm = to_imx_timer(ced); + unsigned long flags; + + /* + * The timer interrupt generation is disabled at least + * for enough time to call mxc_set_next_event() + */ + local_irq_save(flags); + + /* Disable interrupt in GPT module */ + imxtm->gpt->gpt_irq_disable(imxtm); + + if (mode != imxtm->cem) { + u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); + /* Set event time into far-far future */ + writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); + + /* Clear pending interrupt */ + imxtm->gpt->gpt_irq_acknowledge(imxtm); + } + +#ifdef DEBUG + printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n", + clock_event_mode_label[imxtm->cem], + clock_event_mode_label[mode]); +#endif /* DEBUG */ + + /* Remember timer mode */ + imxtm->cem = mode; + local_irq_restore(flags); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + printk(KERN_ERR"mxc_set_mode: Periodic mode is not " + "supported for i.MX\n"); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* + * Do not put overhead of interrupt enable/disable into + * mxc_set_next_event(), the core has about 4 minutes + * to call mxc_set_next_event() or shutdown clock after + * mode switching + */ + local_irq_save(flags); + imxtm->gpt->gpt_irq_enable(imxtm); + local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + /* Left event sources disabled, no more interrupts appear */ + break; + } +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *ced = dev_id; + struct imx_timer *imxtm = to_imx_timer(ced); + uint32_t tstat; + + tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat); + + imxtm->gpt->gpt_irq_acknowledge(imxtm); + + ced->event_handler(ced); + + return IRQ_HANDLED; +} + +static int __init mxc_clockevent_init(struct imx_timer *imxtm) +{ + struct clock_event_device *ced = &imxtm->ced; + struct irqaction *act = &imxtm->act; + + imxtm->cem = CLOCK_EVT_MODE_UNUSED; + + ced->name = "mxc_timer1"; + ced->features = CLOCK_EVT_FEAT_ONESHOT; + ced->set_mode = mxc_set_mode; + ced->set_next_event = imxtm->gpt->set_next_event; + ced->rating = 200; + ced->cpumask = cpumask_of(0); + clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per), + 0xff, 0xfffffffe); + + act->name = "i.MX Timer Tick"; + act->flags = IRQF_TIMER | IRQF_IRQPOLL; + act->handler = mxc_timer_interrupt; + act->dev_id = ced; + + return setup_irq(imxtm->irq, act); +} + +static void imx1_gpt_setup_tctl(struct imx_timer *imxtm) +{ + u32 tctl_val; + + tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; + writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); +} +#define imx21_gpt_setup_tctl imx1_gpt_setup_tctl + +static void imx31_gpt_setup_tctl(struct imx_timer *imxtm) +{ + u32 tctl_val; + + tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; + if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) + tctl_val |= V2_TCTL_CLK_OSC_DIV8; + else + tctl_val |= V2_TCTL_CLK_PER; + + writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); +} + +static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm) +{ + u32 tctl_val; + + tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; + if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) { + tctl_val |= V2_TCTL_CLK_OSC_DIV8; + /* 24 / 8 = 3 MHz */ + writel_relaxed(7 << V2_TPRER_PRE24M, imxtm->base + MXC_TPRER); + tctl_val |= V2_TCTL_24MEN; + } else { + tctl_val |= V2_TCTL_CLK_PER; + } + + writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); +} + +static const struct imx_gpt_data imx1_gpt_data = { + .reg_tstat = MX1_2_TSTAT, + .reg_tcn = MX1_2_TCN, + .reg_tcmp = MX1_2_TCMP, + .gpt_irq_enable = imx1_gpt_irq_enable, + .gpt_irq_disable = imx1_gpt_irq_disable, + .gpt_irq_acknowledge = imx1_gpt_irq_acknowledge, + .gpt_setup_tctl = imx1_gpt_setup_tctl, + .set_next_event = mx1_2_set_next_event, +}; + +static const struct imx_gpt_data imx21_gpt_data = { + .reg_tstat = MX1_2_TSTAT, + .reg_tcn = MX1_2_TCN, + .reg_tcmp = MX1_2_TCMP, + .gpt_irq_enable = imx21_gpt_irq_enable, + .gpt_irq_disable = imx21_gpt_irq_disable, + .gpt_irq_acknowledge = imx21_gpt_irq_acknowledge, + .gpt_setup_tctl = imx21_gpt_setup_tctl, + .set_next_event = mx1_2_set_next_event, +}; + +static const struct imx_gpt_data imx31_gpt_data = { + .reg_tstat = V2_TSTAT, + .reg_tcn = V2_TCN, + .reg_tcmp = V2_TCMP, + .gpt_irq_enable = imx31_gpt_irq_enable, + .gpt_irq_disable = imx31_gpt_irq_disable, + .gpt_irq_acknowledge = imx31_gpt_irq_acknowledge, + .gpt_setup_tctl = imx31_gpt_setup_tctl, + .set_next_event = v2_set_next_event, +}; + +static const struct imx_gpt_data imx6dl_gpt_data = { + .reg_tstat = V2_TSTAT, + .reg_tcn = V2_TCN, + .reg_tcmp = V2_TCMP, + .gpt_irq_enable = imx6dl_gpt_irq_enable, + .gpt_irq_disable = imx6dl_gpt_irq_disable, + .gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge, + .gpt_setup_tctl = imx6dl_gpt_setup_tctl, + .set_next_event = v2_set_next_event, +}; + +static void __init _mxc_timer_init(struct imx_timer *imxtm) +{ + switch (imxtm->type) { + case GPT_TYPE_IMX1: + imxtm->gpt = &imx1_gpt_data; + break; + case GPT_TYPE_IMX21: + imxtm->gpt = &imx21_gpt_data; + break; + case GPT_TYPE_IMX31: + imxtm->gpt = &imx31_gpt_data; + break; + case GPT_TYPE_IMX6DL: + imxtm->gpt = &imx6dl_gpt_data; + break; + default: + BUG(); + } + + if (IS_ERR(imxtm->clk_per)) { + pr_err("i.MX timer: unable to get clk\n"); + return; + } + + if (!IS_ERR(imxtm->clk_ipg)) + clk_prepare_enable(imxtm->clk_ipg); + + clk_prepare_enable(imxtm->clk_per); + + /* + * Initialise to a known state (all timers off, and timing reset) + */ + + writel_relaxed(0, imxtm->base + MXC_TCTL); + writel_relaxed(0, imxtm->base + MXC_TPRER); /* see datasheet note */ + + imxtm->gpt->gpt_setup_tctl(imxtm); + + /* init and register the timer to the framework */ + mxc_clocksource_init(imxtm); + mxc_clockevent_init(imxtm); +} + +void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type) +{ + struct imx_timer *imxtm; + + imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL); + BUG_ON(!imxtm); + + imxtm->clk_per = clk_get_sys("imx-gpt.0", "per"); + imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg"); + + imxtm->base = ioremap(pbase, SZ_4K); + BUG_ON(!imxtm->base); + + imxtm->type = type; + + _mxc_timer_init(imxtm); +} + +static void __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type type) +{ + struct imx_timer *imxtm; + static int initialized; + + /* Support one instance only */ + if (initialized) + return; + + imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL); + BUG_ON(!imxtm); + + imxtm->base = of_iomap(np, 0); + WARN_ON(!imxtm->base); + imxtm->irq = irq_of_parse_and_map(np, 0); + + imxtm->clk_ipg = of_clk_get_by_name(np, "ipg"); + + /* Try osc_per first, and fall back to per otherwise */ + imxtm->clk_per = of_clk_get_by_name(np, "osc_per"); + if (IS_ERR(imxtm->clk_per)) + imxtm->clk_per = of_clk_get_by_name(np, "per"); + + imxtm->type = type; + + _mxc_timer_init(imxtm); + + initialized = 1; +} + +static void __init imx1_timer_init_dt(struct device_node *np) +{ + mxc_timer_init_dt(np, GPT_TYPE_IMX1); +} + +static void __init imx21_timer_init_dt(struct device_node *np) +{ + mxc_timer_init_dt(np, GPT_TYPE_IMX21); +} + +static void __init imx31_timer_init_dt(struct device_node *np) +{ + enum imx_gpt_type type = GPT_TYPE_IMX31; + + /* + * We were using the same compatible string for i.MX6Q/D and i.MX6DL/S + * GPT device, while they actually have different programming model. + * This is a workaround to keep the existing i.MX6DL/S DTBs continue + * working with the new kernel. + */ + if (of_machine_is_compatible("fsl,imx6dl")) + type = GPT_TYPE_IMX6DL; + + mxc_timer_init_dt(np, type); +} + +static void __init imx6dl_timer_init_dt(struct device_node *np) +{ + mxc_timer_init_dt(np, GPT_TYPE_IMX6DL); +} + +CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 6de62a96e79c..99b9a9792975 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -30,6 +30,7 @@ config ARM_GIC_V3_ITS config ARM_NVIC bool select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_CHIP config ARM_VIC diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c index 4ff0805fca01..5fac9100f6cb 100644 --- a/drivers/irqchip/irq-nvic.c +++ b/drivers/irqchip/irq-nvic.c @@ -49,6 +49,31 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs) handle_IRQ(irq, regs); } +static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + int i, ret; + irq_hw_number_t hwirq; + unsigned int type = IRQ_TYPE_NONE; + struct of_phandle_args *irq_data = arg; + + ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args, + irq_data->args_count, &hwirq, &type); + if (ret) + return ret; + + for (i = 0; i < nr_irqs; i++) + irq_map_generic_chip(domain, virq + i, hwirq + i); + + return 0; +} + +static const struct irq_domain_ops nvic_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .alloc = nvic_irq_domain_alloc, + .free = irq_domain_free_irqs_top, +}; + static int __init nvic_of_init(struct device_node *node, struct device_node *parent) { @@ -70,7 +95,8 @@ static int __init nvic_of_init(struct device_node *node, irqs = NVIC_MAX_IRQ; nvic_irq_domain = - irq_domain_add_linear(node, irqs, &irq_generic_chip_ops, NULL); + irq_domain_add_linear(node, irqs, &nvic_irq_domain_ops, NULL); + if (!nvic_irq_domain) { pr_warn("Failed to allocate irq domain\n"); return -ENOMEM; diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c index 9521057d4744..b932ecb7b730 100644 --- a/drivers/irqchip/irq-vf610-mscm-ir.c +++ b/drivers/irqchip/irq-vf610-mscm-ir.c @@ -47,6 +47,7 @@ struct vf610_mscm_ir_chip_data { void __iomem *mscm_ir_base; u16 cpu_mask; u16 saved_irsprc[MSCM_IRSPRC_NUM]; + bool is_nvic; }; static struct vf610_mscm_ir_chip_data *mscm_ir_data; @@ -101,7 +102,7 @@ static void vf610_mscm_ir_enable(struct irq_data *data) writew_relaxed(chip_data->cpu_mask, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); - irq_chip_unmask_parent(data); + irq_chip_enable_parent(data); } static void vf610_mscm_ir_disable(struct irq_data *data) @@ -111,7 +112,7 @@ static void vf610_mscm_ir_disable(struct irq_data *data) writew_relaxed(0x0, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); - irq_chip_mask_parent(data); + irq_chip_disable_parent(data); } static struct irq_chip vf610_mscm_ir_irq_chip = { @@ -143,10 +144,17 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi domain->host_data); gic_data.np = domain->parent->of_node; - gic_data.args_count = 3; - gic_data.args[0] = GIC_SPI; - gic_data.args[1] = irq_data->args[0]; - gic_data.args[2] = irq_data->args[1]; + + if (mscm_ir_data->is_nvic) { + gic_data.args_count = 1; + gic_data.args[0] = irq_data->args[0]; + } else { + gic_data.args_count = 3; + gic_data.args[0] = GIC_SPI; + gic_data.args[1] = irq_data->args[0]; + gic_data.args[2] = irq_data->args[1]; + } + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); } @@ -199,6 +207,9 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node, goto out_unmap; } + if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic")) + mscm_ir_data->is_nvic = true; + cpu_pm_register_notifier(&mscm_ir_notifier_block); return 0; diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 868036f70f8f..8406c668ecdc 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -49,6 +49,14 @@ config OMAP_GPMC interfacing to a variety of asynchronous as well as synchronous memory drives like NOR, NAND, OneNAND, SRAM. +config OMAP_GPMC_DEBUG + bool + depends on OMAP_GPMC + help + Enables verbose debugging mostly to decode the bootloader provided + timings. Enable this during development to configure devices + connected to the GPMC bus. + config MVEBU_DEVBUS bool "Marvell EBU Device Bus Controller" default y diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index c94ea0d68746..8911e51d410a 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -403,7 +403,7 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) p->cycle2cyclediffcsen); } -#ifdef DEBUG +#ifdef CONFIG_OMAP_GPMC_DEBUG /** * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it. * @cs: Chip Select Region @@ -612,7 +612,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max } l = gpmc_cs_read_reg(cs, reg); -#ifdef DEBUG +#ifdef CONFIG_OMAP_GPMC_DEBUG pr_info( "GPMC CS%d: %-17s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n", cs, name, ticks, gpmc_get_clk_period(cs, cd) * ticks / 1000, @@ -767,7 +767,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, GPMC_CONFIG1_CLKACTIVATIONTIME_MAX, clk_activation, GPMC_CD_FCLK); -#ifdef DEBUG +#ifdef CONFIG_OMAP_GPMC_DEBUG pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n", cs, (div * gpmc_get_fclk_period()) / 1000, div); #endif 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/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h new file mode 100644 index 000000000000..728df28b00d5 --- /dev/null +++ b/include/dt-bindings/clock/imx7d-clock.h @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. + * + * 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 __DT_BINDINGS_CLOCK_IMX7D_H +#define __DT_BINDINGS_CLOCK_IMX7D_H + +#define IMX7D_OSC_24M_CLK 0 +#define IMX7D_PLL_ARM_MAIN 1 +#define IMX7D_PLL_ARM_MAIN_CLK 2 +#define IMX7D_PLL_ARM_MAIN_SRC 3 +#define IMX7D_PLL_ARM_MAIN_BYPASS 4 +#define IMX7D_PLL_SYS_MAIN 5 +#define IMX7D_PLL_SYS_MAIN_CLK 6 +#define IMX7D_PLL_SYS_MAIN_SRC 7 +#define IMX7D_PLL_SYS_MAIN_BYPASS 8 +#define IMX7D_PLL_SYS_MAIN_480M 9 +#define IMX7D_PLL_SYS_MAIN_240M 10 +#define IMX7D_PLL_SYS_MAIN_120M 11 +#define IMX7D_PLL_SYS_MAIN_480M_CLK 12 +#define IMX7D_PLL_SYS_MAIN_240M_CLK 13 +#define IMX7D_PLL_SYS_MAIN_120M_CLK 14 +#define IMX7D_PLL_SYS_PFD0_392M_CLK 15 +#define IMX7D_PLL_SYS_PFD0_196M 16 +#define IMX7D_PLL_SYS_PFD0_196M_CLK 17 +#define IMX7D_PLL_SYS_PFD1_332M_CLK 18 +#define IMX7D_PLL_SYS_PFD1_166M 19 +#define IMX7D_PLL_SYS_PFD1_166M_CLK 20 +#define IMX7D_PLL_SYS_PFD2_270M_CLK 21 +#define IMX7D_PLL_SYS_PFD2_135M 22 +#define IMX7D_PLL_SYS_PFD2_135M_CLK 23 +#define IMX7D_PLL_SYS_PFD3_CLK 24 +#define IMX7D_PLL_SYS_PFD4_CLK 25 +#define IMX7D_PLL_SYS_PFD5_CLK 26 +#define IMX7D_PLL_SYS_PFD6_CLK 27 +#define IMX7D_PLL_SYS_PFD7_CLK 28 +#define IMX7D_PLL_ENET_MAIN 29 +#define IMX7D_PLL_ENET_MAIN_CLK 30 +#define IMX7D_PLL_ENET_MAIN_SRC 31 +#define IMX7D_PLL_ENET_MAIN_BYPASS 32 +#define IMX7D_PLL_ENET_MAIN_500M 33 +#define IMX7D_PLL_ENET_MAIN_250M 34 +#define IMX7D_PLL_ENET_MAIN_125M 35 +#define IMX7D_PLL_ENET_MAIN_100M 36 +#define IMX7D_PLL_ENET_MAIN_50M 37 +#define IMX7D_PLL_ENET_MAIN_40M 38 +#define IMX7D_PLL_ENET_MAIN_25M 39 +#define IMX7D_PLL_ENET_MAIN_500M_CLK 40 +#define IMX7D_PLL_ENET_MAIN_250M_CLK 41 +#define IMX7D_PLL_ENET_MAIN_125M_CLK 42 +#define IMX7D_PLL_ENET_MAIN_100M_CLK 43 +#define IMX7D_PLL_ENET_MAIN_50M_CLK 44 +#define IMX7D_PLL_ENET_MAIN_40M_CLK 45 +#define IMX7D_PLL_ENET_MAIN_25M_CLK 46 +#define IMX7D_PLL_DRAM_MAIN 47 +#define IMX7D_PLL_DRAM_MAIN_CLK 48 +#define IMX7D_PLL_DRAM_MAIN_SRC 49 +#define IMX7D_PLL_DRAM_MAIN_BYPASS 50 +#define IMX7D_PLL_DRAM_MAIN_533M 51 +#define IMX7D_PLL_DRAM_MAIN_533M_CLK 52 +#define IMX7D_PLL_AUDIO_MAIN 53 +#define IMX7D_PLL_AUDIO_MAIN_CLK 54 +#define IMX7D_PLL_AUDIO_MAIN_SRC 55 +#define IMX7D_PLL_AUDIO_MAIN_BYPASS 56 +#define IMX7D_PLL_VIDEO_MAIN_CLK 57 +#define IMX7D_PLL_VIDEO_MAIN 58 +#define IMX7D_PLL_VIDEO_MAIN_SRC 59 +#define IMX7D_PLL_VIDEO_MAIN_BYPASS 60 +#define IMX7D_USB_MAIN_480M_CLK 61 +#define IMX7D_ARM_A7_ROOT_CLK 62 +#define IMX7D_ARM_A7_ROOT_SRC 63 +#define IMX7D_ARM_A7_ROOT_CG 64 +#define IMX7D_ARM_A7_ROOT_DIV 65 +#define IMX7D_ARM_M4_ROOT_CLK 66 +#define IMX7D_ARM_M4_ROOT_SRC 67 +#define IMX7D_ARM_M4_ROOT_CG 68 +#define IMX7D_ARM_M4_ROOT_DIV 69 +#define IMX7D_ARM_M0_ROOT_CLK 70 +#define IMX7D_ARM_M0_ROOT_SRC 71 +#define IMX7D_ARM_M0_ROOT_CG 72 +#define IMX7D_ARM_M0_ROOT_DIV 73 +#define IMX7D_MAIN_AXI_ROOT_CLK 74 +#define IMX7D_MAIN_AXI_ROOT_SRC 75 +#define IMX7D_MAIN_AXI_ROOT_CG 76 +#define IMX7D_MAIN_AXI_ROOT_DIV 77 +#define IMX7D_DISP_AXI_ROOT_CLK 78 +#define IMX7D_DISP_AXI_ROOT_SRC 79 +#define IMX7D_DISP_AXI_ROOT_CG 80 +#define IMX7D_DISP_AXI_ROOT_DIV 81 +#define IMX7D_ENET_AXI_ROOT_CLK 82 +#define IMX7D_ENET_AXI_ROOT_SRC 83 +#define IMX7D_ENET_AXI_ROOT_CG 84 +#define IMX7D_ENET_AXI_ROOT_DIV 85 +#define IMX7D_NAND_USDHC_BUS_ROOT_CLK 86 +#define IMX7D_NAND_USDHC_BUS_ROOT_SRC 87 +#define IMX7D_NAND_USDHC_BUS_ROOT_CG 88 +#define IMX7D_NAND_USDHC_BUS_ROOT_DIV 89 +#define IMX7D_AHB_CHANNEL_ROOT_CLK 90 +#define IMX7D_AHB_CHANNEL_ROOT_SRC 91 +#define IMX7D_AHB_CHANNEL_ROOT_CG 92 +#define IMX7D_AHB_CHANNEL_ROOT_DIV 93 +#define IMX7D_DRAM_PHYM_ROOT_CLK 94 +#define IMX7D_DRAM_PHYM_ROOT_SRC 95 +#define IMX7D_DRAM_PHYM_ROOT_CG 96 +#define IMX7D_DRAM_PHYM_ROOT_DIV 97 +#define IMX7D_DRAM_ROOT_CLK 98 +#define IMX7D_DRAM_ROOT_SRC 99 +#define IMX7D_DRAM_ROOT_CG 100 +#define IMX7D_DRAM_ROOT_DIV 101 +#define IMX7D_DRAM_PHYM_ALT_ROOT_CLK 102 +#define IMX7D_DRAM_PHYM_ALT_ROOT_SRC 103 +#define IMX7D_DRAM_PHYM_ALT_ROOT_CG 104 +#define IMX7D_DRAM_PHYM_ALT_ROOT_DIV 105 +#define IMX7D_DRAM_ALT_ROOT_CLK 106 +#define IMX7D_DRAM_ALT_ROOT_SRC 107 +#define IMX7D_DRAM_ALT_ROOT_CG 108 +#define IMX7D_DRAM_ALT_ROOT_DIV 109 +#define IMX7D_USB_HSIC_ROOT_CLK 110 +#define IMX7D_USB_HSIC_ROOT_SRC 111 +#define IMX7D_USB_HSIC_ROOT_CG 112 +#define IMX7D_USB_HSIC_ROOT_DIV 113 +#define IMX7D_PCIE_CTRL_ROOT_CLK 114 +#define IMX7D_PCIE_CTRL_ROOT_SRC 115 +#define IMX7D_PCIE_CTRL_ROOT_CG 116 +#define IMX7D_PCIE_CTRL_ROOT_DIV 117 +#define IMX7D_PCIE_PHY_ROOT_CLK 118 +#define IMX7D_PCIE_PHY_ROOT_SRC 119 +#define IMX7D_PCIE_PHY_ROOT_CG 120 +#define IMX7D_PCIE_PHY_ROOT_DIV 121 +#define IMX7D_EPDC_PIXEL_ROOT_CLK 122 +#define IMX7D_EPDC_PIXEL_ROOT_SRC 123 +#define IMX7D_EPDC_PIXEL_ROOT_CG 124 +#define IMX7D_EPDC_PIXEL_ROOT_DIV 125 +#define IMX7D_LCDIF_PIXEL_ROOT_CLK 126 +#define IMX7D_LCDIF_PIXEL_ROOT_SRC 127 +#define IMX7D_LCDIF_PIXEL_ROOT_CG 128 +#define IMX7D_LCDIF_PIXEL_ROOT_DIV 129 +#define IMX7D_MIPI_DSI_ROOT_CLK 130 +#define IMX7D_MIPI_DSI_ROOT_SRC 131 +#define IMX7D_MIPI_DSI_ROOT_CG 132 +#define IMX7D_MIPI_DSI_ROOT_DIV 133 +#define IMX7D_MIPI_CSI_ROOT_CLK 134 +#define IMX7D_MIPI_CSI_ROOT_SRC 135 +#define IMX7D_MIPI_CSI_ROOT_CG 136 +#define IMX7D_MIPI_CSI_ROOT_DIV 137 +#define IMX7D_MIPI_DPHY_ROOT_CLK 138 +#define IMX7D_MIPI_DPHY_ROOT_SRC 139 +#define IMX7D_MIPI_DPHY_ROOT_CG 140 +#define IMX7D_MIPI_DPHY_ROOT_DIV 141 +#define IMX7D_SAI1_ROOT_CLK 142 +#define IMX7D_SAI1_ROOT_SRC 143 +#define IMX7D_SAI1_ROOT_CG 144 +#define IMX7D_SAI1_ROOT_DIV 145 +#define IMX7D_SAI2_ROOT_CLK 146 +#define IMX7D_SAI2_ROOT_SRC 147 +#define IMX7D_SAI2_ROOT_CG 148 +#define IMX7D_SAI2_ROOT_DIV 149 +#define IMX7D_SAI3_ROOT_CLK 150 +#define IMX7D_SAI3_ROOT_SRC 151 +#define IMX7D_SAI3_ROOT_CG 152 +#define IMX7D_SAI3_ROOT_DIV 153 +#define IMX7D_SPDIF_ROOT_CLK 154 +#define IMX7D_SPDIF_ROOT_SRC 155 +#define IMX7D_SPDIF_ROOT_CG 156 +#define IMX7D_SPDIF_ROOT_DIV 157 +#define IMX7D_ENET1_REF_ROOT_CLK 158 +#define IMX7D_ENET1_REF_ROOT_SRC 159 +#define IMX7D_ENET1_REF_ROOT_CG 160 +#define IMX7D_ENET1_REF_ROOT_DIV 161 +#define IMX7D_ENET1_TIME_ROOT_CLK 162 +#define IMX7D_ENET1_TIME_ROOT_SRC 163 +#define IMX7D_ENET1_TIME_ROOT_CG 164 +#define IMX7D_ENET1_TIME_ROOT_DIV 165 +#define IMX7D_ENET2_REF_ROOT_CLK 166 +#define IMX7D_ENET2_REF_ROOT_SRC 167 +#define IMX7D_ENET2_REF_ROOT_CG 168 +#define IMX7D_ENET2_REF_ROOT_DIV 169 +#define IMX7D_ENET2_TIME_ROOT_CLK 170 +#define IMX7D_ENET2_TIME_ROOT_SRC 171 +#define IMX7D_ENET2_TIME_ROOT_CG 172 +#define IMX7D_ENET2_TIME_ROOT_DIV 173 +#define IMX7D_ENET_PHY_REF_ROOT_CLK 174 +#define IMX7D_ENET_PHY_REF_ROOT_SRC 175 +#define IMX7D_ENET_PHY_REF_ROOT_CG 176 +#define IMX7D_ENET_PHY_REF_ROOT_DIV 177 +#define IMX7D_EIM_ROOT_CLK 178 +#define IMX7D_EIM_ROOT_SRC 179 +#define IMX7D_EIM_ROOT_CG 180 +#define IMX7D_EIM_ROOT_DIV 181 +#define IMX7D_NAND_ROOT_CLK 182 +#define IMX7D_NAND_ROOT_SRC 183 +#define IMX7D_NAND_ROOT_CG 184 +#define IMX7D_NAND_ROOT_DIV 185 +#define IMX7D_QSPI_ROOT_CLK 186 +#define IMX7D_QSPI_ROOT_SRC 187 +#define IMX7D_QSPI_ROOT_CG 188 +#define IMX7D_QSPI_ROOT_DIV 189 +#define IMX7D_USDHC1_ROOT_CLK 190 +#define IMX7D_USDHC1_ROOT_SRC 191 +#define IMX7D_USDHC1_ROOT_CG 192 +#define IMX7D_USDHC1_ROOT_DIV 193 +#define IMX7D_USDHC2_ROOT_CLK 194 +#define IMX7D_USDHC2_ROOT_SRC 195 +#define IMX7D_USDHC2_ROOT_CG 196 +#define IMX7D_USDHC2_ROOT_DIV 197 +#define IMX7D_USDHC3_ROOT_CLK 198 +#define IMX7D_USDHC3_ROOT_SRC 199 +#define IMX7D_USDHC3_ROOT_CG 200 +#define IMX7D_USDHC3_ROOT_DIV 201 +#define IMX7D_CAN1_ROOT_CLK 202 +#define IMX7D_CAN1_ROOT_SRC 203 +#define IMX7D_CAN1_ROOT_CG 204 +#define IMX7D_CAN1_ROOT_DIV 205 +#define IMX7D_CAN2_ROOT_CLK 206 +#define IMX7D_CAN2_ROOT_SRC 207 +#define IMX7D_CAN2_ROOT_CG 208 +#define IMX7D_CAN2_ROOT_DIV 209 +#define IMX7D_I2C1_ROOT_CLK 210 +#define IMX7D_I2C1_ROOT_SRC 211 +#define IMX7D_I2C1_ROOT_CG 212 +#define IMX7D_I2C1_ROOT_DIV 213 +#define IMX7D_I2C2_ROOT_CLK 214 +#define IMX7D_I2C2_ROOT_SRC 215 +#define IMX7D_I2C2_ROOT_CG 216 +#define IMX7D_I2C2_ROOT_DIV 217 +#define IMX7D_I2C3_ROOT_CLK 218 +#define IMX7D_I2C3_ROOT_SRC 219 +#define IMX7D_I2C3_ROOT_CG 220 +#define IMX7D_I2C3_ROOT_DIV 221 +#define IMX7D_I2C4_ROOT_CLK 222 +#define IMX7D_I2C4_ROOT_SRC 223 +#define IMX7D_I2C4_ROOT_CG 224 +#define IMX7D_I2C4_ROOT_DIV 225 +#define IMX7D_UART1_ROOT_CLK 226 +#define IMX7D_UART1_ROOT_SRC 227 +#define IMX7D_UART1_ROOT_CG 228 +#define IMX7D_UART1_ROOT_DIV 229 +#define IMX7D_UART2_ROOT_CLK 230 +#define IMX7D_UART2_ROOT_SRC 231 +#define IMX7D_UART2_ROOT_CG 232 +#define IMX7D_UART2_ROOT_DIV 233 +#define IMX7D_UART3_ROOT_CLK 234 +#define IMX7D_UART3_ROOT_SRC 235 +#define IMX7D_UART3_ROOT_CG 236 +#define IMX7D_UART3_ROOT_DIV 237 +#define IMX7D_UART4_ROOT_CLK 238 +#define IMX7D_UART4_ROOT_SRC 239 +#define IMX7D_UART4_ROOT_CG 240 +#define IMX7D_UART4_ROOT_DIV 241 +#define IMX7D_UART5_ROOT_CLK 242 +#define IMX7D_UART5_ROOT_SRC 243 +#define IMX7D_UART5_ROOT_CG 244 +#define IMX7D_UART5_ROOT_DIV 245 +#define IMX7D_UART6_ROOT_CLK 246 +#define IMX7D_UART6_ROOT_SRC 247 +#define IMX7D_UART6_ROOT_CG 248 +#define IMX7D_UART6_ROOT_DIV 249 +#define IMX7D_UART7_ROOT_CLK 250 +#define IMX7D_UART7_ROOT_SRC 251 +#define IMX7D_UART7_ROOT_CG 252 +#define IMX7D_UART7_ROOT_DIV 253 +#define IMX7D_ECSPI1_ROOT_CLK 254 +#define IMX7D_ECSPI1_ROOT_SRC 255 +#define IMX7D_ECSPI1_ROOT_CG 256 +#define IMX7D_ECSPI1_ROOT_DIV 257 +#define IMX7D_ECSPI2_ROOT_CLK 258 +#define IMX7D_ECSPI2_ROOT_SRC 259 +#define IMX7D_ECSPI2_ROOT_CG 260 +#define IMX7D_ECSPI2_ROOT_DIV 261 +#define IMX7D_ECSPI3_ROOT_CLK 262 +#define IMX7D_ECSPI3_ROOT_SRC 263 +#define IMX7D_ECSPI3_ROOT_CG 264 +#define IMX7D_ECSPI3_ROOT_DIV 265 +#define IMX7D_ECSPI4_ROOT_CLK 266 +#define IMX7D_ECSPI4_ROOT_SRC 267 +#define IMX7D_ECSPI4_ROOT_CG 268 +#define IMX7D_ECSPI4_ROOT_DIV 269 +#define IMX7D_PWM1_ROOT_CLK 270 +#define IMX7D_PWM1_ROOT_SRC 271 +#define IMX7D_PWM1_ROOT_CG 272 +#define IMX7D_PWM1_ROOT_DIV 273 +#define IMX7D_PWM2_ROOT_CLK 274 +#define IMX7D_PWM2_ROOT_SRC 275 +#define IMX7D_PWM2_ROOT_CG 276 +#define IMX7D_PWM2_ROOT_DIV 277 +#define IMX7D_PWM3_ROOT_CLK 278 +#define IMX7D_PWM3_ROOT_SRC 279 +#define IMX7D_PWM3_ROOT_CG 280 +#define IMX7D_PWM3_ROOT_DIV 281 +#define IMX7D_PWM4_ROOT_CLK 282 +#define IMX7D_PWM4_ROOT_SRC 283 +#define IMX7D_PWM4_ROOT_CG 284 +#define IMX7D_PWM4_ROOT_DIV 285 +#define IMX7D_FLEXTIMER1_ROOT_CLK 286 +#define IMX7D_FLEXTIMER1_ROOT_SRC 287 +#define IMX7D_FLEXTIMER1_ROOT_CG 288 +#define IMX7D_FLEXTIMER1_ROOT_DIV 289 +#define IMX7D_FLEXTIMER2_ROOT_CLK 290 +#define IMX7D_FLEXTIMER2_ROOT_SRC 291 +#define IMX7D_FLEXTIMER2_ROOT_CG 292 +#define IMX7D_FLEXTIMER2_ROOT_DIV 293 +#define IMX7D_SIM1_ROOT_CLK 294 +#define IMX7D_SIM1_ROOT_SRC 295 +#define IMX7D_SIM1_ROOT_CG 296 +#define IMX7D_SIM1_ROOT_DIV 297 +#define IMX7D_SIM2_ROOT_CLK 298 +#define IMX7D_SIM2_ROOT_SRC 299 +#define IMX7D_SIM2_ROOT_CG 300 +#define IMX7D_SIM2_ROOT_DIV 301 +#define IMX7D_GPT1_ROOT_CLK 302 +#define IMX7D_GPT1_ROOT_SRC 303 +#define IMX7D_GPT1_ROOT_CG 304 +#define IMX7D_GPT1_ROOT_DIV 305 +#define IMX7D_GPT2_ROOT_CLK 306 +#define IMX7D_GPT2_ROOT_SRC 307 +#define IMX7D_GPT2_ROOT_CG 308 +#define IMX7D_GPT2_ROOT_DIV 309 +#define IMX7D_GPT3_ROOT_CLK 310 +#define IMX7D_GPT3_ROOT_SRC 311 +#define IMX7D_GPT3_ROOT_CG 312 +#define IMX7D_GPT3_ROOT_DIV 313 +#define IMX7D_GPT4_ROOT_CLK 314 +#define IMX7D_GPT4_ROOT_SRC 315 +#define IMX7D_GPT4_ROOT_CG 316 +#define IMX7D_GPT4_ROOT_DIV 317 +#define IMX7D_TRACE_ROOT_CLK 318 +#define IMX7D_TRACE_ROOT_SRC 319 +#define IMX7D_TRACE_ROOT_CG 320 +#define IMX7D_TRACE_ROOT_DIV 321 +#define IMX7D_WDOG1_ROOT_CLK 322 +#define IMX7D_WDOG_ROOT_SRC 323 +#define IMX7D_WDOG_ROOT_CG 324 +#define IMX7D_WDOG_ROOT_DIV 325 +#define IMX7D_CSI_MCLK_ROOT_CLK 326 +#define IMX7D_CSI_MCLK_ROOT_SRC 327 +#define IMX7D_CSI_MCLK_ROOT_CG 328 +#define IMX7D_CSI_MCLK_ROOT_DIV 329 +#define IMX7D_AUDIO_MCLK_ROOT_CLK 330 +#define IMX7D_AUDIO_MCLK_ROOT_SRC 331 +#define IMX7D_AUDIO_MCLK_ROOT_CG 332 +#define IMX7D_AUDIO_MCLK_ROOT_DIV 333 +#define IMX7D_WRCLK_ROOT_CLK 334 +#define IMX7D_WRCLK_ROOT_SRC 335 +#define IMX7D_WRCLK_ROOT_CG 336 +#define IMX7D_WRCLK_ROOT_DIV 337 +#define IMX7D_CLKO1_ROOT_SRC 338 +#define IMX7D_CLKO1_ROOT_CG 339 +#define IMX7D_CLKO1_ROOT_DIV 340 +#define IMX7D_CLKO2_ROOT_SRC 341 +#define IMX7D_CLKO2_ROOT_CG 342 +#define IMX7D_CLKO2_ROOT_DIV 343 +#define IMX7D_MAIN_AXI_ROOT_PRE_DIV 344 +#define IMX7D_DISP_AXI_ROOT_PRE_DIV 345 +#define IMX7D_ENET_AXI_ROOT_PRE_DIV 346 +#define IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV 347 +#define IMX7D_AHB_CHANNEL_ROOT_PRE_DIV 348 +#define IMX7D_USB_HSIC_ROOT_PRE_DIV 349 +#define IMX7D_PCIE_CTRL_ROOT_PRE_DIV 350 +#define IMX7D_PCIE_PHY_ROOT_PRE_DIV 351 +#define IMX7D_EPDC_PIXEL_ROOT_PRE_DIV 352 +#define IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV 353 +#define IMX7D_MIPI_DSI_ROOT_PRE_DIV 354 +#define IMX7D_MIPI_CSI_ROOT_PRE_DIV 355 +#define IMX7D_MIPI_DPHY_ROOT_PRE_DIV 356 +#define IMX7D_SAI1_ROOT_PRE_DIV 357 +#define IMX7D_SAI2_ROOT_PRE_DIV 358 +#define IMX7D_SAI3_ROOT_PRE_DIV 359 +#define IMX7D_SPDIF_ROOT_PRE_DIV 360 +#define IMX7D_ENET1_REF_ROOT_PRE_DIV 361 +#define IMX7D_ENET1_TIME_ROOT_PRE_DIV 362 +#define IMX7D_ENET2_REF_ROOT_PRE_DIV 363 +#define IMX7D_ENET2_TIME_ROOT_PRE_DIV 364 +#define IMX7D_ENET_PHY_REF_ROOT_PRE_DIV 365 +#define IMX7D_EIM_ROOT_PRE_DIV 366 +#define IMX7D_NAND_ROOT_PRE_DIV 367 +#define IMX7D_QSPI_ROOT_PRE_DIV 368 +#define IMX7D_USDHC1_ROOT_PRE_DIV 369 +#define IMX7D_USDHC2_ROOT_PRE_DIV 370 +#define IMX7D_USDHC3_ROOT_PRE_DIV 371 +#define IMX7D_CAN1_ROOT_PRE_DIV 372 +#define IMX7D_CAN2_ROOT_PRE_DIV 373 +#define IMX7D_I2C1_ROOT_PRE_DIV 374 +#define IMX7D_I2C2_ROOT_PRE_DIV 375 +#define IMX7D_I2C3_ROOT_PRE_DIV 376 +#define IMX7D_I2C4_ROOT_PRE_DIV 377 +#define IMX7D_UART1_ROOT_PRE_DIV 378 +#define IMX7D_UART2_ROOT_PRE_DIV 379 +#define IMX7D_UART3_ROOT_PRE_DIV 380 +#define IMX7D_UART4_ROOT_PRE_DIV 381 +#define IMX7D_UART5_ROOT_PRE_DIV 382 +#define IMX7D_UART6_ROOT_PRE_DIV 383 +#define IMX7D_UART7_ROOT_PRE_DIV 384 +#define IMX7D_ECSPI1_ROOT_PRE_DIV 385 +#define IMX7D_ECSPI2_ROOT_PRE_DIV 386 +#define IMX7D_ECSPI3_ROOT_PRE_DIV 387 +#define IMX7D_ECSPI4_ROOT_PRE_DIV 388 +#define IMX7D_PWM1_ROOT_PRE_DIV 389 +#define IMX7D_PWM2_ROOT_PRE_DIV 390 +#define IMX7D_PWM3_ROOT_PRE_DIV 391 +#define IMX7D_PWM4_ROOT_PRE_DIV 392 +#define IMX7D_FLEXTIMER1_ROOT_PRE_DIV 393 +#define IMX7D_FLEXTIMER2_ROOT_PRE_DIV 394 +#define IMX7D_SIM1_ROOT_PRE_DIV 395 +#define IMX7D_SIM2_ROOT_PRE_DIV 396 +#define IMX7D_GPT1_ROOT_PRE_DIV 397 +#define IMX7D_GPT2_ROOT_PRE_DIV 398 +#define IMX7D_GPT3_ROOT_PRE_DIV 399 +#define IMX7D_GPT4_ROOT_PRE_DIV 400 +#define IMX7D_TRACE_ROOT_PRE_DIV 401 +#define IMX7D_WDOG_ROOT_PRE_DIV 402 +#define IMX7D_CSI_MCLK_ROOT_PRE_DIV 403 +#define IMX7D_AUDIO_MCLK_ROOT_PRE_DIV 404 +#define IMX7D_WRCLK_ROOT_PRE_DIV 405 +#define IMX7D_CLKO1_ROOT_PRE_DIV 406 +#define IMX7D_CLKO2_ROOT_PRE_DIV 407 +#define IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV 408 +#define IMX7D_DRAM_ALT_ROOT_PRE_DIV 409 +#define IMX7D_LVDS1_IN_CLK 410 +#define IMX7D_LVDS1_OUT_SEL 411 +#define IMX7D_LVDS1_OUT_CLK 412 +#define IMX7D_CLK_DUMMY 413 +#define IMX7D_GPT_3M_CLK 414 +#define IMX7D_OCRAM_CLK 415 +#define IMX7D_OCRAM_S_CLK 416 +#define IMX7D_WDOG2_ROOT_CLK 417 +#define IMX7D_WDOG3_ROOT_CLK 418 +#define IMX7D_WDOG4_ROOT_CLK 419 +#define IMX7D_SDMA_CORE_CLK 420 +#define IMX7D_USB1_MAIN_480M_CLK 421 +#define IMX7D_USB_CTRL_CLK 422 +#define IMX7D_USB_PHY1_CLK 423 +#define IMX7D_USB_PHY2_CLK 424 +#define IMX7D_IPG_ROOT_CLK 425 +#define IMX7D_SAI1_IPG_CLK 426 +#define IMX7D_SAI2_IPG_CLK 427 +#define IMX7D_SAI3_IPG_CLK 428 +#define IMX7D_PLL_AUDIO_TEST_DIV 429 +#define IMX7D_PLL_AUDIO_POST_DIV 430 +#define IMX7D_PLL_VIDEO_TEST_DIV 431 +#define IMX7D_PLL_VIDEO_POST_DIV 432 +#define IMX7D_MU_ROOT_CLK 433 +#define IMX7D_SEMA4_HS_ROOT_CLK 434 +#define IMX7D_PLL_DRAM_TEST_DIV 435 +#define IMX7D_CLK_END 436 +#endif /* __DT_BINDINGS_CLOCK_IMX7D_H */ diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index 979d24a6799f..d19763439472 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -193,6 +193,7 @@ #define VF610_PLL6_BYPASS 180 #define VF610_PLL7_BYPASS 181 #define VF610_CLK_SNVS 182 -#define VF610_CLK_END 183 +#define VF610_CLK_DAP 183 +#define VF610_CLK_END 184 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ diff --git a/include/dt-bindings/clock/zx296702-clock.h b/include/dt-bindings/clock/zx296702-clock.h new file mode 100644 index 000000000000..e683dbb7e7c5 --- /dev/null +++ b/include/dt-bindings/clock/zx296702-clock.h @@ -0,0 +1,170 @@ +/* + * 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 __DT_BINDINGS_CLOCK_ZX296702_H +#define __DT_BINDINGS_CLOCK_ZX296702_H + +#define ZX296702_OSC 0 +#define ZX296702_PLL_A9 1 +#define ZX296702_PLL_A9_350M 2 +#define ZX296702_PLL_MAC_1000M 3 +#define ZX296702_PLL_MAC_333M 4 +#define ZX296702_PLL_MM0_1188M 5 +#define ZX296702_PLL_MM0_396M 6 +#define ZX296702_PLL_MM0_198M 7 +#define ZX296702_PLL_MM1_108M 8 +#define ZX296702_PLL_MM1_72M 9 +#define ZX296702_PLL_MM1_54M 10 +#define ZX296702_PLL_LSP_104M 11 +#define ZX296702_PLL_LSP_26M 12 +#define ZX296702_PLL_AUDIO_294M912 13 +#define ZX296702_PLL_DDR_266M 14 +#define ZX296702_CLK_148M5 15 +#define ZX296702_MATRIX_ACLK 16 +#define ZX296702_MAIN_HCLK 17 +#define ZX296702_MAIN_PCLK 18 +#define ZX296702_CLK_500 19 +#define ZX296702_CLK_250 20 +#define ZX296702_CLK_125 21 +#define ZX296702_CLK_74M25 22 +#define ZX296702_A9_WCLK 23 +#define ZX296702_A9_AS1_ACLK_MUX 24 +#define ZX296702_A9_TRACE_CLKIN_MUX 25 +#define ZX296702_A9_AS1_ACLK_DIV 26 +#define ZX296702_CLK_2 27 +#define ZX296702_CLK_27 28 +#define ZX296702_DECPPU_ACLK_MUX 29 +#define ZX296702_PPU_ACLK_MUX 30 +#define ZX296702_MALI400_ACLK_MUX 31 +#define ZX296702_VOU_ACLK_MUX 32 +#define ZX296702_VOU_MAIN_WCLK_MUX 33 +#define ZX296702_VOU_AUX_WCLK_MUX 34 +#define ZX296702_VOU_SCALER_WCLK_MUX 35 +#define ZX296702_R2D_ACLK_MUX 36 +#define ZX296702_R2D_WCLK_MUX 37 +#define ZX296702_CLK_50 38 +#define ZX296702_CLK_25 39 +#define ZX296702_CLK_12 40 +#define ZX296702_CLK_16M384 41 +#define ZX296702_CLK_32K768 42 +#define ZX296702_SEC_WCLK_DIV 43 +#define ZX296702_DDR_WCLK_MUX 44 +#define ZX296702_NAND_WCLK_MUX 45 +#define ZX296702_LSP_26_WCLK_MUX 46 +#define ZX296702_A9_AS0_ACLK 47 +#define ZX296702_A9_AS1_ACLK 48 +#define ZX296702_A9_TRACE_CLKIN 49 +#define ZX296702_DECPPU_AXI_M_ACLK 50 +#define ZX296702_DECPPU_AHB_S_HCLK 51 +#define ZX296702_PPU_AXI_M_ACLK 52 +#define ZX296702_PPU_AHB_S_HCLK 53 +#define ZX296702_VOU_AXI_M_ACLK 54 +#define ZX296702_VOU_APB_PCLK 55 +#define ZX296702_VOU_MAIN_CHANNEL_WCLK 56 +#define ZX296702_VOU_AUX_CHANNEL_WCLK 57 +#define ZX296702_VOU_HDMI_OSCLK_CEC 58 +#define ZX296702_VOU_SCALER_WCLK 59 +#define ZX296702_MALI400_AXI_M_ACLK 60 +#define ZX296702_MALI400_APB_PCLK 61 +#define ZX296702_R2D_WCLK 62 +#define ZX296702_R2D_AXI_M_ACLK 63 +#define ZX296702_R2D_AHB_HCLK 64 +#define ZX296702_DDR3_AXI_S0_ACLK 65 +#define ZX296702_DDR3_APB_PCLK 66 +#define ZX296702_DDR3_WCLK 67 +#define ZX296702_USB20_0_AHB_HCLK 68 +#define ZX296702_USB20_0_EXTREFCLK 69 +#define ZX296702_USB20_1_AHB_HCLK 70 +#define ZX296702_USB20_1_EXTREFCLK 71 +#define ZX296702_USB20_2_AHB_HCLK 72 +#define ZX296702_USB20_2_EXTREFCLK 73 +#define ZX296702_GMAC_AXI_M_ACLK 74 +#define ZX296702_GMAC_APB_PCLK 75 +#define ZX296702_GMAC_125_CLKIN 76 +#define ZX296702_GMAC_RMII_CLKIN 77 +#define ZX296702_GMAC_25M_CLK 78 +#define ZX296702_NANDFLASH_AHB_HCLK 79 +#define ZX296702_NANDFLASH_WCLK 80 +#define ZX296702_LSP0_APB_PCLK 81 +#define ZX296702_LSP0_AHB_HCLK 82 +#define ZX296702_LSP0_26M_WCLK 83 +#define ZX296702_LSP0_104M_WCLK 84 +#define ZX296702_LSP0_16M384_WCLK 85 +#define ZX296702_LSP1_APB_PCLK 86 +#define ZX296702_LSP1_26M_WCLK 87 +#define ZX296702_LSP1_104M_WCLK 88 +#define ZX296702_LSP1_32K_CLK 89 +#define ZX296702_AON_HCLK 90 +#define ZX296702_SYS_CTRL_PCLK 91 +#define ZX296702_DMA_PCLK 92 +#define ZX296702_DMA_ACLK 93 +#define ZX296702_SEC_HCLK 94 +#define ZX296702_AES_WCLK 95 +#define ZX296702_DES_WCLK 96 +#define ZX296702_IRAM_ACLK 97 +#define ZX296702_IROM_ACLK 98 +#define ZX296702_BOOT_CTRL_HCLK 99 +#define ZX296702_EFUSE_CLK_30 100 +#define ZX296702_VOU_MAIN_CHANNEL_DIV 101 +#define ZX296702_VOU_AUX_CHANNEL_DIV 102 +#define ZX296702_VOU_TV_ENC_HD_DIV 103 +#define ZX296702_VOU_TV_ENC_SD_DIV 104 +#define ZX296702_VL0_MUX 105 +#define ZX296702_VL1_MUX 106 +#define ZX296702_VL2_MUX 107 +#define ZX296702_GL0_MUX 108 +#define ZX296702_GL1_MUX 109 +#define ZX296702_GL2_MUX 110 +#define ZX296702_WB_MUX 111 +#define ZX296702_HDMI_MUX 112 +#define ZX296702_VOU_TV_ENC_HD_MUX 113 +#define ZX296702_VOU_TV_ENC_SD_MUX 114 +#define ZX296702_VL0_CLK 115 +#define ZX296702_VL1_CLK 116 +#define ZX296702_VL2_CLK 117 +#define ZX296702_GL0_CLK 118 +#define ZX296702_GL1_CLK 119 +#define ZX296702_GL2_CLK 120 +#define ZX296702_WB_CLK 121 +#define ZX296702_CL_CLK 122 +#define ZX296702_MAIN_MIX_CLK 123 +#define ZX296702_AUX_MIX_CLK 124 +#define ZX296702_HDMI_CLK 125 +#define ZX296702_VOU_TV_ENC_HD_DAC_CLK 126 +#define ZX296702_VOU_TV_ENC_SD_DAC_CLK 127 +#define ZX296702_A9_PERIPHCLK 128 +#define ZX296702_TOPCLK_END 129 + +#define ZX296702_SDMMC1_WCLK_MUX 0 +#define ZX296702_SDMMC1_WCLK_DIV 1 +#define ZX296702_SDMMC1_WCLK 2 +#define ZX296702_SDMMC1_PCLK 3 +#define ZX296702_SPDIF0_WCLK_MUX 4 +#define ZX296702_SPDIF0_WCLK 5 +#define ZX296702_SPDIF0_PCLK 6 +#define ZX296702_SPDIF0_DIV 7 +#define ZX296702_I2S0_WCLK_MUX 8 +#define ZX296702_I2S0_WCLK 9 +#define ZX296702_I2S0_PCLK 10 +#define ZX296702_I2S0_DIV 11 +#define ZX296702_LSP0CLK_END 12 + +#define ZX296702_UART0_WCLK_MUX 0 +#define ZX296702_UART0_WCLK 1 +#define ZX296702_UART0_PCLK 2 +#define ZX296702_UART1_WCLK_MUX 3 +#define ZX296702_UART1_WCLK 4 +#define ZX296702_UART1_PCLK 5 +#define ZX296702_SDMMC0_WCLK_MUX 6 +#define ZX296702_SDMMC0_WCLK_DIV 7 +#define ZX296702_SDMMC0_WCLK 8 +#define ZX296702_SDMMC0_PCLK 9 +#define ZX296702_LSP1CLK_END 10 + +#endif /* __DT_BINDINGS_CLOCK_ZX296702_H */ diff --git a/include/linux/irq.h b/include/linux/irq.h index 62c6901cab55..2633061364b1 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -458,6 +458,8 @@ extern void handle_nested_irq(unsigned int irq); extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY +extern void irq_chip_enable_parent(struct irq_data *data); +extern void irq_chip_disable_parent(struct irq_data *data); extern void irq_chip_ack_parent(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); extern void irq_chip_mask_parent(struct irq_data *data); diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 676d7306a360..744ac0ec98eb 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -258,6 +258,10 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, /* V2 interfaces to support hierarchy IRQ domains. */ extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, unsigned int virq); +extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq, struct irq_chip *chip, + void *chip_data, irq_flow_handler_t handler, + void *handler_data, const char *handler_name); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, unsigned int flags, unsigned int size, @@ -281,10 +285,6 @@ extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, irq_hw_number_t hwirq, struct irq_chip *chip, void *chip_data); -extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq, - irq_hw_number_t hwirq, struct irq_chip *chip, - void *chip_data, irq_flow_handler_t handler, - void *handler_data, const char *handler_name); extern void irq_domain_reset_irq_data(struct irq_data *irq_data); extern void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, diff --git a/include/linux/reset/bcm63xx_pmb.h b/include/linux/reset/bcm63xx_pmb.h new file mode 100644 index 000000000000..bb4af7b5eb36 --- /dev/null +++ b/include/linux/reset/bcm63xx_pmb.h @@ -0,0 +1,88 @@ +/* + * Broadcom BCM63xx Processor Monitor Bus shared routines (SMP and reset) + * + * Copyright (C) 2015, Broadcom Corporation + * Author: Florian Fainelli <f.fainelli@gmail.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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __BCM63XX_PMB_H +#define __BCM63XX_PMB_H + +#include <linux/io.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/err.h> + +/* PMB Master controller register */ +#define PMB_CTRL 0x00 +#define PMC_PMBM_START (1 << 31) +#define PMC_PMBM_TIMEOUT (1 << 30) +#define PMC_PMBM_SLAVE_ERR (1 << 29) +#define PMC_PMBM_BUSY (1 << 28) +#define PMC_PMBM_READ (0 << 20) +#define PMC_PMBM_WRITE (1 << 20) +#define PMB_WR_DATA 0x04 +#define PMB_TIMEOUT 0x08 +#define PMB_RD_DATA 0x0C + +#define PMB_BUS_ID_SHIFT 8 + +/* Perform the low-level PMB master operation, shared between reads and + * writes. + */ +static inline int __bpcm_do_op(void __iomem *master, unsigned int addr, + u32 off, u32 op) +{ + unsigned int timeout = 1000; + u32 cmd; + + cmd = (PMC_PMBM_START | op | (addr & 0xff) << 12 | off); + writel(cmd, master + PMB_CTRL); + do { + cmd = readl(master + PMB_CTRL); + if (!(cmd & PMC_PMBM_START)) + return 0; + + if (cmd & PMC_PMBM_SLAVE_ERR) + return -EIO; + + if (cmd & PMC_PMBM_TIMEOUT) + return -ETIMEDOUT; + + udelay(1); + } while (timeout-- > 0); + + return -ETIMEDOUT; +} + +static inline int bpcm_rd(void __iomem *master, unsigned int addr, + u32 off, u32 *val) +{ + int ret = 0; + + ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_READ); + *val = readl(master + PMB_RD_DATA); + + return ret; +} + +static inline int bpcm_wr(void __iomem *master, unsigned int addr, + u32 off, u32 val) +{ + int ret = 0; + + writel(val, master + PMB_WR_DATA); + ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_WRITE); + + return ret; +} + +#endif /* __BCM63XX_PMB_H */ diff --git a/include/soc/imx/revision.h b/include/soc/imx/revision.h new file mode 100644 index 000000000000..9ea346924c35 --- /dev/null +++ b/include/soc/imx/revision.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Linaro Ltd. + * + * 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 __SOC_IMX_REVISION_H__ +#define __SOC_IMX_REVISION_H__ + +#define IMX_CHIP_REVISION_1_0 0x10 +#define IMX_CHIP_REVISION_1_1 0x11 +#define IMX_CHIP_REVISION_1_2 0x12 +#define IMX_CHIP_REVISION_1_3 0x13 +#define IMX_CHIP_REVISION_1_4 0x14 +#define IMX_CHIP_REVISION_1_5 0x15 +#define IMX_CHIP_REVISION_2_0 0x20 +#define IMX_CHIP_REVISION_2_1 0x21 +#define IMX_CHIP_REVISION_2_2 0x22 +#define IMX_CHIP_REVISION_2_3 0x23 +#define IMX_CHIP_REVISION_3_0 0x30 +#define IMX_CHIP_REVISION_3_1 0x31 +#define IMX_CHIP_REVISION_3_2 0x32 +#define IMX_CHIP_REVISION_3_3 0x33 +#define IMX_CHIP_REVISION_UNKNOWN 0xff + +int mx27_revision(void); +int mx31_revision(void); +int mx35_revision(void); +int mx51_revision(void); +int mx53_revision(void); + +unsigned int imx_get_soc_revision(void); +void imx_print_silicon_rev(const char *cpu, int srev); + +#endif /* __SOC_IMX_REVISION_H__ */ diff --git a/include/soc/imx/timer.h b/include/soc/imx/timer.h new file mode 100644 index 000000000000..bbbafd65f464 --- /dev/null +++ b/include/soc/imx/timer.h @@ -0,0 +1,26 @@ +/* + * Copyright 2015 Linaro Ltd. + * + * 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 __SOC_IMX_TIMER_H__ +#define __SOC_IMX_TIMER_H__ + +enum imx_gpt_type { + GPT_TYPE_IMX1, /* i.MX1 */ + GPT_TYPE_IMX21, /* i.MX21/27 */ + GPT_TYPE_IMX31, /* i.MX31/35/25/37/51/6Q */ + GPT_TYPE_IMX6DL, /* i.MX6DL/SX/SL */ +}; + +/* + * This is a stop-gap solution for clock drivers like imx1/imx21 which call + * mxc_timer_init() to initialize timer for non-DT boot. It can be removed + * when these legacy non-DT support is converted or dropped. + */ +void mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type); + +#endif /* __SOC_IMX_TIMER_H__ */ 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); diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index e9b4cb0cd7ed..1e5ac4e776da 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -331,6 +331,9 @@ * Extra serial register definitions for the internal UARTs * in TI OMAP processors. */ +#define OMAP1_UART1_BASE 0xfffb0000 +#define OMAP1_UART2_BASE 0xfffb0800 +#define OMAP1_UART3_BASE 0xfffb9800 #define UART_OMAP_MDR1 0x08 /* Mode definition register */ #define UART_OMAP_MDR2 0x09 /* Mode definition register 2 */ #define UART_OMAP_SCR 0x10 /* Supplementary control register */ diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index eb9a4ea394ab..2456fe89719c 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -876,6 +876,34 @@ void irq_cpu_offline(void) #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY /** + * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if + * NULL) + * @data: Pointer to interrupt specific data + */ +void irq_chip_enable_parent(struct irq_data *data) +{ + data = data->parent_data; + if (data->chip->irq_enable) + data->chip->irq_enable(data); + else + data->chip->irq_unmask(data); +} + +/** + * irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if + * NULL) + * @data: Pointer to interrupt specific data + */ +void irq_chip_disable_parent(struct irq_data *data) +{ + data = data->parent_data; + if (data->chip->irq_disable) + data->chip->irq_disable(data); + else + data->chip->irq_mask(data); +} + +/** * irq_chip_ack_parent - Acknowledge the parent interrupt * @data: Pointer to interrupt specific data */ diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index 61024e8abdef..15b370daf234 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c @@ -360,7 +360,7 @@ static struct lock_class_key irq_nested_lock_class; int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw_irq) { - struct irq_data *data = irq_get_irq_data(virq); + struct irq_data *data = irq_domain_get_irq_data(d, virq); struct irq_domain_chip_generic *dgc = d->gc; struct irq_chip_generic *gc; struct irq_chip_type *ct; @@ -405,8 +405,7 @@ int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, else data->mask = 1 << idx; - irq_set_chip_and_handler(virq, chip, ct->handler); - irq_set_chip_data(virq, gc); + irq_domain_set_info(d, virq, hw_irq, chip, gc, ct->handler, NULL, NULL); irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set); return 0; } diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 7fac311057b8..41bf6dc49f59 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1232,6 +1232,27 @@ struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, return (irq_data && irq_data->domain == domain) ? irq_data : NULL; } +/** + * irq_domain_set_info - Set the complete data for a @virq in @domain + * @domain: Interrupt domain to match + * @virq: IRQ number + * @hwirq: The hardware interrupt number + * @chip: The associated interrupt chip + * @chip_data: The associated interrupt chip data + * @handler: The interrupt flow handler + * @handler_data: The interrupt flow handler data + * @handler_name: The interrupt handler name + */ +void irq_domain_set_info(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq, struct irq_chip *chip, + void *chip_data, irq_flow_handler_t handler, + void *handler_data, const char *handler_name) +{ + irq_set_chip_and_handler_name(virq, chip, handler, handler_name); + irq_set_chip_data(virq, chip_data); + irq_set_handler_data(virq, handler_data); +} + static void irq_domain_check_hierarchy(struct irq_domain *domain) { } |