ARM: SoC platform changes for 3.19

New and updated SoC support, notable changes include:
 
 * bcm: brcmstb SMP support
 * bcm: initial iproc/cygnus support
 * exynos: Exynos4415 SoC support
 * exynos: PMU and suspend support for Exynos5420
 * exynos: PMU support for Exynos3250
 * exynos: pm related maintenance
 * imx: new LS1021A SoC support
 * imx: vybrid 610 global timer support
 * integrator: convert to using multiplatform configuration
 * mediatek: earlyprintk support for mt8127/mt8135
 * meson: meson8 soc and l2 cache controller support
 * mvebu: Armada 38x CPU hotplug support
 * mvebu: drop support for prerelease Armada 375 Z1 stepping
 * mvebu: extended suspend support, now works on Armada 370/XP
 * omap: hwmod related maintenance
 * omap: prcm cleanup
 * pxa: initial pxa27x DT handling
 * rockchip: SMP support for rk3288
 * rockchip: add cpu frequency scaling support
 * shmobile: r8a7740 power domain support
 * shmobile: various small restart, timer, pci apmu changes
 * sunxi: Allwinner A80 (sun9i) earlyprintk support
 * ux500: power domain support
 
 Overall, a significant chunk of changes, coming mostly from
 the usual suspects: omap, shmobile, samsung and mvebu, all of
 which already contain a lot of platform specific code in
 arch/arm.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIVAwUAVIcjyGCrR//JCVInAQJJCRAA1Tm+HZGiAiTvXEAcm/T9tIA08uqtawHt
 cqyEAUyrnE8QxE4EhUd2pTw4EunVusqKF5EsDxOzw7b3ukUdLAWZE7bqBOSIJLqn
 hrfsQQ8dXLbyC7T/CHPnBVeM+pn9LiIc9qzpZ0YToiMnHBBI4vKFQntBjd31yoRE
 hN08I6AmDjQolOzzlqR1fuM0uZaKiHIcytdauTt3Vfqgg7FTHcTy3u1kClHTR1Lp
 m/KuDothGpR5OKjSnUQz7EO5V3KJEnaKey8z2xM1a7DLLAvJ6r2+DUaDopv9Dbz1
 W/V3H7fi5tLvillVa8xmlmzqWZbPc1xw8MWqvHZSWIMRZqloAHpC1VWKn0ZuH4SW
 5Bj4ubSrpYjJxjKYfrxtjmuzru3A2jWBNTSP5A4nsny0C3AUsXkfRmRS0VNdegF8
 sUdQ1MF8vEMpQT3QPH88+ccFHeIgqbcayhKqLPf7r8q0kwlym5N7Y2amU2A/O6qz
 +324r+yzfSA70VgJZ5EhXxWVDOPB4Lc8EtoWnH6T/kjncIMwzEsbEbyB3X1OaREW
 pVn3PNo06VjHLYoiHX+8G99pOFR/JZvaQs6jGCXLs+Orjp5WfP+kafkWqcB5GAKU
 Pfd3AQsl6rKAITdu0XsTdPiICNS4CmBiWYPepQsTa3pQaNgB7fwZNQKelNRIdGc+
 dF1lnQ7CXLQ=
 =lFoH
 -----END PGP SIGNATURE-----

Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC platform changes from Arnd Bergmann:
 "New and updated SoC support, notable changes include:

   - bcm:
        brcmstb SMP support
        initial iproc/cygnus support
   - exynos:
        Exynos4415 SoC support
        PMU and suspend support for Exynos5420
        PMU support for Exynos3250
        pm related maintenance
   - imx:
        new LS1021A SoC support
        vybrid 610 global timer support
   - integrator:
        convert to using multiplatform configuration
   - mediatek:
        earlyprintk support for mt8127/mt8135
   - meson:
        meson8 soc and l2 cache controller support
   - mvebu:
        Armada 38x CPU hotplug support
        drop support for prerelease Armada 375 Z1 stepping
        extended suspend support, now works on Armada 370/XP
   - omap:
        hwmod related maintenance
        prcm cleanup
   - pxa:
        initial pxa27x DT handling
   - rockchip:
        SMP support for rk3288
        add cpu frequency scaling support
   - shmobile:
        r8a7740 power domain support
        various small restart, timer, pci apmu changes
   - sunxi:
        Allwinner A80 (sun9i) earlyprintk support
   - ux500:
        power domain support

  Overall, a significant chunk of changes, coming mostly from the usual
  suspects: omap, shmobile, samsung and mvebu, all of which already
  contain a lot of platform specific code in arch/arm"

* tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (187 commits)
  ARM: mvebu: use the cpufreq-dt platform_data for independent clocks
  soc: integrator: Add terminating entry for integrator_cm_match
  ARM: mvebu: add SDRAM controller description for Armada XP
  ARM: mvebu: adjust mbus controller description on Armada 370/XP
  ARM: mvebu: add suspend/resume DT information for Armada XP GP
  ARM: mvebu: synchronize secondary CPU clocks on resume
  ARM: mvebu: make sure MMU is disabled in armada_370_xp_cpu_resume
  ARM: mvebu: Armada XP GP specific suspend/resume code
  ARM: mvebu: reserve the first 10 KB of each memory bank for suspend/resume
  ARM: mvebu: implement suspend/resume support for Armada XP
  clk: mvebu: add suspend/resume for gatable clocks
  bus: mvebu-mbus: provide a mechanism to save SDRAM window configuration
  bus: mvebu-mbus: suspend/resume support
  clocksource: time-armada-370-xp: add suspend/resume support
  irqchip: armada-370-xp: Add suspend/resume support
  ARM: add lolevel debug support for asm9260
  ARM: add mach-asm9260
  ARM: EXYNOS: use u8 for val[] in struct exynos_pmu_conf
  power: reset: imx-snvs-poweroff: add power off driver for i.mx6
  ARM: imx: temporarily remove CONFIG_SOC_FSL from LS1021A
  ...
This commit is contained in:
Linus Torvalds 2014-12-09 14:38:28 -08:00
commit 6cd94d5e57
214 changed files with 6336 additions and 2360 deletions

View File

@ -7,32 +7,14 @@ world, which changes the way some things have to be initialized. This makes
a need to provide an interface for such platforms to specify available firmware
operations and call them when needed.
Firmware operations can be specified using struct firmware_ops
struct firmware_ops {
/*
* Enters CPU idle mode
*/
int (*do_idle)(void);
/*
* Sets boot address of specified physical CPU
*/
int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
/*
* Boots specified physical CPU
*/
int (*cpu_boot)(int cpu);
/*
* Initializes L2 cache
*/
int (*l2x0_init)(void);
};
and then registered with register_firmware_ops function
Firmware operations can be specified by filling in a struct firmware_ops
with appropriate callbacks and then registering it with register_firmware_ops()
function.
void register_firmware_ops(const struct firmware_ops *ops)
the ops pointer must be non-NULL.
The ops pointer must be non-NULL. More information about struct firmware_ops
and its members can be found in arch/arm/include/asm/firmware.h header.
There is a default, empty set of operations provided, so there is no need to
set anything if platform does not require firmware operations.

View File

@ -37,16 +37,26 @@ SunXi family
http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
- Allwinner A23
+ Not Supported
+ Datasheet
http://dl.linux-sunxi.org/A23/A23%20Datasheet%20V1.0%2020130830.pdf
+ User Manual
http://dl.linux-sunxi.org/A23/A23%20User%20Manual%20V1.0%2020130830.pdf
* Quad ARM Cortex-A7 based SoCs
- Allwinner A31 (sun6i)
+ Datasheet
http://dl.linux-sunxi.org/A31/A31%20Datasheet%20-%20v1.00%20(2012-12-24).pdf
http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20datasheet%20V1.3%2020131106.pdf
+ User Manual
http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20user%20manual%20V1.1%2020130630.pdf
- Allwinner A31s (sun6i)
+ Not Supported
+ Datasheet
http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20datasheet%20V1.3%2020131106.pdf
+ User Manual
http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20User%20Manual%20%20V1.0%2020130322.pdf
* Quad ARM Cortex-A15, Quad ARM Cortex-A7 based SoCs
- Allwinner A80
+ Not Supported
+ Datasheet
http://dl.linux-sunxi.org/A80/A80_Datasheet_Revision_1.0_0404.pdf

View File

@ -2,7 +2,9 @@ Amlogic MesonX device tree bindings
-------------------------------------------
Boards with the Amlogic Meson6 SoC shall have the following properties:
Required root node property:
compatible: "amlogic,meson6"
compatible = "amlogic,meson6";
Boards with the Amlogic Meson8 SoC shall have the following properties:
Required root node property:
compatible: "amlogic,meson8";

View File

@ -227,6 +227,15 @@ nodes to be present and contain the properties described below.
# List of phandles to idle state nodes supported
by this cpu [3].
- rockchip,pmu
Usage: optional for systems that have an "enable-method"
property value of "rockchip,rk3066-smp"
While optional, it is the preferred way to get access to
the cpu-core power-domains.
Value type: <phandle>
Definition: Specifies the syscon node controlling the cpu core
power domains.
Example 1 (dual-cluster big.LITTLE system 32-bit):
cpus {

View File

@ -0,0 +1,12 @@
Allwinner sunXi Platforms Device Tree Bindings
Each device tree must specify which Allwinner SoC it uses,
using one of the following compatible strings:
allwinner,sun4i-a10
allwinner,sun5i-a10s
allwinner,sun5i-a13
allwinner,sun6i-a31
allwinner,sun7i-a20
allwinner,sun8i-a23
allwinner,sun9i-a80

View File

@ -0,0 +1,35 @@
* ST-Ericsson UX500 PM Domains
UX500 supports multiple PM domains which are used to gate power to one or
more peripherals on the SOC.
The implementation of PM domains for UX500 are based upon the generic PM domain
and use the corresponding DT bindings.
==PM domain providers==
Required properties:
- compatible: Must be "stericsson,ux500-pm-domains".
- #power-domain-cells : Number of cells in a power domain specifier, must be 1.
Example:
pm_domains: pm_domains0 {
compatible = "stericsson,ux500-pm-domains";
#power-domain-cells = <1>;
};
==PM domain consumers==
Required properties:
- power-domains: A phandle and PM domain specifier. Below are the list of
valid specifiers:
Index Specifier
----- ---------
0 DOMAIN_VAPE
Example:
sdi0_per1@80126000 {
compatible = "arm,pl18x", "arm,primecell";
power-domains = <&pm_domains DOMAIN_VAPE>
};

View File

@ -48,9 +48,12 @@ Required properties:
- compatible: Should be set to "marvell,mbus-controller".
- reg: Device's register space.
Two entries are expected (see the examples below):
the first one controls the devices decoding window and
the second one controls the SDRAM decoding window.
Two or three entries are expected (see the examples below):
the first one controls the devices decoding window,
the second one controls the SDRAM decoding window and
the third controls the MBus bridge (only with the
marvell,armada370-mbus and marvell,armadaxp-mbus
compatible strings)
Example:
@ -67,7 +70,7 @@ Example:
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
@ -126,7 +129,7 @@ are skipped.
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* more children ...*/
@ -170,7 +173,7 @@ Using this macro, the above example would be:
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
/* other children */
@ -266,7 +269,7 @@ See the example below, where a more complete device tree is shown:
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
mbusc: mbus-controller@20000 {
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
};
interrupt-controller@20000 {

View File

@ -0,0 +1,21 @@
Device Tree bindings for MVEBU SDRAM controllers
The Marvell EBU SoCs all have a SDRAM controller. The SDRAM controller
differs from one SoC variant to another, but they also share a number
of commonalities.
For now, this Device Tree binding documentation only documents the
Armada XP SDRAM controller.
Required properties:
- compatible: for Armada XP, "marvell,armada-xp-sdram-controller"
- reg: a resource specifier for the register space, which should
include all SDRAM controller registers as per the datasheet.
Example:
sdramc@1400 {
compatible = "marvell,armada-xp-sdram-controller";
reg = <0x1400 0x500>;
};

View File

@ -0,0 +1,23 @@
i.mx6 Poweroff Driver
SNVS_LPCR in SNVS module can power off the whole system by pull
PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
If you don't want to use PMIC_ON_REQ as power on/off control,
please set status='disabled' to disable this driver.
Required Properties:
-compatible: "fsl,sec-v4.0-poweroff"
-reg: Specifies the physical address of the SNVS_LPCR register
Example:
snvs@020cc000 {
compatible = "fsl,sec-v4.0-mon", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x020cc000 0x4000>;
.....
snvs_poweroff: snvs-poweroff@38 {
compatible = "fsl,sec-v4.0-poweroff";
reg = <0x38 0x4>;
};
}

View File

@ -91,6 +91,7 @@ lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
mediatek MediaTek Inc.
merrii Merrii Technology Co., Ltd.
micrel Micrel Inc.
microchip Microchip Technology Inc.
micron Micron Technology Inc.

View File

@ -1379,6 +1379,7 @@ F: arch/arm/configs/lager_defconfig
F: arch/arm/configs/mackerel_defconfig
F: arch/arm/configs/marzen_defconfig
F: arch/arm/configs/shmobile_defconfig
F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/
F: drivers/sh/

View File

@ -320,24 +320,6 @@ config ARCH_MULTIPLATFORM
select SPARSE_IRQ
select USE_OF
config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family"
select ARM_AMBA
select ARM_PATCH_PHYS_VIRT if MMU
select AUTO_ZRELADDR
select COMMON_CLK
select COMMON_CLK_VERSATILE
select GENERIC_CLOCKEVENTS
select HAVE_TCM
select ICST
select MULTI_IRQ_HANDLER
select PLAT_VERSATILE
select SPARSE_IRQ
select USE_OF
select VERSATILE_FPGA_IRQ
help
Support for ARM's Integrator platform.
config ARCH_REALVIEW
bool "ARM Ltd. RealView family"
select ARCH_WANT_OPTIONAL_GPIOLIB
@ -857,6 +839,8 @@ config ARCH_VIRT
#
source "arch/arm/mach-mvebu/Kconfig"
source "arch/arm/mach-asm9260/Kconfig"
source "arch/arm/mach-at91/Kconfig"
source "arch/arm/mach-axxia/Kconfig"

View File

@ -93,6 +93,27 @@ choice
prompt "Kernel low-level debugging port"
depends on DEBUG_LL
config DEBUG_ASM9260_UART
bool "Kernel low-level debugging via asm9260 UART"
depends on MACH_ASM9260
help
Say Y here if you want the debug print routines to direct
their output to an UART or USART port on asm9260 based
machines.
DEBUG_UART_PHYS | DEBUG_UART_VIRT
0x80000000 | 0xf0000000 | UART0
0x80004000 | 0xf0004000 | UART1
0x80008000 | 0xf0008000 | UART2
0x8000c000 | 0xf000c000 | UART3
0x80010000 | 0xf0010000 | UART4
0x80014000 | 0xf0014000 | UART5
0x80018000 | 0xf0018000 | UART6
0x8001c000 | 0xf001c000 | UART7
0x80020000 | 0xf0020000 | UART8
0x80024000 | 0xf0024000 | UART9
config AT91_DEBUG_LL_DBGU0
bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10 and 9rl"
depends on HAVE_AT91_DBGU0
@ -113,7 +134,7 @@ choice
config DEBUG_BCM_5301X
bool "Kernel low-level debugging on BCM5301X UART1"
depends on ARCH_BCM_5301X
select DEBUG_UART_PL01X
select DEBUG_UART_8250
config DEBUG_BCM_KONA_UART
bool "Kernel low-level debugging messages via BCM KONA UART"
@ -139,6 +160,17 @@ choice
Say Y here if you want kernel low-level debugging support
on Marvell Berlin SoC based platforms.
config DEBUG_BRCMSTB_UART
bool "Use BRCMSTB UART for low-level debug"
depends on ARCH_BRCMSTB
select DEBUG_UART_8250
help
Say Y here if you want the debug print routines to direct
their output to the first serial port on these devices.
If you have a Broadcom STB chip and would like early print
messages to appear over the UART, select this option.
config DEBUG_CLPS711X_UART1
bool "Kernel low-level debugging messages via UART1"
depends on ARCH_CLPS711X
@ -653,6 +685,64 @@ choice
Say Y here if you want kernel low-level debugging support
on Rockchip RK32xx based platforms.
config DEBUG_R7S72100_SCIF2
bool "Kernel low-level debugging messages via SCIF2 on R7S72100"
depends on ARCH_R7S72100
help
Say Y here if you want kernel low-level debugging support
via SCIF2 on Renesas RZ/A1H (R7S72100).
config DEBUG_RCAR_GEN1_SCIF0
bool "Kernel low-level debugging messages via SCIF0 on R8A7778"
depends on ARCH_R8A7778
help
Say Y here if you want kernel low-level debugging support
via SCIF0 on Renesas R-Car M1A (R8A7778).
config DEBUG_RCAR_GEN1_SCIF2
bool "Kernel low-level debugging messages via SCIF2 on R8A7779"
depends on ARCH_R8A7779
help
Say Y here if you want kernel low-level debugging support
via SCIF2 on Renesas R-Car H1 (R8A7779).
config DEBUG_RCAR_GEN2_SCIF0
bool "Kernel low-level debugging messages via SCIF0 on R8A7790/R8A7791/R8A7793)"
depends on ARCH_R8A7790 || ARCH_R8A7791 || ARCH_R8A7793
help
Say Y here if you want kernel low-level debugging support
via SCIF0 on Renesas R-Car H2 (R8A7790), M2-W (R8A7791), or
M2-N (R8A7793).
config DEBUG_RCAR_GEN2_SCIF2
bool "Kernel low-level debugging messages via SCIF2 on R8A7794"
depends on ARCH_R8A7794
help
Say Y here if you want kernel low-level debugging support
via SCIF2 on Renesas R-Car E2 (R8A7794).
config DEBUG_RMOBILE_SCIFA0
bool "Kernel low-level debugging messages via SCIFA0 on R8A73A4/SH7372"
depends on ARCH_R8A73A4 || ARCH_SH7372
help
Say Y here if you want kernel low-level debugging support
via SCIFA0 on Renesas R-Mobile APE6 (R8A73A4) or SH-Mobile
AP4 (SH7372).
config DEBUG_RMOBILE_SCIFA1
bool "Kernel low-level debugging messages via SCIFA1 on R8A7740"
depends on ARCH_R8A7740
help
Say Y here if you want kernel low-level debugging support
via SCIFA1 on Renesas R-Mobile A1 (R8A7740).
config DEBUG_RMOBILE_SCIFA4
bool "Kernel low-level debugging messages via SCIFA4 on SH73A0"
depends on ARCH_SH73A0
help
Say Y here if you want kernel low-level debugging support
via SCIFA4 on Renesas SH-Mobile AG5 (SH73A0).
config DEBUG_S3C_UART0
depends on PLAT_SAMSUNG
select DEBUG_EXYNOS_UART if ARCH_EXYNOS
@ -723,6 +813,14 @@ choice
their output to UART 2. The port must have been initialised
by the boot-loader before use.
config DEBUG_SA1100
depends on ARCH_SA1100
bool "Use SA1100 UARTs for low-level debug"
help
Say Y here if you want kernel low-level debugging support
on SA-11x0 UART ports. The kernel will check for the first
enabled UART in a sequence 3-1-2.
config DEBUG_SOCFPGA_UART
depends on ARCH_SOCFPGA
bool "Use SOCFPGA UART for low-level debug"
@ -731,6 +829,14 @@ choice
Say Y here if you want kernel low-level debugging support
on SOCFPGA based platforms.
config DEBUG_SUN9I_UART0
bool "Kernel low-level debugging messages via sun9i UART0"
depends on MACH_SUN9I
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
on Allwinner A80 based platforms on the UART0.
config DEBUG_SUNXI_UART0
bool "Kernel low-level debugging messages via sunXi UART0"
depends on ARCH_SUNXI
@ -866,6 +972,22 @@ choice
Say Y here if you want kernel low-level debugging support
for Mediatek mt6589 based platforms on UART0.
config DEBUG_MT8127_UART0
bool "Mediatek mt8127 UART0"
depends on ARCH_MEDIATEK
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
for Mediatek mt8127 based platforms on UART0.
config DEBUG_MT8135_UART3
bool "Mediatek mt8135 UART3"
depends on ARCH_MEDIATEK
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
for Mediatek mt8135 based platforms on UART3.
config DEBUG_VEXPRESS_UART0_DETECT
bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
depends on ARCH_VEXPRESS && CPU_CP15_MMU
@ -1041,7 +1163,9 @@ config DEBUG_STI_UART
config DEBUG_LL_INCLUDE
string
default "debug/sa1100.S" if DEBUG_SA1100
default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
default "debug/asm9260.S" if DEBUG_ASM9260_UART
default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2
default "debug/meson.S" if DEBUG_MESON_UARTAO
default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
@ -1061,6 +1185,14 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX6SX_UART
default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF2
default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA0
default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA1
default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA4
default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
default "debug/s5pv210.S" if DEBUG_S5PV210_UART
default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
@ -1106,6 +1238,7 @@ config DEBUG_UART_PHYS
default 0x02530c00 if DEBUG_KEYSTONE_UART0
default 0x02531000 if DEBUG_KEYSTONE_UART1
default 0x03010fe0 if ARCH_RPC
default 0x07000000 if DEBUG_SUN9I_UART0
default 0x10009000 if DEBUG_REALVIEW_STD_PORT || \
DEBUG_VEXPRESS_UART0_CA9
default 0x1010c000 if DEBUG_REALVIEW_PB1176_PORT
@ -1113,7 +1246,9 @@ config DEBUG_UART_PHYS
default 0x10126000 if DEBUG_RK3X_UART1
default 0x101f1000 if ARCH_VERSATILE
default 0x101fb000 if DEBUG_NOMADIK_UART
default 0x11002000 if DEBUG_MT8127_UART0
default 0x11006000 if DEBUG_MT6589_UART0
default 0x11009000 if DEBUG_MT8135_UART3
default 0x16000000 if ARCH_INTEGRATOR
default 0x18000300 if DEBUG_BCM_5301X
default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
@ -1135,6 +1270,7 @@ config DEBUG_UART_PHYS
default 0x78000000 if DEBUG_CNS3XXX
default 0x7c0003f8 if FOOTBRIDGE
default 0x78000000 if DEBUG_CNS3XXX
default 0x80010000 if DEBUG_ASM9260_UART
default 0x80070000 if DEBUG_IMX23_UART
default 0x80074000 if DEBUG_IMX28_UART
default 0x80230000 if DEBUG_PICOXCELL_UART
@ -1152,7 +1288,14 @@ config DEBUG_UART_PHYS
default 0xd4018000 if DEBUG_MMP_UART3
default 0xe0000000 if ARCH_SPEAR13XX
default 0xe4007000 if DEBUG_HIP04_UART
default 0xe6c40000 if DEBUG_RMOBILE_SCIFA0
default 0xe6c50000 if DEBUG_RMOBILE_SCIFA1
default 0xe6c80000 if DEBUG_RMOBILE_SCIFA4
default 0xe6e58000 if DEBUG_RCAR_GEN2_SCIF2
default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0
default 0xe8008000 if DEBUG_R7S72100_SCIF2
default 0xf0000be0 if ARCH_EBSA110
default 0xf040ab00 if DEBUG_BRCMSTB_UART
default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
ARCH_ORION5X
@ -1164,24 +1307,33 @@ config DEBUG_UART_PHYS
default 0xff690000 if DEBUG_RK32_UART2
default 0xffc02000 if DEBUG_SOCFPGA_UART
default 0xffd82340 if ARCH_IOP13XX
default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0
default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2
default 0xfff36000 if DEBUG_HIGHBANK_UART
default 0xfffe8600 if DEBUG_UART_BCM63XX
default 0xfffff700 if ARCH_IOP33X
depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_LL_UART_EFM32 || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX
DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
config DEBUG_UART_VIRT
hex "Virtual base address of debug UART"
default 0xe0010fe0 if ARCH_RPC
default 0xe1000000 if DEBUG_MSM_UART
default 0xf0000be0 if ARCH_EBSA110
default 0xf0010000 if DEBUG_ASM9260_UART
default 0xf01fb000 if DEBUG_NOMADIK_UART
default 0xf0201000 if DEBUG_BCM2835
default 0xf1000300 if DEBUG_BCM_5301X
default 0xf1002000 if DEBUG_MT8127_UART0
default 0xf1006000 if DEBUG_MT6589_UART0
default 0xf1009000 if DEBUG_MT8135_UART3
default 0xf11f1000 if ARCH_VERSATILE
default 0xf1600000 if ARCH_INTEGRATOR
default 0xf1c28000 if DEBUG_SUNXI_UART0
@ -1190,6 +1342,7 @@ config DEBUG_UART_VIRT
default 0xf6200000 if DEBUG_PXA_UART1
default 0xf4090000 if ARCH_LPC32XX
default 0xf4200000 if ARCH_GEMINI
default 0xf7000000 if DEBUG_SUN9I_UART0
default 0xf7000000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART0 || \
DEBUG_S3C2410_UART0)
default 0xf7004000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART1 || \
@ -1204,6 +1357,7 @@ config DEBUG_UART_VIRT
default 0xfb002000 if DEBUG_CNS3XXX
default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
default 0xfc40ab00 if DEBUG_BRCMSTB_UART
default 0xfcfe8600 if DEBUG_UART_BCM63XX
default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
default 0xfd000000 if ARCH_SPEAR13XX
@ -1244,12 +1398,12 @@ config DEBUG_UART_VIRT
depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX
DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
config DEBUG_UART_8250_SHIFT
int "Register offset shift for the 8250 debug UART"
depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
default 0 if FOOTBRIDGE || ARCH_IOP32X
default 0 if FOOTBRIDGE || ARCH_IOP32X || DEBUG_BCM_5301X
default 2
config DEBUG_UART_8250_WORD
@ -1260,7 +1414,8 @@ config DEBUG_UART_8250_WORD
ARCH_KEYSTONE || \
DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
DEBUG_DAVINCI_DA8XX_UART2 || \
DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2
DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 || \
DEBUG_BRCMSTB_UART
config DEBUG_UART_8250_FLOW_CONTROL
bool "Enable flow control for 8250 UART"

View File

@ -180,7 +180,8 @@
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>,
<0x20250 0x8>;
};
mpic: interrupt-controller@20000 {

View File

@ -23,6 +23,7 @@
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include "armada-xp-mv78460.dtsi"
/ {
@ -48,6 +49,14 @@
<0x00000001 0x00000000 0x00000001 0x00000000>;
};
cpus {
pm_pic {
ctrl-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>,
<&gpio0 17 GPIO_ACTIVE_LOW>,
<&gpio0 18 GPIO_ACTIVE_LOW>;
};
};
soc {
ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
@ -115,7 +124,15 @@
serial@12300 {
status = "okay";
};
pinctrl {
pinctrl-0 = <&pic_pins>;
pinctrl-names = "default";
pic_pins: pic-pins-0 {
marvell,pins = "mpp16", "mpp17",
"mpp18";
marvell,function = "gpio";
};
};
sata@a0000 {
nr-ports = <2>;
status = "okay";

View File

@ -35,6 +35,11 @@
};
internal-regs {
sdramc@1400 {
compatible = "marvell,armada-xp-sdram-controller";
reg = <0x1400 0x500>;
};
L2: l2-cache {
compatible = "marvell,aurora-system-cache";
reg = <0x08000 0x1000>;

View File

@ -6,8 +6,18 @@
/ {
core-module@10000000 {
compatible = "arm,core-module-integrator";
compatible = "arm,core-module-integrator", "syscon";
reg = <0x10000000 0x200>;
/* Use core module LED to indicate CPU load */
led@0c.0 {
compatible = "register-bit-led";
offset = <0x0c>;
mask = <0x01>;
label = "integrator:core_module";
linux,default-trigger = "cpu0";
default-state = "on";
};
};
ebi@12000000 {
@ -82,5 +92,41 @@
reg = <0x19000000 0x1000>;
interrupts = <4>;
};
syscon {
/* Debug registers mapped as syscon */
compatible = "syscon";
reg = <0x1a000000 0x10>;
led@04.0 {
compatible = "register-bit-led";
offset = <0x04>;
mask = <0x01>;
label = "integrator:green0";
linux,default-trigger = "heartbeat";
default-state = "on";
};
led@04.1 {
compatible = "register-bit-led";
offset = <0x04>;
mask = <0x02>;
label = "integrator:yellow";
default-state = "off";
};
led@04.2 {
compatible = "register-bit-led";
offset = <0x04>;
mask = <0x04>;
label = "integrator:red";
default-state = "off";
};
led@04.3 {
compatible = "register-bit-led";
offset = <0x04>;
mask = <0x08>;
label = "integrator:green1";
default-state = "off";
};
};
};
};

View File

@ -64,6 +64,7 @@
#include "twl4030.dtsi"
#include "twl4030_omap3.dtsi"
#include <dt-bindings/input/input.h>
&mmc1 {
vmmc-supply = <&vmmc1>;
@ -75,6 +76,22 @@
ti,pullups = <0x000001>;
};
&twl_keypad {
linux,keymap = <
MATRIX_KEY(0x00, 0x01, KEY_A)
MATRIX_KEY(0x00, 0x02, KEY_B)
MATRIX_KEY(0x00, 0x03, KEY_LEFT)
MATRIX_KEY(0x01, 0x01, KEY_UP)
MATRIX_KEY(0x01, 0x02, KEY_ENTER)
MATRIX_KEY(0x01, 0x03, KEY_DOWN)
MATRIX_KEY(0x02, 0x01, KEY_RIGHT)
MATRIX_KEY(0x02, 0x02, KEY_C)
MATRIX_KEY(0x02, 0x03, KEY_D)
>;
};
&hsusb1_phy {
reset-gpios = <&twl_gpio 6 GPIO_ACTIVE_LOW>;
};

View File

@ -895,7 +895,7 @@
reg = <0x58002000 0x1000>;
status = "disabled";
ti,hwmods = "dss_rfbi";
clocks = <&dss_dss_clk>, <&dss_fck>;
clocks = <&dss_dss_clk>, <&l3_div_ck>;
clock-names = "fck", "ick";
};

View File

@ -1018,14 +1018,6 @@
reg = <0x1120>;
};
dss_fck: dss_fck {
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&l3_div_ck>;
ti,bit-shift = <1>;
reg = <0x1120>;
};
fdif_fck: fdif_fck {
#clock-cells = <0>;
compatible = "ti,divider-clock";

View File

@ -11,6 +11,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/mfd/dbx500-prcmu.h>
#include <dt-bindings/arm/ux500_pm_domains.h>
#include "skeleton.dtsi"
/ {
@ -43,6 +44,10 @@
interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
};
pm_domains: pm_domains0 {
compatible = "stericsson,ux500-pm-domains";
#power-domain-cells = <1>;
};
clocks {
compatible = "stericsson,u8500-clks";
@ -636,6 +641,7 @@
clock-frequency = <400000>;
clocks = <&prcc_kclk 3 3>, <&prcc_pclk 3 3>;
clock-names = "i2cclk", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
i2c@80122000 {
@ -651,6 +657,7 @@
clocks = <&prcc_kclk 1 2>, <&prcc_pclk 1 2>;
clock-names = "i2cclk", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
i2c@80128000 {
@ -666,6 +673,7 @@
clocks = <&prcc_kclk 1 6>, <&prcc_pclk 1 6>;
clock-names = "i2cclk", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
i2c@80110000 {
@ -681,6 +689,7 @@
clocks = <&prcc_kclk 2 0>, <&prcc_pclk 2 0>;
clock-names = "i2cclk", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
i2c@8012a000 {
@ -696,6 +705,7 @@
clocks = <&prcc_kclk 1 9>, <&prcc_pclk 1 10>;
clock-names = "i2cclk", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
ssp@80002000 {
@ -709,6 +719,7 @@
dmas = <&dma 8 0 0x2>, /* Logical - DevToMem */
<&dma 8 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
ssp@80003000 {
@ -722,6 +733,7 @@
dmas = <&dma 9 0 0x2>, /* Logical - DevToMem */
<&dma 9 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
spi@8011a000 {
@ -736,6 +748,7 @@
dmas = <&dma 0 0 0x2>, /* Logical - DevToMem */
<&dma 0 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
spi@80112000 {
@ -750,6 +763,7 @@
dmas = <&dma 35 0 0x2>, /* Logical - DevToMem */
<&dma 35 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
spi@80111000 {
@ -764,6 +778,7 @@
dmas = <&dma 33 0 0x2>, /* Logical - DevToMem */
<&dma 33 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
spi@80129000 {
@ -778,6 +793,7 @@
dmas = <&dma 40 0 0x2>, /* Logical - DevToMem */
<&dma 40 0 0x0>; /* Logical - MemToDev */
dma-names = "rx", "tx";
power-domains = <&pm_domains DOMAIN_VAPE>;
};
uart@80120000 {
@ -836,6 +852,7 @@
clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
@ -851,6 +868,7 @@
clocks = <&prcc_kclk 2 4>, <&prcc_pclk 2 6>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
@ -866,6 +884,7 @@
clocks = <&prcc_kclk 3 4>, <&prcc_pclk 3 4>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
@ -881,6 +900,7 @@
clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
@ -896,6 +916,7 @@
clocks = <&prcc_kclk 2 2>, <&prcc_pclk 2 4>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
@ -911,6 +932,7 @@
clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};

View File

@ -25,7 +25,8 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM_MOBILE=y
CONFIG_ARCH_BCM_21664=y
CONFIG_ARCH_BCM_281XX=y
CONFIG_ARM_THUMBEE=y
CONFIG_SMP=y
CONFIG_PREEMPT=y

View File

@ -8,6 +8,9 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_MULTI_V4T=y
CONFIG_ARCH_MULTI_V5=y
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_INTEGRATOR=y
CONFIG_ARCH_INTEGRATOR_AP=y
CONFIG_ARCH_INTEGRATOR_CP=y

View File

@ -28,7 +28,7 @@ struct firmware_ops {
/*
* Enters CPU idle mode
*/
int (*do_idle)(void);
int (*do_idle)(unsigned long mode);
/*
* Sets boot address of specified physical CPU
*/
@ -41,6 +41,14 @@ struct firmware_ops {
* Initializes L2 cache
*/
int (*l2x0_init)(void);
/*
* Enter system-wide suspend.
*/
int (*suspend)(void);
/*
* Restore state of privileged hardware after system-wide suspend.
*/
int (*resume)(void);
};
/* Global pointer for current firmware_ops structure, can't be NULL. */

View File

@ -0,0 +1,29 @@
/* Debugging macro include header
*
* Copyright (C) 1994-1999 Russell King
* Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
* Modified for ASM9260 by Oleksij Remepl <linux@rempel-privat.de>
*
* 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
ldr \rp, = CONFIG_DEBUG_UART_PHYS
ldr \rv, = CONFIG_DEBUG_UART_VIRT
.endm
.macro waituart,rd,rx
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0x50] @ TXDATA
.endm
.macro busyuart,rd,rx
1002: ldr \rd, [\rx, #0x60] @ STAT
tst \rd, #1 << 27 @ TXEMPTY
beq 1002b @ wait until transmit done
.endm

View File

@ -0,0 +1,52 @@
/*
* Renesas SCIF(A) debugging macro include header
*
* Based on r8a7790.S
*
* Copyright (C) 2012-2013 Renesas Electronics Corporation
* Copyright (C) 1994-1999 Russell King
*
* 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.
*/
#define SCIF_PHYS CONFIG_DEBUG_UART_PHYS
#define SCIF_VIRT ((SCIF_PHYS & 0x00ffffff) | 0xfd000000)
#if CONFIG_DEBUG_UART_PHYS < 0xe6e00000
/* SCIFA */
#define FTDR 0x20
#define FSR 0x14
#else
/* SCIF */
#define FTDR 0x0c
#define FSR 0x10
#endif
#define TDFE (1 << 5)
#define TEND (1 << 6)
.macro addruart, rp, rv, tmp
ldr \rp, =SCIF_PHYS
ldr \rv, =SCIF_VIRT
.endm
.macro waituart, rd, rx
1001: ldrh \rd, [\rx, #FSR]
tst \rd, #TDFE
beq 1001b
.endm
.macro senduart, rd, rx
strb \rd, [\rx, #FTDR]
ldrh \rd, [\rx, #FSR]
bic \rd, \rd, #TEND
strh \rd, [\rx, #FSR]
.endm
.macro busyuart, rd, rx
1001: ldrh \rd, [\rx, #FSR]
tst \rd, #TEND
beq 1001b
.endm

View File

@ -1,4 +1,4 @@
/* arch/arm/mach-sa1100/include/mach/debug-macro.S
/* arch/arm/include/debug/sa1100.S
*
* Debugging macro include header
*
@ -10,7 +10,13 @@
* published by the Free Software Foundation.
*
*/
#include <mach/hardware.h>
#define UTCR3 0x0c
#define UTDR 0x14
#define UTSR1 0x20
#define UTCR3_TXE 0x00000002 /* Transmit Enable */
#define UTSR1_TBY 0x00000001 /* Transmitter BusY (read) */
#define UTSR1_TNF 0x00000004 /* Transmit FIFO Not Full (read) */
.macro addruart, rp, rv, tmp
mrc p15, 0, \rp, c1, c0

View File

@ -0,0 +1,6 @@
config MACH_ASM9260
bool "Alphascale ASM9260"
depends on ARCH_MULTI_V5
select CPU_ARM926T
help
Support for Alphascale ASM9260 based platform.

View File

@ -5,8 +5,56 @@ menuconfig ARCH_BCM
if ARCH_BCM
comment "IPROC architected SoCs"
config ARCH_BCM_IPROC
bool
select ARM_GIC
select CACHE_L2X0
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select ARM_GLOBAL_TIMER
select CLKSRC_MMIO
select ARCH_REQUIRE_GPIOLIB
select ARM_AMBA
select PINCTRL
help
This enables support for systems based on Broadcom IPROC architected SoCs.
The IPROC complex contains one or more ARM CPUs along with common
core periperals. Application specific SoCs are created by adding a
uArchitecture containing peripherals outside of the IPROC complex.
Currently supported SoCs are Cygnus.
config ARCH_BCM_CYGNUS
bool "Broadcom Cygnus Support" if ARCH_MULTI_V7
select ARCH_BCM_IPROC
help
Enable support for the Cygnus family,
which includes the following variants:
BCM11300, BCM11320, BCM11350, BCM11360,
BCM58300, BCM58302, BCM58303, BCM58305.
config ARCH_BCM_5301X
bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
select ARCH_BCM_IPROC
help
Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
This is a network SoC line mostly used in home routers and
wifi access points, it's internal name is Northstar.
This inclused the following SoC: BCM53010, BCM53011, BCM53012,
BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
BCM4708 and BCM4709.
Do not confuse this with the BCM4760 which is a totally
different SoC or with the older BCM47XX and BCM53XX based
network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
comment "KONA architected SoCs"
config ARCH_BCM_MOBILE
bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7
bool
select ARCH_REQUIRE_GPIOLIB
select ARM_ERRATA_754322
select ARM_ERRATA_775420
@ -15,16 +63,13 @@ config ARCH_BCM_MOBILE
select TICK_ONESHOT
select HAVE_ARM_ARCH_TIMER
select PINCTRL
select ARCH_BCM_MOBILE_SMP if SMP
help
This enables support for systems based on Broadcom mobile SoCs.
if ARCH_BCM_MOBILE
menu "Broadcom Mobile SoC Selection"
config ARCH_BCM_281XX
bool "Broadcom BCM281XX SoC family"
default y
select ARCH_BCM_MOBILE
select HAVE_SMP
help
Enable support for the BCM281XX family, which includes
@ -33,7 +78,7 @@ config ARCH_BCM_281XX
config ARCH_BCM_21664
bool "Broadcom BCM21664 SoC family"
default y
select ARCH_BCM_MOBILE
select HAVE_SMP
help
Enable support for the BCM21664 family, which includes
@ -41,19 +86,18 @@ config ARCH_BCM_21664
config ARCH_BCM_MOBILE_L2_CACHE
bool "Broadcom mobile SoC level 2 cache support"
depends on (ARCH_BCM_281XX || ARCH_BCM_21664)
depends on ARCH_BCM_MOBILE
default y
select CACHE_L2X0
select ARCH_BCM_MOBILE_SMC
config ARCH_BCM_MOBILE_SMC
bool
depends on ARCH_BCM_281XX || ARCH_BCM_21664
depends on ARCH_BCM_MOBILE
config ARCH_BCM_MOBILE_SMP
bool "Broadcom mobile SoC SMP support"
depends on (ARCH_BCM_281XX || ARCH_BCM_21664) && SMP
default y
bool
depends on ARCH_BCM_MOBILE
select HAVE_ARM_SCU
select ARM_ERRATA_764369
help
@ -61,9 +105,7 @@ config ARCH_BCM_MOBILE_SMP
Provided as an option so SMP support for SoCs of this type
can be disabled for an SMP-enabled kernel.
endmenu
endif
comment "Other Architectures"
config ARCH_BCM2835
bool "Broadcom BCM2835 family" if ARCH_MULTI_V6
@ -78,27 +120,6 @@ config ARCH_BCM2835
This enables support for the Broadcom BCM2835 SoC. This SoC is
used in the Raspberry Pi and Roku 2 devices.
config ARCH_BCM_5301X
bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
select ARM_GIC
select CACHE_L2X0
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select ARM_GLOBAL_TIMER
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
help
Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
This is a network SoC line mostly used in home routers and
wifi access points, it's internal name is Northstar.
This inclused the following SoC: BCM53010, BCM53011, BCM53012,
BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
BCM4708 and BCM4709.
Do not confuse this with the BCM4760 which is a totally
different SoC or with the older BCM47XX and BCM53XX based
network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
config ARCH_BCM_63XX
bool "Broadcom BCM63xx DSL SoC" if ARCH_MULTI_V7
depends on MMU
@ -118,10 +139,7 @@ config ARCH_BCM_63XX
config ARCH_BRCMSTB
bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
depends on MMU
select ARM_GIC
select MIGHT_HAVE_PCI
select HAVE_SMP
select HAVE_ARM_ARCH_TIMER
select BRCMSTB_GISB_ARB
select BRCMSTB_L2_IRQ

View File

@ -10,6 +10,9 @@
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# Cygnus
obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o
# BCM281XX
obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o
@ -38,5 +41,7 @@ obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o
obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o
ifeq ($(CONFIG_ARCH_BRCMSTB),y)
CFLAGS_platsmp-brcmstb.o += -march=armv7-a
obj-y += brcmstb.o
obj-$(CONFIG_SMP) += headsmp-brcmstb.o platsmp-brcmstb.o
endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2014 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <asm/mach/arch.h>
static const char const *bcm_cygnus_dt_compat[] = {
"brcm,cygnus",
NULL,
};
DT_MACHINE_START(BCM_CYGNUS_DT, "Broadcom Cygnus SoC")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.dt_compat = bcm_cygnus_dt_compat,
MACHINE_END

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2013-2014 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __BRCMSTB_H__
#define __BRCMSTB_H__
void brcmstb_secondary_startup(void);
#endif /* __BRCMSTB_H__ */

View File

@ -0,0 +1,33 @@
/*
* SMP boot code for secondary CPUs
* Based on arch/arm/mach-tegra/headsmp.S
*
* Copyright (C) 2010 NVIDIA, Inc.
* Copyright (C) 2013-2014 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <asm/assembler.h>
#include <linux/linkage.h>
#include <linux/init.h>
.section ".text.head", "ax"
ENTRY(brcmstb_secondary_startup)
/*
* Ensure CPU is in a sane state by disabling all IRQs and switching
* into SVC mode.
*/
setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
bl v7_invalidate_l1
b secondary_startup
ENDPROC(brcmstb_secondary_startup)

View File

@ -0,0 +1,329 @@
/*
* Broadcom STB CPU SMP and hotplug support for ARM
*
* Copyright (C) 2013-2014 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/printk.h>
#include <linux/regmap.h>
#include <linux/smp.h>
#include <linux/mfd/syscon.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/mach-types.h>
#include <asm/smp_plat.h>
#include "brcmstb.h"
enum {
ZONE_MAN_CLKEN_MASK = BIT(0),
ZONE_MAN_RESET_CNTL_MASK = BIT(1),
ZONE_MAN_MEM_PWR_MASK = BIT(4),
ZONE_RESERVED_1_MASK = BIT(5),
ZONE_MAN_ISO_CNTL_MASK = BIT(6),
ZONE_MANUAL_CONTROL_MASK = BIT(7),
ZONE_PWR_DN_REQ_MASK = BIT(9),
ZONE_PWR_UP_REQ_MASK = BIT(10),
ZONE_BLK_RST_ASSERT_MASK = BIT(12),
ZONE_PWR_OFF_STATE_MASK = BIT(25),
ZONE_PWR_ON_STATE_MASK = BIT(26),
ZONE_DPG_PWR_STATE_MASK = BIT(28),
ZONE_MEM_PWR_STATE_MASK = BIT(29),
ZONE_RESET_STATE_MASK = BIT(31),
CPU0_PWR_ZONE_CTRL_REG = 1,
CPU_RESET_CONFIG_REG = 2,
};
static void __iomem *cpubiuctrl_block;
static void __iomem *hif_cont_block;
static u32 cpu0_pwr_zone_ctrl_reg;
static u32 cpu_rst_cfg_reg;
static u32 hif_cont_reg;
#ifdef CONFIG_HOTPLUG_CPU
/*
* We must quiesce a dying CPU before it can be killed by the boot CPU. Because
* one or more cache may be disabled, we must flush to ensure coherency. We
* cannot use traditionl completion structures or spinlocks as they rely on
* coherency.
*/
static DEFINE_PER_CPU_ALIGNED(int, per_cpu_sw_state);
static int per_cpu_sw_state_rd(u32 cpu)
{
sync_cache_r(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
return per_cpu(per_cpu_sw_state, cpu);
}
static void per_cpu_sw_state_wr(u32 cpu, int val)
{
dmb();
per_cpu(per_cpu_sw_state, cpu) = val;
sync_cache_w(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
}
#else
static inline void per_cpu_sw_state_wr(u32 cpu, int val) { }
#endif
static void __iomem *pwr_ctrl_get_base(u32 cpu)
{
void __iomem *base = cpubiuctrl_block + cpu0_pwr_zone_ctrl_reg;
base += (cpu_logical_map(cpu) * 4);
return base;
}
static u32 pwr_ctrl_rd(u32 cpu)
{
void __iomem *base = pwr_ctrl_get_base(cpu);
return readl_relaxed(base);
}
static void pwr_ctrl_wr(u32 cpu, u32 val)
{
void __iomem *base = pwr_ctrl_get_base(cpu);
writel(val, base);
}
static void cpu_rst_cfg_set(u32 cpu, int set)
{
u32 val;
val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
if (set)
val |= BIT(cpu_logical_map(cpu));
else
val &= ~BIT(cpu_logical_map(cpu));
writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
}
static void cpu_set_boot_addr(u32 cpu, unsigned long boot_addr)
{
const int reg_ofs = cpu_logical_map(cpu) * 8;
writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
}
static void brcmstb_cpu_boot(u32 cpu)
{
/* Mark this CPU as "up" */
per_cpu_sw_state_wr(cpu, 1);
/*
* Set the reset vector to point to the secondary_startup
* routine
*/
cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
/* Unhalt the cpu */
cpu_rst_cfg_set(cpu, 0);
}
static void brcmstb_cpu_power_on(u32 cpu)
{
/*
* The secondary cores power was cut, so we must go through
* power-on initialization.
*/
u32 tmp;
/* Request zone power up */
pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
/* Wait for the power up FSM to complete */
do {
tmp = pwr_ctrl_rd(cpu);
} while (!(tmp & ZONE_PWR_ON_STATE_MASK));
}
static int brcmstb_cpu_get_power_state(u32 cpu)
{
int tmp = pwr_ctrl_rd(cpu);
return (tmp & ZONE_RESET_STATE_MASK) ? 0 : 1;
}
#ifdef CONFIG_HOTPLUG_CPU
static void brcmstb_cpu_die(u32 cpu)
{
v7_exit_coherency_flush(all);
per_cpu_sw_state_wr(cpu, 0);
/* Sit and wait to die */
wfi();
/* We should never get here... */
while (1)
;
}
static int brcmstb_cpu_kill(u32 cpu)
{
u32 tmp;
while (per_cpu_sw_state_rd(cpu))
;
/* Program zone reset */
pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
ZONE_PWR_DN_REQ_MASK);
/* Verify zone reset */
tmp = pwr_ctrl_rd(cpu);
if (!(tmp & ZONE_RESET_STATE_MASK))
pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
__func__, cpu);
/* Wait for power down */
do {
tmp = pwr_ctrl_rd(cpu);
} while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
/* Flush pipeline before resetting CPU */
mb();
/* Assert reset on the CPU */
cpu_rst_cfg_set(cpu, 1);
return 1;
}
#endif /* CONFIG_HOTPLUG_CPU */
static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
{
int rc = 0;
char *name;
struct device_node *syscon_np = NULL;
name = "syscon-cpu";
syscon_np = of_parse_phandle(np, name, 0);
if (!syscon_np) {
pr_err("can't find phandle %s\n", name);
rc = -EINVAL;
goto cleanup;
}
cpubiuctrl_block = of_iomap(syscon_np, 0);
if (!cpubiuctrl_block) {
pr_err("iomap failed for cpubiuctrl_block\n");
rc = -EINVAL;
goto cleanup;
}
rc = of_property_read_u32_index(np, name, CPU0_PWR_ZONE_CTRL_REG,
&cpu0_pwr_zone_ctrl_reg);
if (rc) {
pr_err("failed to read 1st entry from %s property (%d)\n", name,
rc);
rc = -EINVAL;
goto cleanup;
}
rc = of_property_read_u32_index(np, name, CPU_RESET_CONFIG_REG,
&cpu_rst_cfg_reg);
if (rc) {
pr_err("failed to read 2nd entry from %s property (%d)\n", name,
rc);
rc = -EINVAL;
goto cleanup;
}
cleanup:
of_node_put(syscon_np);
return rc;
}
static int __init setup_hifcont_regs(struct device_node *np)
{
int rc = 0;
char *name;
struct device_node *syscon_np = NULL;
name = "syscon-cont";
syscon_np = of_parse_phandle(np, name, 0);
if (!syscon_np) {
pr_err("can't find phandle %s\n", name);
rc = -EINVAL;
goto cleanup;
}
hif_cont_block = of_iomap(syscon_np, 0);
if (!hif_cont_block) {
pr_err("iomap failed for hif_cont_block\n");
rc = -EINVAL;
goto cleanup;
}
/* Offset is at top of hif_cont_block */
hif_cont_reg = 0;
cleanup:
of_node_put(syscon_np);
return rc;
}
static void __init brcmstb_cpu_ctrl_setup(unsigned int max_cpus)
{
int rc;
struct device_node *np;
char *name;
name = "brcm,brcmstb-smpboot";
np = of_find_compatible_node(NULL, NULL, name);
if (!np) {
pr_err("can't find compatible node %s\n", name);
return;
}
rc = setup_hifcpubiuctrl_regs(np);
if (rc)
return;
rc = setup_hifcont_regs(np);
if (rc)
return;
}
static int brcmstb_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/* Missing the brcm,brcmstb-smpboot DT node? */
if (!cpubiuctrl_block || !hif_cont_block)
return -ENODEV;
/* Bring up power to the core if necessary */
if (brcmstb_cpu_get_power_state(cpu) == 0)
brcmstb_cpu_power_on(cpu);
brcmstb_cpu_boot(cpu);
return 0;
}
static struct smp_operations brcmstb_smp_ops __initdata = {
.smp_prepare_cpus = brcmstb_cpu_ctrl_setup,
.smp_boot_secondary = brcmstb_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = brcmstb_cpu_kill,
.cpu_die = brcmstb_cpu_die,
#endif
};
CPU_METHOD_OF_DECLARE(brcmstb_smp, "brcm,brahma-b15", &brcmstb_smp_ops);

View File

@ -1,10 +1,11 @@
menuconfig ARCH_BERLIN
bool "Marvell Berlin SoCs" if ARCH_MULTI_V7
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select ARM_GIC
select GENERIC_IRQ_CHIP
select DW_APB_ICTL
select DW_APB_TIMER_OF
select GENERIC_IRQ_CHIP
select PINCTRL
if ARCH_BERLIN

View File

@ -24,6 +24,7 @@ menuconfig ARCH_EXYNOS
select PM_GENERIC_DOMAINS if PM_RUNTIME
select S5P_DEV_MFC
select SRAM
select MFD_SYSCON
help
Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
@ -75,6 +76,11 @@ config SOC_EXYNOS4412
default y
depends on ARCH_EXYNOS4
config SOC_EXYNOS4415
bool "SAMSUNG EXYNOS4415"
default y
depends on ARCH_EXYNOS4
config SOC_EXYNOS5250
bool "SAMSUNG EXYNOS5250"
default y
@ -123,4 +129,9 @@ config EXYNOS5420_MCPM
This is needed to provide CPU and cluster power management
on Exynos5420 implementing big.LITTLE.
config EXYNOS_CPU_SUSPEND
bool
select ARM_CPU_SUSPEND
default PM_SLEEP || ARM_EXYNOS_CPUIDLE
endif

View File

@ -11,13 +11,15 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)
obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o
obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm.o sleep.o
obj-$(CONFIG_PM_SLEEP) += suspend.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec)
obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
CFLAGS_mcpm-exynos.o += -march=armv7-a

View File

@ -12,7 +12,6 @@
#ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
#define __ARCH_ARM_MACH_EXYNOS_COMMON_H
#include <linux/reboot.h>
#include <linux/of.h>
#define EXYNOS3250_SOC_ID 0xE3472000
@ -111,11 +110,19 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
soc_is_exynos5420() || soc_is_exynos5800())
extern u32 cp15_save_diag;
extern u32 cp15_save_power;
extern void __iomem *sysram_ns_base_addr;
extern void __iomem *sysram_base_addr;
extern void __iomem *pmu_base_addr;
void exynos_sysram_init(void);
enum {
FW_DO_IDLE_SLEEP,
FW_DO_IDLE_AFTR,
};
void exynos_firmware_init(void);
extern u32 exynos_get_eint_wake_mask(void);
@ -127,32 +134,20 @@ static inline void exynos_pm_init(void) {}
#endif
extern void exynos_cpu_resume(void);
extern void exynos_cpu_resume_ns(void);
extern struct smp_operations exynos_smp_ops;
/* PMU(Power Management Unit) support */
#define PMU_TABLE_END (-1U)
enum sys_powerdown {
SYS_AFTR,
SYS_LPA,
SYS_SLEEP,
NUM_SYS_POWERDOWN,
};
struct exynos_pmu_conf {
unsigned int offset;
unsigned int val[NUM_SYS_POWERDOWN];
};
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
extern void exynos_cpu_power_down(int cpu);
extern void exynos_cpu_power_up(int cpu);
extern int exynos_cpu_power_state(int cpu);
extern void exynos_cluster_power_down(int cluster);
extern void exynos_cluster_power_up(int cluster);
extern int exynos_cluster_power_state(int cluster);
extern void exynos_cpu_save_register(void);
extern void exynos_cpu_restore_register(void);
extern void exynos_pm_central_suspend(void);
extern int exynos_pm_central_resume(void);
extern void exynos_enter_aftr(void);
extern void s5p_init_cpu(void __iomem *cpuid_addr);

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Header for EXYNOS PMU Driver support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __EXYNOS_PMU_H
#define __EXYNOS_PMU_H
enum sys_powerdown {
SYS_AFTR,
SYS_LPA,
SYS_SLEEP,
NUM_SYS_POWERDOWN,
};
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
#endif /* __EXYNOS_PMU_H */

View File

@ -87,28 +87,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
},
};
static void exynos_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
u32 val = 0x1;
void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
if (of_machine_is_compatible("samsung,exynos5440")) {
u32 status;
np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
addr = of_iomap(np, 0) + 0xbc;
status = __raw_readl(addr);
addr = of_iomap(np, 0) + 0xcc;
val = __raw_readl(addr);
val = (val & 0xffff0000) | (status & 0xffff);
}
__raw_writel(val, addr);
}
static struct platform_device exynos_cpuidle = {
.name = "exynos_cpuidle",
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@ -202,6 +180,7 @@ static const struct of_device_id exynos_dt_pmu_match[] = {
{ .compatible = "samsung,exynos4210-pmu" },
{ .compatible = "samsung,exynos4212-pmu" },
{ .compatible = "samsung,exynos4412-pmu" },
{ .compatible = "samsung,exynos4415-pmu" },
{ .compatible = "samsung,exynos5250-pmu" },
{ .compatible = "samsung,exynos5260-pmu" },
{ .compatible = "samsung,exynos5410-pmu" },
@ -268,6 +247,9 @@ static void __init exynos_dt_machine_init(void)
exynos_sysram_init();
if (of_machine_is_compatible("samsung,exynos4210") ||
of_machine_is_compatible("samsung,exynos4212") ||
(of_machine_is_compatible("samsung,exynos4412") &&
of_machine_is_compatible("samsung,trats2")) ||
of_machine_is_compatible("samsung,exynos5250"))
platform_device_register(&exynos_cpuidle);
@ -283,6 +265,7 @@ static char const *exynos_dt_compat[] __initconst = {
"samsung,exynos4210",
"samsung,exynos4212",
"samsung,exynos4412",
"samsung,exynos4415",
"samsung,exynos5",
"samsung,exynos5250",
"samsung,exynos5260",
@ -328,7 +311,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
.init_machine = exynos_dt_machine_init,
.init_late = exynos_init_late,
.dt_compat = exynos_dt_compat,
.restart = exynos_restart,
.reserve = exynos_reserve,
.dt_fixup = exynos_dt_fixup,
MACHINE_END

View File

@ -14,16 +14,44 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/firmware.h>
#include <asm/suspend.h>
#include <mach/map.h>
#include "common.h"
#include "smc.h"
static int exynos_do_idle(void)
#define EXYNOS_SLEEP_MAGIC 0x00000bad
#define EXYNOS_AFTR_MAGIC 0xfcba0d10
#define EXYNOS_BOOT_ADDR 0x8
#define EXYNOS_BOOT_FLAG 0xc
static void exynos_save_cp15(void)
{
/* Save Power control and Diagnostic registers */
asm ("mrc p15, 0, %0, c15, c0, 0\n"
"mrc p15, 0, %1, c15, c0, 1\n"
: "=r" (cp15_save_power), "=r" (cp15_save_diag)
: : "cc");
}
static int exynos_do_idle(unsigned long mode)
{
switch (mode) {
case FW_DO_IDLE_AFTR:
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_save_cp15();
__raw_writel(virt_to_phys(exynos_cpu_resume_ns),
sysram_ns_base_addr + 0x24);
__raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
break;
case FW_DO_IDLE_SLEEP:
exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
}
return 0;
}
@ -69,10 +97,43 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
return 0;
}
static int exynos_cpu_suspend(unsigned long arg)
{
flush_cache_all();
outer_flush_all();
exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
pr_info("Failed to suspend the system\n");
writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
return 1;
}
static int exynos_suspend(void)
{
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_save_cp15();
writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
writel(virt_to_phys(exynos_cpu_resume_ns),
sysram_ns_base_addr + EXYNOS_BOOT_ADDR);
return cpu_suspend(0, exynos_cpu_suspend);
}
static int exynos_resume(void)
{
writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
return 0;
}
static const struct firmware_ops exynos_firmware_ops = {
.do_idle = exynos_do_idle,
.do_idle = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL,
.set_cpu_boot_addr = exynos_set_cpu_boot_addr,
.cpu_boot = exynos_cpu_boot,
.suspend = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL,
.resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
};
void __init exynos_firmware_init(void)

View File

@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <asm/cputype.h>
#include <asm/cp15.h>
@ -30,6 +31,8 @@
#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
static void __iomem *ns_sram_base_addr;
/*
* The common v7_exit_coherency_flush API could not be used because of the
* Erratum 799270 workaround. This macro is the same as the common one (in
@ -318,10 +321,26 @@ static const struct of_device_id exynos_dt_mcpm_match[] = {
{},
};
static void exynos_mcpm_setup_entry_point(void)
{
/*
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
* as part of secondary_cpu_start(). Let's redirect it to the
* mcpm_entry_point(). This is done during both secondary boot-up as
* well as system resume.
*/
__raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
__raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
__raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
}
static struct syscore_ops exynos_mcpm_syscore_ops = {
.resume = exynos_mcpm_setup_entry_point,
};
static int __init exynos_mcpm_init(void)
{
struct device_node *node;
void __iomem *ns_sram_base_addr;
unsigned int value, i;
int ret;
@ -387,16 +406,9 @@ static int __init exynos_mcpm_init(void)
pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
}
/*
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
* as part of secondary_cpu_start(). Let's redirect it to the
* mcpm_entry_point().
*/
__raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */
__raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */
__raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
exynos_mcpm_setup_entry_point();
iounmap(ns_sram_base_addr);
register_syscore_ops(&exynos_mcpm_syscore_ops);
return ret;
}

View File

@ -126,6 +126,18 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
*/
void exynos_cpu_power_down(int cpu)
{
if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
of_machine_is_compatible("samsung,exynos5800"))) {
/*
* Bypass power down for CPU0 during suspend. Check for
* the SYS_PWR_REG value to decide if we are suspending
* the system.
*/
int val = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
if (!(val & S5P_CORE_LOCAL_PWR_EN))
return;
}
pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
}
@ -203,6 +215,26 @@ static inline void __iomem *cpu_boot_reg(int cpu)
return boot_reg;
}
/*
* Set wake up by local power mode and execute software reset for given core.
*
* Currently this is needed only when booting secondary CPU on Exynos3250.
*/
static void exynos_core_restart(u32 core_id)
{
u32 val;
if (!of_machine_is_compatible("samsung,exynos3250"))
return;
val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
pr_info("CPU%u: Software reset\n", core_id);
pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET);
}
/*
* Write pen_release in a way that is guaranteed to be visible to all
* observers, irrespective of whether they're taking part in coherency
@ -279,6 +311,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
return -ETIMEDOUT;
}
}
exynos_core_restart(core_id);
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
* Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS - Power Management support
@ -15,109 +15,45 @@
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/cpu_pm.h>
#include <linux/io.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/firmware.h>
#include <asm/smp_scu.h>
#include <asm/suspend.h>
#include <plat/pm-common.h>
#include <plat/regs-srom.h>
#include <mach/map.h>
#include "common.h"
#include "exynos-pmu.h"
#include "regs-pmu.h"
#include "regs-sys.h"
/**
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
* @hwirq: Hardware IRQ signal of the GIC
* @mask: Mask in PMU wake-up mask register
*/
struct exynos_wkup_irq {
unsigned int hwirq;
u32 mask;
};
static struct sleep_save exynos5_sys_save[] = {
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
};
static struct sleep_save exynos_core_save[] = {
/* SROM side */
SAVE_ITEM(S5P_SROM_BW),
SAVE_ITEM(S5P_SROM_BC0),
SAVE_ITEM(S5P_SROM_BC1),
SAVE_ITEM(S5P_SROM_BC2),
SAVE_ITEM(S5P_SROM_BC3),
};
/*
* GIC wake-up support
*/
static u32 exynos_irqwake_intmask = 0xffffffff;
static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
{ 75, BIT(1) }, /* RTC alarm */
{ 76, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
static inline void __iomem *exynos_boot_vector_addr(void)
{
const struct exynos_wkup_irq *wkup_irq;
if (soc_is_exynos5250())
wkup_irq = exynos5250_wkup_irq;
else
wkup_irq = exynos4_wkup_irq;
while (wkup_irq->mask) {
if (wkup_irq->hwirq == data->hwirq) {
if (!state)
exynos_irqwake_intmask |= wkup_irq->mask;
else
exynos_irqwake_intmask &= ~wkup_irq->mask;
return 0;
}
++wkup_irq;
if (samsung_rev() == EXYNOS4210_REV_1_1)
return pmu_base_addr + S5P_INFORM7;
else if (samsung_rev() == EXYNOS4210_REV_1_0)
return sysram_base_addr + 0x24;
return pmu_base_addr + S5P_INFORM0;
}
return -ENOENT;
static inline void __iomem *exynos_boot_vector_flag(void)
{
if (samsung_rev() == EXYNOS4210_REV_1_1)
return pmu_base_addr + S5P_INFORM6;
else if (samsung_rev() == EXYNOS4210_REV_1_0)
return sysram_base_addr + 0x20;
return pmu_base_addr + S5P_INFORM1;
}
#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
pmu_base_addr + S5P_INFORM7 : \
(samsung_rev() == EXYNOS4210_REV_1_0 ? \
(sysram_base_addr + 0x24) : \
pmu_base_addr + S5P_INFORM0))
#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
pmu_base_addr + S5P_INFORM6 : \
(samsung_rev() == EXYNOS4210_REV_1_0 ? \
(sysram_base_addr + 0x20) : \
pmu_base_addr + S5P_INFORM1))
#define S5P_CHECK_AFTR 0xFCBA0D10
#define S5P_CHECK_SLEEP 0x00000BAD
/* For Cortex-A9 Diagnostic and Power control register */
static unsigned int save_arm_register[2];
static void exynos_cpu_save_register(void)
void exynos_cpu_save_register(void)
{
unsigned long tmp;
@ -134,7 +70,7 @@ static void exynos_cpu_save_register(void)
save_arm_register[1] = tmp;
}
static void exynos_cpu_restore_register(void)
void exynos_cpu_restore_register(void)
{
unsigned long tmp;
@ -153,7 +89,7 @@ static void exynos_cpu_restore_register(void)
: "cc");
}
static void exynos_pm_central_suspend(void)
void exynos_pm_central_suspend(void)
{
unsigned long tmp;
@ -161,9 +97,13 @@ static void exynos_pm_central_suspend(void)
tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
}
static int exynos_pm_central_resume(void)
int exynos_pm_central_resume(void)
{
unsigned long tmp;
@ -194,17 +134,26 @@ static void exynos_set_wakeupmask(long mask)
static void exynos_cpu_set_boot_vector(long flags)
{
__raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
__raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
__raw_writel(virt_to_phys(exynos_cpu_resume),
exynos_boot_vector_addr());
__raw_writel(flags, exynos_boot_vector_flag());
}
static int exynos_aftr_finisher(unsigned long flags)
{
int ret;
exynos_set_wakeupmask(0x0000ff3e);
exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
/* Set value of power down register for aftr mode */
exynos_sys_powerdown_conf(SYS_AFTR);
ret = call_firmware_op(do_idle, FW_DO_IDLE_AFTR);
if (ret == -ENOSYS) {
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register();
exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
cpu_do_idle();
}
return 1;
}
@ -214,13 +163,12 @@ void exynos_enter_aftr(void)
cpu_pm_enter();
exynos_pm_central_suspend();
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register();
cpu_suspend(0, exynos_aftr_finisher);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
scu_enable(S5P_VA_SCU);
if (call_firmware_op(resume) == -ENOSYS)
exynos_cpu_restore_register();
}
@ -228,182 +176,3 @@ void exynos_enter_aftr(void)
cpu_pm_exit();
}
static int exynos_cpu_suspend(unsigned long arg)
{
#ifdef CONFIG_CACHE_L2X0
outer_flush_all();
#endif
if (soc_is_exynos5250())
flush_cache_all();
/* issue the standby signal into the pm unit. */
cpu_do_idle();
pr_info("Failed to suspend the system\n");
return 1; /* Aborting suspend */
}
static void exynos_pm_prepare(void)
{
unsigned int tmp;
/* Set wake-up mask registers */
pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (soc_is_exynos5250()) {
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
tmp = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
}
/* Set value of power down register for sleep mode */
exynos_sys_powerdown_conf(SYS_SLEEP);
pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
/* ensure at least INFORM0 has the resume address */
pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
static int exynos_pm_suspend(void)
{
unsigned long tmp;
exynos_pm_central_suspend();
/* Setting SEQ_OPTION register */
tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register();
return 0;
}
static void exynos_pm_resume(void)
{
if (exynos_pm_central_resume())
goto early_wakeup;
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_restore_register();
/* For release retention */
pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
if (soc_is_exynos5250())
s3c_pm_do_restore(exynos5_sys_save,
ARRAY_SIZE(exynos5_sys_save));
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
early_wakeup:
/* Clear SLEEP mode set in INFORM1 */
pmu_raw_writel(0x0, S5P_INFORM1);
return;
}
static struct syscore_ops exynos_pm_syscore_ops = {
.suspend = exynos_pm_suspend,
.resume = exynos_pm_resume,
};
/*
* Suspend Ops
*/
static int exynos_suspend_enter(suspend_state_t state)
{
int ret;
s3c_pm_debug_init();
S3C_PMDBG("%s: suspending the system...\n", __func__);
S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
exynos_irqwake_intmask, exynos_get_eint_wake_mask());
if (exynos_irqwake_intmask == -1U
&& exynos_get_eint_wake_mask() == -1U) {
pr_err("%s: No wake-up sources!\n", __func__);
pr_err("%s: Aborting sleep\n", __func__);
return -EINVAL;
}
s3c_pm_save_uarts();
exynos_pm_prepare();
flush_cache_all();
s3c_pm_check_store();
ret = cpu_suspend(0, exynos_cpu_suspend);
if (ret)
return ret;
s3c_pm_restore_uarts();
S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
pmu_raw_readl(S5P_WAKEUP_STAT));
s3c_pm_check_restore();
S3C_PMDBG("%s: resuming the system...\n", __func__);
return 0;
}
static int exynos_suspend_prepare(void)
{
s3c_pm_check_prepare();
return 0;
}
static void exynos_suspend_finish(void)
{
s3c_pm_check_cleanup();
}
static const struct platform_suspend_ops exynos_suspend_ops = {
.enter = exynos_suspend_enter,
.prepare = exynos_suspend_prepare,
.finish = exynos_suspend_finish,
.valid = suspend_valid_only_mem,
};
void __init exynos_pm_init(void)
{
u32 tmp;
/* Platform-specific GIC callback */
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
/* All wakeup disable */
tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
tmp |= ((0xFF << 8) | (0x1F << 1));
pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
register_syscore_ops(&exynos_pm_syscore_ops);
suspend_set_ops(&exynos_suspend_ops);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
* Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* EXYNOS - CPU PMU(Power Management Unit) support
@ -10,12 +10,136 @@
*/
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include "common.h"
#include "exynos-pmu.h"
#include "regs-pmu.h"
static const struct exynos_pmu_conf *exynos_pmu_config;
#define PMU_TABLE_END (-1U)
struct exynos_pmu_conf {
unsigned int offset;
u8 val[NUM_SYS_POWERDOWN];
};
struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
const struct exynos_pmu_conf *pmu_config_extra;
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
void (*powerdown_conf_extra)(enum sys_powerdown);
};
struct exynos_pmu_context {
struct device *dev;
const struct exynos_pmu_data *pmu_data;
};
static void __iomem *pmu_base_addr;
static struct exynos_pmu_context *pmu_context;
static inline void pmu_raw_writel(u32 val, u32 offset)
{
writel_relaxed(val, pmu_base_addr + offset);
}
static inline u32 pmu_raw_readl(u32 offset)
{
return readl_relaxed(pmu_base_addr + offset);
}
static struct exynos_pmu_conf exynos3250_pmu_config[] = {
/* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */
{ EXYNOS3_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS3_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS3_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x3} },
{ EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS3_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS3_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
{ EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG, { 0x3, 0x3, 0x3} },
{ EXYNOS3_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS3_CAM_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_LCD0_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_MAUDIO_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ PMU_TABLE_END,},
};
static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
@ -264,6 +388,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
{ EXYNOS5_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_JPEG_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_JPEG_MEM_OPTION, { 0x10, 0x10, 0x0} },
{ EXYNOS5_HSI_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_MCUIOP_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_SATA_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
@ -315,6 +440,189 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
{ PMU_TABLE_END,},
};
static struct exynos_pmu_conf exynos5420_pmu_config[] = {
/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
{ EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_ARM_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_ARM_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_CORE2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_CORE3_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_KFC_L2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} },
{ EXYNOS5_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x0} },
{ EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG, { 0x3, 0x0, 0x0} },
{ EXYNOS5_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x0, 0x1} },
{ EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_INTRAM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
{ EXYNOS5420_INTROM_MEM_SYS_PWR_REG, { 0x3, 0x0, 0x3} },
{ EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
{ EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x0, 0x0} },
{ EXYNOS5_GSCL_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_DISP1_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_MAU_SYS_PWR_REG, { 0x7, 0x7, 0x0} },
{ EXYNOS5420_G2D_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_MSC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_FSYS_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_FSYS2_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_PSGEN_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_PERIC_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5420_WCORE_SYS_PWR_REG, { 0x7, 0x0, 0x0} },
{ EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ PMU_TABLE_END,},
};
static unsigned int const exynos3250_list_feed[] = {
EXYNOS3_ARM_CORE_OPTION(0),
EXYNOS3_ARM_CORE_OPTION(1),
EXYNOS3_ARM_CORE_OPTION(2),
EXYNOS3_ARM_CORE_OPTION(3),
EXYNOS3_ARM_COMMON_OPTION,
EXYNOS3_TOP_PWR_OPTION,
EXYNOS3_CORE_TOP_PWR_OPTION,
S5P_CAM_OPTION,
S5P_MFC_OPTION,
S5P_G3D_OPTION,
S5P_LCD0_OPTION,
S5P_ISP_OPTION,
};
static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode)
{
unsigned int i;
unsigned int tmp;
/* Enable only SC_FEEDBACK */
for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
tmp = pmu_raw_readl(exynos3250_list_feed[i]);
tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER);
tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK;
pmu_raw_writel(tmp, exynos3250_list_feed[i]);
}
if (mode != SYS_SLEEP)
return;
pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION);
pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION);
pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION);
pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION,
EXYNOS3_EXT_REGULATOR_COREBLK_DURATION);
}
static unsigned int const exynos5_list_both_cnt_feed[] = {
EXYNOS5_ARM_CORE0_OPTION,
EXYNOS5_ARM_CORE1_OPTION,
@ -335,7 +643,76 @@ static unsigned int const exynos5_list_disable_wfi_wfe[] = {
EXYNOS5_ISP_ARM_OPTION,
};
static void exynos5_init_pmu(void)
static unsigned int const exynos5420_list_disable_pmu_reg[] = {
EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG,
EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG,
EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG,
EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG,
EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG,
EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG,
EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG,
EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG,
EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG,
EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG,
EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG,
EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,
};
static void exynos5_power_off(void)
{
unsigned int tmp;
pr_info("Power down.\n");
tmp = pmu_raw_readl(EXYNOS_PS_HOLD_CONTROL);
tmp ^= (1 << 8);
pmu_raw_writel(tmp, EXYNOS_PS_HOLD_CONTROL);
/* Wait a little so we don't give a false warning below */
mdelay(100);
pr_err("Power down failed, please power off system manually.\n");
while (1)
;
}
void exynos5420_powerdown_conf(enum sys_powerdown mode)
{
u32 this_cluster;
this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
/*
* set the cluster id to IROM register to ensure that we wake
* up with the current cluster.
*/
pmu_raw_writel(this_cluster, EXYNOS_IROM_DATA2);
}
static void exynos5_powerdown_conf(enum sys_powerdown mode)
{
unsigned int i;
unsigned int tmp;
@ -372,33 +749,60 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
{
unsigned int i;
if (soc_is_exynos5250())
exynos5_init_pmu();
const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
pmu_raw_writel(exynos_pmu_config[i].val[mode],
exynos_pmu_config[i].offset);
if (pmu_data->powerdown_conf)
pmu_data->powerdown_conf(mode);
if (soc_is_exynos4412()) {
for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++)
pmu_raw_writel(exynos4412_pmu_config[i].val[mode],
exynos4412_pmu_config[i].offset);
if (pmu_data->pmu_config) {
for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
pmu_data->pmu_config[i].offset);
}
if (pmu_data->powerdown_conf_extra)
pmu_data->powerdown_conf_extra(mode);
if (pmu_data->pmu_config_extra) {
for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
pmu_data->pmu_config_extra[i].offset);
}
}
static int __init exynos_pmu_init(void)
static void exynos3250_pmu_init(void)
{
unsigned int value;
exynos_pmu_config = exynos4210_pmu_config;
/*
* To prevent from issuing new bus request form L2 memory system
* If core status is power down, should be set '1' to L2 power down
*/
value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION);
value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION);
if (soc_is_exynos4210()) {
exynos_pmu_config = exynos4210_pmu_config;
pr_info("EXYNOS4210 PMU Initialize\n");
} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
exynos_pmu_config = exynos4x12_pmu_config;
pr_info("EXYNOS4x12 PMU Initialize\n");
} else if (soc_is_exynos5250()) {
/* Enable USE_STANDBY_WFI for all CORE */
pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
/*
* Set PSHOLD port for output high
*/
value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
value |= S5P_PS_HOLD_OUTPUT_HIGH;
pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
/*
* Enable signal for PSHOLD port
*/
value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
value |= S5P_PS_HOLD_EN;
pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
}
static void exynos5250_pmu_init(void)
{
unsigned int value;
/*
* When SYS_WDTRESET is set, watchdog timer reset request
* is ignored by power management unit.
@ -410,13 +814,192 @@ static int __init exynos_pmu_init(void)
value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
value &= ~EXYNOS5_SYS_WDTRESET;
pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
exynos_pmu_config = exynos5250_pmu_config;
pr_info("EXYNOS5250 PMU Initialize\n");
} else {
pr_info("EXYNOS: PMU not supported\n");
}
static void exynos5420_pmu_init(void)
{
unsigned int value;
int i;
/*
* Set the CMU_RESET, CMU_SYSCLK and CMU_CLKSTOP registers
* for local power blocks to Low initially as per Table 8-4:
* "System-Level Power-Down Configuration Registers".
*/
for (i = 0; i < ARRAY_SIZE(exynos5420_list_disable_pmu_reg); i++)
pmu_raw_writel(0, exynos5420_list_disable_pmu_reg[i]);
/* Enable USE_STANDBY_WFI for all CORE */
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
value = pmu_raw_readl(EXYNOS_L2_OPTION(0));
value &= ~EXYNOS5_USE_RETENTION;
pmu_raw_writel(value, EXYNOS_L2_OPTION(0));
value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
value &= ~EXYNOS5_USE_RETENTION;
pmu_raw_writel(value, EXYNOS_L2_OPTION(1));
/*
* If L2_COMMON is turned off, clocks related to ATB async
* bridge are gated. Thus, when ISP power is gated, LPI
* may get stuck.
*/
value = pmu_raw_readl(EXYNOS5420_LPI_MASK);
value |= EXYNOS5420_ATB_ISP_ARM;
pmu_raw_writel(value, EXYNOS5420_LPI_MASK);
value = pmu_raw_readl(EXYNOS5420_LPI_MASK1);
value |= EXYNOS5420_ATB_KFC;
pmu_raw_writel(value, EXYNOS5420_LPI_MASK1);
/* Prevent issue of new bus request from L2 memory */
value = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
pmu_raw_writel(value, EXYNOS5420_ARM_COMMON_OPTION);
value = pmu_raw_readl(EXYNOS5420_KFC_COMMON_OPTION);
value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
pmu_raw_writel(value, EXYNOS5420_KFC_COMMON_OPTION);
/* This setting is to reduce suspend/resume time */
pmu_raw_writel(DUR_WAIT_RESET, EXYNOS5420_LOGIC_RESET_DURATION3);
/* Serialized CPU wakeup of Eagle */
pmu_raw_writel(SPREAD_ENABLE, EXYNOS5420_ARM_INTR_SPREAD_ENABLE);
pmu_raw_writel(SPREAD_USE_STANDWFI,
EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);
pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
pm_power_off = exynos5_power_off;
pr_info("EXYNOS5420 PMU initialized\n");
}
static int pmu_restart_notify(struct notifier_block *this,
unsigned long code, void *unused)
{
pmu_raw_writel(0x1, EXYNOS_SWRESET);
return NOTIFY_DONE;
}
static const struct exynos_pmu_data exynos3250_pmu_data = {
.pmu_config = exynos3250_pmu_config,
.pmu_init = exynos3250_pmu_init,
.powerdown_conf_extra = exynos3250_powerdown_conf_extra,
};
static const struct exynos_pmu_data exynos4210_pmu_data = {
.pmu_config = exynos4210_pmu_config,
};
static const struct exynos_pmu_data exynos4212_pmu_data = {
.pmu_config = exynos4x12_pmu_config,
};
static const struct exynos_pmu_data exynos4412_pmu_data = {
.pmu_config = exynos4x12_pmu_config,
.pmu_config_extra = exynos4412_pmu_config,
};
static const struct exynos_pmu_data exynos5250_pmu_data = {
.pmu_config = exynos5250_pmu_config,
.pmu_init = exynos5250_pmu_init,
.powerdown_conf = exynos5_powerdown_conf,
};
static struct exynos_pmu_data exynos5420_pmu_data = {
.pmu_config = exynos5420_pmu_config,
.pmu_init = exynos5420_pmu_init,
.powerdown_conf = exynos5420_powerdown_conf,
};
/*
* PMU platform driver and devicetree bindings.
*/
static const struct of_device_id exynos_pmu_of_device_ids[] = {
{
.compatible = "samsung,exynos3250-pmu",
.data = &exynos3250_pmu_data,
}, {
.compatible = "samsung,exynos4210-pmu",
.data = &exynos4210_pmu_data,
}, {
.compatible = "samsung,exynos4212-pmu",
.data = &exynos4212_pmu_data,
}, {
.compatible = "samsung,exynos4412-pmu",
.data = &exynos4412_pmu_data,
}, {
.compatible = "samsung,exynos5250-pmu",
.data = &exynos5250_pmu_data,
}, {
.compatible = "samsung,exynos5420-pmu",
.data = &exynos5420_pmu_data,
},
{ /*sentinel*/ },
};
/*
* Exynos PMU restart notifier, handles restart functionality
*/
static struct notifier_block pmu_restart_handler = {
.notifier_call = pmu_restart_notify,
.priority = 128,
};
static int exynos_pmu_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct resource *res;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pmu_base_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(pmu_base_addr))
return PTR_ERR(pmu_base_addr);
pmu_context = devm_kzalloc(&pdev->dev,
sizeof(struct exynos_pmu_context),
GFP_KERNEL);
if (!pmu_context) {
dev_err(dev, "Cannot allocate memory.\n");
return -ENOMEM;
}
pmu_context->dev = dev;
match = of_match_node(exynos_pmu_of_device_ids, dev->of_node);
pmu_context->pmu_data = match->data;
if (pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init();
platform_set_drvdata(pdev, pmu_context);
ret = register_restart_handler(&pmu_restart_handler);
if (ret)
dev_warn(dev, "can't register restart handler err=%d\n", ret);
dev_dbg(dev, "Exynos PMU Driver probe done\n");
return 0;
}
arch_initcall(exynos_pmu_init);
static struct platform_driver exynos_pmu_driver = {
.driver = {
.name = "exynos-pmu",
.owner = THIS_MODULE,
.of_match_table = exynos_pmu_of_device_ids,
},
.probe = exynos_pmu_probe,
};
static int __init exynos_pmu_init(void)
{
return platform_driver_register(&exynos_pmu_driver);
}
postcore_initcall(exynos_pmu_init);

View File

@ -19,9 +19,24 @@
#define S5P_CENTRAL_SEQ_OPTION 0x0208
#define S5P_USE_STANDBY_WFI0 (1 << 16)
#define S5P_USE_STANDBY_WFI1 (1 << 17)
#define S5P_USE_STANDBY_WFI2 (1 << 19)
#define S5P_USE_STANDBY_WFI3 (1 << 20)
#define S5P_USE_STANDBY_WFE0 (1 << 24)
#define S5P_USE_STANDBY_WFE1 (1 << 25)
#define S5P_USE_STANDBY_WFE2 (1 << 27)
#define S5P_USE_STANDBY_WFE3 (1 << 28)
#define S5P_USE_STANDBY_WFI_ALL \
(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFI1 | \
S5P_USE_STANDBY_WFI2 | S5P_USE_STANDBY_WFI3 | \
S5P_USE_STANDBY_WFE0 | S5P_USE_STANDBY_WFE1 | \
S5P_USE_STANDBY_WFE2 | S5P_USE_STANDBY_WFE3)
#define S5P_USE_DELAYED_RESET_ASSERTION BIT(12)
#define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n)
#define EXYNOS_WAKEUP_FROM_LOWPWR (1 << 28)
#define EXYNOS_SWRESET 0x0400
#define EXYNOS5440_SWRESET 0x00C4
@ -36,6 +51,7 @@
#define S5P_INFORM7 0x081C
#define S5P_PMU_SPARE3 0x090C
#define EXYNOS_IROM_DATA2 0x0988
#define S5P_ARM_CORE0_LOWPWR 0x1000
#define S5P_DIS_IRQ_CORE0 0x1004
#define S5P_DIS_IRQ_CENTRAL0 0x1008
@ -118,6 +134,31 @@
#define EXYNOS_COMMON_OPTION(_nr) \
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_CORE_LOCAL_PWR_EN 0x3
#define EXYNOS_ARM_COMMON_STATUS 0x2504
#define EXYNOS_COMMON_OPTION(_nr) \
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_ARM_L2_CONFIGURATION 0x2600
#define EXYNOS_L2_CONFIGURATION(_nr) \
(EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
#define EXYNOS_L2_STATUS(_nr) \
(EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
#define EXYNOS_L2_OPTION(_nr) \
(EXYNOS_L2_CONFIGURATION(_nr) + 0x8)
#define EXYNOS_L2_COMMON_PWR_EN 0x3
#define EXYNOS_ARM_CORE_X_STATUS_OFFSET 0x4
#define EXYNOS5_APLL_SYSCLK_CONFIGURATION 0x2A00
#define EXYNOS5_APLL_SYSCLK_STATUS 0x2A04
#define EXYNOS5_ARM_L2_OPTION 0x2608
#define EXYNOS5_USE_RETENTION BIT(4)
#define EXYNOS5_L2RSTDISABLE_VALUE BIT(3)
#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
#define S5P_PAD_RET_GPIO_OPTION 0x3108
#define S5P_PAD_RET_UART_OPTION 0x3128
@ -126,7 +167,19 @@
#define S5P_PAD_RET_EBIA_OPTION 0x3188
#define S5P_PAD_RET_EBIB_OPTION 0x31A8
#define S5P_PS_HOLD_CONTROL 0x330C
#define S5P_PS_HOLD_EN (1 << 31)
#define S5P_PS_HOLD_OUTPUT_HIGH (3 << 8)
#define S5P_CAM_OPTION 0x3C08
#define S5P_MFC_OPTION 0x3C48
#define S5P_G3D_OPTION 0x3C68
#define S5P_LCD0_OPTION 0x3C88
#define S5P_LCD1_OPTION 0x3CA8
#define S5P_ISP_OPTION S5P_LCD1_OPTION
#define S5P_CORE_LOCAL_PWR_EN 0x3
#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8)
/* Only for EXYNOS4210 */
#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154
@ -185,11 +238,116 @@
#define S5P_DIS_IRQ_CORE3 0x1034
#define S5P_DIS_IRQ_CENTRAL3 0x1038
/* Only for EXYNOS3XXX */
#define EXYNOS3_ARM_CORE0_SYS_PWR_REG 0x1000
#define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004
#define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008
#define EXYNOS3_ARM_CORE1_SYS_PWR_REG 0x1010
#define EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG 0x1014
#define EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG 0x1018
#define EXYNOS3_ISP_ARM_SYS_PWR_REG 0x1050
#define EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1054
#define EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1058
#define EXYNOS3_ARM_COMMON_SYS_PWR_REG 0x1080
#define EXYNOS3_ARM_L2_SYS_PWR_REG 0x10C0
#define EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG 0x1100
#define EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG 0x1104
#define EXYNOS3_CMU_RESET_SYS_PWR_REG 0x110C
#define EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG 0x1110
#define EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG 0x1114
#define EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG 0x111C
#define EXYNOS3_APLL_SYSCLK_SYS_PWR_REG 0x1120
#define EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG 0x1124
#define EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG 0x1128
#define EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG 0x112C
#define EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG 0x1130
#define EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG 0x1134
#define EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG 0x1138
#define EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG 0x1140
#define EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1148
#define EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG 0x114C
#define EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG 0x1150
#define EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG 0x1154
#define EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG 0x1158
#define EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG 0x1160
#define EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG 0x1168
#define EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG 0x116C
#define EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG 0x1170
#define EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG 0x1174
#define EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG 0x1178
#define EXYNOS3_TOP_BUS_SYS_PWR_REG 0x1180
#define EXYNOS3_TOP_RETENTION_SYS_PWR_REG 0x1184
#define EXYNOS3_TOP_PWR_SYS_PWR_REG 0x1188
#define EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG 0x1190
#define EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG 0x1194
#define EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG 0x1198
#define EXYNOS3_LOGIC_RESET_SYS_PWR_REG 0x11A0
#define EXYNOS3_OSCCLK_GATE_SYS_PWR_REG 0x11A4
#define EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG 0x11B0
#define EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG 0x11B4
#define EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
#define EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG 0x1204
#define EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG 0x1208
#define EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1218
#define EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220
#define EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG 0x1224
#define EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1228
#define EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG 0x122C
#define EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230
#define EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234
#define EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1238
#define EXYNOS3_PAD_ISOLATION_SYS_PWR_REG 0x1240
#define EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG 0x1260
#define EXYNOS3_XUSBXTI_SYS_PWR_REG 0x1280
#define EXYNOS3_XXTI_SYS_PWR_REG 0x1284
#define EXYNOS3_EXT_REGULATOR_SYS_PWR_REG 0x12C0
#define EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG 0x12C4
#define EXYNOS3_GPIO_MODE_SYS_PWR_REG 0x1300
#define EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG 0x1340
#define EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG 0x1344
#define EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG 0x1348
#define EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG 0x1350
#define EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG 0x1354
#define EXYNOS3_CAM_SYS_PWR_REG 0x1380
#define EXYNOS3_MFC_SYS_PWR_REG 0x1388
#define EXYNOS3_G3D_SYS_PWR_REG 0x138C
#define EXYNOS3_LCD0_SYS_PWR_REG 0x1390
#define EXYNOS3_ISP_SYS_PWR_REG 0x1394
#define EXYNOS3_MAUDIO_SYS_PWR_REG 0x1398
#define EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG 0x13B0
#define EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG 0x13B4
#define EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG 0x13B8
#define EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG 0x13C0
#define EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG 0x13C4
#define EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG 0x13C8
#define EXYNOS3_ARM_CORE0_OPTION 0x2008
#define EXYNOS3_ARM_CORE_OPTION(_nr) \
(EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80))
#define EXYNOS3_ARM_COMMON_OPTION 0x2408
#define EXYNOS3_TOP_PWR_OPTION 0x2C48
#define EXYNOS3_CORE_TOP_PWR_OPTION 0x2CA8
#define EXYNOS3_XUSBXTI_DURATION 0x341C
#define EXYNOS3_XXTI_DURATION 0x343C
#define EXYNOS3_EXT_REGULATOR_DURATION 0x361C
#define EXYNOS3_EXT_REGULATOR_COREBLK_DURATION 0x363C
#define XUSBXTI_DURATION 0x00000BB8
#define XXTI_DURATION XUSBXTI_DURATION
#define EXT_REGULATOR_DURATION 0x00001D4C
#define EXT_REGULATOR_COREBLK_DURATION EXT_REGULATOR_DURATION
/* for XXX_OPTION */
#define EXYNOS3_OPTION_USE_SC_COUNTER (1 << 0)
#define EXYNOS3_OPTION_USE_SC_FEEDBACK (1 << 1)
#define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7)
/* For EXYNOS5 */
#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408
#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C
#define EXYNOS5_USE_RETENTION BIT(4)
#define EXYNOS5_SYS_WDTRESET (1 << 20)
#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000
@ -329,4 +487,204 @@ static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
}
/* Only for EXYNOS5420 */
#define EXYNOS5420_ISP_ARM_OPTION 0x2488
#define EXYNOS5420_L2RSTDISABLE_VALUE BIT(3)
#define EXYNOS5420_LPI_MASK 0x0004
#define EXYNOS5420_LPI_MASK1 0x0008
#define EXYNOS5420_UFS BIT(8)
#define EXYNOS5420_ATB_KFC BIT(13)
#define EXYNOS5420_ATB_ISP_ARM BIT(19)
#define EXYNOS5420_EMULATION BIT(31)
#define ATB_ISP_ARM BIT(12)
#define ATB_KFC BIT(13)
#define ATB_NOC BIT(14)
#define EXYNOS5420_ARM_INTR_SPREAD_ENABLE 0x0100
#define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI 0x0104
#define EXYNOS5420_UP_SCHEDULER 0x0120
#define SPREAD_ENABLE 0xF
#define SPREAD_USE_STANDWFI 0xF
#define EXYNOS5420_BB_CON1 0x0784
#define EXYNOS5420_BB_SEL_EN BIT(31)
#define EXYNOS5420_BB_PMOS_EN BIT(7)
#define EXYNOS5420_BB_1300X 0XF
#define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024
#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028
#define EXYNOS5420_ARM_CORE3_SYS_PWR_REG 0x1030
#define EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG 0x1034
#define EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG 0x1038
#define EXYNOS5420_KFC_CORE0_SYS_PWR_REG 0x1040
#define EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG 0x1044
#define EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG 0x1048
#define EXYNOS5420_KFC_CORE1_SYS_PWR_REG 0x1050
#define EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG 0x1054
#define EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG 0x1058
#define EXYNOS5420_KFC_CORE2_SYS_PWR_REG 0x1060
#define EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG 0x1064
#define EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG 0x1068
#define EXYNOS5420_KFC_CORE3_SYS_PWR_REG 0x1070
#define EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG 0x1074
#define EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG 0x1078
#define EXYNOS5420_ISP_ARM_SYS_PWR_REG 0x1090
#define EXYNOS5420_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1094
#define EXYNOS5420_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1098
#define EXYNOS5420_ARM_COMMON_SYS_PWR_REG 0x10A0
#define EXYNOS5420_KFC_COMMON_SYS_PWR_REG 0x10B0
#define EXYNOS5420_KFC_L2_SYS_PWR_REG 0x10D0
#define EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG 0x1158
#define EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG 0x115C
#define EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG 0x1160
#define EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG 0x1174
#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG 0x1178
#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG 0x11B8
#define EXYNOS5420_INTROM_MEM_SYS_PWR_REG 0x11BC
#define EXYNOS5420_ONENANDXL_MEM_SYS_PWR 0x11C0
#define EXYNOS5420_USBDEV_MEM_SYS_PWR 0x11CC
#define EXYNOS5420_USBDEV1_MEM_SYS_PWR 0x11D0
#define EXYNOS5420_SDMMC_MEM_SYS_PWR 0x11D4
#define EXYNOS5420_CSSYS_MEM_SYS_PWR 0x11D8
#define EXYNOS5420_SECSS_MEM_SYS_PWR 0x11DC
#define EXYNOS5420_ROTATOR_MEM_SYS_PWR 0x11E0
#define EXYNOS5420_INTRAM_MEM_SYS_PWR 0x11E4
#define EXYNOS5420_INTROM_MEM_SYS_PWR 0x11E8
#define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1208
#define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1210
#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG 0x1214
#define EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1218
#define EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG 0x121C
#define EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1220
#define EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG 0x1224
#define EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1228
#define EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG 0x122C
#define EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG 0x1230
#define EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG 0x1234
#define EXYNOS5420_DISP1_SYS_PWR_REG 0x1410
#define EXYNOS5420_MAU_SYS_PWR_REG 0x1414
#define EXYNOS5420_G2D_SYS_PWR_REG 0x1418
#define EXYNOS5420_MSC_SYS_PWR_REG 0x141C
#define EXYNOS5420_FSYS_SYS_PWR_REG 0x1420
#define EXYNOS5420_FSYS2_SYS_PWR_REG 0x1424
#define EXYNOS5420_PSGEN_SYS_PWR_REG 0x1428
#define EXYNOS5420_PERIC_SYS_PWR_REG 0x142C
#define EXYNOS5420_WCORE_SYS_PWR_REG 0x1430
#define EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG 0x1490
#define EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG 0x1494
#define EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG 0x1498
#define EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG 0x149C
#define EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG 0x14A0
#define EXYNOS5420_CMU_CLKSTOP_FSYS2_SYS_PWR_REG 0x14A4
#define EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG 0x14A8
#define EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG 0x14AC
#define EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG 0x14B0
#define EXYNOS5420_CMU_SYSCLK_TOPPWR_SYS_PWR_REG 0x14BC
#define EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG 0x14D0
#define EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG 0x14D4
#define EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG 0x14D8
#define EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG 0x14DC
#define EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG 0x14E0
#define EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG 0x14E4
#define EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG 0x14E8
#define EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG 0x14EC
#define EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG 0x14F0
#define EXYNOS5420_CMU_SYSCLK_SYSMEM_TOPPWR_SYS_PWR_REG 0x14F4
#define EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG 0x1570
#define EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG 0x1574
#define EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG 0x1578
#define EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG 0x157C
#define EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG 0x1590
#define EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG 0x1594
#define EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG 0x1598
#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG 0x159C
#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG 0x15A0
#define EXYNOS5420_SFR_AXI_CGDIS1 0x15E4
#define EXYNOS_ARM_CORE2_CONFIGURATION 0x2100
#define EXYNOS5420_ARM_CORE2_OPTION 0x2108
#define EXYNOS_ARM_CORE3_CONFIGURATION 0x2180
#define EXYNOS5420_ARM_CORE3_OPTION 0x2188
#define EXYNOS5420_ARM_COMMON_STATUS 0x2504
#define EXYNOS5420_ARM_COMMON_OPTION 0x2508
#define EXYNOS5420_KFC_COMMON_STATUS 0x2584
#define EXYNOS5420_KFC_COMMON_OPTION 0x2588
#define EXYNOS5420_LOGIC_RESET_DURATION3 0x2D1C
#define EXYNOS5420_PAD_RET_GPIO_OPTION 0x30C8
#define EXYNOS5420_PAD_RET_UART_OPTION 0x30E8
#define EXYNOS5420_PAD_RET_MMCA_OPTION 0x3108
#define EXYNOS5420_PAD_RET_MMCB_OPTION 0x3128
#define EXYNOS5420_PAD_RET_MMCC_OPTION 0x3148
#define EXYNOS5420_PAD_RET_HSI_OPTION 0x3168
#define EXYNOS5420_PAD_RET_SPI_OPTION 0x31C8
#define EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION 0x31E8
#define EXYNOS_PAD_RET_DRAM_OPTION 0x3008
#define EXYNOS_PAD_RET_MAUDIO_OPTION 0x3028
#define EXYNOS_PAD_RET_JTAG_OPTION 0x3048
#define EXYNOS_PAD_RET_GPIO_OPTION 0x3108
#define EXYNOS_PAD_RET_UART_OPTION 0x3128
#define EXYNOS_PAD_RET_MMCA_OPTION 0x3148
#define EXYNOS_PAD_RET_MMCB_OPTION 0x3168
#define EXYNOS_PAD_RET_EBIA_OPTION 0x3188
#define EXYNOS_PAD_RET_EBIB_OPTION 0x31A8
#define EXYNOS_PS_HOLD_CONTROL 0x330C
/* For SYS_PWR_REG */
#define EXYNOS_SYS_PWR_CFG BIT(0)
#define EXYNOS5420_MFC_CONFIGURATION 0x4060
#define EXYNOS5420_MFC_STATUS 0x4064
#define EXYNOS5420_MFC_OPTION 0x4068
#define EXYNOS5420_G3D_CONFIGURATION 0x4080
#define EXYNOS5420_G3D_STATUS 0x4084
#define EXYNOS5420_G3D_OPTION 0x4088
#define EXYNOS5420_DISP0_CONFIGURATION 0x40A0
#define EXYNOS5420_DISP0_STATUS 0x40A4
#define EXYNOS5420_DISP0_OPTION 0x40A8
#define EXYNOS5420_DISP1_CONFIGURATION 0x40C0
#define EXYNOS5420_DISP1_STATUS 0x40C4
#define EXYNOS5420_DISP1_OPTION 0x40C8
#define EXYNOS5420_MAU_CONFIGURATION 0x40E0
#define EXYNOS5420_MAU_STATUS 0x40E4
#define EXYNOS5420_MAU_OPTION 0x40E8
#define EXYNOS5420_FSYS2_OPTION 0x4168
#define EXYNOS5420_PSGEN_OPTION 0x4188
/* For EXYNOS_CENTRAL_SEQ_OPTION */
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE0 BIT(16)
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE1 BUT(17)
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE0 BIT(24)
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE1 BIT(25)
#define EXYNOS5420_ARM_USE_STANDBY_WFI0 BIT(4)
#define EXYNOS5420_ARM_USE_STANDBY_WFI1 BIT(5)
#define EXYNOS5420_ARM_USE_STANDBY_WFI2 BIT(6)
#define EXYNOS5420_ARM_USE_STANDBY_WFI3 BIT(7)
#define EXYNOS5420_KFC_USE_STANDBY_WFI0 BIT(8)
#define EXYNOS5420_KFC_USE_STANDBY_WFI1 BIT(9)
#define EXYNOS5420_KFC_USE_STANDBY_WFI2 BIT(10)
#define EXYNOS5420_KFC_USE_STANDBY_WFI3 BIT(11)
#define EXYNOS5420_ARM_USE_STANDBY_WFE0 BIT(16)
#define EXYNOS5420_ARM_USE_STANDBY_WFE1 BIT(17)
#define EXYNOS5420_ARM_USE_STANDBY_WFE2 BIT(18)
#define EXYNOS5420_ARM_USE_STANDBY_WFE3 BIT(19)
#define EXYNOS5420_KFC_USE_STANDBY_WFE0 BIT(20)
#define EXYNOS5420_KFC_USE_STANDBY_WFE1 BIT(21)
#define EXYNOS5420_KFC_USE_STANDBY_WFE2 BIT(22)
#define EXYNOS5420_KFC_USE_STANDBY_WFE3 BIT(23)
#define DUR_WAIT_RESET 0xF
#define EXYNOS5420_USE_STANDBY_WFI_ALL (EXYNOS5420_ARM_USE_STANDBY_WFI0 \
| EXYNOS5420_ARM_USE_STANDBY_WFI1 \
| EXYNOS5420_ARM_USE_STANDBY_WFI2 \
| EXYNOS5420_ARM_USE_STANDBY_WFI3 \
| EXYNOS5420_KFC_USE_STANDBY_WFI0 \
| EXYNOS5420_KFC_USE_STANDBY_WFI1 \
| EXYNOS5420_KFC_USE_STANDBY_WFI2 \
| EXYNOS5420_KFC_USE_STANDBY_WFI3)
#endif /* __ASM_ARCH_REGS_PMU_H */

View File

@ -16,6 +16,7 @@
*/
#include <linux/linkage.h>
#include "smc.h"
#define CPU_MASK 0xff0ffff0
#define CPU_CORTEX_A9 0x410fc090
@ -55,3 +56,30 @@ ENTRY(exynos_cpu_resume)
#endif
b cpu_resume
ENDPROC(exynos_cpu_resume)
.align
ENTRY(exynos_cpu_resume_ns)
mrc p15, 0, r0, c0, c0, 0
ldr r1, =CPU_MASK
and r0, r0, r1
ldr r1, =CPU_CORTEX_A9
cmp r0, r1
bne skip_cp15
adr r0, cp15_save_power
ldr r1, [r0]
adr r0, cp15_save_diag
ldr r2, [r0]
mov r0, #SMC_CMD_C15RESUME
dsb
smc #0
skip_cp15:
b cpu_resume
ENDPROC(exynos_cpu_resume_ns)
.globl cp15_save_diag
cp15_save_diag:
.long 0 @ cp15 diagnostic
.globl cp15_save_power
cp15_save_power:
.long 0 @ cp15 power control

View File

@ -26,6 +26,10 @@
#define SMC_CMD_L2X0INVALL (-24)
#define SMC_CMD_L2X0DEBUG (-25)
#ifndef __ASSEMBLY__
extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
#endif /* __ASSEMBLY__ */
#endif

View File

@ -0,0 +1,566 @@
/*
* Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS - Suspend support
*
* Based on arch/arm/mach-s3c2410/pm.c
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/cpu_pm.h>
#include <linux/io.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/err.h>
#include <linux/regulator/machine.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/firmware.h>
#include <asm/mcpm.h>
#include <asm/smp_scu.h>
#include <asm/suspend.h>
#include <plat/pm-common.h>
#include <plat/regs-srom.h>
#include "common.h"
#include "regs-pmu.h"
#include "regs-sys.h"
#include "exynos-pmu.h"
#define S5P_CHECK_SLEEP 0x00000BAD
#define REG_TABLE_END (-1U)
#define EXYNOS5420_CPU_STATE 0x28
/**
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
* @hwirq: Hardware IRQ signal of the GIC
* @mask: Mask in PMU wake-up mask register
*/
struct exynos_wkup_irq {
unsigned int hwirq;
u32 mask;
};
static struct sleep_save exynos5_sys_save[] = {
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
};
static struct sleep_save exynos_core_save[] = {
/* SROM side */
SAVE_ITEM(S5P_SROM_BW),
SAVE_ITEM(S5P_SROM_BC0),
SAVE_ITEM(S5P_SROM_BC1),
SAVE_ITEM(S5P_SROM_BC2),
SAVE_ITEM(S5P_SROM_BC3),
};
struct exynos_pm_data {
const struct exynos_wkup_irq *wkup_irq;
struct sleep_save *extra_save;
int num_extra_save;
unsigned int wake_disable_mask;
unsigned int *release_ret_regs;
void (*pm_prepare)(void);
void (*pm_resume_prepare)(void);
void (*pm_resume)(void);
int (*pm_suspend)(void);
int (*cpu_suspend)(unsigned long);
};
struct exynos_pm_data *pm_data;
static int exynos5420_cpu_state;
static unsigned int exynos_pmu_spare3;
/*
* GIC wake-up support
*/
static u32 exynos_irqwake_intmask = 0xffffffff;
static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
{ 76, BIT(1) }, /* RTC alarm */
{ 77, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
{ 75, BIT(1) }, /* RTC alarm */
{ 76, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
unsigned int exynos_release_ret_regs[] = {
S5P_PAD_RET_MAUDIO_OPTION,
S5P_PAD_RET_GPIO_OPTION,
S5P_PAD_RET_UART_OPTION,
S5P_PAD_RET_MMCA_OPTION,
S5P_PAD_RET_MMCB_OPTION,
S5P_PAD_RET_EBIA_OPTION,
S5P_PAD_RET_EBIB_OPTION,
REG_TABLE_END,
};
unsigned int exynos5420_release_ret_regs[] = {
EXYNOS_PAD_RET_DRAM_OPTION,
EXYNOS_PAD_RET_MAUDIO_OPTION,
EXYNOS_PAD_RET_JTAG_OPTION,
EXYNOS5420_PAD_RET_GPIO_OPTION,
EXYNOS5420_PAD_RET_UART_OPTION,
EXYNOS5420_PAD_RET_MMCA_OPTION,
EXYNOS5420_PAD_RET_MMCB_OPTION,
EXYNOS5420_PAD_RET_MMCC_OPTION,
EXYNOS5420_PAD_RET_HSI_OPTION,
EXYNOS_PAD_RET_EBIA_OPTION,
EXYNOS_PAD_RET_EBIB_OPTION,
EXYNOS5420_PAD_RET_SPI_OPTION,
EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
REG_TABLE_END,
};
static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
{
const struct exynos_wkup_irq *wkup_irq;
if (!pm_data->wkup_irq)
return -ENOENT;
wkup_irq = pm_data->wkup_irq;
while (wkup_irq->mask) {
if (wkup_irq->hwirq == data->hwirq) {
if (!state)
exynos_irqwake_intmask |= wkup_irq->mask;
else
exynos_irqwake_intmask &= ~wkup_irq->mask;
return 0;
}
++wkup_irq;
}
return -ENOENT;
}
static int exynos_cpu_do_idle(void)
{
/* issue the standby signal into the pm unit. */
cpu_do_idle();
pr_info("Failed to suspend the system\n");
return 1; /* Aborting suspend */
}
static void exynos_flush_cache_all(void)
{
flush_cache_all();
outer_flush_all();
}
static int exynos_cpu_suspend(unsigned long arg)
{
exynos_flush_cache_all();
return exynos_cpu_do_idle();
}
static int exynos5420_cpu_suspend(unsigned long arg)
{
/* MCPM works with HW CPU identifiers */
unsigned int mpidr = read_cpuid_mpidr();
unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
__raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE);
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
/*
* Residency value passed to mcpm_cpu_suspend back-end
* has to be given clear semantics. Set to 0 as a
* temporary value.
*/
mcpm_cpu_suspend(0);
}
pr_info("Failed to suspend the system\n");
/* return value != 0 means failure */
return 1;
}
static void exynos_pm_set_wakeup_mask(void)
{
/* Set wake-up mask registers */
pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
}
static void exynos_pm_enter_sleep_mode(void)
{
/* Set value of power down register for sleep mode */
exynos_sys_powerdown_conf(SYS_SLEEP);
pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
}
static void exynos_pm_prepare(void)
{
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (pm_data->extra_save)
s3c_pm_do_save(pm_data->extra_save,
pm_data->num_extra_save);
exynos_pm_enter_sleep_mode();
/* ensure at least INFORM0 has the resume address */
pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
static void exynos5420_pm_prepare(void)
{
unsigned int tmp;
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
/*
* The cpu state needs to be saved and restored so that the
* secondary CPUs will enter low power start. Though the U-Boot
* is setting the cpu state with low power flag, the kernel
* needs to restore it back in case, the primary cpu fails to
* suspend for any reason.
*/
exynos5420_cpu_state = __raw_readl(sysram_base_addr +
EXYNOS5420_CPU_STATE);
exynos_pm_enter_sleep_mode();
/* ensure at least INFORM0 has the resume address */
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
tmp &= ~EXYNOS5_USE_RETENTION;
pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
tmp |= EXYNOS5420_UFS;
pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE;
pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION);
tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
tmp |= EXYNOS5420_EMULATION;
pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
tmp |= EXYNOS5420_EMULATION;
pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
}
static int exynos_pm_suspend(void)
{
exynos_pm_central_suspend();
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register();
return 0;
}
static int exynos5420_pm_suspend(void)
{
u32 this_cluster;
exynos_pm_central_suspend();
/* Setting SEQ_OPTION register */
this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
if (!this_cluster)
pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0,
S5P_CENTRAL_SEQ_OPTION);
else
pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0,
S5P_CENTRAL_SEQ_OPTION);
return 0;
}
static void exynos_pm_release_retention(void)
{
unsigned int i;
for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
pm_data->release_ret_regs[i]);
}
static void exynos_pm_resume(void)
{
u32 cpuid = read_cpuid_part();
if (exynos_pm_central_resume())
goto early_wakeup;
/* For release retention */
exynos_pm_release_retention();
if (pm_data->extra_save)
s3c_pm_do_restore_core(pm_data->extra_save,
pm_data->num_extra_save);
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (cpuid == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
if (call_firmware_op(resume) == -ENOSYS
&& cpuid == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_restore_register();
early_wakeup:
/* Clear SLEEP mode set in INFORM1 */
pmu_raw_writel(0x0, S5P_INFORM1);
}
static void exynos5420_prepare_pm_resume(void)
{
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
WARN_ON(mcpm_cpu_powered_up());
}
static void exynos5420_pm_resume(void)
{
unsigned long tmp;
/* Restore the CPU0 low power state register */
tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
EXYNOS5_ARM_CORE0_SYS_PWR_REG);
/* Restore the sysram cpu state register */
__raw_writel(exynos5420_cpu_state,
sysram_base_addr + EXYNOS5420_CPU_STATE);
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
S5P_CENTRAL_SEQ_OPTION);
if (exynos_pm_central_resume())
goto early_wakeup;
/* For release retention */
exynos_pm_release_retention();
pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
early_wakeup:
tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
tmp &= ~EXYNOS5420_UFS;
pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
tmp &= ~EXYNOS5420_EMULATION;
pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
tmp &= ~EXYNOS5420_EMULATION;
pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
/* Clear SLEEP mode set in INFORM1 */
pmu_raw_writel(0x0, S5P_INFORM1);
}
/*
* Suspend Ops
*/
static int exynos_suspend_enter(suspend_state_t state)
{
int ret;
s3c_pm_debug_init();
S3C_PMDBG("%s: suspending the system...\n", __func__);
S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
exynos_irqwake_intmask, exynos_get_eint_wake_mask());
if (exynos_irqwake_intmask == -1U
&& exynos_get_eint_wake_mask() == -1U) {
pr_err("%s: No wake-up sources!\n", __func__);
pr_err("%s: Aborting sleep\n", __func__);
return -EINVAL;
}
s3c_pm_save_uarts();
if (pm_data->pm_prepare)
pm_data->pm_prepare();
flush_cache_all();
s3c_pm_check_store();
ret = call_firmware_op(suspend);
if (ret == -ENOSYS)
ret = cpu_suspend(0, pm_data->cpu_suspend);
if (ret)
return ret;
if (pm_data->pm_resume_prepare)
pm_data->pm_resume_prepare();
s3c_pm_restore_uarts();
S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
pmu_raw_readl(S5P_WAKEUP_STAT));
s3c_pm_check_restore();
S3C_PMDBG("%s: resuming the system...\n", __func__);
return 0;
}
static int exynos_suspend_prepare(void)
{
int ret;
/*
* REVISIT: It would be better if struct platform_suspend_ops
* .prepare handler get the suspend_state_t as a parameter to
* avoid hard-coding the suspend to mem state. It's safe to do
* it now only because the suspend_valid_only_mem function is
* used as the .valid callback used to check if a given state
* is supported by the platform anyways.
*/
ret = regulator_suspend_prepare(PM_SUSPEND_MEM);
if (ret) {
pr_err("Failed to prepare regulators for suspend (%d)\n", ret);
return ret;
}
s3c_pm_check_prepare();
return 0;
}
static void exynos_suspend_finish(void)
{
int ret;
s3c_pm_check_cleanup();
ret = regulator_suspend_finish();
if (ret)
pr_warn("Failed to resume regulators from suspend (%d)\n", ret);
}
static const struct platform_suspend_ops exynos_suspend_ops = {
.enter = exynos_suspend_enter,
.prepare = exynos_suspend_prepare,
.finish = exynos_suspend_finish,
.valid = suspend_valid_only_mem,
};
static const struct exynos_pm_data exynos4_pm_data = {
.wkup_irq = exynos4_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
.pm_suspend = exynos_pm_suspend,
.pm_resume = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
.cpu_suspend = exynos_cpu_suspend,
};
static const struct exynos_pm_data exynos5250_pm_data = {
.wkup_irq = exynos5250_wkup_irq,
.wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
.release_ret_regs = exynos_release_ret_regs,
.extra_save = exynos5_sys_save,
.num_extra_save = ARRAY_SIZE(exynos5_sys_save),
.pm_suspend = exynos_pm_suspend,
.pm_resume = exynos_pm_resume,
.pm_prepare = exynos_pm_prepare,
.cpu_suspend = exynos_cpu_suspend,
};
static struct exynos_pm_data exynos5420_pm_data = {
.wkup_irq = exynos5250_wkup_irq,
.wake_disable_mask = (0x7F << 7) | (0x1F << 1),
.release_ret_regs = exynos5420_release_ret_regs,
.pm_resume_prepare = exynos5420_prepare_pm_resume,
.pm_resume = exynos5420_pm_resume,
.pm_suspend = exynos5420_pm_suspend,
.pm_prepare = exynos5420_pm_prepare,
.cpu_suspend = exynos5420_cpu_suspend,
};
static struct of_device_id exynos_pmu_of_device_ids[] = {
{
.compatible = "samsung,exynos4210-pmu",
.data = &exynos4_pm_data,
}, {
.compatible = "samsung,exynos4212-pmu",
.data = &exynos4_pm_data,
}, {
.compatible = "samsung,exynos4412-pmu",
.data = &exynos4_pm_data,
}, {
.compatible = "samsung,exynos5250-pmu",
.data = &exynos5250_pm_data,
}, {
.compatible = "samsung,exynos5420-pmu",
.data = &exynos5420_pm_data,
},
{ /*sentinel*/ },
};
static struct syscore_ops exynos_pm_syscore_ops;
void __init exynos_pm_init(void)
{
const struct of_device_id *match;
u32 tmp;
of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
if (!match) {
pr_err("Failed to find PMU node\n");
return;
}
pm_data = (struct exynos_pm_data *) match->data;
/* Platform-specific GIC callback */
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
/* All wakeup disable */
tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
tmp |= pm_data->wake_disable_mask;
pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
exynos_pm_syscore_ops.suspend = pm_data->pm_suspend;
exynos_pm_syscore_ops.resume = pm_data->pm_resume;
register_syscore_ops(&exynos_pm_syscore_ops);
suspend_set_ops(&exynos_suspend_ops);
}

View File

@ -633,12 +633,41 @@ config SOC_VF610
bool "Vybrid Family VF610 support"
select ARM_GIC
select PINCTRL_VF610
select VF_PIT_TIMER
select PL310_ERRATA_769419 if CACHE_L2X0
help
This enable support for Freescale Vybrid VF610 processor.
choice
prompt "Clocksource for scheduler clock"
depends on SOC_VF610
default VF_USE_ARM_GLOBAL_TIMER
config VF_USE_ARM_GLOBAL_TIMER
bool "Use ARM Global Timer"
select ARM_GLOBAL_TIMER
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
help
Use the ARM Global Timer as clocksource
config VF_USE_PIT_TIMER
bool "Use PIT timer"
select VF_PIT_TIMER
help
Use SoC Periodic Interrupt Timer (PIT) as clocksource
endchoice
config SOC_LS1021A
bool "Freescale LS1021A support"
select ARM_GIC
select HAVE_ARM_ARCH_TIMER
select PCI_DOMAINS if PCI
select ZONE_DMA if ARM_LPAE
help
This enable support for Freescale LS1021A processor.
endif
source "arch/arm/mach-imx/devices/Kconfig"

View File

@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
imx5-pm-$(CONFIG_PM) += pm-imx5.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o clk.o \
@ -89,7 +89,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
ifdef CONFIG_SOC_IMX6
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@ -110,4 +110,6 @@ obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o
obj-y += devices/

View File

@ -30,8 +30,11 @@
#define ANADIG_DIGPROG_IMX6SL 0x280
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8
#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS 0x2000
#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
@ -56,16 +59,43 @@ static void imx_anatop_enable_fet_odrive(bool enable)
BM_ANADIG_REG_CORE_FET_ODRIVE);
}
static inline void imx_anatop_enable_2p5_pulldown(bool enable)
{
regmap_write(anatop, ANADIG_REG_2P5 + (enable ? REG_SET : REG_CLR),
BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
}
static inline void imx_anatop_disconnect_high_snvs(bool enable)
{
regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
}
void imx_anatop_pre_suspend(void)
{
if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
imx_anatop_enable_2p5_pulldown(true);
else
imx_anatop_enable_weak2p5(true);
imx_anatop_enable_fet_odrive(true);
if (cpu_is_imx6sl())
imx_anatop_disconnect_high_snvs(true);
}
void imx_anatop_post_resume(void)
{
imx_anatop_enable_fet_odrive(false);
if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
imx_anatop_enable_2p5_pulldown(false);
else
imx_anatop_enable_weak2p5(false);
imx_anatop_enable_fet_odrive(false);
if (cpu_is_imx6sl())
imx_anatop_disconnect_high_snvs(false);
}
static void imx_anatop_usb_chrg_detect_disable(void)

107
arch/arm/mach-imx/clk-cpu.c Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
*
* 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.
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
struct clk_cpu {
struct clk_hw hw;
struct clk *div;
struct clk *mux;
struct clk *pll;
struct clk *step;
};
static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
{
return container_of(hw, struct clk_cpu, hw);
}
static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_cpu *cpu = to_clk_cpu(hw);
return clk_get_rate(cpu->div);
}
static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_cpu *cpu = to_clk_cpu(hw);
return clk_round_rate(cpu->pll, rate);
}
static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_cpu *cpu = to_clk_cpu(hw);
int ret;
/* switch to PLL bypass clock */
ret = clk_set_parent(cpu->mux, cpu->step);
if (ret)
return ret;
/* reprogram PLL */
ret = clk_set_rate(cpu->pll, rate);
if (ret) {
clk_set_parent(cpu->mux, cpu->pll);
return ret;
}
/* switch back to PLL clock */
clk_set_parent(cpu->mux, cpu->pll);
/* Ensure the divider is what we expect */
clk_set_rate(cpu->div, rate);
return 0;
}
static const struct clk_ops clk_cpu_ops = {
.recalc_rate = clk_cpu_recalc_rate,
.round_rate = clk_cpu_round_rate,
.set_rate = clk_cpu_set_rate,
};
struct clk *imx_clk_cpu(const char *name, const char *parent_name,
struct clk *div, struct clk *mux, struct clk *pll,
struct clk *step)
{
struct clk_cpu *cpu;
struct clk *clk;
struct clk_init_data init;
cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
if (!cpu)
return ERR_PTR(-ENOMEM);
cpu->div = div;
cpu->mux = mux;
cpu->pll = pll;
cpu->step = step;
init.name = name;
init.ops = &clk_cpu_ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = 1;
cpu->hw.init = &init;
clk = clk_register(NULL, &cpu->hw);
if (IS_ERR(clk))
kfree(cpu);
return clk;
}

View File

@ -125,6 +125,8 @@ static const char *mx53_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", "pll4_sw",
static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_sel", };
static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", };
static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
static const char *step_sels[] = { "lp_apm", };
static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
static struct clk *clk[IMX5_CLK_END];
static struct clk_onecell_data clk_data;
@ -193,7 +195,9 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
clk[IMX5_CLK_USB_PHY_PODF] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
clk[IMX5_CLK_USB_PHY_SEL] = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
clk[IMX5_CLK_CPU_PODF] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
clk[IMX5_CLK_STEP_SEL] = imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels));
clk[IMX5_CLK_CPU_PODF_SEL] = imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels));
clk[IMX5_CLK_CPU_PODF] = imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3);
clk[IMX5_CLK_DI_PRED] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
clk[IMX5_CLK_IIM_GATE] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
clk[IMX5_CLK_UART1_IPG_GATE] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
@ -537,6 +541,11 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_CKO2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
clk[IMX5_CLK_SPDIF_XTAL_SEL] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
clk[IMX5_CLK_ARM] = imx_clk_cpu("arm", "cpu_podf",
clk[IMX5_CLK_CPU_PODF],
clk[IMX5_CLK_CPU_PODF_SEL],
clk[IMX5_CLK_PLL1_SW],
clk[IMX5_CLK_STEP_SEL]);
imx_check_clocks(clk, ARRAY_SIZE(clk));
@ -551,6 +560,9 @@ static void __init mx53_clocks_init(struct device_node *np)
/* move can bus clk to 24MHz */
clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
/* make sure step clock is running from 24MHz */
clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]);
clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
imx_print_silicon_rev("i.MX53", mx53_revision());
clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);

View File

@ -120,6 +120,17 @@ static unsigned int const clks_init_on[] __initconst = {
VF610_CLK_DDR_SEL,
};
static struct clk * __init vf610_get_fixed_clock(
struct device_node *ccm_node, const char *name)
{
struct clk *clk = of_clk_get_by_name(ccm_node, name);
/* Backward compatibility if device tree is missing clks assignments */
if (IS_ERR(clk))
clk = imx_obtain_fixed_clock(name, 0);
return clk;
};
static void __init vf610_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@ -130,13 +141,13 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_SIRC_32K] = imx_clk_fixed("sirc_32k", 32000);
clk[VF610_CLK_FIRC] = imx_clk_fixed("firc", 24000000);
clk[VF610_CLK_SXOSC] = imx_obtain_fixed_clock("sxosc", 0);
clk[VF610_CLK_FXOSC] = imx_obtain_fixed_clock("fxosc", 0);
clk[VF610_CLK_AUDIO_EXT] = imx_obtain_fixed_clock("audio_ext", 0);
clk[VF610_CLK_ENET_EXT] = imx_obtain_fixed_clock("enet_ext", 0);
clk[VF610_CLK_SXOSC] = vf610_get_fixed_clock(ccm_node, "sxosc");
clk[VF610_CLK_FXOSC] = vf610_get_fixed_clock(ccm_node, "fxosc");
clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(ccm_node, "audio_ext");
clk[VF610_CLK_ENET_EXT] = vf610_get_fixed_clock(ccm_node, "enet_ext");
/* Clock source from external clock via LVDs PAD */
clk[VF610_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(ccm_node, "anaclk1");
clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2);

View File

@ -131,4 +131,8 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
CLK_SET_RATE_PARENT, mult, div);
}
struct clk *imx_clk_cpu(const char *name, const char *parent_name,
struct clk *div, struct clk *mux, struct clk *pll,
struct clk *step);
#endif

View File

@ -115,6 +115,7 @@ void imx_anatop_post_resume(void);
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6q_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
int imx_mmdc_get_ddr_type(void);
void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
@ -156,5 +157,6 @@ static inline void imx_init_l2cache(void) {}
#endif
extern struct smp_operations imx_smp_ops;
extern struct smp_operations ls1021a_smp_ops;
#endif

View File

@ -40,6 +40,8 @@ static void __init imx53_dt_init(void)
static void __init imx53_init_late(void)
{
imx53_pm_init();
platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
}
static const char * const imx53_dt_board_compat[] __initconst = {

View File

@ -8,12 +8,62 @@
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
#include "cpuidle.h"
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
/* Set RGMII IO voltage to 1.8V */
phy_write(dev, 0x1d, 0x1f);
phy_write(dev, 0x1e, 0x8);
/* introduce tx clock delay */
phy_write(dev, 0x1d, 0x5);
val = phy_read(dev, 0x1e);
val |= 0x0100;
phy_write(dev, 0x1e, val);
return 0;
}
#define PHY_ID_AR8031 0x004dd074
static void __init imx6sx_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB))
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
ar8031_phy_fixup);
}
static void __init imx6sx_enet_clk_sel(void)
{
struct regmap *gpr;
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
if (!IS_ERR(gpr)) {
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
} else {
pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
}
}
static inline void imx6sx_enet_init(void)
{
imx6sx_enet_phy_init();
imx6sx_enet_clk_sel();
}
static void __init imx6sx_init_machine(void)
{
struct device *parent;
@ -24,6 +74,7 @@ static void __init imx6sx_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
imx6sx_enet_init();
imx_anatop_init();
imx6sx_pm_init();
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2013-2014 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <asm/mach/arch.h>
#include "common.h"
static const char * const ls1021a_dt_compat[] __initconst = {
"fsl,ls1021a",
NULL,
};
DT_MACHINE_START(LS1021A, "Freescale LS1021A")
.smp = smp_ops(ls1021a_smp_ops),
.dt_compat = ls1021a_dt_compat,
MACHINE_END

View File

@ -21,6 +21,12 @@
#define BP_MMDC_MAPSR_PSD 0
#define BP_MMDC_MAPSR_PSS 4
#define MMDC_MDMISC 0x18
#define BM_MMDC_MDMISC_DDR_TYPE 0x18
#define BP_MMDC_MDMISC_DDR_TYPE 0x3
static int ddr_type;
static int imx_mmdc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@ -31,6 +37,12 @@ static int imx_mmdc_probe(struct platform_device *pdev)
mmdc_base = of_iomap(np, 0);
WARN_ON(!mmdc_base);
reg = mmdc_base + MMDC_MDMISC;
/* Get ddr type */
val = readl_relaxed(reg);
ddr_type = (val & BM_MMDC_MDMISC_DDR_TYPE) >>
BP_MMDC_MDMISC_DDR_TYPE;
reg = mmdc_base + MMDC_MAPSR;
/* Enable automatic power saving */
@ -51,6 +63,11 @@ static int imx_mmdc_probe(struct platform_device *pdev)
return 0;
}
int imx_mmdc_get_ddr_type(void)
{
return ddr_type;
}
static struct of_device_id imx_mmdc_dt_ids[] = {
{ .compatible = "fsl,imx6q-mmdc", },
{ /* sentinel */ }

View File

@ -55,6 +55,8 @@
#define IMX_CHIP_REVISION_3_3 0x33
#define IMX_CHIP_REVISION_UNKNOWN 0xff
#define IMX_DDR_TYPE_LPDDR2 1
#ifndef __ASSEMBLY__
extern unsigned int __mxc_cpu_type;
#endif

View File

@ -11,7 +11,10 @@
*/
#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
#include <asm/smp_scu.h>
@ -94,3 +97,33 @@ struct smp_operations imx_smp_ops __initdata = {
.cpu_kill = imx_cpu_kill,
#endif
};
#define DCFG_CCSR_SCRATCHRW1 0x200
static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
return 0;
}
static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
{
struct device_node *np;
void __iomem *dcfg_base;
unsigned long paddr;
np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
dcfg_base = of_iomap(np, 0);
BUG_ON(!dcfg_base);
paddr = virt_to_phys(secondary_startup);
writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1);
iounmap(dcfg_base);
}
struct smp_operations ls1021a_smp_ops __initdata = {
.smp_prepare_cpus = ls1021a_smp_prepare_cpus,
.smp_boot_secondary = ls1021a_boot_secondary,
};

View File

@ -88,7 +88,7 @@ struct imx6_pm_base {
};
struct imx6_pm_socdata {
u32 cpu_type;
u32 ddr_type;
const char *mmdc_compat;
const char *src_compat;
const char *iomuxc_compat;
@ -138,7 +138,6 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
};
static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.cpu_type = MXC_CPU_IMX6Q,
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6q-iomuxc",
@ -148,7 +147,6 @@ static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
.cpu_type = MXC_CPU_IMX6DL,
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6dl-iomuxc",
@ -158,7 +156,6 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
.cpu_type = MXC_CPU_IMX6SL,
.mmdc_compat = "fsl,imx6sl-mmdc",
.src_compat = "fsl,imx6sl-src",
.iomuxc_compat = "fsl,imx6sl-iomuxc",
@ -168,7 +165,6 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
.cpu_type = MXC_CPU_IMX6SX,
.mmdc_compat = "fsl,imx6sx-mmdc",
.src_compat = "fsl,imx6sx-src",
.iomuxc_compat = "fsl,imx6sx-iomuxc",
@ -187,7 +183,7 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
struct imx6_cpu_pm_info {
phys_addr_t pbase; /* The physical address of pm_info. */
phys_addr_t resume_addr; /* The physical resume address for asm code */
u32 cpu_type;
u32 ddr_type;
u32 pm_info_size; /* Size of pm_info. */
struct imx6_pm_base mmdc_base;
struct imx6_pm_base src_base;
@ -521,7 +517,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
goto pl310_cache_map_failed;
}
pm_info->cpu_type = socdata->cpu_type;
pm_info->ddr_type = imx_mmdc_get_ddr_type();
pm_info->mmdc_io_num = socdata->mmdc_io_num;
mmdc_offset_array = socdata->mmdc_io_offset;

View File

@ -45,7 +45,7 @@
*/
#define PM_INFO_PBASE_OFFSET 0x0
#define PM_INFO_RESUME_ADDR_OFFSET 0x4
#define PM_INFO_CPU_TYPE_OFFSET 0x8
#define PM_INFO_DDR_TYPE_OFFSET 0x8
#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC
#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
@ -110,7 +110,7 @@
ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
cmp r3, #MXC_CPU_IMX6SL
cmp r3, #IMX_DDR_TYPE_LPDDR2
bne 4f
/* reset read FIFO, RST_RD_FIFO */
@ -151,7 +151,7 @@
ENTRY(imx6_suspend)
ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
/*
@ -209,8 +209,8 @@ poll_dvfs_set:
ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
add r8, r8, r0
/* i.MX6SL's last 3 IOs need special setting */
cmp r3, #MXC_CPU_IMX6SL
/* LPDDR2's last 3 IOs need special setting */
cmp r3, #IMX_DDR_TYPE_LPDDR2
subeq r7, r7, #0x3
set_mmdc_io_lpm:
ldr r9, [r8], #0x8
@ -218,7 +218,7 @@ set_mmdc_io_lpm:
subs r7, r7, #0x1
bne set_mmdc_io_lpm
cmp r3, #MXC_CPU_IMX6SL
cmp r3, #IMX_DDR_TYPE_LPDDR2
bne set_mmdc_io_lpm_done
ldr r6, =0x1000
ldr r9, [r8], #0x8
@ -324,7 +324,7 @@ resume:
str r7, [r11, #MX6Q_SRC_GPR1]
str r7, [r11, #MX6Q_SRC_GPR2]
ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
mov r5, #0x1
resume_mmdc

View File

@ -1,3 +1,26 @@
config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family" if (ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6)
select ARM_AMBA
select ARM_PATCH_PHYS_VIRT if MMU
select AUTO_ZRELADDR
select COMMON_CLK
select COMMON_CLK_VERSATILE
select GENERIC_CLOCKEVENTS
select HAVE_TCM
select ICST
select MFD_SYSCON
select MULTI_IRQ_HANDLER
select PLAT_VERSATILE
select POWER_RESET
select POWER_RESET_VERSATILE
select POWER_SUPPLY
select SOC_INTEGRATOR_CM
select SPARSE_IRQ
select USE_OF
select VERSATILE_FPGA_IRQ
help
Support for ARM's Integrator platform.
if ARCH_INTEGRATOR
menu "Integrator Options"

View File

@ -4,7 +4,7 @@
# Object file lists.
obj-y := core.o lm.o leds.o
obj-y := core.o lm.o
obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o

View File

@ -11,7 +11,6 @@ void cm_clear_irqs(void);
#define CM_CTRL_LED (1 << 0)
#define CM_CTRL_nMBDET (1 << 1)
#define CM_CTRL_REMAP (1 << 2)
#define CM_CTRL_RESET (1 << 3)
/*
* Integrator/AP,PP2 specific

View File

@ -4,5 +4,3 @@ extern struct amba_pl010_data ap_uart_data;
void integrator_init_early(void);
int integrator_init(bool is_cp);
void integrator_reserve(void);
void integrator_restart(enum reboot_mode, const char *);
void integrator_init_sysfs(struct device *parent, u32 id);

View File

@ -60,40 +60,6 @@ void cm_control(u32 mask, u32 set)
raw_spin_unlock_irqrestore(&cm_lock, flags);
}
static const char *integrator_arch_str(u32 id)
{
switch ((id >> 16) & 0xff) {
case 0x00:
return "ASB little-endian";
case 0x01:
return "AHB little-endian";
case 0x03:
return "AHB-Lite system bus, bi-endian";
case 0x04:
return "AHB";
case 0x08:
return "AHB system bus, ASB processor bus";
default:
return "Unknown";
}
}
static const char *integrator_fpga_str(u32 id)
{
switch ((id >> 12) & 0xf) {
case 0x01:
return "XC4062";
case 0x02:
return "XC4085";
case 0x03:
return "XVC600";
case 0x04:
return "EPM7256AE (Altera PLD)";
default:
return "Unknown";
}
}
void cm_clear_irqs(void)
{
/* disable core module IRQs */
@ -109,7 +75,6 @@ static const struct of_device_id cm_match[] = {
void cm_init(void)
{
struct device_node *cm = of_find_matching_node(NULL, cm_match);
u32 val;
if (!cm) {
pr_crit("no core module node found in device tree\n");
@ -121,13 +86,6 @@ void cm_init(void)
return;
}
cm_clear_irqs();
val = readl(cm_base + INTEGRATOR_HDR_ID_OFFSET);
pr_info("Detected ARM core module:\n");
pr_info(" Manufacturer: %02x\n", (val >> 24));
pr_info(" Architecture: %s\n", integrator_arch_str(val));
pr_info(" FPGA: %s\n", integrator_fpga_str(val));
pr_info(" Build: %02x\n", (val >> 4) & 0xFF);
pr_info(" Rev: %c\n", ('A' + (val & 0x03)));
}
/*
@ -139,64 +97,3 @@ void __init integrator_reserve(void)
{
memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
}
/*
* To reset, we hit the on-board reset register in the system FPGA
*/
void integrator_restart(enum reboot_mode mode, const char *cmd)
{
cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
}
static u32 integrator_id;
static ssize_t intcp_get_manf(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%02x\n", integrator_id >> 24);
}
static struct device_attribute intcp_manf_attr =
__ATTR(manufacturer, S_IRUGO, intcp_get_manf, NULL);
static ssize_t intcp_get_arch(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", integrator_arch_str(integrator_id));
}
static struct device_attribute intcp_arch_attr =
__ATTR(architecture, S_IRUGO, intcp_get_arch, NULL);
static ssize_t intcp_get_fpga(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id));
}
static struct device_attribute intcp_fpga_attr =
__ATTR(fpga, S_IRUGO, intcp_get_fpga, NULL);
static ssize_t intcp_get_build(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF);
}
static struct device_attribute intcp_build_attr =
__ATTR(build, S_IRUGO, intcp_get_build, NULL);
void integrator_init_sysfs(struct device *parent, u32 id)
{
integrator_id = id;
device_create_file(parent, &intcp_manf_attr);
device_create_file(parent, &intcp_arch_attr);
device_create_file(parent, &intcp_fpga_attr);
device_create_file(parent, &intcp_build_attr);
}

View File

@ -1,48 +0,0 @@
/*
* arch/arm/mach-integrator/include/mach/uncompress.h
*
* Copyright (C) 1999 ARM Limited
*
* 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 AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
#define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
#define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
#define AMBA_UART_LCRL (*(volatile unsigned char *)0x16000010)
#define AMBA_UART_CR (*(volatile unsigned char *)0x16000014)
#define AMBA_UART_FR (*(volatile unsigned char *)0x16000018)
/*
* This does not append a newline
*/
static void putc(int c)
{
while (AMBA_UART_FR & (1 << 5))
barrier();
AMBA_UART_DR = c;
}
static inline void flush(void)
{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
/*
* nothing to do
*/
#define arch_decomp_setup()

View File

@ -27,22 +27,15 @@
#include <linux/syscore_ops.h>
#include <linux/amba/bus.h>
#include <linux/amba/kmi.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irqchip.h>
#include <linux/mtd/physmap.h>
#include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/stat.h>
#include <linux/sys_soc.h>
#include <linux/termios.h>
#include <linux/sched_clock.h>
#include <linux/clk-provider.h>
#include <asm/hardware/arm_timer.h>
#include <asm/setup.h>
@ -89,11 +82,6 @@ static void __iomem *ebi_base;
static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
{
.virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
.pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
.length = SZ_4K,
.type = MT_DEVICE
}, {
.virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
.pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
.length = SZ_4K,
@ -257,188 +245,10 @@ struct amba_pl010_data ap_uart_data = {
.set_mctrl = integrator_uart_set_mctrl,
};
/*
* Where is the timer (VA)?
*/
#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
static unsigned long timer_reload;
static u64 notrace integrator_read_sched_clock(void)
{
return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
}
static void integrator_clocksource_init(unsigned long inrate,
void __iomem *base)
{
u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
unsigned long rate = inrate;
if (rate >= 1500000) {
rate /= 16;
ctrl |= TIMER_CTRL_DIV16;
}
writel(0xffff, base + TIMER_LOAD);
writel(ctrl, base + TIMER_CTRL);
clocksource_mmio_init(base + TIMER_VALUE, "timer2",
rate, 200, 16, clocksource_mmio_readl_down);
sched_clock_register(integrator_read_sched_clock, 16, rate);
}
static void __iomem * clkevt_base;
/*
* IRQ handler for the timer
*/
static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
/* clear the interrupt */
writel(1, clkevt_base + TIMER_INTCLR);
evt->event_handler(evt);
return IRQ_HANDLED;
}
static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
{
u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
/* Disable timer */
writel(ctrl, clkevt_base + TIMER_CTRL);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
/* Enable the timer and start the periodic tick */
writel(timer_reload, clkevt_base + TIMER_LOAD);
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
writel(ctrl, clkevt_base + TIMER_CTRL);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* Leave the timer disabled, .set_next_event will enable it */
ctrl &= ~TIMER_CTRL_PERIODIC;
writel(ctrl, clkevt_base + TIMER_CTRL);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
default:
/* Just leave in disabled state */
break;
}
}
static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
{
unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
writel(next, clkevt_base + TIMER_LOAD);
writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
return 0;
}
static struct clock_event_device integrator_clockevent = {
.name = "timer1",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = clkevt_set_mode,
.set_next_event = clkevt_set_next_event,
.rating = 300,
};
static struct irqaction integrator_timer_irq = {
.name = "timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = integrator_timer_interrupt,
.dev_id = &integrator_clockevent,
};
static void integrator_clockevent_init(unsigned long inrate,
void __iomem *base, int irq)
{
unsigned long rate = inrate;
unsigned int ctrl = 0;
clkevt_base = base;
/* Calculate and program a divisor */
if (rate > 0x100000 * HZ) {
rate /= 256;
ctrl |= TIMER_CTRL_DIV256;
} else if (rate > 0x10000 * HZ) {
rate /= 16;
ctrl |= TIMER_CTRL_DIV16;
}
timer_reload = rate / HZ;
writel(ctrl, clkevt_base + TIMER_CTRL);
setup_irq(irq, &integrator_timer_irq);
clockevents_config_and_register(&integrator_clockevent,
rate,
1,
0xffffU);
}
void __init ap_init_early(void)
{
}
static void __init ap_of_timer_init(void)
{
struct device_node *node;
const char *path;
void __iomem *base;
int err;
int irq;
struct clk *clk;
unsigned long rate;
of_clk_init(NULL);
err = of_property_read_string(of_aliases,
"arm,timer-primary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
clk = of_clk_get(node, 0);
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
writel(0, base + TIMER_CTRL);
integrator_clocksource_init(rate, base);
err = of_property_read_string(of_aliases,
"arm,timer-secondary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
irq = irq_of_parse_and_map(node, 0);
clk = of_clk_get(node, 0);
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
writel(0, base + TIMER_CTRL);
integrator_clockevent_init(rate, base, irq);
}
static void __init ap_init_irq_of(void)
{
cm_init();
@ -477,10 +287,6 @@ static void __init ap_init_of(void)
unsigned long sc_dec;
struct device_node *syscon;
struct device_node *ebi;
struct device *parent;
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
u32 ap_sc_id;
int i;
syscon = of_find_matching_node(NULL, ap_syscon_match);
@ -500,28 +306,6 @@ static void __init ap_init_of(void)
of_platform_populate(NULL, of_default_bus_match_table,
ap_auxdata_lookup, NULL);
ap_sc_id = readl(ap_syscon_base);
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return;
soc_dev_attr->soc_id = "XVC";
soc_dev_attr->machine = "Integrator/AP";
soc_dev_attr->family = "Integrator";
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
'A' + (ap_sc_id & 0x0f));
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr->revision);
kfree(soc_dev_attr);
return;
}
parent = soc_device_to_device(soc_dev);
integrator_init_sysfs(parent, ap_sc_id);
sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
for (i = 0; i < 4; i++) {
struct lm_device *lmdev;
@ -553,8 +337,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
.map_io = ap_map_io,
.init_early = ap_init_early,
.init_irq = ap_init_irq_of,
.init_time = ap_of_timer_init,
.init_machine = ap_init_of,
.restart = integrator_restart,
.dt_compat = ap_dt_board_compat,
MACHINE_END

View File

@ -27,7 +27,6 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/sys_soc.h>
#include <linux/sched_clock.h>
#include <asm/setup.h>
@ -274,10 +273,6 @@ static const struct of_device_id intcp_syscon_match[] = {
static void __init intcp_init_of(void)
{
struct device_node *cpcon;
struct device *parent;
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
u32 intcp_sc_id;
cpcon = of_find_matching_node(NULL, intcp_syscon_match);
if (!cpcon)
@ -289,28 +284,6 @@ static void __init intcp_init_of(void)
of_platform_populate(NULL, of_default_bus_match_table,
intcp_auxdata_lookup, NULL);
intcp_sc_id = readl(intcp_con_base);
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return;
soc_dev_attr->soc_id = "XCV";
soc_dev_attr->machine = "Integrator/CP";
soc_dev_attr->family = "Integrator";
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
'A' + (intcp_sc_id & 0x0f));
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr->revision);
kfree(soc_dev_attr);
return;
}
parent = soc_device_to_device(soc_dev);
integrator_init_sysfs(parent, intcp_sc_id);
}
static const char * intcp_dt_board_compat[] = {
@ -324,6 +297,5 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
.init_early = intcp_init_early,
.init_irq = intcp_init_irq_of,
.init_machine = intcp_init_of,
.restart = integrator_restart,
.dt_compat = intcp_dt_board_compat,
MACHINE_END

View File

@ -1,124 +0,0 @@
/*
* Driver for the 4 user LEDs found on the Integrator AP/CP baseboard
* Based on Versatile and RealView machine LED code
*
* License terms: GNU General Public License (GPL) version 2
* Author: Bryan Wu <bryan.wu@canonical.com>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include "hardware.h"
#include "cm.h"
#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
#define LEDREG (__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET)
struct integrator_led {
struct led_classdev cdev;
u8 mask;
};
/*
* The triggers lines up below will only be used if the
* LED triggers are compiled in.
*/
static const struct {
const char *name;
const char *trigger;
} integrator_leds[] = {
{ "integrator:green0", "heartbeat", },
{ "integrator:yellow", },
{ "integrator:red", },
{ "integrator:green1", },
{ "integrator:core_module", "cpu0", },
};
static void integrator_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
struct integrator_led *led = container_of(cdev,
struct integrator_led, cdev);
u32 reg = __raw_readl(LEDREG);
if (b != LED_OFF)
reg |= led->mask;
else
reg &= ~led->mask;
while (__raw_readl(ALPHA_REG) & 1)
cpu_relax();
__raw_writel(reg, LEDREG);
}
static enum led_brightness integrator_led_get(struct led_classdev *cdev)
{
struct integrator_led *led = container_of(cdev,
struct integrator_led, cdev);
u32 reg = __raw_readl(LEDREG);
return (reg & led->mask) ? LED_FULL : LED_OFF;
}
static void cm_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
if (b != LED_OFF)
cm_control(CM_CTRL_LED, CM_CTRL_LED);
else
cm_control(CM_CTRL_LED, 0);
}
static enum led_brightness cm_led_get(struct led_classdev *cdev)
{
u32 reg = cm_get();
return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
}
static int __init integrator_leds_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) {
struct integrator_led *led;
led = kzalloc(sizeof(*led), GFP_KERNEL);
if (!led)
break;
led->cdev.name = integrator_leds[i].name;
if (i == 4) { /* Setting for LED in core module */
led->cdev.brightness_set = cm_led_set;
led->cdev.brightness_get = cm_led_get;
} else {
led->cdev.brightness_set = integrator_led_set;
led->cdev.brightness_get = integrator_led_get;
}
led->cdev.default_trigger = integrator_leds[i].trigger;
led->mask = BIT(i);
if (led_classdev_register(NULL, &led->cdev) < 0) {
kfree(led);
break;
}
}
return 0;
}
/*
* Since we may have triggers on any subsystem, defer registration
* until after subsystem_init.
*/
fs_initcall(integrator_leds_init);
#endif

View File

@ -1,6 +1,6 @@
config ARCH_MEDIATEK
bool "Mediatek MT6589 SoC" if ARCH_MULTI_V7
bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
select ARM_GIC
select MTK_TIMER
help
Support for Mediatek Cortex-A7 Quad-Core-SoC MT6589.
Support for Mediatek MT65xx & MT81xx SoCs

View File

@ -2,6 +2,7 @@ menuconfig ARCH_MESON
bool "Amlogic Meson SoCs" if ARCH_MULTI_V7
select GENERIC_IRQ_CHIP
select ARM_GIC
select CACHE_L2X0
if ARCH_MESON
@ -10,4 +11,9 @@ config MACH_MESON6
default ARCH_MESON
select MESON6_TIMER
config MACH_MESON8
bool "Amlogic Meson8 SoCs support"
default ARCH_MESON
select MESON6_TIMER
endif

View File

@ -16,12 +16,14 @@
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
static const char * const m6_common_board_compat[] = {
static const char * const meson_common_board_compat[] = {
"amlogic,meson6",
"amlogic,meson8",
NULL,
};
DT_MACHINE_START(AML8726_MX, "Amlogic Meson6 platform")
.dt_compat = m6_common_board_compat,
DT_MACHINE_START(MESON, "Amlogic Meson platform")
.dt_compat = meson_common_board_compat,
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
MACHINE_END

View File

@ -7,7 +7,7 @@ CFLAGS_pmsu.o := -march=armv7-a
obj-$(CONFIG_MACH_MVEBU_ANY) += system-controller.o mvebu-soc-id.o
ifeq ($(CONFIG_MACH_MVEBU_V7),y)
obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o pm.o pm-board.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
endif

View File

@ -16,14 +16,8 @@
#define __MACH_ARMADA_370_XP_H
#ifdef CONFIG_SMP
#include <linux/cpumask.h>
#define ARMADA_XP_MAX_CPUS 4
void armada_xp_secondary_startup(void);
extern struct smp_operations armada_xp_smp_ops;
#endif
int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
#endif /* __MACH_ARMADA_370_XP_H */

View File

@ -16,10 +16,12 @@
#include <linux/init.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <linux/clocksource.h>
#include <linux/dma-mapping.h>
#include <linux/memblock.h>
#include <linux/mbus.h>
#include <linux/signal.h>
#include <linux/slab.h>
@ -56,6 +58,54 @@ void __iomem *mvebu_get_scu_base(void)
return scu_base;
}
/*
* When returning from suspend, the platform goes through the
* bootloader, which executes its DDR3 training code. This code has
* the unfortunate idea of using the first 10 KB of each DRAM bank to
* exercise the RAM and calculate the optimal timings. Therefore, this
* area of RAM is overwritten, and shouldn't be used by the kernel if
* suspend/resume is supported.
*/
#ifdef CONFIG_SUSPEND
#define MVEBU_DDR_TRAINING_AREA_SZ (10 * SZ_1K)
static int __init mvebu_scan_mem(unsigned long node, const char *uname,
int depth, void *data)
{
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *reg, *endp;
int l;
if (type == NULL || strcmp(type, "memory"))
return 0;
reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
if (reg == NULL)
reg = of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
endp = reg + (l / sizeof(__be32));
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
u64 base, size;
base = dt_mem_next_cell(dt_root_addr_cells, &reg);
size = dt_mem_next_cell(dt_root_size_cells, &reg);
memblock_reserve(base, MVEBU_DDR_TRAINING_AREA_SZ);
}
return 0;
}
static void __init mvebu_memblock_reserve(void)
{
of_scan_flat_dt(mvebu_scan_mem, NULL);
}
#else
static void __init mvebu_memblock_reserve(void) {}
#endif
/*
* Early versions of Armada 375 SoC have a bug where the BootROM
* leaves an external data abort pending. The kernel is hit by this
@ -124,76 +174,12 @@ static void __init i2c_quirk(void)
return;
}
#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc
static void __init thermal_quirk(void)
{
struct device_node *np;
u32 dev, rev;
int res;
/*
* The early SoC Z1 revision needs a quirk to be applied in order
* for the thermal controller to work properly. This quirk breaks
* the thermal support if applied on a SoC that doesn't need it,
* so we enforce the SoC revision to be known.
*/
res = mvebu_get_soc_id(&dev, &rev);
if (res < 0 || (res == 0 && rev > ARMADA_375_Z1_REV))
return;
for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
struct property *prop;
__be32 newval, *newprop, *oldprop;
int len;
/*
* The register offset is at a wrong location. This quirk
* creates a new reg property as a clone of the previous
* one and corrects the offset.
*/
oldprop = (__be32 *)of_get_property(np, "reg", &len);
if (!oldprop)
continue;
/* Create a duplicate of the 'reg' property */
prop = kzalloc(sizeof(*prop), GFP_KERNEL);
prop->length = len;
prop->name = kstrdup("reg", GFP_KERNEL);
prop->value = kzalloc(len, GFP_KERNEL);
memcpy(prop->value, oldprop, len);
/* Fixup the register offset of the second entry */
oldprop += 2;
newprop = (__be32 *)prop->value + 2;
newval = cpu_to_be32(be32_to_cpu(*oldprop) -
A375_Z1_THERMAL_FIXUP_OFFSET);
*newprop = newval;
of_update_property(np, prop);
/*
* The thermal controller needs some quirk too, so let's change
* the compatible string to reflect this and allow the driver
* the take the necessary action.
*/
prop = kzalloc(sizeof(*prop), GFP_KERNEL);
prop->name = kstrdup("compatible", GFP_KERNEL);
prop->length = sizeof("marvell,armada375-z1-thermal");
prop->value = kstrdup("marvell,armada375-z1-thermal",
GFP_KERNEL);
of_update_property(np, prop);
}
return;
}
static void __init mvebu_dt_init(void)
{
if (of_machine_is_compatible("marvell,armadaxp"))
i2c_quirk();
if (of_machine_is_compatible("marvell,a375-db")) {
if (of_machine_is_compatible("marvell,a375-db"))
external_abort_quirk();
thermal_quirk();
}
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
@ -206,10 +192,16 @@ static const char * const armada_370_xp_dt_compat[] = {
DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
/*
* The following field (.smp) is still needed to ensure backward
* compatibility with old Device Trees that were not specifying the
* cpus enable-method property.
*/
.smp = smp_ops(armada_xp_smp_ops),
.init_machine = mvebu_dt_init,
.init_irq = mvebu_init_irq,
.restart = mvebu_restart,
.reserve = mvebu_memblock_reserve,
.dt_compat = armada_370_xp_dt_compat,
MACHINE_END

View File

@ -1,5 +1,6 @@
/*
* Coherency fabric (Aurora) support for Armada 370 and XP platforms.
* Coherency fabric (Aurora) support for Armada 370, 375, 38x and XP
* platforms.
*
* Copyright (C) 2012 Marvell
*
@ -11,7 +12,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*
* The Armada 370 and Armada XP SOCs have a coherency fabric which is
* The Armada 370, 375, 38x and XP SOCs have a coherency fabric which is
* responsible for ensuring hardware coherency between all CPUs and between
* CPUs and I/O masters. This file initializes the coherency fabric and
* supplies basic routines for configuring and controlling hardware coherency
@ -28,12 +29,10 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mbus.h>
#include <linux/clk.h>
#include <linux/pci.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
#include <asm/mach/map.h>
#include "armada-370-xp.h"
#include "coherency.h"
#include "mvebu-soc-id.h"
@ -42,8 +41,6 @@ void __iomem *coherency_base;
static void __iomem *coherency_cpu_base;
/* Coherency fabric registers */
#define COHERENCY_FABRIC_CFG_OFFSET 0x4
#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
enum {
@ -79,157 +76,8 @@ int set_cpu_coherent(void)
return ll_enable_coherency();
}
/*
* The below code implements the I/O coherency workaround on Armada
* 375. This workaround consists in using the two channels of the
* first XOR engine to trigger a XOR transaction that serves as the
* I/O coherency barrier.
*/
static void __iomem *xor_base, *xor_high_base;
static dma_addr_t coherency_wa_buf_phys[CONFIG_NR_CPUS];
static void *coherency_wa_buf[CONFIG_NR_CPUS];
static bool coherency_wa_enabled;
#define XOR_CONFIG(chan) (0x10 + (chan * 4))
#define XOR_ACTIVATION(chan) (0x20 + (chan * 4))
#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
#define WINDOW_BASE(w) (0x250 + ((w) << 2))
#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
#define WINDOW_OVERRIDE_CTRL(chan) (0x2A0 + ((chan) << 2))
#define XOR_DEST_POINTER(chan) (0x2B0 + (chan * 4))
#define XOR_BLOCK_SIZE(chan) (0x2C0 + (chan * 4))
#define XOR_INIT_VALUE_LOW 0x2E0
#define XOR_INIT_VALUE_HIGH 0x2E4
static inline void mvebu_hwcc_armada375_sync_io_barrier_wa(void)
{
int idx = smp_processor_id();
/* Write '1' to the first word of the buffer */
writel(0x1, coherency_wa_buf[idx]);
/* Wait until the engine is idle */
while ((readl(xor_base + XOR_ACTIVATION(idx)) >> 4) & 0x3)
;
dmb();
/* Trigger channel */
writel(0x1, xor_base + XOR_ACTIVATION(idx));
/* Poll the data until it is cleared by the XOR transaction */
while (readl(coherency_wa_buf[idx]))
;
}
static void __init armada_375_coherency_init_wa(void)
{
const struct mbus_dram_target_info *dram;
struct device_node *xor_node;
struct property *xor_status;
struct clk *xor_clk;
u32 win_enable = 0;
int i;
pr_warn("enabling coherency workaround for Armada 375 Z1, one XOR engine disabled\n");
/*
* Since the workaround uses one XOR engine, we grab a
* reference to its Device Tree node first.
*/
xor_node = of_find_compatible_node(NULL, NULL, "marvell,orion-xor");
BUG_ON(!xor_node);
/*
* Then we mark it as disabled so that the real XOR driver
* will not use it.
*/
xor_status = kzalloc(sizeof(struct property), GFP_KERNEL);
BUG_ON(!xor_status);
xor_status->value = kstrdup("disabled", GFP_KERNEL);
BUG_ON(!xor_status->value);
xor_status->length = 8;
xor_status->name = kstrdup("status", GFP_KERNEL);
BUG_ON(!xor_status->name);
of_update_property(xor_node, xor_status);
/*
* And we remap the registers, get the clock, and do the
* initial configuration of the XOR engine.
*/
xor_base = of_iomap(xor_node, 0);
xor_high_base = of_iomap(xor_node, 1);
xor_clk = of_clk_get_by_name(xor_node, NULL);
BUG_ON(!xor_clk);
clk_prepare_enable(xor_clk);
dram = mv_mbus_dram_info();
for (i = 0; i < 8; i++) {
writel(0, xor_base + WINDOW_BASE(i));
writel(0, xor_base + WINDOW_SIZE(i));
if (i < 4)
writel(0, xor_base + WINDOW_REMAP_HIGH(i));
}
for (i = 0; i < dram->num_cs; i++) {
const struct mbus_dram_window *cs = dram->cs + i;
writel((cs->base & 0xffff0000) |
(cs->mbus_attr << 8) |
dram->mbus_dram_target_id, xor_base + WINDOW_BASE(i));
writel((cs->size - 1) & 0xffff0000, xor_base + WINDOW_SIZE(i));
win_enable |= (1 << i);
win_enable |= 3 << (16 + (2 * i));
}
writel(win_enable, xor_base + WINDOW_BAR_ENABLE(0));
writel(win_enable, xor_base + WINDOW_BAR_ENABLE(1));
writel(0, xor_base + WINDOW_OVERRIDE_CTRL(0));
writel(0, xor_base + WINDOW_OVERRIDE_CTRL(1));
for (i = 0; i < CONFIG_NR_CPUS; i++) {
coherency_wa_buf[i] = kzalloc(PAGE_SIZE, GFP_KERNEL);
BUG_ON(!coherency_wa_buf[i]);
/*
* We can't use the DMA mapping API, since we don't
* have a valid 'struct device' pointer
*/
coherency_wa_buf_phys[i] =
virt_to_phys(coherency_wa_buf[i]);
BUG_ON(!coherency_wa_buf_phys[i]);
/*
* Configure the XOR engine for memset operation, with
* a 128 bytes block size
*/
writel(0x444, xor_base + XOR_CONFIG(i));
writel(128, xor_base + XOR_BLOCK_SIZE(i));
writel(coherency_wa_buf_phys[i],
xor_base + XOR_DEST_POINTER(i));
}
writel(0x0, xor_base + XOR_INIT_VALUE_LOW);
writel(0x0, xor_base + XOR_INIT_VALUE_HIGH);
coherency_wa_enabled = true;
}
static inline void mvebu_hwcc_sync_io_barrier(void)
{
if (coherency_wa_enabled) {
mvebu_hwcc_armada375_sync_io_barrier_wa();
return;
}
writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
}
@ -361,25 +209,41 @@ static int coherency_type(void)
{
struct device_node *np;
const struct of_device_id *match;
int type;
/*
* The coherency fabric is needed:
* - For coherency between processors on Armada XP, so only
* when SMP is enabled.
* - For coherency between the processor and I/O devices, but
* this coherency requires many pre-requisites (write
* allocate cache policy, shareable pages, SMP bit set) that
* are only meant in SMP situations.
*
* Note that this means that on Armada 370, there is currently
* no way to use hardware I/O coherency, because even when
* CONFIG_SMP is enabled, is_smp() returns false due to the
* Armada 370 being a single-core processor. To lift this
* limitation, we would have to find a way to make the cache
* policy set to write-allocate (on all Armada SoCs), and to
* set the shareable attribute in page tables (on all Armada
* SoCs except the Armada 370). Unfortunately, such decisions
* are taken very early in the kernel boot process, at a point
* where we don't know yet on which SoC we are running.
*/
if (!is_smp())
return COHERENCY_FABRIC_TYPE_NONE;
np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
if (np) {
int type = (int) match->data;
/* Armada 370/XP coherency works in both UP and SMP */
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
return type;
/* Armada 375 coherency works only on SMP */
else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp())
return type;
/* Armada 380 coherency works only on SMP */
else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp())
return type;
}
if (!np)
return COHERENCY_FABRIC_TYPE_NONE;
type = (int) match->data;
of_node_put(np);
return type;
}
int coherency_available(void)
@ -407,22 +271,9 @@ int __init coherency_init(void)
static int __init coherency_late_init(void)
{
int type = coherency_type();
if (type == COHERENCY_FABRIC_TYPE_NONE)
return 0;
if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) {
u32 dev, rev;
if (mvebu_get_soc_id(&dev, &rev) == 0 &&
rev == ARMADA_375_Z1_REV)
armada_375_coherency_init_wa();
}
if (coherency_available())
bus_register_notifier(&platform_bus_type,
&mvebu_hwcc_nb);
return 0;
}

View File

@ -24,7 +24,10 @@
#include <asm/cp15.h>
.text
/* Returns the coherency base address in r1 (r0 is untouched) */
/*
* Returns the coherency base address in r1 (r0 is untouched), or 0 if
* the coherency fabric is not enabled.
*/
ENTRY(ll_get_coherency_base)
mrc p15, 0, r1, c1, c0, 0
tst r1, #CR_M @ Check MMU bit enabled
@ -32,8 +35,13 @@ ENTRY(ll_get_coherency_base)
/*
* MMU is disabled, use the physical address of the coherency
* base address.
* base address. However, if the coherency fabric isn't mapped
* (i.e its virtual address is zero), it means coherency is
* not enabled, so we return 0.
*/
ldr r1, =coherency_base
cmp r1, #0
beq 2f
adr r1, 3f
ldr r3, [r1]
ldr r1, [r1, r3]
@ -85,6 +93,9 @@ ENTRY(ll_add_cpu_to_smp_group)
*/
mov r0, lr
bl ll_get_coherency_base
/* Bail out if the coherency is not enabled */
cmp r1, #0
reteq r0
bl ll_get_coherency_cpumask
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
@ -107,6 +118,9 @@ ENTRY(ll_enable_coherency)
*/
mov r0, lr
bl ll_get_coherency_base
/* Bail out if the coherency is not enabled */
cmp r1, #0
reteq r0
bl ll_get_coherency_cpumask
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
@ -131,6 +145,9 @@ ENTRY(ll_disable_coherency)
*/
mov r0, lr
bl ll_get_coherency_base
/* Bail out if the coherency is not enabled */
cmp r1, #0
reteq r0
bl ll_get_coherency_cpumask
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET

View File

@ -25,4 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
void __iomem *mvebu_get_scu_base(void);
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd));
#endif

View File

@ -15,7 +15,6 @@
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/resource.h>
#include "armada-370-xp.h"
static void __iomem *cpu_reset_base;
static size_t cpu_reset_size;

View File

@ -22,5 +22,6 @@
ENTRY(mvebu_cortex_a9_secondary_startup)
ARM_BE8(setend be)
bl v7_invalidate_l1
bl armada_38x_scu_power_up
b secondary_startup
ENDPROC(mvebu_cortex_a9_secondary_startup)

View File

@ -43,21 +43,70 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
else
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup);
smp_wmb();
/*
* Doing this before deasserting the CPUs is needed to wake up CPUs
* in the offline state after using CPU hotplug.
*/
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
ret = mvebu_cpu_reset_deassert(hw_cpu);
if (ret) {
pr_err("Could not start the secondary CPU: %d\n", ret);
return ret;
}
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
return 0;
}
/*
* When a CPU is brought back online, either through CPU hotplug, or
* because of the boot of a kexec'ed kernel, the PMSU configuration
* for this CPU might be in the deep idle state, preventing this CPU
* from receiving interrupts. Here, we therefore take out the current
* CPU from this state, which was entered by armada_38x_cpu_die()
* below.
*/
static void armada_38x_secondary_init(unsigned int cpu)
{
mvebu_v7_pmsu_idle_exit();
}
#ifdef CONFIG_HOTPLUG_CPU
static void armada_38x_cpu_die(unsigned int cpu)
{
/*
* CPU hotplug is implemented by putting offline CPUs into the
* deep idle sleep state.
*/
armada_38x_do_cpu_suspend(true);
}
/*
* We need a dummy function, so that platform_can_cpu_hotplug() knows
* we support CPU hotplug. However, the function does not need to do
* anything, because CPUs going offline can enter the deep idle state
* by themselves, without any help from a still alive CPU.
*/
static int armada_38x_cpu_kill(unsigned int cpu)
{
return 1;
}
#endif
static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
.smp_boot_secondary = mvebu_cortex_a9_boot_secondary,
};
static struct smp_operations armada_38x_smp_ops __initdata = {
.smp_boot_secondary = mvebu_cortex_a9_boot_secondary,
.smp_secondary_init = armada_38x_secondary_init,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = armada_38x_cpu_die,
.cpu_kill = armada_38x_cpu_kill,
#endif
};
CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
&mvebu_cortex_a9_smp_ops);
CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp",
&mvebu_cortex_a9_smp_ops);
&armada_38x_smp_ops);

View File

@ -30,10 +30,12 @@
#include "pmsu.h"
#include "coherency.h"
#define ARMADA_XP_MAX_CPUS 4
#define AXP_BOOTROM_BASE 0xfff00000
#define AXP_BOOTROM_SIZE 0x100000
static struct clk *__init get_cpu_clk(int cpu)
static struct clk *get_cpu_clk(int cpu)
{
struct clk *cpu_clk;
struct device_node *np = of_get_cpu_node(cpu, NULL);
@ -46,29 +48,28 @@ static struct clk *__init get_cpu_clk(int cpu)
return cpu_clk;
}
static void __init set_secondary_cpus_clock(void)
static void set_secondary_cpu_clock(unsigned int cpu)
{
int thiscpu, cpu;
int thiscpu;
unsigned long rate;
struct clk *cpu_clk;
thiscpu = smp_processor_id();
thiscpu = get_cpu();
cpu_clk = get_cpu_clk(thiscpu);
if (!cpu_clk)
return;
goto out;
clk_prepare_enable(cpu_clk);
rate = clk_get_rate(cpu_clk);
/* set all the other CPU clk to the same rate than the boot CPU */
for_each_possible_cpu(cpu) {
if (cpu == thiscpu)
continue;
cpu_clk = get_cpu_clk(cpu);
if (!cpu_clk)
return;
goto out;
clk_set_rate(cpu_clk, rate);
clk_prepare_enable(cpu_clk);
}
out:
put_cpu();
}
static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
@ -78,6 +79,7 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
pr_info("Booting CPU %d\n", cpu);
hw_cpu = cpu_logical_map(cpu);
set_secondary_cpu_clock(hw_cpu);
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
/*
@ -126,7 +128,6 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
struct resource res;
int err;
set_secondary_cpus_clock();
flush_cache_all();
set_cpu_coherent();

View File

@ -0,0 +1,141 @@
/*
* Board-level suspend/resume support.
*
* Copyright (C) 2014 Marvell
*
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include "common.h"
#define ARMADA_XP_GP_PIC_NR_GPIOS 3
static void __iomem *gpio_ctrl;
static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
{
u32 reg, ackcmd;
int i;
/* Put 001 as value on the GPIOs */
reg = readl(gpio_ctrl);
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
reg &= ~BIT(pic_raw_gpios[i]);
reg |= BIT(pic_raw_gpios[0]);
writel(reg, gpio_ctrl);
/* Prepare writing 111 to the GPIOs */
ackcmd = readl(gpio_ctrl);
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
ackcmd |= BIT(pic_raw_gpios[i]);
/*
* Wait a while, the PIC needs quite a bit of time between the
* two GPIO commands.
*/
mdelay(3000);
asm volatile (
/* Align to a cache line */
".balign 32\n\t"
/* Enter self refresh */
"str %[srcmd], [%[sdram_reg]]\n\t"
/*
* Wait 100 cycles for DDR to enter self refresh, by
* doing 50 times two instructions.
*/
"mov r1, #50\n\t"
"1: subs r1, r1, #1\n\t"
"bne 1b\n\t"
/* Issue the command ACK */
"str %[ackcmd], [%[gpio_ctrl]]\n\t"
/* Trap the processor */
"b .\n\t"
: : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
[ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
}
static int mvebu_armada_xp_gp_pm_init(void)
{
struct device_node *np;
struct device_node *gpio_ctrl_np;
int ret = 0, i;
if (!of_machine_is_compatible("marvell,axp-gp"))
return -ENODEV;
np = of_find_node_by_name(NULL, "pm_pic");
if (!np)
return -ENODEV;
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) {
char *name;
struct of_phandle_args args;
pic_gpios[i] = of_get_named_gpio(np, "ctrl-gpios", i);
if (pic_gpios[i] < 0) {
ret = -ENODEV;
goto out;
}
name = kasprintf(GFP_KERNEL, "pic-pin%d", i);
if (!name) {
ret = -ENOMEM;
goto out;
}
ret = gpio_request(pic_gpios[i], name);
if (ret < 0) {
kfree(name);
goto out;
}
ret = gpio_direction_output(pic_gpios[i], 0);
if (ret < 0) {
gpio_free(pic_gpios[i]);
kfree(name);
goto out;
}
ret = of_parse_phandle_with_fixed_args(np, "ctrl-gpios", 2,
i, &args);
if (ret < 0) {
gpio_free(pic_gpios[i]);
kfree(name);
goto out;
}
gpio_ctrl_np = args.np;
pic_raw_gpios[i] = args.args[0];
}
gpio_ctrl = of_iomap(gpio_ctrl_np, 0);
if (!gpio_ctrl)
return -ENOMEM;
mvebu_pm_init(mvebu_armada_xp_gp_pm_enter);
out:
of_node_put(np);
return ret;
}
late_initcall(mvebu_armada_xp_gp_pm_init);

218
arch/arm/mach-mvebu/pm.c Normal file
View File

@ -0,0 +1,218 @@
/*
* Suspend/resume support. Currently supporting Armada XP only.
*
* Copyright (C) 2014 Marvell
*
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/cpu_pm.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mbus.h>
#include <linux/of_address.h>
#include <linux/suspend.h>
#include <asm/cacheflush.h>
#include <asm/outercache.h>
#include <asm/suspend.h>
#include "coherency.h"
#include "pmsu.h"
#define SDRAM_CONFIG_OFFS 0x0
#define SDRAM_CONFIG_SR_MODE_BIT BIT(24)
#define SDRAM_OPERATION_OFFS 0x18
#define SDRAM_OPERATION_SELF_REFRESH 0x7
#define SDRAM_DLB_EVICTION_OFFS 0x30c
#define SDRAM_DLB_EVICTION_THRESHOLD_MASK 0xff
static void (*mvebu_board_pm_enter)(void __iomem *sdram_reg, u32 srcmd);
static void __iomem *sdram_ctrl;
static int mvebu_pm_powerdown(unsigned long data)
{
u32 reg, srcmd;
flush_cache_all();
outer_flush_all();
/*
* Issue a Data Synchronization Barrier instruction to ensure
* that all state saving has been completed.
*/
dsb();
/* Flush the DLB and wait ~7 usec */
reg = readl(sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);
reg &= ~SDRAM_DLB_EVICTION_THRESHOLD_MASK;
writel(reg, sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);
udelay(7);
/* Set DRAM in battery backup mode */
reg = readl(sdram_ctrl + SDRAM_CONFIG_OFFS);
reg &= ~SDRAM_CONFIG_SR_MODE_BIT;
writel(reg, sdram_ctrl + SDRAM_CONFIG_OFFS);
/* Prepare to go to self-refresh */
srcmd = readl(sdram_ctrl + SDRAM_OPERATION_OFFS);
srcmd &= ~0x1F;
srcmd |= SDRAM_OPERATION_SELF_REFRESH;
mvebu_board_pm_enter(sdram_ctrl + SDRAM_OPERATION_OFFS, srcmd);
return 0;
}
#define BOOT_INFO_ADDR 0x3000
#define BOOT_MAGIC_WORD 0xdeadb002
#define BOOT_MAGIC_LIST_END 0xffffffff
/*
* Those registers are accessed before switching the internal register
* base, which is why we hardcode the 0xd0000000 base address, the one
* used by the SoC out of reset.
*/
#define MBUS_WINDOW_12_CTRL 0xd00200b0
#define MBUS_INTERNAL_REG_ADDRESS 0xd0020080
#define SDRAM_WIN_BASE_REG(x) (0x20180 + (0x8*x))
#define SDRAM_WIN_CTRL_REG(x) (0x20184 + (0x8*x))
static phys_addr_t mvebu_internal_reg_base(void)
{
struct device_node *np;
__be32 in_addr[2];
np = of_find_node_by_name(NULL, "internal-regs");
BUG_ON(!np);
/*
* Ask the DT what is the internal register address on this
* platform. In the mvebu-mbus DT binding, 0xf0010000
* corresponds to the internal register window.
*/
in_addr[0] = cpu_to_be32(0xf0010000);
in_addr[1] = 0x0;
return of_translate_address(np, in_addr);
}
static void mvebu_pm_store_bootinfo(void)
{
u32 *store_addr;
phys_addr_t resume_pc;
store_addr = phys_to_virt(BOOT_INFO_ADDR);
resume_pc = virt_to_phys(armada_370_xp_cpu_resume);
/*
* The bootloader expects the first two words to be a magic
* value (BOOT_MAGIC_WORD), followed by the address of the
* resume code to jump to. Then, it expects a sequence of
* (address, value) pairs, which can be used to restore the
* value of certain registers. This sequence must end with the
* BOOT_MAGIC_LIST_END magic value.
*/
writel(BOOT_MAGIC_WORD, store_addr++);
writel(resume_pc, store_addr++);
/*
* Some platforms remap their internal register base address
* to 0xf1000000. However, out of reset, window 12 starts at
* 0xf0000000 and ends at 0xf7ffffff, which would overlap with
* the internal registers. Therefore, disable window 12.
*/
writel(MBUS_WINDOW_12_CTRL, store_addr++);
writel(0x0, store_addr++);
/*
* Set the internal register base address to the value
* expected by Linux, as read from the Device Tree.
*/
writel(MBUS_INTERNAL_REG_ADDRESS, store_addr++);
writel(mvebu_internal_reg_base(), store_addr++);
/*
* Ask the mvebu-mbus driver to store the SDRAM window
* configuration, which has to be restored by the bootloader
* before re-entering the kernel on resume.
*/
store_addr += mvebu_mbus_save_cpu_target(store_addr);
writel(BOOT_MAGIC_LIST_END, store_addr);
}
static int mvebu_pm_enter(suspend_state_t state)
{
if (state != PM_SUSPEND_MEM)
return -EINVAL;
cpu_pm_enter();
mvebu_pm_store_bootinfo();
cpu_suspend(0, mvebu_pm_powerdown);
outer_resume();
mvebu_v7_pmsu_idle_exit();
set_cpu_coherent();
cpu_pm_exit();
return 0;
}
static const struct platform_suspend_ops mvebu_pm_ops = {
.enter = mvebu_pm_enter,
.valid = suspend_valid_only_mem,
};
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
{
struct device_node *np;
struct resource res;
if (!of_machine_is_compatible("marvell,armadaxp"))
return -ENODEV;
np = of_find_compatible_node(NULL, NULL,
"marvell,armada-xp-sdram-controller");
if (!np)
return -ENODEV;
if (of_address_to_resource(np, 0, &res)) {
of_node_put(np);
return -ENODEV;
}
if (!request_mem_region(res.start, resource_size(&res),
np->full_name)) {
of_node_put(np);
return -EBUSY;
}
sdram_ctrl = ioremap(res.start, resource_size(&res));
if (!sdram_ctrl) {
release_mem_region(res.start, resource_size(&res));
of_node_put(np);
return -ENOMEM;
}
of_node_put(np);
mvebu_board_pm_enter = board_pm_enter;
suspend_set_ops(&mvebu_pm_ops);
return 0;
}

View File

@ -20,6 +20,7 @@
#include <linux/clk.h>
#include <linux/cpu_pm.h>
#include <linux/cpufreq-dt.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
@ -39,7 +40,6 @@
#include <asm/suspend.h>
#include <asm/tlbflush.h>
#include "common.h"
#include "armada-370-xp.h"
#define PMSU_BASE_OFFSET 0x100
@ -312,7 +312,7 @@ static int armada_370_xp_cpu_suspend(unsigned long deepidle)
return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
}
static int armada_38x_do_cpu_suspend(unsigned long deepidle)
int armada_38x_do_cpu_suspend(unsigned long deepidle)
{
unsigned long flags = 0;
@ -572,6 +572,10 @@ int mvebu_pmsu_dfs_request(int cpu)
return 0;
}
struct cpufreq_dt_platform_data cpufreq_dt_pd = {
.independent_clocks = true,
};
static int __init armada_xp_pmsu_cpufreq_init(void)
{
struct device_node *np;
@ -644,7 +648,8 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
}
}
platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
platform_device_register_data(NULL, "cpufreq-dt", -1,
&cpufreq_dt_pd, sizeof(cpufreq_dt_pd));
return 0;
}

View File

@ -17,5 +17,8 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
phys_addr_t resume_addr_reg);
void mvebu_v7_pmsu_idle_exit(void);
void armada_370_xp_cpu_resume(void);
int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
int armada_38x_do_cpu_suspend(unsigned long deepidle);
#endif /* __MACH_370_XP_PMSU_H */

View File

@ -12,12 +12,32 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
ENTRY(armada_38x_scu_power_up)
mrc p15, 4, r1, c15, c0 @ get SCU base address
orr r1, r1, #0x8 @ SCU CPU Power Status Register
mrc 15, 0, r0, cr0, cr0, 5 @ get the CPU ID
and r0, r0, #15
add r1, r1, r0
mov r0, #0x0
strb r0, [r1] @ switch SCU power state to Normal mode
ret lr
ENDPROC(armada_38x_scu_power_up)
/*
* This is the entry point through which CPUs exiting cpuidle deep
* idle state are going.
*/
ENTRY(armada_370_xp_cpu_resume)
ARM_BE8(setend be ) @ go BE8 if entered LE
/*
* Disable the MMU that might have been enabled in BootROM if
* this code is used in the resume path of a suspend/resume
* cycle.
*/
mrc p15, 0, r1, c1, c0, 0
bic r1, #1
mcr p15, 0, r1, c1, c0, 0
bl ll_add_cpu_to_smp_group
bl ll_enable_coherency
b cpu_resume
@ -27,13 +47,7 @@ ENTRY(armada_38x_cpu_resume)
/* do we need it for Armada 38x*/
ARM_BE8(setend be ) @ go BE8 if entered LE
bl v7_invalidate_l1
mrc p15, 4, r1, c15, c0 @ get SCU base address
orr r1, r1, #0x8 @ SCU CPU Power Status Register
mrc 15, 0, r0, cr0, cr0, 5 @ get the CPU ID
and r0, r0, #15
add r1, r1, r0
mov r0, #0x0
strb r0, [r1] @ switch SCU power state to Normal mode
bl armada_38x_scu_power_up
b cpu_resume
ENDPROC(armada_38x_cpu_resume)

View File

@ -113,7 +113,7 @@ obj-y += prm_common.o cm_common.o
obj-$(CONFIG_ARCH_OMAP2) += prm2xxx_3xxx.o prm2xxx.o cm2xxx.o
obj-$(CONFIG_ARCH_OMAP3) += prm2xxx_3xxx.o prm3xxx.o cm3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o
omap-prcm-4-5-common = cminst44xx.o cm44xx.o prm44xx.o \
omap-prcm-4-5-common = cminst44xx.o prm44xx.o \
prcm_mpu44xx.o prminst44xx.o \
vc44xx_data.o vp44xx_data.o
obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common)

View File

@ -9,8 +9,7 @@
#include <linux/reboot.h>
#include "common.h"
#include "prm-regbits-33xx.h"
#include "prm33xx.h"
#include "prm.h"
/**
* am3xx_restart - trigger a software restart of the SoC
@ -24,12 +23,5 @@ void am33xx_restart(enum reboot_mode mode, const char *cmd)
{
/* TODO: Handle mode and cmd if necessary */
am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
AM33XX_RST_GLOBAL_WARM_SW_MASK,
AM33XX_PRM_DEVICE_MOD,
AM33XX_PRM_RSTCTRL_OFFSET);
/* OCP barrier */
(void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
AM33XX_PRM_RSTCTRL_OFFSET);
omap_prm_reset_system();
}

View File

@ -257,6 +257,9 @@ static const struct clk_ops dpll1_ck_ops = {
.get_parent = &omap2_init_dpll_parent,
.recalc_rate = &omap3_dpll_recalc,
.set_rate = &omap3_noncore_dpll_set_rate,
.set_parent = &omap3_noncore_dpll_set_parent,
.set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent,
.determine_rate = &omap3_noncore_dpll_determine_rate,
.round_rate = &omap2_dpll_round_rate,
};
@ -367,6 +370,9 @@ static const struct clk_ops dpll4_ck_ops = {
.get_parent = &omap2_init_dpll_parent,
.recalc_rate = &omap3_dpll_recalc,
.set_rate = &omap3_dpll4_set_rate,
.set_parent = &omap3_noncore_dpll_set_parent,
.set_rate_and_parent = &omap3_dpll4_set_rate_and_parent,
.determine_rate = &omap3_noncore_dpll_determine_rate,
.round_rate = &omap2_dpll_round_rate,
};

View File

@ -171,7 +171,8 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
_wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
idlest_val, __clk_get_name(clk->hw.clk));
} else {
cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
idlest_bit);
};
}
@ -771,4 +772,8 @@ void __init ti_clk_init_features(void)
ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
else if (cpu_is_omap34xx())
ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
/* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
if (omap_rev() == OMAP3430_REV_ES1_0)
ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
}

View File

@ -234,6 +234,7 @@ struct ti_clk_features {
};
#define TI_CLK_DPLL_HAS_FREQSEL (1 << 0)
#define TI_CLK_DPLL4_DENY_REPROGRAM (1 << 1)
extern struct ti_clk_features ti_clk_features;

View File

@ -38,6 +38,18 @@
/* needed by omap3_core_dpll_m2_set_rate() */
struct clk *sdrc_ick_p, *arm_fck_p;
/**
* omap3_dpll4_set_rate - set rate for omap3 per-dpll
* @hw: clock to change
* @rate: target rate for clock
* @parent_rate: rate of the parent clock
*
* Check if the current SoC supports the per-dpll reprogram operation
* or not, and then do the rate change if supported. Returns -EINVAL
* if not supported, 0 for success, and potential error codes from the
* clock rate change.
*/
int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@ -46,7 +58,7 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
* on 3430ES1 prevents us from changing DPLL multipliers or dividers
* on DPLL4.
*/
if (omap_rev() == OMAP3430_REV_ES1_0) {
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
return -EINVAL;
}
@ -54,6 +66,30 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
}
/**
* omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
* @hw: clock to change
* @rate: target rate for clock
* @parent_rate: rate of the parent clock
* @index: parent index, 0 - reference clock, 1 - bypass clock
*
* Check if the current SoC support the per-dpll reprogram operation
* or not, and then do the rate + parent change if supported. Returns
* -EINVAL if not supported, 0 for success, and potential error codes
* from the clock rate change.
*/
int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate, u8 index)
{
if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
return -EINVAL;
}
return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
index);
}
void __init omap3_clk_lock_dpll5(void)
{
struct clk *dpll5_clk;

View File

@ -45,17 +45,29 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
* struct cm_ll_data - fn ptrs to per-SoC CM function implementations
* @split_idlest_reg: ptr to the SoC CM-specific split_idlest_reg impl
* @wait_module_ready: ptr to the SoC CM-specific wait_module_ready impl
* @wait_module_idle: ptr to the SoC CM-specific wait_module_idle impl
* @module_enable: ptr to the SoC CM-specific module_enable impl
* @module_disable: ptr to the SoC CM-specific module_disable impl
*/
struct cm_ll_data {
int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
u8 *idlest_reg_id);
int (*wait_module_ready)(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
int (*wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
u8 idlest_shift);
int (*wait_module_idle)(u8 part, s16 prcm_mod, u16 idlest_reg,
u8 idlest_shift);
void (*module_enable)(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs);
};
extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
u8 *idlest_reg_id);
extern int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
u8 idlest_shift);
int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
u8 idlest_shift);
int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs);
extern int cm_register(struct cm_ll_data *cld);
extern int cm_unregister(struct cm_ll_data *cld);

View File

@ -25,8 +25,6 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
#define __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
#include "cm_44xx_54xx.h"
/* CM1 base address */
#define OMAP4430_CM1_BASE 0x4a004000

Some files were not shown because too many files have changed in this diff Show More