Commit 6cd94d5e authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 6c9e9247 842f7d2c
......@@ -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.
......
......@@ -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
\ No newline at end of file
+ Datasheet
http://dl.linux-sunxi.org/A80/A80_Datasheet_Revision_1.0_0404.pdf
......@@ -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"
Required root node property:
compatible = "amlogic,meson6";
Boards with the Amlogic Meson8 SoC shall have the following properties:
Required root node property:
compatible: "amlogic,meson8";
......@@ -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 {
......
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
* 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>
};
......@@ -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 {
......
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>;
};
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>;
};
}
......@@ -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.
......
......@@ -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/
......
......@@ -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"
......
This diff is collapsed.
......@@ -180,7 +180,8 @@ coredivclk: corediv-clock@18740 {
mbusc: mbus-controller@20000 {
compatible = "marvell,mbus-controller";
reg = <0x20000 0x100>, <0x20180 0x20>;
reg = <0x20000 0x100>, <0x20180 0x20>,
<0x20250 0x8>;
};
mpic: interrupt-controller@20000 {
......
......@@ -23,6 +23,7 @@
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include "armada-xp-mv78460.dtsi"
/ {
......@@ -48,6 +49,14 @@ memory {
<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@12200 {
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";
......
......@@ -35,6 +35,11 @@ bootrom {
};
internal-regs {
sdramc@1400 {
compatible = "marvell,armada-xp-sdram-controller";
reg = <0x1400 0x500>;
};
L2: l2-cache {
compatible = "marvell,aurora-system-cache";
reg = <0x08000 0x1000>;
......
......@@ -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 @@ kmi@19000000 {
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";
};
};
};
};
......@@ -64,6 +64,7 @@ twl: twl@48 {
#include "twl4030.dtsi"
#include "twl4030_omap3.dtsi"
#include <dt-bindings/input/input.h>
&mmc1 {
vmmc-supply = <&vmmc1>;
......@@ -75,6 +76,22 @@ &twl_gpio {
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>;
};
......
......@@ -895,7 +895,7 @@ rfbi: encoder@58002000 {
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";
};
......
......@@ -1018,14 +1018,6 @@ dss_48mhz_clk: dss_48mhz_clk {
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";
......
......@@ -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 @@ pmu {
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 @@ i2c@80004000 {
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 @@ i2c@80122000 {
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 @@ i2c@80128000 {
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 @@ i2c@80110000 {
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 @@ i2c@8012a000 {
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 @@ ssp@80002000 {
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 @@ ssp@80003000 {
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 @@ spi@8011a000 {
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 @@ spi@80112000 {
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 @@ spi@80111000 {
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 @@ spi@80129000 {
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 @@ sdi0_per1@80126000 {
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 @@ sdi1_per2@80118000 {
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 @@ sdi2_per3@80005000 {
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 @@ sdi3_per2@80119000 {
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 @@ sdi4_per2@80114000 {
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 @@ sdi5_per3@80008000 {
clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};
......
......@@ -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
......
......@@ -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
......
......@@ -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. */
......
/* 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
/*
* 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
/* 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
......
config MACH_ASM9260
bool "Alphascale ASM9260"
depends on ARCH_MULTI_V5
select CPU_ARM926T
help
Support for Alphascale ASM9260 based platform.
......@@ -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
......
......@@ -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
/*
* 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
/*
* 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__ */
/*
* 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)
/*
* 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);
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
......
......@@ -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
......@@ -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
......@@ -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);
......
/*
* 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 */
......@@ -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
......@@ -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)
......
......@@ -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;
}
......
......@@ -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,
......
/*
* 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;
}
return -ENOENT;
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;
}
#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))
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 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);
}
This diff is collapsed.
This diff is collapsed.
......@@ -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
......@@ -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
This diff is collapsed.
......@@ -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"
......
......@@ -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/
......@@ -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)
......
/*
* 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;
}
......@@ -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]);
......
......@@ -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);
......
......@@ -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
......@@ -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
......@@ -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 = {
......
......@@ -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();
}
......
/*
* 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
......@@ -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 */ }
......
......@@ -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
......
......@@ -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,
};
......@@ -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;
......
......@@ -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
......
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"
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......@@ -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);
}
/*
* 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()
This diff is collapsed.
......@@ -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
This diff is collapsed.
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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment