Commit 994c0e99 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next/soc' of git://git.linaro.org/people/arnd/arm-soc

* 'next/soc' of git://git.linaro.org/people/arnd/arm-soc: (21 commits)
  MAINTAINERS: add ARM/FREESCALE IMX6 entry
  arm/imx: merge i.MX3 and i.MX6
  arm/imx6q: add suspend/resume support
  arm/imx6q: add device tree machine support
  arm/imx6q: add smp and cpu hotplug support
  arm/imx6q: add core drivers clock, gpc, mmdc and src
  arm/imx: add gic_handle_irq function
  arm/imx6q: add core definitions and low-level debug uart
  arm/imx6q: add device tree source
  ARM: highbank: add suspend support
  ARM: highbank: Add cpu hotplug support
  ARM: highbank: add SMP support
  MAINTAINERS: add Calxeda Highbank ARM platform
  ARM: add Highbank core platform support
  ARM: highbank: add devicetree source
  ARM: l2x0: add empty l2x0_of_init
  picoxcell: add a definition of VMALLOC_END
  picoxcell: remove custom ioremap implementation
  picoxcell: add the DTS for the PC7302 board
  picoxcell: add the DTS for pc3x2 and pc3x3 devices
  ...

Fix up trivial conflicts in arch/arm/Kconfig, and some more header file
conflicts in arch/arm/mach-omap2/board-generic.c (as per an ealier merge
by Arnd).
parents 367069f1 abc3f126
Calxeda Highbank Platforms Device Tree Bindings
-----------------------------------------------
Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
properties.
Required root node properties:
- compatible = "calxeda,highbank";
Freescale i.MX Platforms Device Tree Bindings
-----------------------------------------------
i.MX51 Babbage Board i.MX51 Babbage Board
Required root node properties: Required root node properties:
- compatible = "fsl,imx51-babbage", "fsl,imx51"; - compatible = "fsl,imx51-babbage", "fsl,imx51";
...@@ -17,3 +20,7 @@ Required root node properties: ...@@ -17,3 +20,7 @@ Required root node properties:
i.MX53 Smart Mobile Reference Design Board i.MX53 Smart Mobile Reference Design Board
Required root node properties: Required root node properties:
- compatible = "fsl,imx53-smd", "fsl,imx53"; - compatible = "fsl,imx53-smd", "fsl,imx53";
i.MX6 Quad SABRE Automotive Board
Required root node properties:
- compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
Picochip picoXcell device tree bindings.
========================================
Required root node properties:
- compatible:
- "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device.
- "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device.
- "picochip,pc3x3" : picoXcell PC3X3 device based board.
- "picochip,pc3x2" : picoXcell PC3X2 device based board.
Timers required properties:
- compatible = "picochip,pc3x2-timer"
- interrupts : The single IRQ line for the timer.
- clock-freq : The frequency in HZ of the timer.
- reg : The register bank for the timer.
Note: two timers are required - one for the scheduler clock and one for the
event tick/NOHZ.
VIC required properties:
- compatible = "arm,pl192-vic".
- interrupt-controller.
- reg : The register bank for the device.
- #interrupt-cells : Must be 1.
...@@ -692,6 +692,12 @@ F: drivers/mtd/nand/bcm_umi_nand.c ...@@ -692,6 +692,12 @@ F: drivers/mtd/nand/bcm_umi_nand.c
F: drivers/mtd/nand/bcm_umi_bch.c F: drivers/mtd/nand/bcm_umi_bch.c
F: drivers/mtd/nand/nand_bcm_umi.h F: drivers/mtd/nand/nand_bcm_umi.h
ARM/CALXEDA HIGHBANK ARCHITECTURE
M: Rob Herring <rob.herring@calxeda.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-highbank/
ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT
M: Anton Vorontsov <avorontsov@mvista.com> M: Anton Vorontsov <avorontsov@mvista.com>
S: Maintained S: Maintained
...@@ -791,6 +797,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) ...@@ -791,6 +797,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-mx5/ F: arch/arm/mach-mx5/
ARM/FREESCALE IMX6
M: Shawn Guo <shawn.guo@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.linaro.org/people/shawnguo/linux-2.6.git
F: arch/arm/mach-imx/*imx6*
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org> M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
......
...@@ -334,6 +334,20 @@ config ARCH_BCMRING ...@@ -334,6 +334,20 @@ config ARCH_BCMRING
help help
Support for Broadcom's BCMRing platform. Support for Broadcom's BCMRing platform.
config ARCH_HIGHBANK
bool "Calxeda Highbank-based"
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARM_AMBA
select ARM_GIC
select ARM_TIMER_SP804
select CLKDEV_LOOKUP
select CPU_V7
select GENERIC_CLOCKEVENTS
select HAVE_ARM_SCU
select USE_OF
help
Support for the Calxeda Highbank SoC based boards.
config ARCH_CLPS711X config ARCH_CLPS711X
bool "Cirrus Logic CLPS711x/EP721x-based" bool "Cirrus Logic CLPS711x/EP721x-based"
select CPU_ARM720T select CPU_ARM720T
...@@ -623,6 +637,24 @@ config ARCH_TEGRA ...@@ -623,6 +637,24 @@ config ARCH_TEGRA
This enables support for NVIDIA Tegra based systems (Tegra APX, This enables support for NVIDIA Tegra based systems (Tegra APX,
Tegra 6xx and Tegra 2 series). Tegra 6xx and Tegra 2 series).
config ARCH_PICOXCELL
bool "Picochip picoXcell"
select ARCH_REQUIRE_GPIOLIB
select ARM_PATCH_PHYS_VIRT
select ARM_VIC
select CPU_V6K
select DW_APB_TIMER
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
select HAVE_SCHED_CLOCK
select HAVE_TCM
select NO_IOPORT
select USE_OF
help
This enables support for systems based on the Picochip picoXcell
family of Femtocell devices. The picoxcell support requires device tree
for all boards.
config ARCH_PNX4008 config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile" bool "Philips Nexperia PNX4008 Mobile"
select CPU_ARM926T select CPU_ARM926T
...@@ -1398,7 +1430,7 @@ config SMP ...@@ -1398,7 +1430,7 @@ config SMP
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q
depends on MMU depends on MMU
select USE_GENERIC_SMP_HELPERS select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
......
...@@ -128,6 +128,13 @@ choice ...@@ -128,6 +128,13 @@ choice
Say Y here if you want the debug print routines to direct Say Y here if you want the debug print routines to direct
their output to the second serial port on these devices. their output to the second serial port on these devices.
config DEBUG_HIGHBANK_UART
bool "Kernel low-level debugging messages via Highbank UART"
depends on ARCH_HIGHBANK
help
Say Y here if you want the debug print routines to direct
their output to the UART on Highbank based devices.
config DEBUG_IMX1_UART config DEBUG_IMX1_UART
bool "i.MX1 Debug UART" bool "i.MX1 Debug UART"
depends on SOC_IMX1 depends on SOC_IMX1
...@@ -184,6 +191,13 @@ choice ...@@ -184,6 +191,13 @@ choice
Say Y here if you want kernel low-level debugging support Say Y here if you want kernel low-level debugging support
on i.MX50 or i.MX53. on i.MX50 or i.MX53.
config DEBUG_IMX6Q_UART
bool "i.MX6Q Debug UART"
depends on SOC_IMX6Q
help
Say Y here if you want kernel low-level debugging support
on i.MX6Q.
config DEBUG_S3C_UART0 config DEBUG_S3C_UART0
depends on PLAT_SAMSUNG depends on PLAT_SAMSUNG
bool "Use S3C UART 0 for low-level debug" bool "Use S3C UART 0 for low-level debug"
......
...@@ -144,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110) := ebsa110 ...@@ -144,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110) := ebsa110
machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_GEMINI) := gemini machine-$(CONFIG_ARCH_GEMINI) := gemini
machine-$(CONFIG_ARCH_H720X) := h720x machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_HIGHBANK) := highbank
machine-$(CONFIG_ARCH_INTEGRATOR) := integrator machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
machine-$(CONFIG_ARCH_IOP13XX) := iop13xx machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
machine-$(CONFIG_ARCH_IOP32X) := iop32x machine-$(CONFIG_ARCH_IOP32X) := iop32x
...@@ -158,7 +159,7 @@ machine-$(CONFIG_ARCH_MMP) := mmp ...@@ -158,7 +159,7 @@ machine-$(CONFIG_ARCH_MMP) := mmp
machine-$(CONFIG_ARCH_MSM) := msm machine-$(CONFIG_ARCH_MSM) := msm
machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0 machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
machine-$(CONFIG_ARCH_IMX_V4_V5) := imx machine-$(CONFIG_ARCH_IMX_V4_V5) := imx
machine-$(CONFIG_ARCH_MX3) := imx machine-$(CONFIG_ARCH_IMX_V6_V7) := imx
machine-$(CONFIG_ARCH_MX5) := mx5 machine-$(CONFIG_ARCH_MX5) := mx5
machine-$(CONFIG_ARCH_MXS) := mxs machine-$(CONFIG_ARCH_MXS) := mxs
machine-$(CONFIG_ARCH_NETX) := netx machine-$(CONFIG_ARCH_NETX) := netx
...@@ -168,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2) := omap2 ...@@ -168,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2) := omap2
machine-$(CONFIG_ARCH_OMAP3) := omap2 machine-$(CONFIG_ARCH_OMAP3) := omap2
machine-$(CONFIG_ARCH_OMAP4) := omap2 machine-$(CONFIG_ARCH_OMAP4) := omap2
machine-$(CONFIG_ARCH_ORION5X) := orion5x machine-$(CONFIG_ARCH_ORION5X) := orion5x
machine-$(CONFIG_ARCH_PICOXCELL) := picoxcell
machine-$(CONFIG_ARCH_PNX4008) := pnx4008 machine-$(CONFIG_ARCH_PNX4008) := pnx4008
machine-$(CONFIG_ARCH_PRIMA2) := prima2 machine-$(CONFIG_ARCH_PRIMA2) := prima2
machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_PXA) := pxa
......
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/>.
*/
/dts-v1/;
/* First 4KB has pen for secondary cores. */
/memreserve/ 0x00000000 0x0001000;
/ {
model = "Calxeda Highbank";
compatible = "calxeda,highbank";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
next-level-cache = <&L2>;
};
cpu@2 {
compatible = "arm,cortex-a9";
reg = <2>;
next-level-cache = <&L2>;
};
cpu@3 {
compatible = "arm,cortex-a9";
reg = <3>;
next-level-cache = <&L2>;
};
};
memory {
name = "memory";
device_type = "memory";
reg = <0x00000000 0xff900000>;
};
chosen {
bootargs = "console=ttyAMA0";
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
interrupt-parent = <&intc>;
ranges;
timer@fff10600 {
compatible = "arm,smp-twd";
reg = <0xfff10600 0x20>;
interrupts = <1 13 0xf04>;
};
watchdog@fff10620 {
compatible = "arm,cortex-a9-wdt";
reg = <0xfff10620 0x20>;
interrupts = <1 14 0xf04>;
};
intc: interrupt-controller@fff11000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#size-cells = <0>;
#address-cells = <1>;
interrupt-controller;
interrupt-parent;
reg = <0xfff11000 0x1000>,
<0xfff10100 0x100>;
};
L2: l2-cache {
compatible = "arm,pl310-cache";
reg = <0xfff12000 0x1000>;
interrupts = <0 70 4>;
cache-unified;
cache-level = <2>;
};
pmu {
compatible = "arm,cortex-a9-pmu";
interrupts = <0 76 4 0 75 4 0 74 4 0 73 4>;
};
sata@ffe08000 {
compatible = "calxeda,hb-ahci";
reg = <0xffe08000 0x10000>;
interrupts = <0 83 4>;
};
sdhci@ffe0e000 {
compatible = "calxeda,hb-sdhci";
reg = <0xffe0e000 0x1000>;
interrupts = <0 90 4>;
};
ipc@fff20000 {
compatible = "arm,pl320", "arm,primecell";
reg = <0xfff20000 0x1000>;
interrupts = <0 7 4>;
};
gpioe: gpio@fff30000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xfff30000 0x1000>;
interrupts = <0 14 4>;
};
gpiof: gpio@fff31000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xfff31000 0x1000>;
interrupts = <0 15 4>;
};
gpiog: gpio@fff32000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xfff32000 0x1000>;
interrupts = <0 16 4>;
};
gpioh: gpio@fff33000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xfff33000 0x1000>;
interrupts = <0 17 4>;
};
timer {
compatible = "arm,sp804", "arm,primecell";
reg = <0xfff34000 0x1000>;
interrupts = <0 18 4>;
};
rtc@fff35000 {
compatible = "arm,pl031", "arm,primecell";
reg = <0xfff35000 0x1000>;
interrupts = <0 19 4>;
};
serial@fff36000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xfff36000 0x1000>;
interrupts = <0 20 4>;
};
smic@fff3a000 {
compatible = "ipmi-smic";
device_type = "ipmi";
reg = <0xfff3a000 0x1000>;
interrupts = <0 24 4>;
reg-size = <4>;
reg-spacing = <4>;
};
sregs@fff3c000 {
compatible = "calxeda,hb-sregs";
reg = <0xfff3c000 0x1000>;
};
dma@fff3d000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0xfff3d000 0x1000>;
interrupts = <0 92 4>;
};
};
};
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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
*/
/dts-v1/;
/include/ "imx6q.dtsi"
/ {
model = "Freescale i.MX6 Quad SABRE Automotive Board";
compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
chosen {
bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
};
memory {
reg = <0x10000000 0x80000000>;
};
soc {
aips-bus@02100000 { /* AIPS2 */
enet@02188000 {
phy-mode = "rgmii";
local-mac-address = [00 04 9F 01 1B 61];
status = "okay";
};
usdhc@02198000 { /* uSDHC3 */
cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
status = "okay";
};
usdhc@0219c000 { /* uSDHC4 */
fsl,card-wired;
status = "okay";
};
uart3: uart@021f0000 { /* UART4 */
status = "okay";
};
};
};
leds {
compatible = "gpio-leds";
debug-led {
label = "Heartbeat";
gpios = <&gpio2 25 0>; /* GPIO3_25 */
linux,default-trigger = "heartbeat";
};
};
};
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/ "skeleton.dtsi"
/ {
aliases {
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
next-level-cache = <&L2>;
};
cpu@2 {
compatible = "arm,cortex-a9";
reg = <2>;
next-level-cache = <&L2>;
};
cpu@3 {
compatible = "arm,cortex-a9";
reg = <3>;
next-level-cache = <&L2>;
};
};
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
reg = <0x00a01000 0x1000>,
<0x00a00100 0x100>;
};
clocks {
#address-cells = <1>;
#size-cells = <0>;
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
clock-frequency = <32768>;
};
ckih1 {
compatible = "fsl,imx-ckih1", "fixed-clock";
clock-frequency = <0>;
};
osc {
compatible = "fsl,imx-osc", "fixed-clock";
clock-frequency = <24000000>;
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
interrupt-parent = <&intc>;
ranges;
timer@00a00600 {
compatible = "arm,smp-twd";
reg = <0x00a00600 0x100>;
interrupts = <1 13 0xf4>;
};
L2: l2-cache@00a02000 {
compatible = "arm,pl310-cache";
reg = <0x00a02000 0x1000>;
interrupts = <0 92 0x04>;
cache-unified;
cache-level = <2>;
};
aips-bus@02000000 { /* AIPS1 */
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x02000000 0x100000>;
ranges;
spba-bus@02000000 {
compatible = "fsl,spba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x02000000 0x40000>;
ranges;
spdif@02004000 {
reg = <0x02004000 0x4000>;
interrupts = <0 52 0x04>;
};
ecspi@02008000 { /* eCSPI1 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <0 31 0x04>;
status = "disabled";
};
ecspi@0200c000 { /* eCSPI2 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <0 32 0x04>;
status = "disabled";
};
ecspi@02010000 { /* eCSPI3 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <0 33 0x04>;
status = "disabled";
};
ecspi@02014000 { /* eCSPI4 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <0 34 0x04>;
status = "disabled";
};
ecspi@02018000 { /* eCSPI5 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02018000 0x4000>;
interrupts = <0 35 0x04>;
status = "disabled";
};
uart0: uart@02020000 { /* UART1 */
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <0 26 0x04>;
status = "disabled";
};
esai@02024000 {
reg = <0x02024000 0x4000>;
interrupts = <0 51 0x04>;
};
ssi@02028000 { /* SSI1 */
reg = <0x02028000 0x4000>;
interrupts = <0 46 0x04>;
};
ssi@0202c000 { /* SSI2 */
reg = <0x0202c000 0x4000>;
interrupts = <0 47 0x04>;
};
ssi@02030000 { /* SSI3 */
reg = <0x02030000 0x4000>;
interrupts = <0 48 0x04>;
};
asrc@02034000 {
reg = <0x02034000 0x4000>;
interrupts = <0 50 0x04>;
};
spba@0203c000 {
reg = <0x0203c000 0x4000>;
};
};
vpu@02040000 {
reg = <0x02040000 0x3c000>;
interrupts = <0 3 0x04 0 12 0x04>;
};
aipstz@0207c000 { /* AIPSTZ1 */
reg = <0x0207c000 0x4000>;
};
pwm@02080000 { /* PWM1 */
reg = <0x02080000 0x4000>;
interrupts = <0 83 0x04>;
};
pwm@02084000 { /* PWM2 */
reg = <0x02084000 0x4000>;
interrupts = <0 84 0x04>;
};
pwm@02088000 { /* PWM3 */
reg = <0x02088000 0x4000>;
interrupts = <0 85 0x04>;
};
pwm@0208c000 { /* PWM4 */
reg = <0x0208c000 0x4000>;
interrupts = <0 86 0x04>;
};
flexcan@02090000 { /* CAN1 */
reg = <0x02090000 0x4000>;
interrupts = <0 110 0x04>;
};
flexcan@02094000 { /* CAN2 */
reg = <0x02094000 0x4000>;
interrupts = <0 111 0x04>;
};
gpt@02098000 {
compatible = "fsl,imx6q-gpt";
reg = <0x02098000 0x4000>;
interrupts = <0 55 0x04>;
};
gpio0: gpio@0209c000 { /* GPIO1 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x0209c000 0x4000>;
interrupts = <0 66 0x04 0 67 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio1: gpio@020a0000 { /* GPIO2 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020a0000 0x4000>;
interrupts = <0 68 0x04 0 69 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio2: gpio@020a4000 { /* GPIO3 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020a4000 0x4000>;
interrupts = <0 70 0x04 0 71 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio3: gpio@020a8000 { /* GPIO4 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020a8000 0x4000>;
interrupts = <0 72 0x04 0 73 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio4: gpio@020ac000 { /* GPIO5 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020ac000 0x4000>;
interrupts = <0 74 0x04 0 75 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio5: gpio@020b0000 { /* GPIO6 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020b0000 0x4000>;
interrupts = <0 76 0x04 0 77 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
gpio6: gpio@020b4000 { /* GPIO7 */
compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
reg = <0x020b4000 0x4000>;
interrupts = <0 78 0x04 0 79 0x04>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
};
kpp@020b8000 {
reg = <0x020b8000 0x4000>;
interrupts = <0 82 0x04>;
};
wdog@020bc000 { /* WDOG1 */
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020bc000 0x4000>;
interrupts = <0 80 0x04>;
status = "disabled";
};
wdog@020c0000 { /* WDOG2 */
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020c0000 0x4000>;
interrupts = <0 81 0x04>;
status = "disabled";
};
ccm@020c4000 {
compatible = "fsl,imx6q-ccm";
reg = <0x020c4000 0x4000>;
interrupts = <0 87 0x04 0 88 0x04>;
};
anatop@020c8000 {
compatible = "fsl,imx6q-anatop";
reg = <0x020c8000 0x1000>;
interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
};
usbphy@020c9000 { /* USBPHY1 */
reg = <0x020c9000 0x1000>;
interrupts = <0 44 0x04>;
};
usbphy@020ca000 { /* USBPHY2 */
reg = <0x020ca000 0x1000>;
interrupts = <0 45 0x04>;
};
snvs@020cc000 {
reg = <0x020cc000 0x4000>;
interrupts = <0 19 0x04 0 20 0x04>;
};
epit@020d0000 { /* EPIT1 */
reg = <0x020d0000 0x4000>;
interrupts = <0 56 0x04>;
};
epit@020d4000 { /* EPIT2 */
reg = <0x020d4000 0x4000>;
interrupts = <0 57 0x04>;
};
src@020d8000 {
compatible = "fsl,imx6q-src";
reg = <0x020d8000 0x4000>;
interrupts = <0 91 0x04 0 96 0x04>;
};
gpc@020dc000 {
compatible = "fsl,imx6q-gpc";
reg = <0x020dc000 0x4000>;
interrupts = <0 89 0x04 0 90 0x04>;
};
iomuxc@020e0000 {
reg = <0x020e0000 0x4000>;
};
dcic@020e4000 { /* DCIC1 */
reg = <0x020e4000 0x4000>;
interrupts = <0 124 0x04>;
};
dcic@020e8000 { /* DCIC2 */
reg = <0x020e8000 0x4000>;
interrupts = <0 125 0x04>;
};
sdma@020ec000 {
compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <0 2 0x04>;
};
};
aips-bus@02100000 { /* AIPS2 */
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x02100000 0x100000>;
ranges;
caam@02100000 {
reg = <0x02100000 0x40000>;
interrupts = <0 105 0x04 0 106 0x04>;
};
aipstz@0217c000 { /* AIPSTZ2 */
reg = <0x0217c000 0x4000>;
};
enet@02188000 {
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupts = <0 118 0x04 0 119 0x04>;
status = "disabled";
};
mlb@0218c000 {
reg = <0x0218c000 0x4000>;
interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
};
usdhc@02190000 { /* uSDHC1 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <0 22 0x04>;
status = "disabled";
};
usdhc@02194000 { /* uSDHC2 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <0 23 0x04>;
status = "disabled";
};
usdhc@02198000 { /* uSDHC3 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
status = "disabled";
};
usdhc@0219c000 { /* uSDHC4 */
compatible = "fsl,imx6q-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <0 25 0x04>;
status = "disabled";
};
i2c@021a0000 { /* I2C1 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <0 36 0x04>;
status = "disabled";
};
i2c@021a4000 { /* I2C2 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
reg = <0x021a4000 0x4000>;
interrupts = <0 37 0x04>;
status = "disabled";
};
i2c@021a8000 { /* I2C3 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
reg = <0x021a8000 0x4000>;
interrupts = <0 38 0x04>;
status = "disabled";
};
romcp@021ac000 {
reg = <0x021ac000 0x4000>;
};
mmdc@021b0000 { /* MMDC0 */
compatible = "fsl,imx6q-mmdc";
reg = <0x021b0000 0x4000>;
};
mmdc@021b4000 { /* MMDC1 */
reg = <0x021b4000 0x4000>;
};
weim@021b8000 {
reg = <0x021b8000 0x4000>;
interrupts = <0 14 0x04>;
};
ocotp@021bc000 {
reg = <0x021bc000 0x4000>;
};
ocotp@021c0000 {
reg = <0x021c0000 0x4000>;
interrupts = <0 21 0x04>;
};
tzasc@021d0000 { /* TZASC1 */
reg = <0x021d0000 0x4000>;
interrupts = <0 108 0x04>;
};
tzasc@021d4000 { /* TZASC2 */
reg = <0x021d4000 0x4000>;
interrupts = <0 109 0x04>;
};
audmux@021d8000 {
reg = <0x021d8000 0x4000>;
};
mipi@021dc000 { /* MIPI-CSI */
reg = <0x021dc000 0x4000>;
};
mipi@021e0000 { /* MIPI-DSI */
reg = <0x021e0000 0x4000>;
};
vdoa@021e4000 {
reg = <0x021e4000 0x4000>;
interrupts = <0 18 0x04>;
};
uart1: uart@021e8000 { /* UART2 */
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <0 27 0x04>;
status = "disabled";
};
uart2: uart@021ec000 { /* UART3 */
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021ec000 0x4000>;
interrupts = <0 28 0x04>;
status = "disabled";
};
uart3: uart@021f0000 { /* UART4 */
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f0000 0x4000>;
interrupts = <0 29 0x04>;
status = "disabled";
};
uart4: uart@021f4000 { /* UART5 */
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
interrupts = <0 30 0x04>;
status = "disabled";
};
};
};
};
/*
* Copyright (C) 2011 Picochip, Jamie Iles
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/ "skeleton.dtsi"
/ {
model = "Picochip picoXcell PC3X2";
compatible = "picochip,pc3x2";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,1176jz-s";
clock-frequency = <400000000>;
reg = <0>;
d-cache-line-size = <32>;
d-cache-size = <32768>;
i-cache-line-size = <32>;
i-cache-size = <32768>;
};
};
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
pclk: clock@0 {
compatible = "fixed-clock";
clock-outputs = "bus", "pclk";
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
};
paxi {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x80000000 0x400000>;
emac: gem@30000 {
compatible = "cadence,gem";
reg = <0x30000 0x10000>;
interrupts = <31>;
};
dmac1: dmac@40000 {
compatible = "snps,dw-dmac";
reg = <0x40000 0x10000>;
interrupts = <25>;
};
dmac2: dmac@50000 {
compatible = "snps,dw-dmac";
reg = <0x50000 0x10000>;
interrupts = <26>;
};
vic0: interrupt-controller@60000 {
compatible = "arm,pl192-vic";
interrupt-controller;
reg = <0x60000 0x1000>;
#interrupt-cells = <1>;
};
vic1: interrupt-controller@64000 {
compatible = "arm,pl192-vic";
interrupt-controller;
reg = <0x64000 0x1000>;
#interrupt-cells = <1>;
};
fuse: picoxcell-fuse@80000 {
compatible = "picoxcell,fuse-pc3x2";
reg = <0x80000 0x10000>;
};
ssi: picoxcell-spi@90000 {
compatible = "picoxcell,spi";
reg = <0x90000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <10>;
};
ipsec: spacc@100000 {
compatible = "picochip,spacc-ipsec";
reg = <0x100000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <24>;
ref-clock = <&pclk>, "ref";
};
srtp: spacc@140000 {
compatible = "picochip,spacc-srtp";
reg = <0x140000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <23>;
};
l2_engine: spacc@180000 {
compatible = "picochip,spacc-l2";
reg = <0x180000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <22>;
ref-clock = <&pclk>, "ref";
};
apb {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x200000 0x80000>;
rtc0: rtc@00000 {
compatible = "picochip,pc3x2-rtc";
clock-freq = <200000000>;
reg = <0x00000 0xf>;
interrupt-parent = <&vic1>;
interrupts = <8>;
};
timer0: timer@10000 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <4>;
clock-freq = <200000000>;
reg = <0x10000 0x14>;
};
timer1: timer@10014 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <5>;
clock-freq = <200000000>;
reg = <0x10014 0x14>;
};
timer2: timer@10028 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <6>;
clock-freq = <200000000>;
reg = <0x10028 0x14>;
};
timer3: timer@1003c {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <7>;
clock-freq = <200000000>;
reg = <0x1003c 0x14>;
};
gpio: gpio@20000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
reg-io-width = <4>;
banka: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
gpio-generic,nr-gpio = <8>;
regoffset-dat = <0x50>;
regoffset-set = <0x00>;
regoffset-dirout = <0x04>;
};
bankb: gpio-controller@1 {
compatible = "snps,dw-apb-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
gpio-generic,nr-gpio = <8>;
regoffset-dat = <0x54>;
regoffset-set = <0x0c>;
regoffset-dirout = <0x10>;
};
};
uart0: uart@30000 {
compatible = "snps,dw-apb-uart";
reg = <0x30000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <10>;
clock-frequency = <3686400>;
reg-shift = <2>;
reg-io-width = <4>;
};
uart1: uart@40000 {
compatible = "snps,dw-apb-uart";
reg = <0x40000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <9>;
clock-frequency = <3686400>;
reg-shift = <2>;
reg-io-width = <4>;
};
wdog: watchdog@50000 {
compatible = "snps,dw-apb-wdg";
reg = <0x50000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <11>;
bus-clock = <&pclk>, "bus";
};
};
};
rwid-axi {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
ebi@50000000 {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x40000000 0x08000000
1 0 0x48000000 0x08000000
2 0 0x50000000 0x08000000
3 0 0x58000000 0x08000000>;
};
axi2pico@c0000000 {
compatible = "picochip,axi2pico-pc3x2";
reg = <0xc0000000 0x10000>;
interrupts = <13 14 15 16 17 18 19 20 21>;
};
};
};
/*
* Copyright (C) 2011 Picochip, Jamie Iles
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/ "skeleton.dtsi"
/ {
model = "Picochip picoXcell PC3X3";
compatible = "picochip,pc3x3";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,1176jz-s";
cpu-clock = <&arm_clk>, "cpu";
reg = <0>;
d-cache-line-size = <32>;
d-cache-size = <32768>;
i-cache-line-size = <32>;
i-cache-size = <32768>;
};
};
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
clkgate: clkgate@800a0048 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x800a0048 4>;
compatible = "picochip,pc3x3-clk-gate";
tzprot_clk: clock@0 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <0>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
spi_clk: clock@1 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <1>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
dmac0_clk: clock@2 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <2>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
dmac1_clk: clock@3 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <3>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
ebi_clk: clock@4 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <4>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
ipsec_clk: clock@5 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <5>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
l2_clk: clock@6 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <6>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
trng_clk: clock@7 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <7>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
fuse_clk: clock@8 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <8>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
otp_clk: clock@9 {
compatible = "picochip,pc3x3-gated-clk";
clock-outputs = "bus";
picochip,clk-disable-bit = <9>;
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
};
arm_clk: clock@11 {
compatible = "picochip,pc3x3-pll";
reg = <0x800a0050 0x8>;
picochip,min-freq = <140000000>;
picochip,max-freq = <700000000>;
ref-clock = <&ref_clk>, "ref";
clock-outputs = "cpu";
};
pclk: clock@12 {
compatible = "fixed-clock";
clock-outputs = "bus", "pclk";
clock-frequency = <200000000>;
ref-clock = <&ref_clk>, "ref";
};
};
paxi {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x80000000 0x400000>;
emac: gem@30000 {
compatible = "cadence,gem";
reg = <0x30000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <31>;
};
dmac1: dmac@40000 {
compatible = "snps,dw-dmac";
reg = <0x40000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <25>;
};
dmac2: dmac@50000 {
compatible = "snps,dw-dmac";
reg = <0x50000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <26>;
};
vic0: interrupt-controller@60000 {
compatible = "arm,pl192-vic";
interrupt-controller;
reg = <0x60000 0x1000>;
#interrupt-cells = <1>;
};
vic1: interrupt-controller@64000 {
compatible = "arm,pl192-vic";
interrupt-controller;
reg = <0x64000 0x1000>;
#interrupt-cells = <1>;
};
fuse: picoxcell-fuse@80000 {
compatible = "picoxcell,fuse-pc3x3";
reg = <0x80000 0x10000>;
};
ssi: picoxcell-spi@90000 {
compatible = "picoxcell,spi";
reg = <0x90000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <10>;
};
ipsec: spacc@100000 {
compatible = "picochip,spacc-ipsec";
reg = <0x100000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <24>;
ref-clock = <&ipsec_clk>, "ref";
};
srtp: spacc@140000 {
compatible = "picochip,spacc-srtp";
reg = <0x140000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <23>;
};
l2_engine: spacc@180000 {
compatible = "picochip,spacc-l2";
reg = <0x180000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <22>;
ref-clock = <&l2_clk>, "ref";
};
apb {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x200000 0x80000>;
rtc0: rtc@00000 {
compatible = "picochip,pc3x2-rtc";
clock-freq = <200000000>;
reg = <0x00000 0xf>;
interrupt-parent = <&vic0>;
interrupts = <8>;
};
timer0: timer@10000 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <4>;
clock-freq = <200000000>;
reg = <0x10000 0x14>;
};
timer1: timer@10014 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <5>;
clock-freq = <200000000>;
reg = <0x10014 0x14>;
};
gpio: gpio@20000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
reg-io-width = <4>;
banka: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
gpio-generic,nr-gpio = <8>;
regoffset-dat = <0x50>;
regoffset-set = <0x00>;
regoffset-dirout = <0x04>;
};
bankb: gpio-controller@1 {
compatible = "snps,dw-apb-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
gpio-generic,nr-gpio = <16>;
regoffset-dat = <0x54>;
regoffset-set = <0x0c>;
regoffset-dirout = <0x10>;
};
bankd: gpio-controller@2 {
compatible = "snps,dw-apb-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
gpio-generic,nr-gpio = <30>;
regoffset-dat = <0x5c>;
regoffset-set = <0x24>;
regoffset-dirout = <0x28>;
};
};
uart0: uart@30000 {
compatible = "snps,dw-apb-uart";
reg = <0x30000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <10>;
clock-frequency = <3686400>;
reg-shift = <2>;
reg-io-width = <4>;
};
uart1: uart@40000 {
compatible = "snps,dw-apb-uart";
reg = <0x40000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <9>;
clock-frequency = <3686400>;
reg-shift = <2>;
reg-io-width = <4>;
};
wdog: watchdog@50000 {
compatible = "snps,dw-apb-wdg";
reg = <0x50000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <11>;
bus-clock = <&pclk>, "bus";
};
timer2: timer@60000 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <6>;
clock-freq = <200000000>;
reg = <0x60000 0x14>;
};
timer3: timer@60014 {
compatible = "picochip,pc3x2-timer";
interrupt-parent = <&vic0>;
interrupts = <7>;
clock-freq = <200000000>;
reg = <0x60014 0x14>;
};
};
};
rwid-axi {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
ebi@50000000 {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x40000000 0x08000000
1 0 0x48000000 0x08000000
2 0 0x50000000 0x08000000
3 0 0x58000000 0x08000000>;
};
axi2pico@c0000000 {
compatible = "picochip,axi2pico-pc3x3";
reg = <0xc0000000 0x10000>;
interrupt-parent = <&vic0>;
interrupts = <13 14 15 16 17 18 19 20 21>;
};
otp@ffff8000 {
compatible = "picochip,otp-pc3x3";
reg = <0xffff8000 0x8000>;
};
};
};
/*
* Copyright (C) 2011 Picochip, Jamie Iles
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
/dts-v1/;
/include/ "picoxcell-pc3x2.dtsi"
/ {
model = "Picochip PC7302 (PC3X2)";
compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
memory {
device_type = "memory";
reg = <0x0 0x08000000>;
};
chosen {
linux,stdout-path = &uart0;
};
clocks {
ref_clk: clock@1 {
compatible = "fixed-clock";
clock-outputs = "ref";
clock-frequency = <20000000>;
};
};
rwid-axi {
ebi@50000000 {
nand: gpio-nand@2,0 {
compatible = "gpio-control-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <2 0x0000 0x1000>;
bus-clock = <&pclk>, "bus";
gpio-control-nand,io-sync-reg =
<0x00000000 0x80220000>;
gpios = <&banka 1 0 /* rdy */
&banka 2 0 /* nce */
&banka 3 0 /* ale */
&banka 4 0 /* cle */
0 /* nwp */>;
boot@100000 {
label = "Boot";
reg = <0x100000 0x80000>;
};
redundant-boot@200000 {
label = "Redundant Boot";
reg = <0x200000 0x80000>;
};
boot-env@300000 {
label = "Boot Evironment";
reg = <0x300000 0x20000>;
};
redundant-boot-env@320000 {
label = "Redundant Boot Environment";
reg = <0x300000 0x20000>;
};
kernel@380000 {
label = "Kernel";
reg = <0x380000 0x800000>;
};
fs@b80000 {
label = "File System";
reg = <0xb80000 0xf480000>;
};
};
};
};
};
/*
* Copyright (C) 2011 Picochip, Jamie Iles
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
/dts-v1/;
/include/ "picoxcell-pc3x3.dtsi"
/ {
model = "Picochip PC7302 (PC3X3)";
compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
memory {
device_type = "memory";
reg = <0x0 0x08000000>;
};
chosen {
linux,stdout-path = &uart0;
};
clocks {
ref_clk: clock@10 {
compatible = "fixed-clock";
clock-outputs = "ref";
clock-frequency = <20000000>;
};
clkgate: clkgate@800a0048 {
clock@4 {
picochip,clk-no-disable;
};
};
};
rwid-axi {
ebi@50000000 {
nand: gpio-nand@2,0 {
compatible = "gpio-control-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <2 0x0000 0x1000>;
bus-clock = <&ebi_clk>, "bus";
gpio-control-nand,io-sync-reg =
<0x00000000 0x80220000>;
gpios = <&banka 1 0 /* rdy */
&banka 2 0 /* nce */
&banka 3 0 /* ale */
&banka 4 0 /* cle */
0 /* nwp */>;
boot@100000 {
label = "Boot";
reg = <0x100000 0x80000>;
};
redundant-boot@200000 {
label = "Redundant Boot";
reg = <0x200000 0x80000>;
};
boot-env@300000 {
label = "Boot Evironment";
reg = <0x300000 0x20000>;
};
redundant-boot-env@320000 {
label = "Redundant Boot Environment";
reg = <0x300000 0x20000>;
};
kernel@380000 {
label = "Kernel";
reg = <0x380000 0x800000>;
};
fs@b80000 {
label = "File System";
reg = <0xb80000 0xf480000>;
};
};
};
};
};
...@@ -102,7 +102,14 @@ ...@@ -102,7 +102,14 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask); extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
#else
static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
{
return -ENODEV;
}
#endif
struct l2x0_regs { struct l2x0_regs {
unsigned long phy_base; unsigned long phy_base;
...@@ -121,6 +128,6 @@ struct l2x0_regs { ...@@ -121,6 +128,6 @@ struct l2x0_regs {
extern struct l2x0_regs l2x0_saved_regs; extern struct l2x0_regs l2x0_saved_regs;
#endif #endif /* __ASSEMBLY__ */
#endif #endif
obj-y := clock.o highbank.o system.o
obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_PM_SLEEP) += pm.o
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
struct clk {
unsigned long rate;
};
int clk_enable(struct clk *clk)
{
return 0;
}
void clk_disable(struct clk *clk)
{}
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
long clk_round_rate(struct clk *clk, unsigned long rate)
{
return clk->rate;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
return 0;
}
static struct clk eclk = { .rate = 200000000 };
static struct clk pclk = { .rate = 150000000 };
static struct clk_lookup lookups[] = {
{ .clk = &pclk, .con_id = "apb_pclk", },
{ .clk = &pclk, .dev_id = "sp804", },
{ .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
{ .clk = &pclk, .dev_id = "fff36000.serial", },
};
void __init highbank_clocks_init(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
}
extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
extern void highbank_clocks_init(void);
extern void __iomem *scu_base_addr;
#ifdef CONFIG_DEBUG_HIGHBANK_UART
extern void highbank_lluart_map_io(void);
#else
static inline void highbank_lluart_map_io(void) {}
#endif
/*
* Copyright 2010-2011 Calxeda, Inc.
*
* 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/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <asm/cacheflush.h>
#include <asm/unified.h>
#include <asm/smp_scu.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/timer-sp.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <mach/irqs.h>
#include "core.h"
#include "sysregs.h"
void __iomem *sregs_base;
#define HB_SCU_VIRT_BASE 0xfee00000
void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
static struct map_desc scu_io_desc __initdata = {
.virtual = HB_SCU_VIRT_BASE,
.pfn = 0, /* run-time */
.length = SZ_4K,
.type = MT_DEVICE,
};
static void __init highbank_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 highbank_map_io(void)
{
highbank_scu_map_io();
highbank_lluart_map_io();
}
#define HB_JUMP_TABLE_PHYS(cpu) (0x40 + (0x10 * (cpu)))
#define HB_JUMP_TABLE_VIRT(cpu) phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
void highbank_set_cpu_jump(int cpu, void *jump_addr)
{
writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
HB_JUMP_TABLE_PHYS(cpu) + 15);
}
const static struct of_device_id irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{}
};
static void __init highbank_init_irq(void)
{
of_irq_init(irq_match);
l2x0_of_init(0, ~0UL);
}
static void __init highbank_timer_init(void)
{
int irq;
struct device_node *np;
void __iomem *timer_base;
/* Map system registers */
np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
sregs_base = of_iomap(np, 0);
WARN_ON(!sregs_base);
np = of_find_compatible_node(NULL, NULL, "arm,sp804");
timer_base = of_iomap(np, 0);
WARN_ON(!timer_base);
irq = irq_of_parse_and_map(np, 0);
highbank_clocks_init();
sp804_clocksource_init(timer_base + 0x20, "timer1");
sp804_clockevents_init(timer_base, irq, "timer0");
}
static struct sys_timer highbank_timer = {
.init = highbank_timer_init,
};
static void highbank_power_off(void)
{
hignbank_set_pwr_shutdown();
scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
while (1)
cpu_do_idle();
}
static void __init highbank_init(void)
{
pm_power_off = highbank_power_off;
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *highbank_match[] __initconst = {
"calxeda,highbank",
NULL,
};
DT_MACHINE_START(HIGHBANK, "Highbank")
.map_io = highbank_map_io,
.init_irq = highbank_init_irq,
.timer = &highbank_timer,
.init_machine = highbank_init,
.dt_compat = highbank_match,
MACHINE_END
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <asm/smp_scu.h>
#include <asm/cacheflush.h>
#include "core.h"
extern void secondary_startup(void);
int platform_cpu_kill(unsigned int cpu)
{
return 1;
}
/*
* platform-specific code to shutdown a CPU
*
*/
void platform_cpu_die(unsigned int cpu)
{
flush_cache_all();
highbank_set_cpu_jump(cpu, secondary_startup);
scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
cpu_do_idle();
/* We should never return from idle */
panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
}
int platform_cpu_disable(unsigned int cpu)
{
/*
* CPU0 should not be shut down via hotplug. cpu_idle can WFI
* or a proper shutdown or hibernate should be used.
*/
return cpu == 0 ? -EPERM : 0;
}
/*
* Debugging macro include header
*
* Copyright (C) 1994-1999 Russell King
* Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
*
* 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.
*/
.macro addruart,rp,rv,tmp
movw \rv, #0x6000
movt \rv, #0xfee3
movw \rp, #0x6000
movt \rp, #0xfff3
.endm
#include <asm/hardware/debug-pl01x.S>
#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
#ifndef __MACH_IO_H
#define __MACH_IO_H
#define __io(a) ({ (void)(a); __typesafe_io(0); })
#define __mem_pci(a) (a)
#endif
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
#define NR_IRQS 192
#endif
/*
* Copyright 2010-2011 Calxeda, Inc.
*
* 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/>.
*/
#ifndef __MACH_SYSTEM_H
#define __MACH_SYSTEM_H
static inline void arch_idle(void)
{
cpu_do_idle();
}
extern void arch_reset(char mode, const char *cmd);
#endif
#ifndef __MACH_TIMEX_H
#define __MACH_TIMEX_H
#define CLOCK_TICK_RATE 1000000
#endif
#ifndef __MACH_UNCOMPRESS_H
#define __MACH_UNCOMPRESS_H
#define putc(c)
#define flush()
#define arch_decomp_setup()
#define arch_decomp_wdog()
#endif
#define VMALLOC_END 0xFEE00000UL
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/init.h>
#include <asm/page.h>
#include <asm/sizes.h>
#include <asm/mach/map.h>
#define HB_DEBUG_LL_PHYS_BASE 0xfff36000
#define HB_DEBUG_LL_VIRT_BASE 0xfee36000
static struct map_desc lluart_io_desc __initdata = {
.virtual = HB_DEBUG_LL_VIRT_BASE,
.pfn = __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
.length = SZ_4K,
.type = MT_DEVICE,
};
void __init highbank_lluart_map_io(void)
{
iotable_init(&lluart_io_desc, 1);
}
/*
* Copyright 2010-2011 Calxeda, Inc.
* Based on localtimer.c, Copyright (C) 2002 ARM 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/init.h>
#include <linux/clockchips.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/smp_twd.h>
/*
* Setup the local clock events for a CPU.
*/
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
if (!twd_base) {
twd_base = of_iomap(np, 0);
WARN_ON(!twd_base);
}
evt->irq = irq_of_parse_and_map(np, 0);
twd_timer_setup(evt);
return 0;
}
/*
* Copyright 2010-2011 Calxeda, Inc.
* Based on platsmp.c, Copyright (C) 2002 ARM 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/init.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/smp_scu.h>
#include <asm/hardware/gic.h>
#include "core.h"
extern void secondary_startup(void);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
gic_secondary_init(0);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
gic_raise_softirq(cpumask_of(cpu), 0);
return 0;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
void __init smp_init_cpus(void)
{
unsigned int i, ncores;
ncores = scu_get_core_count(scu_base_addr);
/* sanity check */
if (ncores > NR_CPUS) {
printk(KERN_WARNING
"highbank: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n",
ncores, NR_CPUS);
ncores = NR_CPUS;
}
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
set_smp_cross_call(gic_raise_softirq);
}
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
int i;
scu_enable(scu_base_addr);
/*
* Write the address of secondary startup into the jump table
* The cores are in wfi and wait until they receive a soft interrupt
* and a non-zero value to jump to. Then the secondary CPU branches
* to this address.
*/
for (i = 1; i < max_cpus; i++)
highbank_set_cpu_jump(i, secondary_startup);
}
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/init.h>
#include <linux/io.h>
#include <linux/suspend.h>
#include <asm/proc-fns.h>
#include <asm/smp_scu.h>
#include <asm/suspend.h>
#include "core.h"
#include "sysregs.h"
static int highbank_suspend_finish(unsigned long val)
{
cpu_do_idle();
return 0;
}
static int highbank_pm_enter(suspend_state_t state)
{
hignbank_set_pwr_suspend();
highbank_set_cpu_jump(0, cpu_resume);
scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
cpu_suspend(0, highbank_suspend_finish);
return 0;
}
static const struct platform_suspend_ops highbank_pm_ops = {
.enter = highbank_pm_enter,
.valid = suspend_valid_only_mem,
};
static int __init highbank_pm_init(void)
{
suspend_set_ops(&highbank_pm_ops);
return 0;
}
module_init(highbank_pm_init);
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/>.
*/
#ifndef _MACH_HIGHBANK__SYSREGS_H_
#define _MACH_HIGHBANK__SYSREGS_H_
#include <linux/io.h>
extern void __iomem *sregs_base;
#define HB_SREG_A9_PWR_REQ 0xf00
#define HB_SREG_A9_BOOT_STAT 0xf04
#define HB_SREG_A9_BOOT_DATA 0xf08
#define HB_PWR_SUSPEND 0
#define HB_PWR_SOFT_RESET 1
#define HB_PWR_HARD_RESET 2
#define HB_PWR_SHUTDOWN 3
static inline void hignbank_set_pwr_suspend(void)
{
writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
}
static inline void hignbank_set_pwr_shutdown(void)
{
writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
}
static inline void hignbank_set_pwr_soft_reset(void)
{
writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
}
static inline void hignbank_set_pwr_hard_reset(void)
{
writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
}
#endif
/*
* Copyright 2011 Calxeda, Inc.
*
* 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/io.h>
#include <asm/smp_scu.h>
#include <asm/proc-fns.h>
#include "core.h"
#include "sysregs.h"
void arch_reset(char mode, const char *cmd)
{
if (mode == 'h')
hignbank_set_pwr_hard_reset();
else
hignbank_set_pwr_soft_reset();
scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
cpu_do_idle();
}
config IMX_HAVE_DMA_V1 config IMX_HAVE_DMA_V1
bool bool
config HAVE_IMX_GPC
bool
config HAVE_IMX_MMDC
bool
config HAVE_IMX_SRC
bool
# #
# ARCH_MX31 and ARCH_MX35 are left for compatibility # ARCH_MX31 and ARCH_MX35 are left for compatibility
# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2. # Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
...@@ -64,6 +74,7 @@ config SOC_IMX31 ...@@ -64,6 +74,7 @@ config SOC_IMX31
select ARCH_MXC_AUDMUX_V2 select ARCH_MXC_AUDMUX_V2
select ARCH_MX31 select ARCH_MX31
select MXC_AVIC select MXC_AVIC
select SMP_ON_UP if SMP
config SOC_IMX35 config SOC_IMX35
bool bool
...@@ -73,6 +84,7 @@ config SOC_IMX35 ...@@ -73,6 +84,7 @@ config SOC_IMX35
select HAVE_EPIT select HAVE_EPIT
select ARCH_MX35 select ARCH_MX35
select MXC_AVIC select MXC_AVIC
select SMP_ON_UP if SMP
if ARCH_IMX_V4_V5 if ARCH_IMX_V4_V5
...@@ -341,7 +353,7 @@ config MACH_IMX27IPCAM ...@@ -341,7 +353,7 @@ config MACH_IMX27IPCAM
endif endif
if ARCH_MX3 if ARCH_IMX_V6_V7
comment "MX31 platforms:" comment "MX31 platforms:"
...@@ -592,4 +604,20 @@ config MACH_VPR200 ...@@ -592,4 +604,20 @@ config MACH_VPR200
Include support for VPR200 platform. This includes specific Include support for VPR200 platform. This includes specific
configurations for the board and its peripherals. configurations for the board and its peripherals.
comment "i.MX6 family:"
config SOC_IMX6Q
bool "i.MX6 Quad support"
select ARM_GIC
select CACHE_L2X0
select CPU_V7
select HAVE_ARM_SCU
select HAVE_IMX_GPC
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select USE_OF
help
This enables support for Freescale i.MX6 Quad processor.
endif endif
...@@ -60,3 +60,14 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o ...@@ -60,3 +60,14 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
obj-$(CONFIG_DEBUG_LL) += lluart.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
obj-$(CONFIG_CPU_V7) += head-v7.o
AFLAGS_head-v7.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
...@@ -17,3 +17,7 @@ initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000 ...@@ -17,3 +17,7 @@ initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000
zreladdr-$(CONFIG_ARCH_MX3) += 0x80008000 zreladdr-$(CONFIG_ARCH_MX3) += 0x80008000
params_phys-$(CONFIG_ARCH_MX3) := 0x80000100 params_phys-$(CONFIG_ARCH_MX3) := 0x80000100
initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000 initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000
zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000
params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100
initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/hardware.h>
#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
#define PLL1_SYS (PLL_BASE + 0x000)
#define PLL2_BUS (PLL_BASE + 0x030)
#define PLL3_USB_OTG (PLL_BASE + 0x010)
#define PLL4_AUDIO (PLL_BASE + 0x070)
#define PLL5_VIDEO (PLL_BASE + 0x0a0)
#define PLL6_MLB (PLL_BASE + 0x0d0)
#define PLL7_USB_HOST (PLL_BASE + 0x020)
#define PLL8_ENET (PLL_BASE + 0x0e0)
#define PFD_480 (PLL_BASE + 0x0f0)
#define PFD_528 (PLL_BASE + 0x100)
#define PLL_NUM_OFFSET 0x010
#define PLL_DENOM_OFFSET 0x020
#define PFD0 7
#define PFD1 15
#define PFD2 23
#define PFD3 31
#define PFD_FRAC_MASK 0x3f
#define BM_PLL_BYPASS (0x1 << 16)
#define BM_PLL_ENABLE (0x1 << 13)
#define BM_PLL_POWER_DOWN (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31)
#define BP_PLL_SYS_DIV_SELECT 0
#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
#define BP_PLL_BUS_DIV_SELECT 0
#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
#define BP_PLL_USB_DIV_SELECT 0
#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
#define BP_PLL_AV_DIV_SELECT 0
#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
#define BP_PLL_ENET_DIV_SELECT 0
#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
#define BM_PLL_ENET_EN_SATA (0x1 << 20)
#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
#define CCR (CCM_BASE + 0x00)
#define CCDR (CCM_BASE + 0x04)
#define CSR (CCM_BASE + 0x08)
#define CCSR (CCM_BASE + 0x0c)
#define CACRR (CCM_BASE + 0x10)
#define CBCDR (CCM_BASE + 0x14)
#define CBCMR (CCM_BASE + 0x18)
#define CSCMR1 (CCM_BASE + 0x1c)
#define CSCMR2 (CCM_BASE + 0x20)
#define CSCDR1 (CCM_BASE + 0x24)
#define CS1CDR (CCM_BASE + 0x28)
#define CS2CDR (CCM_BASE + 0x2c)
#define CDCDR (CCM_BASE + 0x30)
#define CHSCCDR (CCM_BASE + 0x34)
#define CSCDR2 (CCM_BASE + 0x38)
#define CSCDR3 (CCM_BASE + 0x3c)
#define CSCDR4 (CCM_BASE + 0x40)
#define CWDR (CCM_BASE + 0x44)
#define CDHIPR (CCM_BASE + 0x48)
#define CDCR (CCM_BASE + 0x4c)
#define CTOR (CCM_BASE + 0x50)
#define CLPCR (CCM_BASE + 0x54)
#define CISR (CCM_BASE + 0x58)
#define CIMR (CCM_BASE + 0x5c)
#define CCOSR (CCM_BASE + 0x60)
#define CGPR (CCM_BASE + 0x64)
#define CCGR0 (CCM_BASE + 0x68)
#define CCGR1 (CCM_BASE + 0x6c)
#define CCGR2 (CCM_BASE + 0x70)
#define CCGR3 (CCM_BASE + 0x74)
#define CCGR4 (CCM_BASE + 0x78)
#define CCGR5 (CCM_BASE + 0x7c)
#define CCGR6 (CCM_BASE + 0x80)
#define CCGR7 (CCM_BASE + 0x84)
#define CMEOR (CCM_BASE + 0x88)
#define CG0 0
#define CG1 2
#define CG2 4
#define CG3 6
#define CG4 8
#define CG5 10
#define CG6 12
#define CG7 14
#define CG8 16
#define CG9 18
#define CG10 20
#define CG11 22
#define CG12 24
#define CG13 26
#define CG14 28
#define CG15 30
#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
#define BM_CCSR_STEP_SEL (0x1 << 8)
#define BP_CACRR_ARM_PODF 0
#define BM_CACRR_ARM_PODF (0x7 << 0)
#define BP_CBCDR_PERIPH2_CLK2_PODF 0
#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
#define BP_CBCDR_AXI_SEL 6
#define BM_CBCDR_AXI_SEL (0x3 << 6)
#define BP_CBCDR_IPG_PODF 8
#define BM_CBCDR_IPG_PODF (0x3 << 8)
#define BP_CBCDR_AHB_PODF 10
#define BM_CBCDR_AHB_PODF (0x7 << 10)
#define BP_CBCDR_AXI_PODF 16
#define BM_CBCDR_AXI_PODF (0x7 << 16)
#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
#define BP_CBCDR_PERIPH_CLK_SEL 25
#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
#define BP_CBCDR_PERIPH2_CLK_SEL 26
#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
#define BP_CBCDR_PERIPH_CLK2_PODF 27
#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
#define BP_CBCMR_GPU2D_AXI_SEL 0
#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
#define BP_CBCMR_GPU3D_AXI_SEL 1
#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
#define BP_CBCMR_GPU3D_CORE_SEL 4
#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
#define BP_CBCMR_GPU3D_SHADER_SEL 8
#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
#define BP_CBCMR_PCIE_AXI_SEL 10
#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
#define BP_CBCMR_VDO_AXI_SEL 11
#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
#define BP_CBCMR_PERIPH_CLK2_SEL 12
#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
#define BP_CBCMR_VPU_AXI_SEL 14
#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
#define BP_CBCMR_GPU2D_CORE_SEL 16
#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
#define BP_CBCMR_PERIPH2_CLK2_SEL 20
#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
#define BP_CBCMR_GPU2D_CORE_PODF 23
#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
#define BP_CBCMR_GPU3D_CORE_PODF 26
#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
#define BP_CBCMR_GPU3D_SHADER_PODF 29
#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
#define BP_CSCMR1_PERCLK_PODF 0
#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
#define BP_CSCMR1_SSI1_SEL 10
#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
#define BP_CSCMR1_SSI2_SEL 12
#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
#define BP_CSCMR1_SSI3_SEL 14
#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
#define BP_CSCMR1_USDHC1_SEL 16
#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
#define BP_CSCMR1_USDHC2_SEL 17
#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
#define BP_CSCMR1_USDHC3_SEL 18
#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
#define BP_CSCMR1_USDHC4_SEL 19
#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
#define BP_CSCMR1_EMI_PODF 20
#define BM_CSCMR1_EMI_PODF (0x7 << 20)
#define BP_CSCMR1_EMI_SLOW_PODF 23
#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
#define BP_CSCMR1_EMI_SEL 27
#define BM_CSCMR1_EMI_SEL (0x3 << 27)
#define BP_CSCMR1_EMI_SLOW_SEL 29
#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
#define BP_CSCMR2_CAN_PODF 2
#define BM_CSCMR2_CAN_PODF (0x3f << 2)
#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
#define BP_CSCMR2_ESAI_SEL 19
#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
#define BP_CSCDR1_UART_PODF 0
#define BM_CSCDR1_UART_PODF (0x3f << 0)
#define BP_CSCDR1_USDHC1_PODF 11
#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
#define BP_CSCDR1_USDHC2_PODF 16
#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
#define BP_CSCDR1_USDHC3_PODF 19
#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
#define BP_CSCDR1_USDHC4_PODF 22
#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
#define BP_CSCDR1_VPU_AXI_PODF 25
#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
#define BP_CS1CDR_SSI1_PODF 0
#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
#define BP_CS1CDR_SSI1_PRED 6
#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
#define BP_CS1CDR_ESAI_PRED 9
#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
#define BP_CS1CDR_SSI3_PODF 16
#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
#define BP_CS1CDR_SSI3_PRED 22
#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
#define BP_CS1CDR_ESAI_PODF 25
#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
#define BP_CS2CDR_SSI2_PODF 0
#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
#define BP_CS2CDR_SSI2_PRED 6
#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
#define BP_CS2CDR_LDB_DI0_SEL 9
#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
#define BP_CS2CDR_LDB_DI1_SEL 12
#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
#define BP_CS2CDR_ENFC_SEL 16
#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
#define BP_CS2CDR_ENFC_PRED 18
#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
#define BP_CS2CDR_ENFC_PODF 21
#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
#define BP_CDCDR_ASRC_SERIAL_SEL 7
#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
#define BP_CDCDR_ASRC_SERIAL_PODF 9
#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
#define BP_CDCDR_ASRC_SERIAL_PRED 12
#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
#define BP_CDCDR_SPDIF_SEL 20
#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
#define BP_CDCDR_SPDIF_PODF 22
#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
#define BP_CDCDR_SPDIF_PRED 25
#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
#define BP_CDCDR_HSI_TX_PODF 29
#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
#define BP_CDCDR_HSI_TX_SEL 28
#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
#define BP_CHSCCDR_IPU1_DI0_SEL 0
#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
#define BP_CHSCCDR_IPU1_DI1_SEL 9
#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
#define BP_CSCDR2_IPU2_DI0_SEL 0
#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
#define BP_CSCDR2_IPU2_DI1_SEL 9
#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
#define BP_CSCDR2_ECSPI_CLK_PODF 19
#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
#define BP_CSCDR3_IPU1_HSP_SEL 9
#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
#define BP_CSCDR3_IPU1_HSP_PODF 11
#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
#define BP_CSCDR3_IPU2_HSP_SEL 14
#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
#define BP_CSCDR3_IPU2_HSP_PODF 16
#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
#define BP_CLPCR_LPM 0
#define BM_CLPCR_LPM (0x3 << 0)
#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
#define BM_CLPCR_SBYOS (0x1 << 6)
#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
#define BM_CLPCR_VSTBY (0x1 << 8)
#define BP_CLPCR_STBY_COUNT 9
#define BM_CLPCR_STBY_COUNT (0x3 << 9)
#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
#define FREQ_480M 480000000
#define FREQ_528M 528000000
#define FREQ_594M 594000000
#define FREQ_650M 650000000
#define FREQ_1300M 1300000000
static struct clk pll1_sys;
static struct clk pll2_bus;
static struct clk pll3_usb_otg;
static struct clk pll4_audio;
static struct clk pll5_video;
static struct clk pll6_mlb;
static struct clk pll7_usb_host;
static struct clk pll8_enet;
static struct clk apbh_dma_clk;
static struct clk arm_clk;
static struct clk ipg_clk;
static struct clk ahb_clk;
static struct clk axi_clk;
static struct clk mmdc_ch0_axi_clk;
static struct clk mmdc_ch1_axi_clk;
static struct clk periph_clk;
static struct clk periph_pre_clk;
static struct clk periph_clk2_clk;
static struct clk periph2_clk;
static struct clk periph2_pre_clk;
static struct clk periph2_clk2_clk;
static struct clk gpu2d_core_clk;
static struct clk gpu3d_core_clk;
static struct clk gpu3d_shader_clk;
static struct clk ipg_perclk;
static struct clk emi_clk;
static struct clk emi_slow_clk;
static struct clk can1_clk;
static struct clk uart_clk;
static struct clk usdhc1_clk;
static struct clk usdhc2_clk;
static struct clk usdhc3_clk;
static struct clk usdhc4_clk;
static struct clk vpu_clk;
static struct clk hsi_tx_clk;
static struct clk ipu1_di0_pre_clk;
static struct clk ipu1_di1_pre_clk;
static struct clk ipu2_di0_pre_clk;
static struct clk ipu2_di1_pre_clk;
static struct clk ipu1_clk;
static struct clk ipu2_clk;
static struct clk ssi1_clk;
static struct clk ssi3_clk;
static struct clk esai_clk;
static struct clk ssi2_clk;
static struct clk spdif_clk;
static struct clk asrc_serial_clk;
static struct clk gpu2d_axi_clk;
static struct clk gpu3d_axi_clk;
static struct clk pcie_clk;
static struct clk vdo_axi_clk;
static struct clk ldb_di0_clk;
static struct clk ldb_di1_clk;
static struct clk ipu1_di0_clk;
static struct clk ipu1_di1_clk;
static struct clk ipu2_di0_clk;
static struct clk ipu2_di1_clk;
static struct clk enfc_clk;
static struct clk dummy_clk = {};
static unsigned long external_high_reference;
static unsigned long external_low_reference;
static unsigned long oscillator_reference;
static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
{
return oscillator_reference;
}
static unsigned long get_high_reference_clock_rate(struct clk *clk)
{
return external_high_reference;
}
static unsigned long get_low_reference_clock_rate(struct clk *clk)
{
return external_low_reference;
}
static struct clk ckil_clk = {
.get_rate = get_low_reference_clock_rate,
};
static struct clk ckih_clk = {
.get_rate = get_high_reference_clock_rate,
};
static struct clk osc_clk = {
.get_rate = get_oscillator_reference_clock_rate,
};
static inline void __iomem *pll_get_reg_addr(struct clk *pll)
{
if (pll == &pll1_sys)
return PLL1_SYS;
else if (pll == &pll2_bus)
return PLL2_BUS;
else if (pll == &pll3_usb_otg)
return PLL3_USB_OTG;
else if (pll == &pll4_audio)
return PLL4_AUDIO;
else if (pll == &pll5_video)
return PLL5_VIDEO;
else if (pll == &pll6_mlb)
return PLL6_MLB;
else if (pll == &pll7_usb_host)
return PLL7_USB_HOST;
else if (pll == &pll8_enet)
return PLL8_ENET;
else
BUG();
return NULL;
}
static int pll_enable(struct clk *clk)
{
int timeout = 0x100000;
void __iomem *reg;
u32 val;
reg = pll_get_reg_addr(clk);
val = readl_relaxed(reg);
val &= ~BM_PLL_BYPASS;
val &= ~BM_PLL_POWER_DOWN;
/* 480MHz PLLs have the opposite definition for power bit */
if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
val |= BM_PLL_POWER_DOWN;
writel_relaxed(val, reg);
/* Wait for PLL to lock */
while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
cpu_relax();
if (unlikely(!timeout))
return -EBUSY;
/* Enable the PLL output now */
val = readl_relaxed(reg);
val |= BM_PLL_ENABLE;
writel_relaxed(val, reg);
return 0;
}
static void pll_disable(struct clk *clk)
{
void __iomem *reg;
u32 val;
reg = pll_get_reg_addr(clk);
val = readl_relaxed(reg);
val &= ~BM_PLL_ENABLE;
val |= BM_PLL_BYPASS;
val |= BM_PLL_POWER_DOWN;
if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
val &= ~BM_PLL_POWER_DOWN;
writel_relaxed(val, reg);
}
static unsigned long pll1_sys_get_rate(struct clk *clk)
{
u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
BP_PLL_SYS_DIV_SELECT;
return clk_get_rate(clk->parent) * div / 2;
}
static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
{
u32 val, div;
if (rate < FREQ_650M || rate > FREQ_1300M)
return -EINVAL;
div = rate * 2 / clk_get_rate(clk->parent);
val = readl_relaxed(PLL1_SYS);
val &= ~BM_PLL_SYS_DIV_SELECT;
val |= div << BP_PLL_SYS_DIV_SELECT;
writel_relaxed(val, PLL1_SYS);
return 0;
}
static unsigned long pll8_enet_get_rate(struct clk *clk)
{
u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
BP_PLL_ENET_DIV_SELECT;
switch (div) {
case 0:
return 25000000;
case 1:
return 50000000;
case 2:
return 100000000;
case 3:
return 125000000;
}
return 0;
}
static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
{
u32 val, div;
switch (rate) {
case 25000000:
div = 0;
break;
case 50000000:
div = 1;
break;
case 100000000:
div = 2;
break;
case 125000000:
div = 3;
break;
default:
return -EINVAL;
}
val = readl_relaxed(PLL8_ENET);
val &= ~BM_PLL_ENET_DIV_SELECT;
val |= div << BP_PLL_ENET_DIV_SELECT;
writel_relaxed(val, PLL8_ENET);
return 0;
}
static unsigned long pll_av_get_rate(struct clk *clk)
{
void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
unsigned long parent_rate = clk_get_rate(clk->parent);
u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
BP_PLL_AV_DIV_SELECT;
return (parent_rate * div) + ((parent_rate / mfd) * mfn);
}
static int pll_av_set_rate(struct clk *clk, unsigned long rate)
{
void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
unsigned int parent_rate = clk_get_rate(clk->parent);
u32 val, div;
u32 mfn, mfd = 1000000;
s64 temp64;
if (rate < FREQ_650M || rate > FREQ_1300M)
return -EINVAL;
div = rate / parent_rate;
temp64 = (u64) (rate - div * parent_rate);
temp64 *= mfd;
do_div(temp64, parent_rate);
mfn = temp64;
val = readl_relaxed(reg);
val &= ~BM_PLL_AV_DIV_SELECT;
val |= div << BP_PLL_AV_DIV_SELECT;
writel_relaxed(val, reg);
writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
return 0;
}
static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
{
void __iomem *reg;
if (clk == &pll2_bus) {
reg = PLL2_BUS;
*bp = BP_PLL_BUS_DIV_SELECT;
*bm = BM_PLL_BUS_DIV_SELECT;
} else if (clk == &pll3_usb_otg) {
reg = PLL3_USB_OTG;
*bp = BP_PLL_USB_DIV_SELECT;
*bm = BM_PLL_USB_DIV_SELECT;
} else if (clk == &pll7_usb_host) {
reg = PLL7_USB_HOST;
*bp = BP_PLL_USB_DIV_SELECT;
*bm = BM_PLL_USB_DIV_SELECT;
} else {
BUG();
}
return reg;
}
static unsigned long pll_get_rate(struct clk *clk)
{
void __iomem *reg;
u32 div, bp, bm;
reg = pll_get_div_reg_bit(clk, &bp, &bm);
div = (readl_relaxed(reg) & bm) >> bp;
return (div == 1) ? clk_get_rate(clk->parent) * 22 :
clk_get_rate(clk->parent) * 20;
}
static int pll_set_rate(struct clk *clk, unsigned long rate)
{
void __iomem *reg;
u32 val, div, bp, bm;
if (rate == FREQ_528M)
div = 1;
else if (rate == FREQ_480M)
div = 0;
else
return -EINVAL;
reg = pll_get_div_reg_bit(clk, &bp, &bm);
val = readl_relaxed(reg);
val &= ~bm;
val |= div << bp;
writel_relaxed(val, reg);
return 0;
}
#define pll2_bus_get_rate pll_get_rate
#define pll2_bus_set_rate pll_set_rate
#define pll3_usb_otg_get_rate pll_get_rate
#define pll3_usb_otg_set_rate pll_set_rate
#define pll7_usb_host_get_rate pll_get_rate
#define pll7_usb_host_set_rate pll_set_rate
#define pll4_audio_get_rate pll_av_get_rate
#define pll4_audio_set_rate pll_av_set_rate
#define pll5_video_get_rate pll_av_get_rate
#define pll5_video_set_rate pll_av_set_rate
#define pll6_mlb_get_rate NULL
#define pll6_mlb_set_rate NULL
#define DEF_PLL(name) \
static struct clk name = { \
.enable = pll_enable, \
.disable = pll_disable, \
.get_rate = name##_get_rate, \
.set_rate = name##_set_rate, \
.parent = &osc_clk, \
}
DEF_PLL(pll1_sys);
DEF_PLL(pll2_bus);
DEF_PLL(pll3_usb_otg);
DEF_PLL(pll4_audio);
DEF_PLL(pll5_video);
DEF_PLL(pll6_mlb);
DEF_PLL(pll7_usb_host);
DEF_PLL(pll8_enet);
static unsigned long pfd_get_rate(struct clk *clk)
{
u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
u32 frac, bp_frac;
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.enable(&apbh_dma_clk);
bp_frac = clk->enable_shift - 7;
frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
do_div(tmp, frac);
return tmp;
}
static int pfd_set_rate(struct clk *clk, unsigned long rate)
{
u32 val, frac, bp_frac;
u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.enable(&apbh_dma_clk);
/*
* Round up the divider so that we don't set a rate
* higher than what is requested
*/
tmp += rate / 2;
do_div(tmp, rate);
frac = tmp;
frac = (frac < 12) ? 12 : frac;
frac = (frac > 35) ? 35 : frac;
/*
* The frac field always starts from 7 bits lower
* position of enable bit
*/
bp_frac = clk->enable_shift - 7;
val = readl_relaxed(clk->enable_reg);
val &= ~(PFD_FRAC_MASK << bp_frac);
val |= frac << bp_frac;
writel_relaxed(val, clk->enable_reg);
tmp = (u64) clk_get_rate(clk->parent) * 18;
do_div(tmp, frac);
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.disable(&apbh_dma_clk);
return 0;
}
static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
{
u32 frac;
u64 tmp;
tmp = (u64) clk_get_rate(clk->parent) * 18;
tmp += rate / 2;
do_div(tmp, rate);
frac = tmp;
frac = (frac < 12) ? 12 : frac;
frac = (frac > 35) ? 35 : frac;
tmp = (u64) clk_get_rate(clk->parent) * 18;
do_div(tmp, frac);
return tmp;
}
static int pfd_enable(struct clk *clk)
{
u32 val;
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.enable(&apbh_dma_clk);
val = readl_relaxed(clk->enable_reg);
val &= ~(1 << clk->enable_shift);
writel_relaxed(val, clk->enable_reg);
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.disable(&apbh_dma_clk);
return 0;
}
static void pfd_disable(struct clk *clk)
{
u32 val;
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.enable(&apbh_dma_clk);
val = readl_relaxed(clk->enable_reg);
val |= 1 << clk->enable_shift;
writel_relaxed(val, clk->enable_reg);
if (apbh_dma_clk.usecount == 0)
apbh_dma_clk.disable(&apbh_dma_clk);
}
#define DEF_PFD(name, er, es, p) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = pfd_enable, \
.disable = pfd_disable, \
.get_rate = pfd_get_rate, \
.set_rate = pfd_set_rate, \
.round_rate = pfd_round_rate, \
.parent = p, \
}
DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
static unsigned long pll2_200m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
}
static struct clk pll2_200m = {
.parent = &pll2_pfd_400m,
.get_rate = pll2_200m_get_rate,
};
static unsigned long pll3_120m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 4;
}
static struct clk pll3_120m = {
.parent = &pll3_usb_otg,
.get_rate = pll3_120m_get_rate,
};
static unsigned long pll3_80m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 6;
}
static struct clk pll3_80m = {
.parent = &pll3_usb_otg,
.get_rate = pll3_80m_get_rate,
};
static unsigned long pll3_60m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 8;
}
static struct clk pll3_60m = {
.parent = &pll3_usb_otg,
.get_rate = pll3_60m_get_rate,
};
static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
{
u32 val = readl_relaxed(CCSR);
if (parent == &pll1_sys) {
val &= ~BM_CCSR_PLL1_SW_SEL;
val &= ~BM_CCSR_STEP_SEL;
} else if (parent == &osc_clk) {
val |= BM_CCSR_PLL1_SW_SEL;
val &= ~BM_CCSR_STEP_SEL;
} else if (parent == &pll2_pfd_400m) {
val |= BM_CCSR_PLL1_SW_SEL;
val |= BM_CCSR_STEP_SEL;
} else {
return -EINVAL;
}
writel_relaxed(val, CCSR);
return 0;
}
static struct clk pll1_sw_clk = {
.parent = &pll1_sys,
.set_parent = pll1_sw_clk_set_parent,
};
static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
{
u32 min_pred, temp_pred, old_err, err;
if (div >= 512) {
*pred = 8;
*podf = 64;
} else if (div >= 8) {
min_pred = (div - 1) / 64 + 1;
old_err = 8;
for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
err = div % temp_pred;
if (err == 0) {
*pred = temp_pred;
break;
}
err = temp_pred - err;
if (err < old_err) {
old_err = err;
*pred = temp_pred;
}
}
*podf = (div + *pred - 1) / *pred;
} else if (div < 8) {
*pred = div;
*podf = 1;
}
}
static int _clk_enable(struct clk *clk)
{
u32 reg;
reg = readl_relaxed(clk->enable_reg);
reg |= 0x3 << clk->enable_shift;
writel_relaxed(reg, clk->enable_reg);
return 0;
}
static void _clk_disable(struct clk *clk)
{
u32 reg;
reg = readl_relaxed(clk->enable_reg);
reg &= ~(0x3 << clk->enable_shift);
writel_relaxed(reg, clk->enable_reg);
}
struct divider {
struct clk *clk;
void __iomem *reg;
u32 bp_pred;
u32 bm_pred;
u32 bp_podf;
u32 bm_podf;
};
#define DEF_CLK_DIV1(d, c, r, b) \
static struct divider d = { \
.clk = c, \
.reg = r, \
.bp_podf = BP_##r##_##b##_PODF, \
.bm_podf = BM_##r##_##b##_PODF, \
}
DEF_CLK_DIV1(arm_div, &arm_clk, CACRR, ARM);
DEF_CLK_DIV1(ipg_div, &ipg_clk, CBCDR, IPG);
DEF_CLK_DIV1(ahb_div, &ahb_clk, CBCDR, AHB);
DEF_CLK_DIV1(axi_div, &axi_clk, CBCDR, AXI);
DEF_CLK_DIV1(mmdc_ch0_axi_div, &mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI);
DEF_CLK_DIV1(mmdc_ch1_axi_div, &mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI);
DEF_CLK_DIV1(periph_clk2_div, &periph_clk2_clk, CBCDR, PERIPH_CLK2);
DEF_CLK_DIV1(periph2_clk2_div, &periph2_clk2_clk, CBCDR, PERIPH2_CLK2);
DEF_CLK_DIV1(gpu2d_core_div, &gpu2d_core_clk, CBCMR, GPU2D_CORE);
DEF_CLK_DIV1(gpu3d_core_div, &gpu3d_core_clk, CBCMR, GPU3D_CORE);
DEF_CLK_DIV1(gpu3d_shader_div, &gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
DEF_CLK_DIV1(ipg_perclk_div, &ipg_perclk, CSCMR1, PERCLK);
DEF_CLK_DIV1(emi_div, &emi_clk, CSCMR1, EMI);
DEF_CLK_DIV1(emi_slow_div, &emi_slow_clk, CSCMR1, EMI_SLOW);
DEF_CLK_DIV1(can_div, &can1_clk, CSCMR2, CAN);
DEF_CLK_DIV1(uart_div, &uart_clk, CSCDR1, UART);
DEF_CLK_DIV1(usdhc1_div, &usdhc1_clk, CSCDR1, USDHC1);
DEF_CLK_DIV1(usdhc2_div, &usdhc2_clk, CSCDR1, USDHC2);
DEF_CLK_DIV1(usdhc3_div, &usdhc3_clk, CSCDR1, USDHC3);
DEF_CLK_DIV1(usdhc4_div, &usdhc4_clk, CSCDR1, USDHC4);
DEF_CLK_DIV1(vpu_div, &vpu_clk, CSCDR1, VPU_AXI);
DEF_CLK_DIV1(hsi_tx_div, &hsi_tx_clk, CDCDR, HSI_TX);
DEF_CLK_DIV1(ipu1_di0_pre_div, &ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
DEF_CLK_DIV1(ipu1_di1_pre_div, &ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP);
DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP);
#define DEF_CLK_DIV2(d, c, r, b) \
static struct divider d = { \
.clk = c, \
.reg = r, \
.bp_pred = BP_##r##_##b##_PRED, \
.bm_pred = BM_##r##_##b##_PRED, \
.bp_podf = BP_##r##_##b##_PODF, \
.bm_podf = BM_##r##_##b##_PODF, \
}
DEF_CLK_DIV2(ssi1_div, &ssi1_clk, CS1CDR, SSI1);
DEF_CLK_DIV2(ssi3_div, &ssi3_clk, CS1CDR, SSI3);
DEF_CLK_DIV2(esai_div, &esai_clk, CS1CDR, ESAI);
DEF_CLK_DIV2(ssi2_div, &ssi2_clk, CS2CDR, SSI2);
DEF_CLK_DIV2(enfc_div, &enfc_clk, CS2CDR, ENFC);
DEF_CLK_DIV2(spdif_div, &spdif_clk, CDCDR, SPDIF);
DEF_CLK_DIV2(asrc_serial_div, &asrc_serial_clk, CDCDR, ASRC_SERIAL);
static struct divider *dividers[] = {
&arm_div,
&ipg_div,
&ahb_div,
&axi_div,
&mmdc_ch0_axi_div,
&mmdc_ch1_axi_div,
&periph_clk2_div,
&periph2_clk2_div,
&gpu2d_core_div,
&gpu3d_core_div,
&gpu3d_shader_div,
&ipg_perclk_div,
&emi_div,
&emi_slow_div,
&can_div,
&uart_div,
&usdhc1_div,
&usdhc2_div,
&usdhc3_div,
&usdhc4_div,
&vpu_div,
&hsi_tx_div,
&ipu1_di0_pre_div,
&ipu1_di1_pre_div,
&ipu2_di0_pre_div,
&ipu2_di1_pre_div,
&ipu1_div,
&ipu2_div,
&ssi1_div,
&ssi3_div,
&esai_div,
&ssi2_div,
&enfc_div,
&spdif_div,
&asrc_serial_div,
};
static unsigned long ldb_di_clk_get_rate(struct clk *clk)
{
u32 val = readl_relaxed(CSCMR2);
val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
BM_CSCMR2_LDB_DI1_IPU_DIV;
if (val)
return clk_get_rate(clk->parent) / 7;
else
return clk_get_rate(clk->parent) * 2 / 7;
}
static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
u32 val = readl_relaxed(CSCMR2);
if (rate * 7 <= parent_rate + parent_rate / 20)
val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
else
val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
writel_relaxed(val, CSCMR2);
return 0;
}
static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
if (rate * 7 <= parent_rate + parent_rate / 20)
return parent_rate / 7;
else
return 2 * parent_rate / 7;
}
static unsigned long _clk_get_rate(struct clk *clk)
{
struct divider *d;
u32 val, pred, podf;
int i, num;
if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
return ldb_di_clk_get_rate(clk);
num = ARRAY_SIZE(dividers);
for (i = 0; i < num; i++)
if (dividers[i]->clk == clk) {
d = dividers[i];
break;
}
if (i == num)
return clk_get_rate(clk->parent);
val = readl_relaxed(d->reg);
pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
return clk_get_rate(clk->parent) / (pred * podf);
}
static int clk_busy_wait(struct clk *clk)
{
int timeout = 0x100000;
u32 bm;
if (clk == &axi_clk)
bm = BM_CDHIPR_AXI_PODF_BUSY;
else if (clk == &ahb_clk)
bm = BM_CDHIPR_AHB_PODF_BUSY;
else if (clk == &mmdc_ch0_axi_clk)
bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
else if (clk == &periph_clk)
bm = BM_CDHIPR_PERIPH_SEL_BUSY;
else if (clk == &arm_clk)
bm = BM_CDHIPR_ARM_PODF_BUSY;
else
return -EINVAL;
while ((readl_relaxed(CDHIPR) & bm) && --timeout)
cpu_relax();
if (unlikely(!timeout))
return -EBUSY;
return 0;
}
static int _clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
struct divider *d;
u32 val, div, max_div, pred = 0, podf;
int i, num;
if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
return ldb_di_clk_set_rate(clk, rate);
num = ARRAY_SIZE(dividers);
for (i = 0; i < num; i++)
if (dividers[i]->clk == clk) {
d = dividers[i];
break;
}
if (i == num)
return -EINVAL;
max_div = ((d->bm_pred >> d->bp_pred) + 1) *
((d->bm_pred >> d->bp_pred) + 1);
div = parent_rate / rate;
if (div == 0)
div++;
if ((parent_rate / div != rate) || div > max_div)
return -EINVAL;
if (d->bm_pred) {
calc_pred_podf_dividers(div, &pred, &podf);
} else {
pred = 1;
podf = div;
}
val = readl_relaxed(d->reg);
val &= ~(d->bm_pred | d->bm_podf);
val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
writel_relaxed(val, d->reg);
if (clk == &axi_clk || clk == &ahb_clk ||
clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
return clk_busy_wait(clk);
return 0;
}
static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
u32 div = parent_rate / rate;
u32 div_max, pred = 0, podf;
struct divider *d;
int i, num;
if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
return ldb_di_clk_round_rate(clk, rate);
num = ARRAY_SIZE(dividers);
for (i = 0; i < num; i++)
if (dividers[i]->clk == clk) {
d = dividers[i];
break;
}
if (i == num)
return -EINVAL;
if (div == 0 || parent_rate % rate)
div++;
if (d->bm_pred) {
calc_pred_podf_dividers(div, &pred, &podf);
div = pred * podf;
} else {
div_max = (d->bm_podf >> d->bp_podf) + 1;
if (div > div_max)
div = div_max;
}
return parent_rate / div;
}
struct multiplexer {
struct clk *clk;
void __iomem *reg;
u32 bp;
u32 bm;
int pnum;
struct clk *parents[];
};
static struct multiplexer axi_mux = {
.clk = &axi_clk,
.reg = CBCDR,
.bp = BP_CBCDR_AXI_SEL,
.bm = BM_CBCDR_AXI_SEL,
.parents = {
&periph_clk,
&pll2_pfd_400m,
&pll3_pfd_540m,
NULL
},
};
static struct multiplexer periph_mux = {
.clk = &periph_clk,
.reg = CBCDR,
.bp = BP_CBCDR_PERIPH_CLK_SEL,
.bm = BM_CBCDR_PERIPH_CLK_SEL,
.parents = {
&periph_pre_clk,
&periph_clk2_clk,
NULL
},
};
static struct multiplexer periph_pre_mux = {
.clk = &periph_pre_clk,
.reg = CBCMR,
.bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
.bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
.parents = {
&pll2_bus,
&pll2_pfd_400m,
&pll2_pfd_352m,
&pll2_200m,
NULL
},
};
static struct multiplexer periph_clk2_mux = {
.clk = &periph_clk2_clk,
.reg = CBCMR,
.bp = BP_CBCMR_PERIPH_CLK2_SEL,
.bm = BM_CBCMR_PERIPH_CLK2_SEL,
.parents = {
&pll3_usb_otg,
&osc_clk,
NULL
},
};
static struct multiplexer periph2_mux = {
.clk = &periph2_clk,
.reg = CBCDR,
.bp = BP_CBCDR_PERIPH2_CLK_SEL,
.bm = BM_CBCDR_PERIPH2_CLK_SEL,
.parents = {
&periph2_pre_clk,
&periph2_clk2_clk,
NULL
},
};
static struct multiplexer periph2_pre_mux = {
.clk = &periph2_pre_clk,
.reg = CBCMR,
.bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
.bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
.parents = {
&pll2_bus,
&pll2_pfd_400m,
&pll2_pfd_352m,
&pll2_200m,
NULL
},
};
static struct multiplexer periph2_clk2_mux = {
.clk = &periph2_clk2_clk,
.reg = CBCMR,
.bp = BP_CBCMR_PERIPH2_CLK2_SEL,
.bm = BM_CBCMR_PERIPH2_CLK2_SEL,
.parents = {
&pll3_usb_otg,
&osc_clk,
NULL
},
};
static struct multiplexer gpu2d_axi_mux = {
.clk = &gpu2d_axi_clk,
.reg = CBCMR,
.bp = BP_CBCMR_GPU2D_AXI_SEL,
.bm = BM_CBCMR_GPU2D_AXI_SEL,
.parents = {
&axi_clk,
&ahb_clk,
NULL
},
};
static struct multiplexer gpu3d_axi_mux = {
.clk = &gpu3d_axi_clk,
.reg = CBCMR,
.bp = BP_CBCMR_GPU3D_AXI_SEL,
.bm = BM_CBCMR_GPU3D_AXI_SEL,
.parents = {
&axi_clk,
&ahb_clk,
NULL
},
};
static struct multiplexer gpu3d_core_mux = {
.clk = &gpu3d_core_clk,
.reg = CBCMR,
.bp = BP_CBCMR_GPU3D_CORE_SEL,
.bm = BM_CBCMR_GPU3D_CORE_SEL,
.parents = {
&mmdc_ch0_axi_clk,
&pll3_usb_otg,
&pll2_pfd_594m,
&pll2_pfd_400m,
NULL
},
};
static struct multiplexer gpu3d_shader_mux = {
.clk = &gpu3d_shader_clk,
.reg = CBCMR,
.bp = BP_CBCMR_GPU3D_SHADER_SEL,
.bm = BM_CBCMR_GPU3D_SHADER_SEL,
.parents = {
&mmdc_ch0_axi_clk,
&pll3_usb_otg,
&pll2_pfd_594m,
&pll3_pfd_720m,
NULL
},
};
static struct multiplexer pcie_axi_mux = {
.clk = &pcie_clk,
.reg = CBCMR,
.bp = BP_CBCMR_PCIE_AXI_SEL,
.bm = BM_CBCMR_PCIE_AXI_SEL,
.parents = {
&axi_clk,
&ahb_clk,
NULL
},
};
static struct multiplexer vdo_axi_mux = {
.clk = &vdo_axi_clk,
.reg = CBCMR,
.bp = BP_CBCMR_VDO_AXI_SEL,
.bm = BM_CBCMR_VDO_AXI_SEL,
.parents = {
&axi_clk,
&ahb_clk,
NULL
},
};
static struct multiplexer vpu_axi_mux = {
.clk = &vpu_clk,
.reg = CBCMR,
.bp = BP_CBCMR_VPU_AXI_SEL,
.bm = BM_CBCMR_VPU_AXI_SEL,
.parents = {
&axi_clk,
&pll2_pfd_400m,
&pll2_pfd_352m,
NULL
},
};
static struct multiplexer gpu2d_core_mux = {
.clk = &gpu2d_core_clk,
.reg = CBCMR,
.bp = BP_CBCMR_GPU2D_CORE_SEL,
.bm = BM_CBCMR_GPU2D_CORE_SEL,
.parents = {
&axi_clk,
&pll3_usb_otg,
&pll2_pfd_352m,
&pll2_pfd_400m,
NULL
},
};
#define DEF_SSI_MUX(id) \
static struct multiplexer ssi##id##_mux = { \
.clk = &ssi##id##_clk, \
.reg = CSCMR1, \
.bp = BP_CSCMR1_SSI##id##_SEL, \
.bm = BM_CSCMR1_SSI##id##_SEL, \
.parents = { \
&pll3_pfd_508m, \
&pll3_pfd_454m, \
&pll4_audio, \
NULL \
}, \
}
DEF_SSI_MUX(1);
DEF_SSI_MUX(2);
DEF_SSI_MUX(3);
#define DEF_USDHC_MUX(id) \
static struct multiplexer usdhc##id##_mux = { \
.clk = &usdhc##id##_clk, \
.reg = CSCMR1, \
.bp = BP_CSCMR1_USDHC##id##_SEL, \
.bm = BM_CSCMR1_USDHC##id##_SEL, \
.parents = { \
&pll2_pfd_400m, \
&pll2_pfd_352m, \
NULL \
}, \
}
DEF_USDHC_MUX(1);
DEF_USDHC_MUX(2);
DEF_USDHC_MUX(3);
DEF_USDHC_MUX(4);
static struct multiplexer emi_mux = {
.clk = &emi_clk,
.reg = CSCMR1,
.bp = BP_CSCMR1_EMI_SEL,
.bm = BM_CSCMR1_EMI_SEL,
.parents = {
&axi_clk,
&pll3_usb_otg,
&pll2_pfd_400m,
&pll2_pfd_352m,
NULL
},
};
static struct multiplexer emi_slow_mux = {
.clk = &emi_slow_clk,
.reg = CSCMR1,
.bp = BP_CSCMR1_EMI_SLOW_SEL,
.bm = BM_CSCMR1_EMI_SLOW_SEL,
.parents = {
&axi_clk,
&pll3_usb_otg,
&pll2_pfd_400m,
&pll2_pfd_352m,
NULL
},
};
static struct multiplexer esai_mux = {
.clk = &esai_clk,
.reg = CSCMR2,
.bp = BP_CSCMR2_ESAI_SEL,
.bm = BM_CSCMR2_ESAI_SEL,
.parents = {
&pll4_audio,
&pll3_pfd_508m,
&pll3_pfd_454m,
&pll3_usb_otg,
NULL
},
};
#define DEF_LDB_DI_MUX(id) \
static struct multiplexer ldb_di##id##_mux = { \
.clk = &ldb_di##id##_clk, \
.reg = CS2CDR, \
.bp = BP_CS2CDR_LDB_DI##id##_SEL, \
.bm = BM_CS2CDR_LDB_DI##id##_SEL, \
.parents = { \
&pll5_video, \
&pll2_pfd_352m, \
&pll2_pfd_400m, \
&pll3_pfd_540m, \
&pll3_usb_otg, \
NULL \
}, \
}
DEF_LDB_DI_MUX(0);
DEF_LDB_DI_MUX(1);
static struct multiplexer enfc_mux = {
.clk = &enfc_clk,
.reg = CS2CDR,
.bp = BP_CS2CDR_ENFC_SEL,
.bm = BM_CS2CDR_ENFC_SEL,
.parents = {
&pll2_pfd_352m,
&pll2_bus,
&pll3_usb_otg,
&pll2_pfd_400m,
NULL
},
};
static struct multiplexer spdif_mux = {
.clk = &spdif_clk,
.reg = CDCDR,
.bp = BP_CDCDR_SPDIF_SEL,
.bm = BM_CDCDR_SPDIF_SEL,
.parents = {
&pll4_audio,
&pll3_pfd_508m,
&pll3_pfd_454m,
&pll3_usb_otg,
NULL
},
};
static struct multiplexer asrc_serial_mux = {
.clk = &asrc_serial_clk,
.reg = CDCDR,
.bp = BP_CDCDR_ASRC_SERIAL_SEL,
.bm = BM_CDCDR_ASRC_SERIAL_SEL,
.parents = {
&pll4_audio,
&pll3_pfd_508m,
&pll3_pfd_454m,
&pll3_usb_otg,
NULL
},
};
static struct multiplexer hsi_tx_mux = {
.clk = &hsi_tx_clk,
.reg = CDCDR,
.bp = BP_CDCDR_HSI_TX_SEL,
.bm = BM_CDCDR_HSI_TX_SEL,
.parents = {
&pll3_120m,
&pll2_pfd_400m,
NULL
},
};
#define DEF_IPU_DI_PRE_MUX(r, i, d) \
static struct multiplexer ipu##i##_di##d##_pre_mux = { \
.clk = &ipu##i##_di##d##_pre_clk, \
.reg = r, \
.bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \
.bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \
.parents = { \
&mmdc_ch0_axi_clk, \
&pll3_usb_otg, \
&pll5_video, \
&pll2_pfd_352m, \
&pll2_pfd_400m, \
&pll3_pfd_540m, \
NULL \
}, \
}
DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
#define DEF_IPU_DI_MUX(r, i, d) \
static struct multiplexer ipu##i##_di##d##_mux = { \
.clk = &ipu##i##_di##d##_clk, \
.reg = r, \
.bp = BP_##r##_IPU##i##_DI##d##_SEL, \
.bm = BM_##r##_IPU##i##_DI##d##_SEL, \
.parents = { \
&ipu##i##_di##d##_pre_clk, \
&dummy_clk, \
&dummy_clk, \
&ldb_di0_clk, \
&ldb_di1_clk, \
NULL \
}, \
}
DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
DEF_IPU_DI_MUX(CSCDR2, 2, 0);
DEF_IPU_DI_MUX(CSCDR2, 2, 1);
#define DEF_IPU_MUX(id) \
static struct multiplexer ipu##id##_mux = { \
.clk = &ipu##id##_clk, \
.reg = CSCDR3, \
.bp = BP_CSCDR3_IPU##id##_HSP_SEL, \
.bm = BM_CSCDR3_IPU##id##_HSP_SEL, \
.parents = { \
&mmdc_ch0_axi_clk, \
&pll2_pfd_400m, \
&pll3_120m, \
&pll3_pfd_540m, \
NULL \
}, \
}
DEF_IPU_MUX(1);
DEF_IPU_MUX(2);
static struct multiplexer *multiplexers[] = {
&axi_mux,
&periph_mux,
&periph_pre_mux,
&periph_clk2_mux,
&periph2_mux,
&periph2_pre_mux,
&periph2_clk2_mux,
&gpu2d_axi_mux,
&gpu3d_axi_mux,
&gpu3d_core_mux,
&gpu3d_shader_mux,
&pcie_axi_mux,
&vdo_axi_mux,
&vpu_axi_mux,
&gpu2d_core_mux,
&ssi1_mux,
&ssi2_mux,
&ssi3_mux,
&usdhc1_mux,
&usdhc2_mux,
&usdhc3_mux,
&usdhc4_mux,
&emi_mux,
&emi_slow_mux,
&esai_mux,
&ldb_di0_mux,
&ldb_di1_mux,
&enfc_mux,
&spdif_mux,
&asrc_serial_mux,
&hsi_tx_mux,
&ipu1_di0_pre_mux,
&ipu1_di0_mux,
&ipu1_di1_pre_mux,
&ipu1_di1_mux,
&ipu2_di0_pre_mux,
&ipu2_di0_mux,
&ipu2_di1_pre_mux,
&ipu2_di1_mux,
&ipu1_mux,
&ipu2_mux,
};
static int _clk_set_parent(struct clk *clk, struct clk *parent)
{
struct multiplexer *m;
int i, num;
u32 val;
num = ARRAY_SIZE(multiplexers);
for (i = 0; i < num; i++)
if (multiplexers[i]->clk == clk) {
m = multiplexers[i];
break;
}
if (i == num)
return -EINVAL;
i = 0;
while (m->parents[i]) {
if (parent == m->parents[i])
break;
i++;
}
if (!m->parents[i])
return -EINVAL;
val = readl_relaxed(m->reg);
val &= ~m->bm;
val |= i << m->bp;
writel_relaxed(val, m->reg);
if (clk == &periph_clk)
return clk_busy_wait(clk);
return 0;
}
#define DEF_NG_CLK(name, p) \
static struct clk name = { \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
}
DEF_NG_CLK(periph_clk2_clk, &osc_clk);
DEF_NG_CLK(periph_pre_clk, &pll2_bus);
DEF_NG_CLK(periph_clk, &periph_pre_clk);
DEF_NG_CLK(periph2_clk2_clk, &osc_clk);
DEF_NG_CLK(periph2_pre_clk, &pll2_bus);
DEF_NG_CLK(periph2_clk, &periph2_pre_clk);
DEF_NG_CLK(axi_clk, &periph_clk);
DEF_NG_CLK(emi_clk, &axi_clk);
DEF_NG_CLK(arm_clk, &pll1_sw_clk);
DEF_NG_CLK(ahb_clk, &periph_clk);
DEF_NG_CLK(ipg_clk, &ahb_clk);
DEF_NG_CLK(ipg_perclk, &ipg_clk);
DEF_NG_CLK(ipu1_di0_pre_clk, &pll3_pfd_540m);
DEF_NG_CLK(ipu1_di1_pre_clk, &pll3_pfd_540m);
DEF_NG_CLK(ipu2_di0_pre_clk, &pll3_pfd_540m);
DEF_NG_CLK(ipu2_di1_pre_clk, &pll3_pfd_540m);
DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg);
#define DEF_CLK(name, er, es, p, s) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = _clk_enable, \
.disable = _clk_disable, \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
.secondary = s, \
}
DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL);
DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL);
DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL);
DEF_CLK(asrc_clk, CCGR0, CG3, &pll4_audio, NULL);
DEF_CLK(can1_serial_clk, CCGR0, CG8, &pll3_usb_otg, NULL);
DEF_CLK(can1_clk, CCGR0, CG7, &pll3_usb_otg, &can1_serial_clk);
DEF_CLK(can2_serial_clk, CCGR0, CG10, &pll3_usb_otg, NULL);
DEF_CLK(can2_clk, CCGR0, CG9, &pll3_usb_otg, &can2_serial_clk);
DEF_CLK(ecspi1_clk, CCGR1, CG0, &pll3_60m, NULL);
DEF_CLK(ecspi2_clk, CCGR1, CG1, &pll3_60m, NULL);
DEF_CLK(ecspi3_clk, CCGR1, CG2, &pll3_60m, NULL);
DEF_CLK(ecspi4_clk, CCGR1, CG3, &pll3_60m, NULL);
DEF_CLK(ecspi5_clk, CCGR1, CG4, &pll3_60m, NULL);
DEF_CLK(enet_clk, CCGR1, CG5, &ipg_clk, NULL);
DEF_CLK(esai_clk, CCGR1, CG8, &pll3_usb_otg, NULL);
DEF_CLK(gpt_serial_clk, CCGR1, CG11, &ipg_perclk, NULL);
DEF_CLK(gpt_clk, CCGR1, CG10, &ipg_perclk, &gpt_serial_clk);
DEF_CLK(gpu2d_core_clk, CCGR1, CG12, &pll2_pfd_352m, &gpu2d_axi_clk);
DEF_CLK(gpu3d_core_clk, CCGR1, CG13, &pll2_pfd_594m, &gpu3d_axi_clk);
DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m, &gpu3d_axi_clk);
DEF_CLK(hdmi_iahb_clk, CCGR2, CG0, &ahb_clk, NULL);
DEF_CLK(hdmi_isfr_clk, CCGR2, CG2, &pll3_pfd_540m, &hdmi_iahb_clk);
DEF_CLK(i2c1_clk, CCGR2, CG3, &ipg_perclk, NULL);
DEF_CLK(i2c2_clk, CCGR2, CG4, &ipg_perclk, NULL);
DEF_CLK(i2c3_clk, CCGR2, CG5, &ipg_perclk, NULL);
DEF_CLK(iim_clk, CCGR2, CG6, &ipg_clk, NULL);
DEF_CLK(enfc_clk, CCGR2, CG7, &pll2_pfd_352m, NULL);
DEF_CLK(ipu1_clk, CCGR3, CG0, &mmdc_ch0_axi_clk, NULL);
DEF_CLK(ipu1_di0_clk, CCGR3, CG1, &ipu1_di0_pre_clk, NULL);
DEF_CLK(ipu1_di1_clk, CCGR3, CG2, &ipu1_di1_pre_clk, NULL);
DEF_CLK(ipu2_clk, CCGR3, CG3, &mmdc_ch0_axi_clk, NULL);
DEF_CLK(ipu2_di0_clk, CCGR3, CG4, &ipu2_di0_pre_clk, NULL);
DEF_CLK(ipu2_di1_clk, CCGR3, CG5, &ipu2_di1_pre_clk, NULL);
DEF_CLK(ldb_di0_clk, CCGR3, CG6, &pll3_pfd_540m, NULL);
DEF_CLK(ldb_di1_clk, CCGR3, CG7, &pll3_pfd_540m, NULL);
DEF_CLK(hsi_tx_clk, CCGR3, CG8, &pll2_pfd_400m, NULL);
DEF_CLK(mlb_clk, CCGR3, CG9, &pll6_mlb, NULL);
DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk, NULL);
DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk, &mmdc_ch0_ipg_clk);
DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk, NULL);
DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk, &mmdc_ch1_ipg_clk);
DEF_CLK(openvg_axi_clk, CCGR3, CG13, &axi_clk, NULL);
DEF_CLK(pwm1_clk, CCGR4, CG8, &ipg_perclk, NULL);
DEF_CLK(pwm2_clk, CCGR4, CG9, &ipg_perclk, NULL);
DEF_CLK(pwm3_clk, CCGR4, CG10, &ipg_perclk, NULL);
DEF_CLK(pwm4_clk, CCGR4, CG11, &ipg_perclk, NULL);
DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk, NULL);
DEF_CLK(gpmi_bch_clk, CCGR4, CG13, &usdhc4_clk, &gpmi_bch_apb_clk);
DEF_CLK(gpmi_apb_clk, CCGR4, CG15, &usdhc3_clk, &gpmi_bch_clk);
DEF_CLK(gpmi_io_clk, CCGR4, CG14, &enfc_clk, &gpmi_apb_clk);
DEF_CLK(sdma_clk, CCGR5, CG3, &ahb_clk, NULL);
DEF_CLK(spba_clk, CCGR5, CG6, &ipg_clk, NULL);
DEF_CLK(spdif_clk, CCGR5, CG7, &pll3_usb_otg, &spba_clk);
DEF_CLK(ssi1_clk, CCGR5, CG9, &pll3_pfd_508m, NULL);
DEF_CLK(ssi2_clk, CCGR5, CG10, &pll3_pfd_508m, NULL);
DEF_CLK(ssi3_clk, CCGR5, CG11, &pll3_pfd_508m, NULL);
DEF_CLK(uart_serial_clk, CCGR5, CG13, &pll3_usb_otg, NULL);
DEF_CLK(uart_clk, CCGR5, CG12, &pll3_80m, &uart_serial_clk);
DEF_CLK(usboh3_clk, CCGR6, CG0, &ipg_clk, NULL);
DEF_CLK(usdhc1_clk, CCGR6, CG1, &pll2_pfd_400m, NULL);
DEF_CLK(usdhc2_clk, CCGR6, CG2, &pll2_pfd_400m, NULL);
DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL);
DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL);
DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL);
DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL);
DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL);
static int pcie_clk_enable(struct clk *clk)
{
u32 val;
val = readl_relaxed(PLL8_ENET);
val |= BM_PLL_ENET_EN_PCIE;
writel_relaxed(val, PLL8_ENET);
return _clk_enable(clk);
}
static void pcie_clk_disable(struct clk *clk)
{
u32 val;
_clk_disable(clk);
val = readl_relaxed(PLL8_ENET);
val &= BM_PLL_ENET_EN_PCIE;
writel_relaxed(val, PLL8_ENET);
}
static struct clk pcie_clk = {
.enable_reg = CCGR4,
.enable_shift = CG0,
.enable = pcie_clk_enable,
.disable = pcie_clk_disable,
.set_parent = _clk_set_parent,
.parent = &axi_clk,
.secondary = &pll8_enet,
};
static int sata_clk_enable(struct clk *clk)
{
u32 val;
val = readl_relaxed(PLL8_ENET);
val |= BM_PLL_ENET_EN_SATA;
writel_relaxed(val, PLL8_ENET);
return _clk_enable(clk);
}
static void sata_clk_disable(struct clk *clk)
{
u32 val;
_clk_disable(clk);
val = readl_relaxed(PLL8_ENET);
val &= BM_PLL_ENET_EN_SATA;
writel_relaxed(val, PLL8_ENET);
}
static struct clk sata_clk = {
.enable_reg = CCGR5,
.enable_shift = CG2,
.enable = sata_clk_enable,
.disable = sata_clk_disable,
.parent = &ipg_clk,
.secondary = &pll8_enet,
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
}
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
_REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
_REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
_REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
_REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
_REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
_REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
_REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
_REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
_REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
_REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
_REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
_REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
_REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
_REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
_REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
_REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
_REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
_REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
_REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
_REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
_REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
_REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
_REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
_REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
_REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
_REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
_REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
_REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
};
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
{
u32 val = readl_relaxed(CLPCR);
val &= ~BM_CLPCR_LPM;
switch (mode) {
case WAIT_CLOCKED:
break;
case WAIT_UNCLOCKED:
val |= 0x1 << BP_CLPCR_LPM;
break;
case STOP_POWER_ON:
val |= 0x2 << BP_CLPCR_LPM;
break;
case WAIT_UNCLOCKED_POWER_OFF:
val |= 0x1 << BP_CLPCR_LPM;
val &= ~BM_CLPCR_VSTBY;
val &= ~BM_CLPCR_SBYOS;
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
case STOP_POWER_OFF:
val |= 0x2 << BP_CLPCR_LPM;
val |= 0x3 << BP_CLPCR_STBY_COUNT;
val |= BM_CLPCR_VSTBY;
val |= BM_CLPCR_SBYOS;
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
default:
return -EINVAL;
}
writel_relaxed(val, CLPCR);
return 0;
}
static struct map_desc imx6q_clock_desc[] = {
imx_map_entry(MX6Q, CCM, MT_DEVICE),
imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
};
int __init mx6q_clocks_init(void)
{
struct device_node *np;
void __iomem *base;
int i, irq;
iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
/* retrieve the freqency of fixed clocks from device tree */
for_each_compatible_node(np, NULL, "fixed-clock") {
u32 rate;
if (of_property_read_u32(np, "clock-frequency", &rate))
continue;
if (of_device_is_compatible(np, "fsl,imx-ckil"))
external_low_reference = rate;
else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
external_high_reference = rate;
else if (of_device_is_compatible(np, "fsl,imx-osc"))
oscillator_reference = rate;
}
for (i = 0; i < ARRAY_SIZE(lookups); i++)
clkdev_add(&lookups[i]);
/* only keep necessary clocks on */
writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0);
writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2);
writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3);
writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4);
writel_relaxed(0x3 << CG0, CCGR5);
writel_relaxed(0, CCGR6);
writel_relaxed(0, CCGR7);
clk_enable(&uart_clk);
clk_enable(&mmdc_ch0_axi_clk);
clk_set_rate(&pll4_audio, FREQ_650M);
clk_set_rate(&pll5_video, FREQ_650M);
clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
clk_set_rate(&gpu3d_core_clk, FREQ_528M);
clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
clk_set_rate(&asrc_serial_clk, 1500000);
clk_set_rate(&enfc_clk, 11000000);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
base = of_iomap(np, 0);
WARN_ON(!base);
irq = irq_of_parse_and_map(np, 0);
mxc_timer_init(&gpt_clk, base, irq);
return 0;
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/io.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/hardware/gic.h>
#define GPC_IMR1 0x008
#define GPC_PGC_CPU_PDN 0x2a0
#define IMR_NUM 4
static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
void imx_gpc_pre_suspend(void)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Tell GPC to power off ARM core when suspend */
writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++) {
gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
}
}
void imx_gpc_post_resume(void)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Keep ARM core powered on for other low-power modes */
writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
}
static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
{
unsigned int idx = d->irq / 32 - 1;
u32 mask;
/* Sanity check for SPI irq */
if (d->irq < 32)
return -EINVAL;
mask = 1 << d->irq % 32;
gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
gpc_wake_irqs[idx] & ~mask;
return 0;
}
static void imx_gpc_irq_unmask(struct irq_data *d)
{
void __iomem *reg;
u32 val;
/* Sanity check for SPI irq */
if (d->irq < 32)
return;
reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
val = readl_relaxed(reg);
val &= ~(1 << d->irq % 32);
writel_relaxed(val, reg);
}
static void imx_gpc_irq_mask(struct irq_data *d)
{
void __iomem *reg;
u32 val;
/* Sanity check for SPI irq */
if (d->irq < 32)
return;
reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
val = readl_relaxed(reg);
val |= 1 << (d->irq % 32);
writel_relaxed(val, reg);
}
void __init imx_gpc_init(void)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
gpc_base = of_iomap(np, 0);
WARN_ON(!gpc_base);
/* Register GPC as the secondary interrupt controller behind GIC */
gic_arch_extn.irq_mask = imx_gpc_irq_mask;
gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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>
#include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/hardware/cache-l2x0.h>
.section ".text.head", "ax"
__CPUINIT
/*
* The secondary kernel init calls v7_flush_dcache_all before it enables
* the L1; however, the L1 comes out of reset in an undefined state, so
* the clean + invalidate performed by v7_flush_dcache_all causes a bunch
* of cache lines with uninitialized data and uninitialized tags to get
* written out to memory, which does really unpleasant things to the main
* processor. We fix this by performing an invalidate, rather than a
* clean + invalidate, before jumping into the kernel.
*
* This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
* to be called for both secondary cores startup and primary core resume
* procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
*/
ENTRY(v7_invalidate_l1)
mov r0, #0
mcr p15, 2, r0, c0, c0, 0
mrc p15, 1, r0, c0, c0, 0
ldr r1, =0x7fff
and r2, r1, r0, lsr #13
ldr r1, =0x3ff
and r3, r1, r0, lsr #3 @ NumWays - 1
add r2, r2, #1 @ NumSets
and r0, r0, #0x7
add r0, r0, #4 @ SetShift
clz r1, r3 @ WayShift
add r4, r3, #1 @ NumWays
1: sub r2, r2, #1 @ NumSets--
mov r3, r4 @ Temp = NumWays
2: subs r3, r3, #1 @ Temp--
mov r5, r3, lsl r1
mov r6, r2, lsl r0
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
mcr p15, 0, r5, c7, c6, 2
bgt 2b
cmp r2, #0
bgt 1b
dsb
isb
mov pc, lr
ENDPROC(v7_invalidate_l1)
#ifdef CONFIG_SMP
ENTRY(v7_secondary_startup)
bl v7_invalidate_l1
b secondary_startup
ENDPROC(v7_secondary_startup)
#endif
/*
* The following code is located into the .data section. This is to
* allow phys_l2x0_saved_regs to be accessed with a relative load
* as we are running on physical address here.
*/
.data
.align
.macro pl310_resume
ldr r2, phys_l2x0_saved_regs
ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value
str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl
mov r1, #0x1
str r1, [r0, #L2X0_CTRL] @ re-enable L2
.endm
ENTRY(v7_cpu_resume)
bl v7_invalidate_l1
pl310_resume
b cpu_resume
ENDPROC(v7_cpu_resume)
.globl phys_l2x0_saved_regs
phys_l2x0_saved_regs:
.long 0
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/errno.h>
#include <asm/cacheflush.h>
#include <mach/common.h>
int platform_cpu_kill(unsigned int cpu)
{
return 1;
}
/*
* platform-specific code to shutdown a CPU
*
* Called with IRQs disabled
*/
void platform_cpu_die(unsigned int cpu)
{
flush_cache_all();
imx_enable_cpu(cpu, false);
cpu_do_idle();
/* We should never return from idle */
panic("cpu %d unexpectedly exit from shutdown\n", cpu);
}
int platform_cpu_disable(unsigned int cpu)
{
/*
* we don't allow CPU 0 to be shutdown (it is still too special
* e.g. clock tick interrupts)
*/
return cpu == 0 ? -EPERM : 0;
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <asm/page.h>
#include <asm/sizes.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
static struct map_desc imx_lluart_desc = {
#ifdef CONFIG_DEBUG_IMX6Q_UART
.virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
.pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
.length = MX6Q_UART4_SIZE,
.type = MT_DEVICE,
#endif
};
void __init imx_lluart_map_io(void)
{
if (imx_lluart_desc.virtual)
iotable_init(&imx_lluart_desc, 1);
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/clockchips.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/smp_twd.h>
/*
* Setup the local clock events for a CPU.
*/
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
if (!twd_base) {
twd_base = of_iomap(np, 0);
WARN_ON(!twd_base);
}
evt->irq = irq_of_parse_and_map(np, 0);
twd_timer_setup(evt);
return 0;
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
#include <mach/hardware.h>
static void __init imx6q_init_machine(void)
{
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
imx6q_pm_init();
}
static void __init imx6q_map_io(void)
{
imx_lluart_map_io();
imx_scu_map_io();
}
static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
struct device_node *interrupt_parent)
{
static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
32 * 7; /* imx6q gets 7 gpio ports */
irq_domain_add_simple(np, gpio_irq_base);
gpio_irq_base += 32;
}
static const struct of_device_id imx6q_irq_match[] __initconst = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{ .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
{ /* sentinel */ }
};
static void __init imx6q_init_irq(void)
{
l2x0_of_init(0, ~0UL);
imx_src_init();
imx_gpc_init();
of_irq_init(imx6q_irq_match);
}
static void __init imx6q_timer_init(void)
{
mx6q_clocks_init();
}
static struct sys_timer imx6q_timer = {
.init = imx6q_timer_init,
};
static const char *imx6q_dt_compat[] __initdata = {
"fsl,imx6q-sabreauto",
NULL,
};
DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
.map_io = imx6q_map_io,
.init_irq = imx6q_init_irq,
.handle_irq = imx6q_handle_irq,
.timer = &imx6q_timer,
.init_machine = imx6q_init_machine,
.dt_compat = imx6q_dt_compat,
MACHINE_END
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#define MMDC_MAPSR 0x404
#define BP_MMDC_MAPSR_PSD 0
#define BP_MMDC_MAPSR_PSS 4
static int __devinit imx_mmdc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
void __iomem *mmdc_base, *reg;
u32 val;
int timeout = 0x400;
mmdc_base = of_iomap(np, 0);
WARN_ON(!mmdc_base);
reg = mmdc_base + MMDC_MAPSR;
/* Enable automatic power saving */
val = readl_relaxed(reg);
val &= ~(1 << BP_MMDC_MAPSR_PSD);
writel_relaxed(val, reg);
/* Ensure it's successfully enabled */
while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
cpu_relax();
if (unlikely(!timeout)) {
pr_warn("%s: failed to enable automatic power saving\n",
__func__);
return -EBUSY;
}
return 0;
}
static struct of_device_id imx_mmdc_dt_ids[] = {
{ .compatible = "fsl,imx6q-mmdc", },
{ /* sentinel */ }
};
static struct platform_driver imx_mmdc_driver = {
.driver = {
.name = "imx-mmdc",
.owner = THIS_MODULE,
.of_match_table = imx_mmdc_dt_ids,
},
.probe = imx_mmdc_probe,
};
static int __init imx_mmdc_init(void)
{
return platform_driver_register(&imx_mmdc_driver);
}
postcore_initcall(imx_mmdc_init);
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/smp.h>
#include <asm/page.h>
#include <asm/smp_scu.h>
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/hardware.h>
static void __iomem *scu_base;
static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
.length = SZ_4K,
.type = MT_DEVICE,
};
void __init imx_scu_map_io(void)
{
unsigned long base;
/* Get SCU base */
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
scu_io_desc.virtual = IMX_IO_P2V(base);
scu_io_desc.pfn = __phys_to_pfn(base);
iotable_init(&scu_io_desc, 1);
scu_base = IMX_IO_ADDRESS(base);
}
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_secondary_init(0);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
imx_set_cpu_jump(cpu, v7_secondary_startup);
imx_enable_cpu(cpu, true);
return 0;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
void __init smp_init_cpus(void)
{
int i, ncores;
ncores = scu_get_core_count(scu_base);
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
set_smp_cross_call(gic_raise_softirq);
}
void imx_smp_prepare(void)
{
scu_enable(scu_base);
}
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
imx_smp_prepare();
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/suspend.h>
#include <asm/cacheflush.h>
#include <asm/proc-fns.h>
#include <asm/suspend.h>
#include <asm/hardware/cache-l2x0.h>
#include <mach/common.h>
#include <mach/hardware.h>
extern unsigned long phys_l2x0_saved_regs;
static int imx6q_suspend_finish(unsigned long val)
{
cpu_do_idle();
return 0;
}
static int imx6q_pm_enter(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_MEM:
imx6q_set_lpm(STOP_POWER_OFF);
imx_gpc_pre_suspend();
imx_set_cpu_jump(0, v7_cpu_resume);
/* Zzz ... */
cpu_suspend(0, imx6q_suspend_finish);
imx_smp_prepare();
imx_gpc_post_resume();
break;
default:
return -EINVAL;
}
return 0;
}
static const struct platform_suspend_ops imx6q_pm_ops = {
.enter = imx6q_pm_enter,
.valid = suspend_valid_only_mem,
};
void __init imx6q_pm_init(void)
{
/*
* The l2x0 core code provides an infrastucture to save and restore
* l2x0 registers across suspend/resume cycle. But because imx6q
* retains L2 content during suspend and needs to resume L2 before
* MMU is enabled, it can only utilize register saving support and
* have to take care of restoring on its own. So we save physical
* address of the data structure used by l2x0 core to save registers,
* and later restore the necessary ones in imx6q resume entry.
*/
phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
suspend_set_ops(&imx6q_pm_ops);
}
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/unified.h>
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
static void __iomem *src_base;
void imx_enable_cpu(int cpu, bool enable)
{
u32 mask, val;
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
val = readl_relaxed(src_base + SRC_SCR);
val = enable ? val | mask : val & ~mask;
writel_relaxed(val, src_base + SRC_SCR);
}
void imx_set_cpu_jump(int cpu, void *jump_addr)
{
writel_relaxed(BSYM(virt_to_phys(jump_addr)),
src_base + SRC_GPR1 + cpu * 8);
}
void __init imx_src_init(void)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
src_base = of_iomap(np, 0);
WARN_ON(!src_base);
}
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
......
obj-y := common.o
obj-y += time.o
obj-y += io.o
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*
* All enquiries to support@picochip.com
*/
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/hardware/vic.h>
#include <mach/map.h>
#include <mach/picoxcell_soc.h>
#include "common.h"
static void __init picoxcell_init_machine(void)
{
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *picoxcell_dt_match[] = {
"picochip,pc3x2",
"picochip,pc3x3",
NULL
};
static const struct of_device_id vic_of_match[] __initconst = {
{ .compatible = "arm,pl192-vic" },
{ /* Sentinel */ }
};
static void __init picoxcell_init_irq(void)
{
vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
}
DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
.map_io = picoxcell_map_io,
.nr_irqs = ARCH_NR_IRQS,
.init_irq = picoxcell_init_irq,
.timer = &picoxcell_timer,
.init_machine = picoxcell_init_machine,
.dt_compat = picoxcell_dt_match,
MACHINE_END
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*
* All enquiries to support@picochip.com
*/
#ifndef __PICOXCELL_COMMON_H__
#define __PICOXCELL_COMMON_H__
#include <asm/mach/time.h>
extern struct sys_timer picoxcell_timer;
extern void picoxcell_map_io(void);
#endif /* __PICOXCELL_COMMON_H__ */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*
* Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
* accesses to the 8250.
*/
#include <linux/serial_reg.h>
#include <mach/hardware.h>
#include <mach/map.h>
#define UART_SHIFT 2
.macro addruart, rp, rv
ldr \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
ldr \rp, =PICOXCELL_UART1_BASE
.endm
.macro senduart,rd,rx
str \rd, [\rx, #UART_TX << UART_SHIFT]
.endm
.macro busyuart,rd,rx
1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT]
and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
bne 1002b
.endm
/* The UART's don't have any flow control IO's wired up. */
.macro waituart,rd,rx
.endm
/*
* entry-macro.S
*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* Low-level IRQ helper macros for picoXcell platforms
*
* 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>
#include <mach/map.h>
#define VA_VIC0 IO_ADDRESS(PICOXCELL_VIC0_BASE)
#define VA_VIC1 IO_ADDRESS(PICOXCELL_VIC1_BASE)
#include <asm/entry-macro-vic2.S>
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* This file contains the hardware definitions of the picoXcell SoC devices.
*
* 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.
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <mach/picoxcell_soc.h>
#endif
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
/* No ioports, but needed for driver compatibility. */
#define __io(a) __typesafe_io(a)
/* No PCI possible on picoxcell. */
#define __mem_pci(a) (a)
#endif /* __ASM_ARM_ARCH_IO_H */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* This file contains the hardware definitions of the picoXcell SoC devices.
*
* 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.
*/
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
#define ARCH_NR_IRQS 64
#define NR_IRQS (128 + ARCH_NR_IRQS)
#define IRQ_VIC0_BASE 0
#define IRQ_VIC1_BASE 32
#endif /* __MACH_IRQS_H */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*/
#ifndef __PICOXCELL_MAP_H__
#define __PICOXCELL_MAP_H__
#define PHYS_TO_IO(x) (((x) & 0x00ffffff) | 0xfe000000)
#ifdef __ASSEMBLY__
#define IO_ADDRESS(x) PHYS_TO_IO((x))
#else
#define IO_ADDRESS(x) (void __iomem __force *)(PHYS_TO_IO((x)))
#endif
#endif /* __PICOXCELL_MAP_H__ */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* This file contains the hardware definitions of the picoXcell SoC devices.
*
* 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.
*/
#ifndef __PICOXCELL_SOC_H__
#define __PICOXCELL_SOC_H__
#define PICOXCELL_UART1_BASE 0x80230000
#define PICOXCELL_PERIPH_BASE 0x80000000
#define PICOXCELL_PERIPH_LENGTH SZ_4M
#define PICOXCELL_VIC0_BASE 0x80060000
#define PICOXCELL_VIC1_BASE 0x80064000
#endif /* __PICOXCELL_SOC_H__ */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*/
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static inline void arch_idle(void)
{
/*
* This should do all the clock switching and wait for interrupt
* tricks.
*/
cpu_do_idle();
}
static inline void arch_reset(int mode, const char *cmd)
{
/* Watchdog reset to go here. */
}
#endif /* __ASM_ARCH_SYSTEM_H */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __TIMEX_H__
#define __TIMEX_H__
/* Bogus value to allow the kernel to compile. */
#define CLOCK_TICK_RATE 1000000
#endif /* __TIMEX_H__ */
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define putc(c)
#define flush()
#define arch_decomp_setup()
#define arch_decomp_wdog()
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*/
#define VMALLOC_END 0xfe000000UL
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*
* All enquiries to support@picochip.com
*/
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
#include <asm/mach/map.h>
#include <mach/map.h>
#include <mach/picoxcell_soc.h>
#include "common.h"
void __init picoxcell_map_io(void)
{
struct map_desc io_map = {
.virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
.pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE),
.length = PICOXCELL_PERIPH_LENGTH,
.type = MT_DEVICE,
};
iotable_init(&io_map, 1);
}
/*
* Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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.
*
* All enquiries to support@picochip.com
*/
#include <linux/dw_apb_timer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched.h>
#include <asm/mach/time.h>
#include <asm/sched_clock.h>
#include "common.h"
static void timer_get_base_and_rate(struct device_node *np,
void __iomem **base, u32 *rate)
{
*base = of_iomap(np, 0);
if (!*base)
panic("Unable to map regs for %s", np->name);
if (of_property_read_u32(np, "clock-freq", rate))
panic("No clock-freq property for %s", np->name);
}
static void picoxcell_add_clockevent(struct device_node *event_timer)
{
void __iomem *iobase;
struct dw_apb_clock_event_device *ced;
u32 irq, rate;
irq = irq_of_parse_and_map(event_timer, 0);
if (irq == NO_IRQ)
panic("No IRQ for clock event timer");
timer_get_base_and_rate(event_timer, &iobase, &rate);
ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
rate);
if (!ced)
panic("Unable to initialise clockevent device");
dw_apb_clockevent_register(ced);
}
static void picoxcell_add_clocksource(struct device_node *source_timer)
{
void __iomem *iobase;
struct dw_apb_clocksource *cs;
u32 rate;
timer_get_base_and_rate(source_timer, &iobase, &rate);
cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
if (!cs)
panic("Unable to initialise clocksource device");
dw_apb_clocksource_start(cs);
dw_apb_clocksource_register(cs);
}
static DEFINE_CLOCK_DATA(cd);
static void __iomem *sched_io_base;
unsigned long long notrace sched_clock(void)
{
cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
return cyc_to_sched_clock(&cd, cyc, (u32)~0);
}
static void notrace picoxcell_update_sched_clock(void)
{
cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
update_sched_clock(&cd, cyc, (u32)~0);
}
static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-rtc" },
{ /* Sentinel */ },
};
static void picoxcell_init_sched_clock(void)
{
struct device_node *sched_timer;
u32 rate;
sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
if (!sched_timer)
panic("No RTC for sched clock to use");
timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
of_node_put(sched_timer);
init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
}
static const struct of_device_id picoxcell_timer_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-timer" },
{},
};
static void __init picoxcell_timer_init(void)
{
struct device_node *event_timer, *source_timer;
event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
if (!event_timer)
panic("No timer for clockevent");
picoxcell_add_clockevent(event_timer);
source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
if (!source_timer)
panic("No timer for clocksource");
picoxcell_add_clocksource(source_timer);
of_node_put(source_timer);
picoxcell_init_sched_clock();
}
struct sys_timer picoxcell_timer = {
.init = picoxcell_timer_init,
};
...@@ -819,10 +819,10 @@ config CACHE_FEROCEON_L2_WRITETHROUGH ...@@ -819,10 +819,10 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
config CACHE_L2X0 config CACHE_L2X0
bool "Enable the L2x0 outer cache controller" bool "Enable the L2x0 outer cache controller"
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \ REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \
ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \ ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \ ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK
default y default y
select OUTER_CACHE select OUTER_CACHE
select OUTER_CACHE_SYNC select OUTER_CACHE_SYNC
......
...@@ -6,7 +6,7 @@ menu "Freescale MXC Implementations" ...@@ -6,7 +6,7 @@ menu "Freescale MXC Implementations"
choice choice
prompt "Freescale CPU family:" prompt "Freescale CPU family:"
default ARCH_MX3 default ARCH_IMX_V6_V7
config ARCH_IMX_V4_V5 config ARCH_IMX_V4_V5
bool "i.MX1, i.MX21, i.MX25, i.MX27" bool "i.MX1, i.MX21, i.MX25, i.MX27"
...@@ -16,10 +16,13 @@ config ARCH_IMX_V4_V5 ...@@ -16,10 +16,13 @@ config ARCH_IMX_V4_V5
This enables support for systems based on the Freescale i.MX ARMv4 This enables support for systems based on the Freescale i.MX ARMv4
and ARMv5 SoCs and ARMv5 SoCs
config ARCH_MX3 config ARCH_IMX_V6_V7
bool "MX3-based" bool "i.MX3, i.MX6"
select AUTO_ZRELADDR if !ZBOOT_ROM
select ARM_PATCH_PHYS_VIRT
help help
This enables support for systems based on the Freescale i.MX3 family This enables support for systems based on the Freescale i.MX3 and i.MX6
family.
config ARCH_MX5 config ARCH_MX5
bool "i.MX50, i.MX51, i.MX53" bool "i.MX50, i.MX51, i.MX53"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# Common support # Common support
obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
# MX51 uses the TZIC interrupt controller, older platforms use AVIC obj-$(CONFIG_ARM_GIC) += gic.o
obj-$(CONFIG_MXC_TZIC) += tzic.o obj-$(CONFIG_MXC_TZIC) += tzic.o
obj-$(CONFIG_MXC_AVIC) += avic.o obj-$(CONFIG_MXC_AVIC) += avic.o
......
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* 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/io.h>
#include <asm/exception.h>
#include <asm/localtimer.h>
#include <asm/hardware/gic.h>
#ifdef CONFIG_SMP
#include <asm/smp.h>
#endif
asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
u32 irqstat, irqnr;
do {
irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
irqnr = irqstat & 0x3ff;
if (irqnr == 1023)
break;
if (irqnr > 29 && irqnr < 1021)
handle_IRQ(irqnr, regs);
#ifdef CONFIG_SMP
else if (irqnr < 16) {
writel_relaxed(irqstat, gic_cpu_base_addr +
GIC_CPU_EOI);
handle_IPI(irqnr, regs);
}
#endif
#ifdef CONFIG_LOCAL_TIMERS
else if (irqnr == 29) {
writel_relaxed(irqstat, gic_cpu_base_addr +
GIC_CPU_EOI);
handle_local_timer(regs);
}
#endif
} while (1);
}
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct platform_device; struct platform_device;
struct clk; struct clk;
enum mxc_cpu_pwr_mode;
extern void mx1_map_io(void); extern void mx1_map_io(void);
extern void mx21_map_io(void); extern void mx21_map_io(void);
...@@ -66,6 +67,7 @@ extern int mx53_clocks_init(unsigned long ckil, unsigned long osc, ...@@ -66,6 +67,7 @@ extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2); unsigned long ckih1, unsigned long ckih2);
extern int mx51_clocks_init_dt(void); extern int mx51_clocks_init_dt(void);
extern int mx53_clocks_init_dt(void); extern int mx53_clocks_init_dt(void);
extern int mx6q_clocks_init(void);
extern struct platform_device *mxc_register_gpio(char *name, int id, extern struct platform_device *mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high); resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
extern void mxc_set_cpu_type(unsigned int type); extern void mxc_set_cpu_type(unsigned int type);
...@@ -88,6 +90,7 @@ extern void imx_print_silicon_rev(const char *cpu, int srev); ...@@ -88,6 +90,7 @@ extern void imx_print_silicon_rev(const char *cpu, int srev);
void avic_handle_irq(struct pt_regs *); void avic_handle_irq(struct pt_regs *);
void tzic_handle_irq(struct pt_regs *); void tzic_handle_irq(struct pt_regs *);
void gic_handle_irq(struct pt_regs *);
#define imx1_handle_irq avic_handle_irq #define imx1_handle_irq avic_handle_irq
#define imx21_handle_irq avic_handle_irq #define imx21_handle_irq avic_handle_irq
...@@ -98,10 +101,36 @@ void tzic_handle_irq(struct pt_regs *); ...@@ -98,10 +101,36 @@ void tzic_handle_irq(struct pt_regs *);
#define imx50_handle_irq tzic_handle_irq #define imx50_handle_irq tzic_handle_irq
#define imx51_handle_irq tzic_handle_irq #define imx51_handle_irq tzic_handle_irq
#define imx53_handle_irq tzic_handle_irq #define imx53_handle_irq tzic_handle_irq
#define imx6q_handle_irq gic_handle_irq
extern void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
#ifdef CONFIG_DEBUG_LL
extern void imx_lluart_map_io(void);
#else
static inline void imx_lluart_map_io(void) {}
#endif
extern void v7_cpu_resume(void);
extern u32 *pl310_get_save_ptr(void);
#ifdef CONFIG_SMP
extern void v7_secondary_startup(void);
extern void imx_scu_map_io(void);
extern void imx_smp_prepare(void);
#else
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
extern void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
extern void imx_src_init(void);
extern void imx_gpc_init(void);
extern void imx_gpc_pre_suspend(void);
extern void imx_gpc_post_resume(void);
extern void imx51_babbage_common_init(void); extern void imx51_babbage_common_init(void);
extern void imx53_ard_common_init(void); extern void imx53_ard_common_init(void);
extern void imx53_evk_common_init(void); extern void imx53_evk_common_init(void);
extern void imx53_qsb_common_init(void); extern void imx53_qsb_common_init(void);
extern void imx53_smd_common_init(void); extern void imx53_smd_common_init(void);
extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
extern void imx6q_pm_init(void);
#endif #endif
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#define UART_PADDR MX51_UART1_BASE_ADDR #define UART_PADDR MX51_UART1_BASE_ADDR
#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART) #elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
#define UART_PADDR MX53_UART1_BASE_ADDR #define UART_PADDR MX53_UART1_BASE_ADDR
#elif defined (CONFIG_DEBUG_IMX6Q_UART)
#define UART_PADDR MX6Q_UART4_BASE_ADDR
#endif #endif
#define UART_VADDR IMX_IO_ADDRESS(UART_PADDR) #define UART_VADDR IMX_IO_ADDRESS(UART_PADDR)
......
...@@ -22,3 +22,9 @@ ...@@ -22,3 +22,9 @@
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
.endm .endm
.macro test_for_ipi, irqnr, irqstat, base, tmp
.endm
.macro test_for_ltirq, irqnr, irqstat, base, tmp
.endm
...@@ -91,6 +91,11 @@ ...@@ -91,6 +91,11 @@
* SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000 * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000
* AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000 * AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000
* AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000 * AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000
* mx6q:
* SCU 0x00a00000+0x001000 -> 0xf4000000+0x001000
* CCM 0x020c4000+0x004000 -> 0xf42c4000+0x004000
* ANATOP 0x020c8000+0x001000 -> 0xf42c8000+0x001000
* UART4 0x021f0000+0x004000 -> 0xf42f0000+0x004000
*/ */
#define IMX_IO_P2V(x) ( \ #define IMX_IO_P2V(x) ( \
0xf4000000 + \ 0xf4000000 + \
...@@ -102,6 +107,7 @@ ...@@ -102,6 +107,7 @@
#include <mach/mxc.h> #include <mach/mxc.h>
#include <mach/mx6q.h>
#include <mach/mx50.h> #include <mach/mx50.h>
#include <mach/mx51.h> #include <mach/mx51.h>
#include <mach/mx53.h> #include <mach/mx53.h>
......
...@@ -14,9 +14,15 @@ ...@@ -14,9 +14,15 @@
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>
/* /*
* SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64 * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
* have 128 IRQs, and those with AVIC have 64.
*
* To support single image, the biggest number should be defined on
* top of the list.
*/ */
#ifdef CONFIG_MXC_TZIC #if defined CONFIG_ARM_GIC
#define MXC_INTERNAL_IRQS 160
#elif defined CONFIG_MXC_TZIC
#define MXC_INTERNAL_IRQS 128 #define MXC_INTERNAL_IRQS 128
#else #else
#define MXC_INTERNAL_IRQS 64 #define MXC_INTERNAL_IRQS 64
......
/*
* Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2011 Linaro Ltd.
*
* 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
*/
#ifndef __MACH_MX6Q_H__
#define __MACH_MX6Q_H__
#define MX6Q_IO_P2V(x) IMX_IO_P2V(x)
#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x))
/*
* The following are the blocks that need to be statically mapped.
* For other blocks, the base address really should be retrieved from
* device tree.
*/
#define MX6Q_SCU_BASE_ADDR 0x00a00000
#define MX6Q_SCU_SIZE 0x1000
#define MX6Q_CCM_BASE_ADDR 0x020c4000
#define MX6Q_CCM_SIZE 0x4000
#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
#define MX6Q_ANATOP_SIZE 0x1000
#define MX6Q_UART4_BASE_ADDR 0x021f0000
#define MX6Q_UART4_SIZE 0x4000
#endif /* __MACH_MX6Q_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment