summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.txt8
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/arm/boot/dts/am335x-bone-common.dtsi3
-rw-r--r--arch/arm/boot/dts/am335x-bone.dts5
-rw-r--r--arch/arm/boot/dts/am335x-boneblack.dts5
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi3
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi10
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi10
-rw-r--r--arch/arm/boot/dts/at91sam9n12.dtsi2
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi2
-rw-r--r--arch/arm/boot/dts/dra7.dtsi1
-rw-r--r--arch/arm/boot/dts/omap2.dtsi1
-rw-r--r--arch/arm/boot/dts/omap3.dtsi4
-rw-r--r--arch/arm/boot/dts/omap4-panda-common.dtsi3
-rw-r--r--arch/arm/boot/dts/omap4-panda-es.dts5
-rw-r--r--arch/arm/boot/dts/omap4-panda.dts5
-rw-r--r--arch/arm/boot/dts/omap4.dtsi1
-rw-r--r--arch/arm/boot/dts/omap5.dtsi1
-rw-r--r--arch/arm/boot/dts/sama5d3.dtsi14
-rw-r--r--arch/arm/mach-at91/Kconfig30
-rw-r--r--arch/arm/mach-at91/Kconfig.non_dt6
-rw-r--r--arch/arm/mach-at91/Makefile6
-rw-r--r--arch/arm/mach-at91/at91_rstc.h53
-rw-r--r--arch/arm/mach-at91/at91_shdwc.h50
-rw-r--r--arch/arm/mach-at91/at91sam9260.c51
-rw-r--r--arch/arm/mach-at91/at91sam9261.c51
-rw-r--r--arch/arm/mach-at91/at91sam9263.c51
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c294
-rw-r--r--arch/arm/mach-at91/at91sam9_alt_reset.S40
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c55
-rw-r--r--arch/arm/mach-at91/at91sam9g45_reset.S45
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c51
-rw-r--r--arch/arm/mach-at91/board-afeb-9260v1.c4
-rw-r--r--arch/arm/mach-at91/board-cam60.c4
-rw-r--r--arch/arm/mach-at91/board-cpu9krea.c4
-rw-r--r--arch/arm/mach-at91/board-dt-rm9200.c13
-rw-r--r--arch/arm/mach-at91/board-dt-sam9.c23
-rw-r--r--arch/arm/mach-at91/board-dt-sama5.c22
-rw-r--r--arch/arm/mach-at91/board-flexibity.c4
-rw-r--r--arch/arm/mach-at91/board-foxg20.c2
-rw-r--r--arch/arm/mach-at91/board-gsia18s.c2
-rw-r--r--arch/arm/mach-at91/board-pcontrol-g20.c2
-rw-r--r--arch/arm/mach-at91/board-sam9-l9260.c4
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c5
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c7
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c5
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek.c4
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c5
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c5
-rw-r--r--arch/arm/mach-at91/board-snapper9260.c4
-rw-r--r--arch/arm/mach-at91/board-stamp9g20.c4
-rw-r--r--arch/arm/mach-at91/generic.h18
-rw-r--r--arch/arm/mach-at91/irq.c270
-rw-r--r--arch/arm/mach-at91/pm.c104
-rw-r--r--arch/arm/mach-at91/setup.c188
-rw-r--r--arch/arm/mach-at91/soc.h2
-rw-r--r--arch/arm/mach-omap2/Kconfig5
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c1
-rw-r--r--arch/arm/mach-omap2/board-am3517crane.c1
-rw-r--r--arch/arm/mach-omap2/board-am3517evm.c1
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c2
-rw-r--r--arch/arm/mach-omap2/board-cm-t3517.c1
-rw-r--r--arch/arm/mach-omap2/board-devkit8000.c1
-rw-r--r--arch/arm/mach-omap2/board-generic.c40
-rw-r--r--arch/arm/mach-omap2/board-ldp.c1
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c1
-rw-r--r--arch/arm/mach-omap2/board-omap3logic.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c1
-rw-r--r--arch/arm/mach-omap2/board-omap3stalker.c1
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c1
-rw-r--r--arch/arm/mach-omap2/board-overo.c1
-rw-r--r--arch/arm/mach-omap2/board-rx51.c1
-rw-r--r--arch/arm/mach-omap2/common.h17
-rw-r--r--arch/arm/mach-omap2/gpmc.c2
-rw-r--r--arch/arm/mach-omap2/io.c6
-rw-r--r--arch/arm/mach-omap2/irq.c409
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c106
-rw-r--r--arch/arm/mach-omap2/omap-secure.h1
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.c20
-rw-r--r--arch/arm/mach-omap2/omap-wakeupgen.h1
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c12
-rw-r--r--arch/arm/mach-omap2/pm.h1
-rw-r--r--arch/arm/mach-omap2/pm44xx.c57
-rw-r--r--arch/arm/mach-omap2/powerdomain.c79
-rw-r--r--arch/arm/mach-omap2/powerdomain.h4
-rw-r--r--arch/arm/mach-omap2/powerdomains54xx_data.c12
-rw-r--r--arch/arm/mach-omap2/powerdomains7xx_data.c14
-rw-r--r--arch/arm/mach-omap2/prm3xxx.c18
-rw-r--r--arch/arm/mach-omap2/prm44xx.c90
-rw-r--r--arch/arm/mach-omap2/prm_common.c2
-rw-r--r--arch/arm/mach-omap2/prminst44xx.c40
-rw-r--r--arch/arm/mach-omap2/prminst44xx.h3
-rw-r--r--arch/arm/mach-omap2/timer.c6
-rw-r--r--drivers/clk/at91/clk-system.c8
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-atmel-pit.c296
-rw-r--r--drivers/edac/Kconfig9
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/altera_edac.c410
-rw-r--r--drivers/memory/Kconfig10
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/atmel-sdramc.c98
-rw-r--r--drivers/power/reset/Kconfig33
-rw-r--r--drivers/power/reset/Makefile2
-rw-r--r--drivers/power/reset/at91-poweroff.c156
-rw-r--r--drivers/power/reset/at91-reset.c252
107 files changed, 2321 insertions, 1498 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index 16f60b41c147..6e3e3e5c611f 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -61,8 +61,8 @@ RAMC SDRAM/DDR Controller required properties:
- compatible: Should be "atmel,at91rm9200-sdramc",
"atmel,at91sam9260-sdramc",
"atmel,at91sam9g45-ddramc",
+ "atmel,sama5d3-ddramc",
- reg: Should contain registers location and length
- For at91sam9263 and at91sam9g45 you must specify 2 entries.
Examples:
@@ -71,12 +71,6 @@ Examples:
reg = <0xffffe800 0x200>;
};
- ramc0: ramc@ffffe400 {
- compatible = "atmel,at91sam9g45-ddramc";
- reg = <0xffffe400 0x200
- 0xffffe600 0x200>;
- };
-
SHDWC Shutdown Controller
required properties:
diff --git a/MAINTAINERS b/MAINTAINERS
index cf24bb56bab9..93e6a92a951d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1381,6 +1381,11 @@ M: Dinh Nguyen <dinguyen@altera.com>
S: Maintained
F: drivers/clk/socfpga/
+ARM/SOCFPGA EDAC SUPPORT
+M: Thor Thayer <tthayer@opensource.altera.com>
+S: Maintained
+F: drivers/edac/altera_edac.
+
ARM/STI ARCHITECTURE
M: Srinivas Kandagatla <srinivas.kandagatla@gmail.com>
M: Maxime Coquelin <maxime.coquelin@st.com>
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index bde1777b62be..d9d98697cca9 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -7,9 +7,6 @@
*/
/ {
- model = "TI AM335x BeagleBone";
- compatible = "ti,am335x-bone", "ti,am33xx";
-
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index 94ee427a6db1..83d40f7655e5 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -10,6 +10,11 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
+/ {
+ model = "TI AM335x BeagleBone";
+ compatible = "ti,am335x-bone", "ti,am33xx";
+};
+
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 305975d3f531..901739fcb85a 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -10,6 +10,11 @@
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
+/ {
+ model = "TI AM335x BeagleBone Black";
+ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 3a0a161342ba..1336984745e2 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -133,10 +133,9 @@
};
intc: interrupt-controller@48200000 {
- compatible = "ti,omap2-intc";
+ compatible = "ti,am33xx-intc";
interrupt-controller;
#interrupt-cells = <1>;
- ti,intc-size = <128>;
reg = <0x48200000 0x1000>;
};
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index bb23c2d33cf8..840958ba556c 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -345,10 +345,14 @@
};
};
- ramc: ramc@ffffe200 {
+ ramc0: ramc@ffffe200 {
compatible = "atmel,at91sam9260-sdramc";
- reg = <0xffffe200 0x200
- 0xffffe800 0x200>;
+ reg = <0xffffe200 0x200>;
+ };
+
+ ramc1: ramc@ffffe800 {
+ compatible = "atmel,at91sam9260-sdramc";
+ reg = <0xffffe800 0x200>;
};
pit: timer@fffffd30 {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 932a669156af..857fd3e0b8a0 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -96,8 +96,14 @@
ramc0: ramc@ffffe400 {
compatible = "atmel,at91sam9g45-ddramc";
- reg = <0xffffe400 0x200
- 0xffffe600 0x200>;
+ reg = <0xffffe400 0x200>;
+ clocks = <&ddrck>;
+ clock-names = "ddrck";
+ };
+
+ ramc1: ramc@ffffe600 {
+ compatible = "atmel,at91sam9g45-ddramc";
+ reg = <0xffffe600 0x200>;
clocks = <&ddrck>;
clock-names = "ddrck";
};
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 2bfac310dbec..68eb9aded164 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -87,6 +87,8 @@
ramc0: ramc@ffffe800 {
compatible = "atmel,at91sam9g45-ddramc";
reg = <0xffffe800 0x200>;
+ clocks = <&ddrck>;
+ clock-names = "ddrck";
};
pmc: pmc@fffffc00 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index e1a5c70b885c..765a1e39858e 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -95,6 +95,8 @@
ramc0: ramc@ffffe800 {
compatible = "atmel,at91sam9g45-ddramc";
reg = <0xffffe800 0x200>;
+ clocks = <&ddrck>;
+ clock-names = "ddrck";
};
pmc: pmc@fffffc00 {
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index d678152db4cb..e09b1afdaef2 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -89,6 +89,7 @@
prm: prm@4ae06000 {
compatible = "ti,dra7-prm";
reg = <0x4ae06000 0x3000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
prm_clocks: clocks {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi
index 8f8c07da4ac1..59d1c297bb30 100644
--- a/arch/arm/boot/dts/omap2.dtsi
+++ b/arch/arm/boot/dts/omap2.dtsi
@@ -75,7 +75,6 @@
compatible = "ti,omap2-intc";
interrupt-controller;
#interrupt-cells = <1>;
- ti,intc-size = <96>;
reg = <0x480FE000 0x1000>;
};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 575a49bf968d..4bea9a851648 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -97,6 +97,7 @@
prm: prm@48306000 {
compatible = "ti,omap3-prm";
reg = <0x48306000 0x4000>;
+ interrupts = <11>;
prm_clocks: clocks {
#address-cells = <1>;
@@ -140,10 +141,9 @@
};
intc: interrupt-controller@48200000 {
- compatible = "ti,omap2-intc";
+ compatible = "ti,omap3-intc";
interrupt-controller;
#interrupt-cells = <1>;
- ti,intc-size = <96>;
reg = <0x48200000 0x1000>;
};
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 8cfa3c8a72b0..150513506c19 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -8,9 +8,6 @@
#include "elpida_ecb240abacn.dtsi"
/ {
- model = "TI OMAP4 PandaBoard";
- compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
-
memory {
device_type = "memory";
reg = <0x80000000 0x40000000>; /* 1 GB */
diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
index 816d1c95b592..2f1dabcc6adf 100644
--- a/arch/arm/boot/dts/omap4-panda-es.dts
+++ b/arch/arm/boot/dts/omap4-panda-es.dts
@@ -10,6 +10,11 @@
#include "omap4460.dtsi"
#include "omap4-panda-common.dtsi"
+/ {
+ model = "TI OMAP4 PandaBoard-ES";
+ compatible = "ti,omap4-panda-es", "ti,omap4-panda", "ti,omap4460", "ti,omap4430", "ti,omap4";
+};
+
/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
&sound {
ti,model = "PandaBoardES";
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index 6189a8b77d7f..a0e28b2e254e 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -9,3 +9,8 @@
#include "omap443x.dtsi"
#include "omap4-panda-common.dtsi"
+
+/ {
+ model = "TI OMAP4 PandaBoard";
+ compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 69408b53200d..7375d4482bff 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -129,6 +129,7 @@
prm: prm@4a306000 {
compatible = "ti,omap4-prm";
reg = <0x4a306000 0x3000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
prm_clocks: clocks {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index fc8df1739f39..df0a09b81ba2 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -131,6 +131,7 @@
prm: prm@4ae06000 {
compatible = "ti,omap5-prm";
reg = <0x4ae06000 0x3000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
prm_clocks: clocks {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index 45013b867c8d..7702a0d120cb 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -402,8 +402,10 @@
};
ramc0: ramc@ffffea00 {
- compatible = "atmel,at91sam9g45-ddramc";
+ compatible = "atmel,sama5d3-ddramc";
reg = <0xffffea00 0x200>;
+ clocks = <&ddrck>, <&mpddr_clk>;
+ clock-names = "ddrck", "mpddr";
};
dbgu: serial@ffffee00 {
@@ -1170,6 +1172,11 @@
#clock-cells = <0>;
reg = <48>;
};
+
+ mpddr_clk: mpddr_clk {
+ #clock-cells = <0>;
+ reg = <49>;
+ };
};
};
@@ -1178,6 +1185,11 @@
reg = <0xfffffe00 0x10>;
};
+ shutdown-controller@fffffe10 {
+ compatible = "atmel,at91sam9x5-shdwc";
+ reg = <0xfffffe10 0x10>;
+ };
+
pit: timer@fffffe30 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffe30 0xf>;
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 6cc6f7aebdae..474c855fa83c 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -28,36 +28,30 @@ config OLD_CLK_AT91
bool
default AT91_PMC_UNIT && AT91_USE_OLD_CLK
-config AT91_SAM9_ALT_RESET
- bool
- default !ARCH_AT91X40
-
-config AT91_SAM9G45_RESET
- bool
- default !ARCH_AT91X40
-
-config AT91_SAM9_TIME
+config OLD_IRQ_AT91
bool
+ select MULTI_IRQ_HANDLER
+ select SPARSE_IRQ
config HAVE_AT91_SMD
bool
config SOC_AT91SAM9
bool
- select AT91_SAM9_TIME
+ select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
select CPU_ARM926T
select GENERIC_CLOCKEVENTS
- select MULTI_IRQ_HANDLER
- select SPARSE_IRQ
+ select MEMORY if USE_OF
+ select ATMEL_SDRAMC if USE_OF
config SOC_SAMA5
bool
- select AT91_SAM9_TIME
+ select ATMEL_AIC5_IRQ
select CPU_V7
select GENERIC_CLOCKEVENTS
- select MULTI_IRQ_HANDLER
- select SPARSE_IRQ
select USE_OF
+ select MEMORY
+ select ATMEL_SDRAMC
menu "Atmel AT91 System-on-Chip"
@@ -70,8 +64,7 @@ config ARCH_AT91X40
depends on !MMU
select CPU_ARM7TDMI
select ARCH_USES_GETTIMEOFFSET
- select MULTI_IRQ_HANDLER
- select SPARSE_IRQ
+ select OLD_IRQ_AT91
help
Select this if you are using one of Atmel's AT91X40 SoC.
@@ -108,11 +101,10 @@ endif
if SOC_SAM_V4_V5
config SOC_AT91RM9200
bool "AT91RM9200"
+ select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
select CPU_ARM920T
select GENERIC_CLOCKEVENTS
select HAVE_AT91_DBGU0
- select MULTI_IRQ_HANDLER
- select SPARSE_IRQ
select HAVE_AT91_USB_CLK
config SOC_AT91SAM9260
diff --git a/arch/arm/mach-at91/Kconfig.non_dt b/arch/arm/mach-at91/Kconfig.non_dt
index 44ace320d2e1..b774c3d3c632 100644
--- a/arch/arm/mach-at91/Kconfig.non_dt
+++ b/arch/arm/mach-at91/Kconfig.non_dt
@@ -14,31 +14,37 @@ config ARCH_AT91RM9200
bool "AT91RM9200"
select SOC_AT91RM9200
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9260
bool "AT91SAM9260 or AT91SAM9XE or AT91SAM9G20"
select SOC_AT91SAM9260
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9261
bool "AT91SAM9261 or AT91SAM9G10"
select SOC_AT91SAM9261
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9263
bool "AT91SAM9263"
select SOC_AT91SAM9263
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
select SOC_AT91SAM9RL
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9G45
bool "AT91SAM9G45"
select SOC_AT91SAM9G45
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
endchoice
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 78e9cec282f4..61d04f9314e7 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -2,15 +2,13 @@
# Makefile for the linux kernel.
#
-obj-y := irq.o gpio.o setup.o sysirq_mask.o
+obj-y := gpio.o setup.o sysirq_mask.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_OLD_IRQ_AT91) += irq.o
obj-$(CONFIG_OLD_CLK_AT91) += clock.o
-obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
-obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
-obj-$(CONFIG_AT91_SAM9_TIME) += at91sam926x_time.o
obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o
# CPU-specific support
diff --git a/arch/arm/mach-at91/at91_rstc.h b/arch/arm/mach-at91/at91_rstc.h
deleted file mode 100644
index a600e6992920..000000000000
--- a/arch/arm/mach-at91/at91_rstc.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_rstc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Reset Controller (RSTC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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.
- */
-
-#ifndef AT91_RSTC_H
-#define AT91_RSTC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_rstc_base;
-
-#define at91_rstc_read(field) \
- __raw_readl(at91_rstc_base + field)
-
-#define at91_rstc_write(field, value) \
- __raw_writel(value, at91_rstc_base + field)
-#else
-.extern at91_rstc_base
-#endif
-
-#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
-#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
-#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
-#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
-#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
-#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
-#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */
-#define AT91_RSTC_RSTTYP_GENERAL (0 << 8)
-#define AT91_RSTC_RSTTYP_WAKEUP (1 << 8)
-#define AT91_RSTC_RSTTYP_WATCHDOG (2 << 8)
-#define AT91_RSTC_RSTTYP_SOFTWARE (3 << 8)
-#define AT91_RSTC_RSTTYP_USER (4 << 8)
-#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */
-#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */
-
-#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
-#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
-#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
-#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
-
-#endif
diff --git a/arch/arm/mach-at91/at91_shdwc.h b/arch/arm/mach-at91/at91_shdwc.h
deleted file mode 100644
index 9e29f31ec9a6..000000000000
--- a/arch/arm/mach-at91/at91_shdwc.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_shdwc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Shutdown Controller (SHDWC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * 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.
- */
-
-#ifndef AT91_SHDWC_H
-#define AT91_SHDWC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_shdwc_base;
-
-#define at91_shdwc_read(field) \
- __raw_readl(at91_shdwc_base + field)
-
-#define at91_shdwc_write(field, value) \
- __raw_writel(value, at91_shdwc_base + field)
-#endif
-
-#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
-#define AT91_SHDW_SHDW (1 << 0) /* Shut Down command */
-#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
-
-#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
-#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */
-#define AT91_SHDW_WKMODE0_NONE 0
-#define AT91_SHDW_WKMODE0_HIGH 1
-#define AT91_SHDW_WKMODE0_LOW 2
-#define AT91_SHDW_WKMODE0_ANYLEVEL 3
-#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
-#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
-#define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */
-#define AT91_SHDW_RTCWKEN (1 << 17) /* Real Time Clock Wake-up Enable */
-
-#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
-#define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */
-#define AT91_SHDW_RTTWK (1 << 16) /* Real-time Timer Wake-up */
-#define AT91_SHDW_RTCWK (1 << 17) /* Real-time Clock Wake-up [SAM9RL] */
-
-#endif
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 3477ba94c4c5..aab1f969a7c3 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -24,7 +25,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
@@ -342,8 +342,6 @@ static void __init at91sam9260_map_io(void)
static void __init at91sam9260_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9260_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
@@ -354,7 +352,6 @@ static void __init at91sam9260_ioremap_registers(void)
static void __init at91sam9260_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT);
@@ -362,6 +359,45 @@ static void __init at91sam9260_initialize(void)
at91_gpio_init(at91sam9260_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_RSTC,
+ .end = AT91SAM9260_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_BASE_SDRAMC,
+ .end = AT91SAM9260_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9260-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_SHDWC,
+ .end = AT91SAM9260_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
+static void __init at91sam9260_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -404,6 +440,11 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
+static void __init at91sam9260_init_time(void)
+{
+ at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
+}
+
AT91_SOC_START(at91sam9260)
.map_io = at91sam9260_map_io,
.default_irq_priority = at91sam9260_default_irq_priority,
@@ -411,5 +452,7 @@ AT91_SOC_START(at91sam9260)
| (1 << AT91SAM9260_ID_IRQ2),
.ioremap_registers = at91sam9260_ioremap_registers,
.register_clocks = at91sam9260_register_clocks,
+ .register_devices = at91sam9260_register_devices,
.init = at91sam9260_initialize,
+ .init_time = at91sam9260_init_time,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index fb164a5d04a9..a8bd35963332 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -23,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
@@ -301,8 +301,6 @@ static void __init at91sam9261_map_io(void)
static void __init at91sam9261_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9261_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
@@ -313,7 +311,6 @@ static void __init at91sam9261_ioremap_registers(void)
static void __init at91sam9261_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT);
@@ -321,6 +318,45 @@ static void __init at91sam9261_initialize(void)
at91_gpio_init(at91sam9261_gpio, 3);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_RSTC,
+ .end = AT91SAM9261_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_BASE_SDRAMC,
+ .end = AT91SAM9261_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9260-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_SHDWC,
+ .end = AT91SAM9261_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
+static void __init at91sam9261_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -363,6 +399,11 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
+static void __init at91sam9261_init_time(void)
+{
+ at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
+}
+
AT91_SOC_START(at91sam9261)
.map_io = at91sam9261_map_io,
.default_irq_priority = at91sam9261_default_irq_priority,
@@ -370,5 +411,7 @@ AT91_SOC_START(at91sam9261)
| (1 << AT91SAM9261_ID_IRQ2),
.ioremap_registers = at91sam9261_ioremap_registers,
.register_clocks = at91sam9261_register_clocks,
+ .register_devices = at91sam9261_register_devices,
.init = at91sam9261_initialize,
+ .init_time = at91sam9261_init_time,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 810fa5f15a51..fbff228cc63e 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -22,7 +23,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
@@ -321,8 +321,6 @@ static void __init at91sam9263_map_io(void)
static void __init at91sam9263_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9263_BASE_SDRAMC0, 512);
at91_ioremap_ramc(1, AT91SAM9263_BASE_SDRAMC1, 512);
at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
@@ -335,7 +333,6 @@ static void __init at91sam9263_ioremap_registers(void)
static void __init at91sam9263_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0);
at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1);
@@ -344,6 +341,45 @@ static void __init at91sam9263_initialize(void)
at91_gpio_init(at91sam9263_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_RSTC,
+ .end = AT91SAM9263_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_BASE_SDRAMC0,
+ .end = AT91SAM9263_BASE_SDRAMC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9260-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SHDWC,
+ .end = AT91SAM9263_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
+static void __init at91sam9263_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -386,11 +422,18 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller (IRQ1) */
};
+static void __init at91sam9263_init_time(void)
+{
+ at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
+}
+
AT91_SOC_START(at91sam9263)
.map_io = at91sam9263_map_io,
.default_irq_priority = at91sam9263_default_irq_priority,
.extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1),
.ioremap_registers = at91sam9263_ioremap_registers,
.register_clocks = at91sam9263_register_clocks,
+ .register_devices = at91sam9263_register_devices,
.init = at91sam9263_initialize,
+ .init_time = at91sam9263_init_time,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
deleted file mode 100644
index 0a9e2fc8f796..000000000000
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
- *
- * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
- * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
- * Converted to ClockSource/ClockEvents by David Brownell.
- *
- * 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-#include <asm/mach/time.h>
-#include <mach/hardware.h>
-
-#define AT91_PIT_MR 0x00 /* Mode Register */
-#define AT91_PIT_PITIEN (1 << 25) /* Timer Interrupt Enable */
-#define AT91_PIT_PITEN (1 << 24) /* Timer Enabled */
-#define AT91_PIT_PIV (0xfffff) /* Periodic Interval Value */
-
-#define AT91_PIT_SR 0x04 /* Status Register */
-#define AT91_PIT_PITS (1 << 0) /* Timer Status */
-
-#define AT91_PIT_PIVR 0x08 /* Periodic Interval Value Register */
-#define AT91_PIT_PIIR 0x0c /* Periodic Interval Image Register */
-#define AT91_PIT_PICNT (0xfff << 20) /* Interval Counter */
-#define AT91_PIT_CPIV (0xfffff) /* Inverval Value */
-
-#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
-#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
-
-static u32 pit_cycle; /* write-once */
-static u32 pit_cnt; /* access only w/system irq blocked */
-static void __iomem *pit_base_addr __read_mostly;
-static struct clk *mck;
-
-static inline unsigned int pit_read(unsigned int reg_offset)
-{
- return __raw_readl(pit_base_addr + reg_offset);
-}
-
-static inline void pit_write(unsigned int reg_offset, unsigned long value)
-{
- __raw_writel(value, pit_base_addr + reg_offset);
-}
-
-/*
- * Clocksource: just a monotonic counter of MCK/16 cycles.
- * We don't care whether or not PIT irqs are enabled.
- */
-static cycle_t read_pit_clk(struct clocksource *cs)
-{
- unsigned long flags;
- u32 elapsed;
- u32 t;
-
- raw_local_irq_save(flags);
- elapsed = pit_cnt;
- t = pit_read(AT91_PIT_PIIR);
- raw_local_irq_restore(flags);
-
- elapsed += PIT_PICNT(t) * pit_cycle;
- elapsed += PIT_CPIV(t);
- return elapsed;
-}
-
-static struct clocksource pit_clk = {
- .name = "pit",
- .rating = 175,
- .read = read_pit_clk,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
-/*
- * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
- */
-static void
-pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
-{
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /* update clocksource counter */
- pit_cnt += pit_cycle * PIT_PICNT(pit_read(AT91_PIT_PIVR));
- pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
- | AT91_PIT_PITIEN);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- BUG();
- /* FALLTHROUGH */
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- /* disable irq, leaving the clocksource active */
- pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
- break;
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
-}
-
-static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
-{
- /* Disable timer */
- pit_write(AT91_PIT_MR, 0);
-}
-
-static void at91sam926x_pit_reset(void)
-{
- /* Disable timer and irqs */
- pit_write(AT91_PIT_MR, 0);
-
- /* Clear any pending interrupts, wait for PIT to stop counting */
- while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
- cpu_relax();
-
- /* Start PIT but don't enable IRQ */
- pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
-}
-
-static void at91sam926x_pit_resume(struct clock_event_device *cedev)
-{
- at91sam926x_pit_reset();
-}
-
-static struct clock_event_device pit_clkevt = {
- .name = "pit",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .shift = 32,
- .rating = 100,
- .set_mode = pit_clkevt_mode,
- .suspend = at91sam926x_pit_suspend,
- .resume = at91sam926x_pit_resume,
-};
-
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
-{
- /*
- * irqs should be disabled here, but as the irq is shared they are only
- * guaranteed to be off if the timer irq is registered first.
- */
- WARN_ON_ONCE(!irqs_disabled());
-
- /* The PIT interrupt may be disabled, and is shared */
- if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
- && (pit_read(AT91_PIT_SR) & AT91_PIT_PITS)) {
- unsigned nr_ticks;
-
- /* Get number of ticks performed before irq, and ack it */
- nr_ticks = PIT_PICNT(pit_read(AT91_PIT_PIVR));
- do {
- pit_cnt += pit_cycle;
- pit_clkevt.event_handler(&pit_clkevt);
- nr_ticks--;
- } while (nr_ticks);
-
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
-}
-
-static struct irqaction at91sam926x_pit_irq = {
- .name = "at91_tick",
- .flags = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = at91sam926x_pit_interrupt,
- .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
-};
-
-#ifdef CONFIG_OF
-static struct of_device_id pit_timer_ids[] = {
- { .compatible = "atmel,at91sam9260-pit" },
- { /* sentinel */ }
-};
-
-static int __init of_at91sam926x_pit_init(void)
-{
- struct device_node *np;
- int ret;
-
- np = of_find_matching_node(NULL, pit_timer_ids);
- if (!np)
- goto err;
-
- pit_base_addr = of_iomap(np, 0);
- if (!pit_base_addr)
- goto node_err;
-
- mck = of_clk_get(np, 0);
-
- /* Get the interrupts property */
- ret = irq_of_parse_and_map(np, 0);
- if (!ret) {
- pr_crit("AT91: PIT: Unable to get IRQ from DT\n");
- if (!IS_ERR(mck))
- clk_put(mck);
- goto ioremap_err;
- }
- at91sam926x_pit_irq.irq = ret;
-
- of_node_put(np);
-
- return 0;
-
-ioremap_err:
- iounmap(pit_base_addr);
-node_err:
- of_node_put(np);
-err:
- return -EINVAL;
-}
-#else
-static int __init of_at91sam926x_pit_init(void)
-{
- return -EINVAL;
-}
-#endif
-
-/*
- * Set up both clocksource and clockevent support.
- */
-void __init at91sam926x_pit_init(void)
-{
- unsigned long pit_rate;
- unsigned bits;
- int ret;
-
- mck = ERR_PTR(-ENOENT);
-
- /* For device tree enabled device: initialize here */
- of_at91sam926x_pit_init();
-
- /*
- * Use our actual MCK to figure out how many MCK/16 ticks per
- * 1/HZ period (instead of a compile-time constant LATCH).
- */
- if (IS_ERR(mck))
- mck = clk_get(NULL, "mck");
-
- if (IS_ERR(mck))
- panic("AT91: PIT: Unable to get mck clk\n");
- pit_rate = clk_get_rate(mck) / 16;
- pit_cycle = (pit_rate + HZ/2) / HZ;
- WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
-
- /* Initialize and enable the timer */
- at91sam926x_pit_reset();
-
- /*
- * Register clocksource. The high order bits of PIV are unused,
- * so this isn't a 32-bit counter unless we get clockevent irqs.
- */
- bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
- pit_clk.mask = CLOCKSOURCE_MASK(bits);
- clocksource_register_hz(&pit_clk, pit_rate);
-
- /* Set up irq handler */
- ret = setup_irq(at91sam926x_pit_irq.irq, &at91sam926x_pit_irq);
- if (ret)
- pr_crit("AT91: PIT: Unable to setup IRQ\n");
-
- /* Set up and register clockevents */
- pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
- pit_clkevt.cpumask = cpumask_of(0);
- clockevents_register_device(&pit_clkevt);
-}
-
-void __init at91sam926x_ioremap_pit(u32 addr)
-{
-#if defined(CONFIG_OF)
- struct device_node *np =
- of_find_matching_node(NULL, pit_timer_ids);
-
- if (np) {
- of_node_put(np);
- return;
- }
-#endif
- pit_base_addr = ioremap(addr, 16);
-
- if (!pit_base_addr)
- panic("Impossible to ioremap PIT\n");
-}
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
deleted file mode 100644
index f039538d3bdb..000000000000
--- a/arch/arm/mach-at91/at91sam9_alt_reset.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * reset AT91SAM9G20 as per errata
- *
- * (C) BitBox Ltd 2010
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
-
- .arm
-
- .globl at91sam9_alt_restart
-
-at91sam9_alt_restart: ldr r0, =at91_ramc_base @ preload constants
- ldr r0, [r0]
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access
- str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9d45496e4932..405427ec05f8 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/clk/at91_pmc.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -371,8 +372,6 @@ static void __init at91sam9g45_map_io(void)
static void __init at91sam9g45_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9G45_BASE_DDRSDRC1, 512);
at91_ioremap_ramc(1, AT91SAM9G45_BASE_DDRSDRC0, 512);
at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
@@ -384,7 +383,6 @@ static void __init at91sam9g45_ioremap_registers(void)
static void __init at91sam9g45_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9g45_restart;
at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
@@ -393,6 +391,50 @@ static void __init at91sam9g45_initialize(void)
at91_gpio_init(at91sam9g45_gpio, 5);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_RSTC,
+ .end = AT91SAM9G45_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC1,
+ .end = AT91SAM9G45_BASE_DDRSDRC1 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = AT91SAM9G45_BASE_DDRSDRC0,
+ .end = AT91SAM9G45_BASE_DDRSDRC0 + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9g45-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9G45_BASE_SHDWC,
+ .end = AT91SAM9G45_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
+static void __init at91sam9g45_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -435,11 +477,18 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller (IRQ0) */
};
+static void __init at91sam9g45_init_time(void)
+{
+ at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
+}
+
AT91_SOC_START(at91sam9g45)
.map_io = at91sam9g45_map_io,
.default_irq_priority = at91sam9g45_default_irq_priority,
.extern_irq = (1 << AT91SAM9G45_ID_IRQ0),
.ioremap_registers = at91sam9g45_ioremap_registers,
.register_clocks = at91sam9g45_register_clocks,
+ .register_devices = at91sam9g45_register_devices,
.init = at91sam9g45_initialize,
+ .init_time = at91sam9g45_init_time,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
deleted file mode 100644
index c40c1e2ef80f..000000000000
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * reset AT91SAM9G45 as per errata
- *
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
- *
- * unless the SDRAM is cleanly shutdown before we hit the
- * reset register it can be left driving the data bus and
- * killing the chance of a subsequent boot from NAND
- *
- * GPLv2 Only
- */
-
-#include <linux/linkage.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-#include "at91_rstc.h"
- .arm
-
-/*
- * at91_ramc_base is an array void*
- * init at NULL if only one DDR controler is present in or DT
- */
- .globl at91sam9g45_restart
-
-at91sam9g45_restart:
- ldr r5, =at91_ramc_base @ preload constants
- ldr r0, [r5]
- ldr r5, [r5, #4] @ ddr1
- cmp r5, #0
- ldr r4, =at91_rstc_base
- ldr r1, [r4]
-
- mov r2, #1
- mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
- ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
-
- .balign 32 @ align to cache line
-
- strne r2, [r5, #AT91_DDRSDRC_RTR] @ disable DDR1 access
- strne r3, [r5, #AT91_DDRSDRC_LPR] @ power down DDR1
- str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access
- str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0
- str r4, [r1, #AT91_RSTC_CR] @ reset processor
-
- b .
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 878d5015daab..f553e4ea034b 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -10,6 +10,7 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/clk/at91_pmc.h>
#include <asm/proc-fns.h>
@@ -23,7 +24,6 @@
#include <mach/hardware.h>
#include "at91_aic.h"
-#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
#include "sam9_smc.h"
@@ -311,8 +311,6 @@ static void __init at91sam9rl_map_io(void)
static void __init at91sam9rl_ioremap_registers(void)
{
- at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
- at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
at91_ioremap_ramc(0, AT91SAM9RL_BASE_SDRAMC, 512);
at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
@@ -323,7 +321,6 @@ static void __init at91sam9rl_ioremap_registers(void)
static void __init at91sam9rl_initialize(void)
{
arm_pm_idle = at91sam9_idle;
- arm_pm_restart = at91sam9_alt_restart;
at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
@@ -332,6 +329,45 @@ static void __init at91sam9rl_initialize(void)
at91_gpio_init(at91sam9rl_gpio, 4);
}
+static struct resource rstc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_RSTC,
+ .end = AT91SAM9RL_BASE_RSTC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9RL_BASE_SDRAMC,
+ .end = AT91SAM9RL_BASE_SDRAMC + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rstc_device = {
+ .name = "at91-sam9260-reset",
+ .resource = rstc_resources,
+ .num_resources = ARRAY_SIZE(rstc_resources),
+};
+
+static struct resource shdwc_resources[] = {
+ [0] = {
+ .start = AT91SAM9RL_BASE_SHDWC,
+ .end = AT91SAM9RL_BASE_SHDWC + SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device shdwc_device = {
+ .name = "at91-poweroff",
+ .resource = shdwc_resources,
+ .num_resources = ARRAY_SIZE(shdwc_resources),
+};
+
+static void __init at91sam9rl_register_devices(void)
+{
+ platform_device_register(&rstc_device);
+ platform_device_register(&shdwc_device);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -374,6 +410,11 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
+static void __init at91sam9rl_init_time(void)
+{
+ at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
+}
+
AT91_SOC_START(at91sam9rl)
.map_io = at91sam9rl_map_io,
.default_irq_priority = at91sam9rl_default_irq_priority,
@@ -382,5 +423,7 @@ AT91_SOC_START(at91sam9rl)
#if defined(CONFIG_OLD_CLK_AT91)
.register_clocks = at91sam9rl_register_clocks,
#endif
+ .register_devices = at91sam9rl_register_devices,
.init = at91sam9rl_initialize,
+ .init_time = at91sam9rl_init_time,
AT91_SOC_END
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 597c649170aa..e76e35ce81e7 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -167,6 +167,8 @@ static struct at91_cf_data afeb9260_cf_data = {
static void __init afeb9260_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -211,7 +213,7 @@ static void __init afeb9260_board_init(void)
MACHINE_START(AFEB9260, "Custom afeb9260 board")
/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = afeb9260_init_early,
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index a30502c8d379..ae827dd2d0d2 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -170,6 +170,8 @@ static void __init cam60_add_device_nand(void)
static void __init cam60_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -188,7 +190,7 @@ static void __init cam60_board_init(void)
MACHINE_START(CAM60, "KwikByte CAM60")
/* Maintainer: KwikByte */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = cam60_init_early,
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 2037f78c84e7..731c8318f4f5 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -322,6 +322,8 @@ static struct mci_platform_data __initdata cpu9krea_mci0_data = {
static void __init cpu9krea_board_init(void)
{
+ at91_register_devices();
+
/* NOR */
cpu9krea_add_device_nor();
/* Serial */
@@ -375,7 +377,7 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260")
MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
#endif
/* Maintainer: Eric Benard - EUKREA Electromatique */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = cpu9krea_init_early,
diff --git a/arch/arm/mach-at91/board-dt-rm9200.c b/arch/arm/mach-at91/board-dt-rm9200.c
index 3a185faee795..61ea21445664 100644
--- a/arch/arm/mach-at91/board-dt-rm9200.c
+++ b/arch/arm/mach-at91/board-dt-rm9200.c
@@ -24,17 +24,6 @@
#include "at91_aic.h"
#include "generic.h"
-
-static const struct of_device_id irq_of_match[] __initconst = {
- { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91rm9200_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static const char *at91rm9200_dt_board_compat[] __initdata = {
"atmel,at91rm9200",
NULL
@@ -43,8 +32,6 @@ static const char *at91rm9200_dt_board_compat[] __initdata = {
DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
.init_time = at91rm9200_timer_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic_handle_irq,
.init_early = at91rm9200_dt_initialize,
- .init_irq = at91rm9200_dt_init_irq,
.dt_compat = at91rm9200_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sam9.c b/arch/arm/mach-at91/board-dt-sam9.c
index 575b0be66ca8..d3048ccdc41f 100644
--- a/arch/arm/mach-at91/board-dt-sam9.c
+++ b/arch/arm/mach-at91/board-dt-sam9.c
@@ -25,26 +25,6 @@
#include "board.h"
#include "generic.h"
-
-static void __init sam9_dt_timer_init(void)
-{
-#if defined(CONFIG_COMMON_CLK)
- of_clk_init(NULL);
-#endif
- at91sam926x_pit_init();
-}
-
-static const struct of_device_id irq_of_match[] __initconst = {
-
- { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static const char *at91_dt_board_compat[] __initdata = {
"atmel,at91sam9",
NULL
@@ -52,10 +32,7 @@ static const char *at91_dt_board_compat[] __initdata = {
DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
/* Maintainer: Atmel */
- .init_time = sam9_dt_timer_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic_handle_irq,
.init_early = at91_dt_initialize,
- .init_irq = at91_dt_init_irq,
.dt_compat = at91_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c
index 075ec0576ada..be6aa2e2c343 100644
--- a/arch/arm/mach-at91/board-dt-sama5.c
+++ b/arch/arm/mach-at91/board-dt-sama5.c
@@ -27,25 +27,6 @@
#include "at91_aic.h"
#include "generic.h"
-static void __init sama5_dt_timer_init(void)
-{
-#if defined(CONFIG_COMMON_CLK)
- of_clk_init(NULL);
-#endif
- at91sam926x_pit_init();
-}
-
-static const struct of_device_id irq_of_match[] __initconst = {
-
- { .compatible = "atmel,sama5d3-aic", .data = at91_aic5_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static int ksz9021rn_phy_fixup(struct phy_device *phy)
{
int value;
@@ -80,11 +61,8 @@ static const char *sama5_dt_board_compat[] __initdata = {
DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
/* Maintainer: Atmel */
- .init_time = sama5_dt_timer_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic5_handle_irq,
.init_early = at91_dt_initialize,
- .init_irq = at91_dt_init_irq,
.init_machine = sama5_dt_device_init,
.dt_compat = sama5_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 68f1ab6bd08f..a6aa4a2432f2 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -138,6 +138,8 @@ static struct gpio_led flexibity_leds[] = {
static void __init flexibity_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -160,7 +162,7 @@ static void __init flexibity_board_init(void)
MACHINE_START(FLEXIBITY, "Flexibity Connect")
/* Maintainer: Maxim Osipov */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = flexibity_init_early,
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 8b22c60bb238..ec290b6ed9d8 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -263,7 +263,7 @@ static void __init foxg20_board_init(void)
MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
/* Maintainer: Sergio Tanzilli */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = foxg20_init_early,
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index b729dd1271bf..bf5cc55c7db6 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -576,7 +576,7 @@ static void __init gsia18s_board_init(void)
}
MACHINE_START(GSIA18S, "GS_IA18_S")
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = gsia18s_init_early,
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index b48d95ec5152..9c26b94ce448 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -219,7 +219,7 @@ static void __init pcontrol_g20_board_init(void)
MACHINE_START(PCONTROL_G20, "PControl G20")
/* Maintainer: pgsellmann@portner-elektronik.at */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = pcontrol_g20_init_early,
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index d24dda67e2d3..c2166e3a236c 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -187,6 +187,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -219,7 +221,7 @@ static void __init ek_board_init(void)
MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
/* Maintainer: Olimex */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 65dea12d685e..bf8a946b4cd0 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -45,7 +45,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
@@ -307,6 +306,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -344,7 +345,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 4637432de08f..e85ada820bfb 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -49,7 +49,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
@@ -561,6 +560,8 @@ static struct gpio_led ek_leds[] = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -603,7 +604,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
@@ -613,7 +614,7 @@ MACHINE_END
MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index fc446097f410..d76680f2a209 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -50,7 +50,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
@@ -439,6 +438,8 @@ static struct platform_device *devices[] __initdata = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -483,7 +484,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index e1be6e25b380..49f075213451 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -410,7 +410,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
@@ -420,7 +420,7 @@ MACHINE_END
MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index b227732b0c83..a517c7f7af92 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -48,7 +48,6 @@
#include <mach/system_rev.h>
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
@@ -471,6 +470,8 @@ static struct platform_device *devices[] __initdata = {
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DGBU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -517,7 +518,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index b64648b4a1fc..8bca329b0293 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -35,7 +35,6 @@
#include "at91_aic.h"
-#include "at91_shdwc.h"
#include "board.h"
#include "sam9_smc.h"
#include "generic.h"
@@ -292,6 +291,8 @@ static void __init ek_add_device_buttons(void) {}
static void __init ek_board_init(void)
{
+ at91_register_devices();
+
/* Serial */
/* DBGU on ttyS0. (Rx & Tx only) */
at91_register_uart(0, 0, 0);
@@ -323,7 +324,7 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
/* Maintainer: Atmel */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = ek_init_early,
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 1b870e6def0c..b4aff840a1a0 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -154,6 +154,8 @@ static void __init snapper9260_add_device_nand(void)
static void __init snapper9260_board_init(void)
{
+ at91_register_devices();
+
at91_add_device_i2c(snapper9260_i2c_devices,
ARRAY_SIZE(snapper9260_i2c_devices));
@@ -178,7 +180,7 @@ static void __init snapper9260_board_init(void)
}
MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = snapper9260_init_early,
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 3b575036ff96..e825641a1dee 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -275,7 +275,7 @@ static void __init stamp9g20evb_board_init(void)
MACHINE_START(PORTUXG20, "taskit PortuxG20")
/* Maintainer: taskit GmbH */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = stamp9g20_init_early,
@@ -285,7 +285,7 @@ MACHINE_END
MACHINE_START(STAMP9G20, "taskit Stamp9G20")
/* Maintainer: taskit GmbH */
- .init_time = at91sam926x_pit_init,
+ .init_time = at91_init_time,
.map_io = at91_map_io,
.handle_irq = at91_aic_handle_irq,
.init_early = stamp9g20_init_early,
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 631fa3b8c16d..189d7c7e7f60 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -8,6 +8,9 @@
* published by the Free Software Foundation.
*/
+#ifndef _AT91_GENERIC_H
+#define _AT91_GENERIC_H
+
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/reboot.h>
@@ -37,12 +40,15 @@ extern int __init at91_aic5_of_init(struct device_node *node,
extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
+ /* Devices */
+extern void __init at91_register_devices(void);
/* Timer */
+extern void __init at91_init_time(void);
extern void at91rm9200_ioremap_st(u32 addr);
extern void at91rm9200_timer_init(void);
extern void at91sam926x_ioremap_pit(u32 addr);
-extern void at91sam926x_pit_init(void);
+extern void at91sam926x_pit_init(int irq);
extern void at91x40_timer_init(void);
/* Clocks */
@@ -62,14 +68,6 @@ extern void at91_irq_resume(void);
/* idle */
extern void at91sam9_idle(void);
-/* reset */
-extern void at91_ioremap_rstc(u32 base_addr);
-extern void at91sam9_alt_restart(enum reboot_mode, const char *);
-extern void at91sam9g45_restart(enum reboot_mode, const char *);
-
-/* shutdown */
-extern void at91_ioremap_shdwc(u32 base_addr);
-
/* Matrix */
extern void at91_ioremap_matrix(u32 base_addr);
@@ -90,3 +88,5 @@ extern int __init at91_gpio_of_irq_setup(struct device_node *node,
struct device_node *parent);
extern u32 at91_get_extern_irq(void);
+
+#endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index 3d192c5aee66..cdb3ec9efd2b 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -48,11 +48,6 @@ void __iomem *at91_aic_base;
static struct irq_domain *at91_aic_domain;
static struct device_node *at91_aic_np;
static unsigned int n_irqs = NR_AIC_IRQS;
-static unsigned long at91_aic_caps = 0;
-
-/* AIC5 introduces a Source Select Register */
-#define AT91_AIC_CAP_AIC5 (1 << 0)
-#define has_aic5() (at91_aic_caps & AT91_AIC_CAP_AIC5)
#ifdef CONFIG_PM
@@ -92,50 +87,14 @@ static int at91_aic_set_wake(struct irq_data *d, unsigned value)
void at91_irq_suspend(void)
{
- int bit = -1;
-
- if (has_aic5()) {
- /* disable enabled irqs */
- while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- }
- /* enable wakeup irqs */
- bit = -1;
- while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- }
- } else {
- at91_aic_write(AT91_AIC_IDCR, *backups);
- at91_aic_write(AT91_AIC_IECR, *wakeups);
- }
+ at91_aic_write(AT91_AIC_IDCR, *backups);
+ at91_aic_write(AT91_AIC_IECR, *wakeups);
}
void at91_irq_resume(void)
{
- int bit = -1;
-
- if (has_aic5()) {
- /* disable wakeup irqs */
- while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- }
- /* enable irqs disabled for suspend */
- bit = -1;
- while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- }
- } else {
- at91_aic_write(AT91_AIC_IDCR, *wakeups);
- at91_aic_write(AT91_AIC_IECR, *backups);
- }
+ at91_aic_write(AT91_AIC_IDCR, *wakeups);
+ at91_aic_write(AT91_AIC_IECR, *backups);
}
#else
@@ -169,21 +128,6 @@ at91_aic_handle_irq(struct pt_regs *regs)
handle_IRQ(irqnr, regs);
}
-asmlinkage void __exception_irq_entry
-at91_aic5_handle_irq(struct pt_regs *regs)
-{
- u32 irqnr;
- u32 irqstat;
-
- irqnr = at91_aic_read(AT91_AIC5_IVR);
- irqstat = at91_aic_read(AT91_AIC5_ISR);
-
- if (!irqstat)
- at91_aic_write(AT91_AIC5_EOICR, 0);
- else
- handle_IRQ(irqnr, regs);
-}
-
static void at91_aic_mask_irq(struct irq_data *d)
{
/* Disable interrupt on AIC */
@@ -192,15 +136,6 @@ static void at91_aic_mask_irq(struct irq_data *d)
clear_backup(d->hwirq);
}
-static void __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
-{
- /* Disable interrupt on AIC5 */
- at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- /* Update ISR cache */
- clear_backup(d->hwirq);
-}
-
static void at91_aic_unmask_irq(struct irq_data *d)
{
/* Enable interrupt on AIC */
@@ -209,15 +144,6 @@ static void at91_aic_unmask_irq(struct irq_data *d)
set_backup(d->hwirq);
}
-static void __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
-{
- /* Enable interrupt on AIC5 */
- at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- /* Update ISR cache */
- set_backup(d->hwirq);
-}
-
static void at91_aic_eoi(struct irq_data *d)
{
/*
@@ -227,11 +153,6 @@ static void at91_aic_eoi(struct irq_data *d)
at91_aic_write(AT91_AIC_EOICR, 0);
}
-static void __maybe_unused at91_aic5_eoi(struct irq_data *d)
-{
- at91_aic_write(AT91_AIC5_EOICR, 0);
-}
-
static unsigned long *at91_extern_irq;
u32 at91_get_extern_irq(void)
@@ -282,16 +203,8 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
if (srctype < 0)
return srctype;
- if (has_aic5()) {
- at91_aic_write(AT91_AIC5_SSR,
- d->hwirq & AT91_AIC5_INTSEL_MSK);
- smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
- at91_aic_write(AT91_AIC5_SMR, smr | srctype);
- } else {
- smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
- & ~AT91_AIC_SRCTYPE;
- at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
- }
+ smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
+ at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
return 0;
}
@@ -331,177 +244,6 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
}
-static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
-{
- int i;
-
- /*
- * Perform 8 End Of Interrupt Command to make sure AIC
- * will not Lock out nIRQ
- */
- for (i = 0; i < 8; i++)
- at91_aic_write(AT91_AIC5_EOICR, 0);
-
- /*
- * Spurious Interrupt ID in Spurious Vector Register.
- * When there is no current interrupt, the IRQ Vector Register
- * reads the value stored in AIC_SPU
- */
- at91_aic_write(AT91_AIC5_SPU, spu_vector);
-
- /* No debugging in AIC: Debug (Protect) Control Register */
- at91_aic_write(AT91_AIC5_DCR, 0);
-
- /* Disable and clear all interrupts initially */
- for (i = 0; i < n_irqs; i++) {
- at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- at91_aic_write(AT91_AIC5_ICCR, 1);
- }
-}
-
-#if defined(CONFIG_OF)
-static unsigned int *at91_aic_irq_priorities;
-
-static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- /* Put virq number in Source Vector Register */
- at91_aic_write(AT91_AIC_SVR(hw), virq);
-
- /* Active Low interrupt, with priority */
- at91_aic_write(AT91_AIC_SMR(hw),
- AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-
- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-}
-
-static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
-
- /* Put virq number in Source Vector Register */
- at91_aic_write(AT91_AIC5_SVR, virq);
-
- /* Active Low interrupt, with priority */
- at91_aic_write(AT91_AIC5_SMR,
- AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-
- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-}
-
-static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq, unsigned int *out_type)
-{
- if (WARN_ON(intsize < 3))
- return -EINVAL;
- if (WARN_ON(intspec[0] >= n_irqs))
- return -EINVAL;
- if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
- || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
- return -EINVAL;
-
- *out_hwirq = intspec[0];
- *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
- at91_aic_irq_priorities[*out_hwirq] = intspec[2];
-
- return 0;
-}
-
-static struct irq_domain_ops at91_aic_irq_ops = {
- .map = at91_aic_irq_map,
- .xlate = at91_aic_irq_domain_xlate,
-};
-
-int __init at91_aic_of_common_init(struct device_node *node,
- struct device_node *parent)
-{
- struct property *prop;
- const __be32 *p;
- u32 val;
-
- at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
- * sizeof(*at91_extern_irq), GFP_KERNEL);
- if (!at91_extern_irq)
- return -ENOMEM;
-
- if (at91_aic_pm_init()) {
- kfree(at91_extern_irq);
- return -ENOMEM;
- }
-
- at91_aic_irq_priorities = kzalloc(n_irqs
- * sizeof(*at91_aic_irq_priorities),
- GFP_KERNEL);
- if (!at91_aic_irq_priorities)
- return -ENOMEM;
-
- at91_aic_base = of_iomap(node, 0);
- at91_aic_np = node;
-
- at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
- &at91_aic_irq_ops, NULL);
- if (!at91_aic_domain)
- panic("Unable to add AIC irq domain (DT)\n");
-
- of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
- if (val >= n_irqs)
- pr_warn("AIC: external irq %d >= %d skip it\n",
- val, n_irqs);
- else
- set_bit(val, at91_extern_irq);
- }
-
- irq_set_default_host(at91_aic_domain);
-
- return 0;
-}
-
-int __init at91_aic_of_init(struct device_node *node,
- struct device_node *parent)
-{
- int err;
-
- err = at91_aic_of_common_init(node, parent);
- if (err)
- return err;
-
- at91_aic_hw_init(n_irqs);
-
- return 0;
-}
-
-int __init at91_aic5_of_init(struct device_node *node,
- struct device_node *parent)
-{
- int err;
-
- at91_aic_caps |= AT91_AIC_CAP_AIC5;
- n_irqs = NR_AIC5_IRQS;
- at91_aic_chip.irq_ack = at91_aic5_mask_irq;
- at91_aic_chip.irq_mask = at91_aic5_mask_irq;
- at91_aic_chip.irq_unmask = at91_aic5_unmask_irq;
- at91_aic_chip.irq_eoi = at91_aic5_eoi;
- at91_aic_irq_ops.map = at91_aic5_irq_map;
-
- err = at91_aic_of_common_init(node, parent);
- if (err)
- return err;
-
- at91_aic5_hw_init(n_irqs);
-
- return 0;
-}
-#endif
-
/*
* Initialize the AIC interrupt controller.
*/
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index e95554532987..4073ab7f38f3 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -34,79 +34,8 @@
#include "pm.h"
#include "gpio.h"
-/*
- * Show the reason for the previous system reset.
- */
-
-#include "at91_rstc.h"
-#include "at91_shdwc.h"
-
static void (*at91_pm_standby)(void);
-static void __init show_reset_status(void)
-{
- static char reset[] __initdata = "reset";
-
- static char general[] __initdata = "general";
- static char wakeup[] __initdata = "wakeup";
- static char watchdog[] __initdata = "watchdog";
- static char software[] __initdata = "software";
- static char user[] __initdata = "user";
- static char unknown[] __initdata = "unknown";
-
- static char signal[] __initdata = "signal";
- static char rtc[] __initdata = "rtc";
- static char rtt[] __initdata = "rtt";
- static char restore[] __initdata = "power-restored";
-
- char *reason, *r2 = reset;
- u32 reset_type, wake_type;
-
- if (!at91_shdwc_base || !at91_rstc_base)
- return;
-
- reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
- wake_type = at91_shdwc_read(AT91_SHDW_SR);
-
- switch (reset_type) {
- case AT91_RSTC_RSTTYP_GENERAL:
- reason = general;
- break;
- case AT91_RSTC_RSTTYP_WAKEUP:
- /* board-specific code enabled the wakeup sources */
- reason = wakeup;
-
- /* "wakeup signal" */
- if (wake_type & AT91_SHDW_WAKEUP0)
- r2 = signal;
- else {
- r2 = reason;
- if (wake_type & AT91_SHDW_RTTWK) /* rtt wakeup */
- reason = rtt;
- else if (wake_type & AT91_SHDW_RTCWK) /* rtc wakeup */
- reason = rtc;
- else if (wake_type == 0) /* power-restored wakeup */
- reason = restore;
- else /* unknown wakeup */
- reason = unknown;
- }
- break;
- case AT91_RSTC_RSTTYP_WATCHDOG:
- reason = watchdog;
- break;
- case AT91_RSTC_RSTTYP_SOFTWARE:
- reason = software;
- break;
- case AT91_RSTC_RSTTYP_USER:
- reason = user;
- break;
- default:
- reason = unknown;
- break;
- }
- pr_info("AT91: Starting after %s %s\n", reason, r2);
-}
-
static int at91_pm_valid_state(suspend_state_t state)
{
switch (state) {
@@ -206,16 +135,19 @@ static int at91_pm_enter(suspend_state_t state)
at91_pinctrl_gpio_suspend();
else
at91_gpio_suspend();
- at91_irq_suspend();
- pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
- /* remember all the always-wake irqs */
- (at91_pmc_read(AT91_PMC_PCSR)
- | (1 << AT91_ID_FIQ)
- | (1 << AT91_ID_SYS)
- | (at91_get_extern_irq()))
- & at91_aic_read(AT91_AIC_IMR),
- state);
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base) {
+ at91_irq_suspend();
+
+ pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+ /* remember all the always-wake irqs */
+ (at91_pmc_read(AT91_PMC_PCSR)
+ | (1 << AT91_ID_FIQ)
+ | (1 << AT91_ID_SYS)
+ | (at91_get_extern_irq()))
+ & at91_aic_read(AT91_AIC_IMR),
+ state);
+ }
switch (state) {
/*
@@ -280,12 +212,17 @@ static int at91_pm_enter(suspend_state_t state)
goto error;
}
- pr_debug("AT91: PM - wakeup %08x\n",
- at91_aic_read(AT91_AIC_IPR) & at91_aic_read(AT91_AIC_IMR));
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
+ pr_debug("AT91: PM - wakeup %08x\n",
+ at91_aic_read(AT91_AIC_IPR) &
+ at91_aic_read(AT91_AIC_IMR));
error:
target_state = PM_SUSPEND_ON;
- at91_irq_resume();
+
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
+ at91_irq_resume();
+
if (of_have_populated_dt())
at91_pinctrl_gpio_resume();
else
@@ -338,7 +275,6 @@ static int __init at91_pm_init(void)
suspend_set_ops(&at91_pm_ops);
- show_reset_status();
return 0;
}
arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index f7a07a58ebb6..51c22a2fcea4 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -5,6 +5,8 @@
* Under GPLv2
*/
+#define pr_fmt(fmt) "AT91: " fmt
+
#include <linux/module.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -20,7 +22,6 @@
#include <mach/cpu.h>
#include <mach/at91_dbgu.h>
-#include "at91_shdwc.h"
#include "soc.h"
#include "generic.h"
#include "pm.h"
@@ -37,7 +38,7 @@ void __init at91rm9200_set_type(int type)
else
at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
- pr_info("AT91: filled in soc subtype: %s\n",
+ pr_info("filled in soc subtype: %s\n",
at91_get_soc_subtype(&at91_soc_initdata));
}
@@ -49,7 +50,8 @@ void __init at91_init_irq_default(void)
void __init at91_init_interrupts(unsigned int *priority)
{
/* Initialize the AIC interrupt controller */
- at91_aic_init(priority, at91_boot_soc.extern_irq);
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91))
+ at91_aic_init(priority, at91_boot_soc.extern_irq);
/* Enable GPIO interrupts */
at91_gpio_irq_setup();
@@ -66,7 +68,7 @@ void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
}
at91_ramc_base[id] = ioremap(addr, size);
if (!at91_ramc_base[id])
- panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr);
+ panic(pr_fmt("Impossible to ioremap ramc.%d 0x%x\n"), id, addr);
}
static struct map_desc sram_desc[2] __initdata;
@@ -83,7 +85,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
desc->length = length;
desc->type = MT_MEMORY_RWX_NONCACHED;
- pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
+ pr_info("sram at 0x%lx of 0x%x mapped at 0x%lx\n",
base, length, desc->virtual);
iotable_init(desc, 1);
@@ -302,45 +304,21 @@ void __init at91_map_io(void)
soc_detect(AT91_BASE_DBGU1);
if (!at91_soc_is_detected())
- panic("AT91: Impossible to detect the SOC type");
+ panic(pr_fmt("Impossible to detect the SOC type"));
- pr_info("AT91: Detected soc type: %s\n",
+ pr_info("Detected soc type: %s\n",
at91_get_soc_type(&at91_soc_initdata));
if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE)
- pr_info("AT91: Detected soc subtype: %s\n",
+ pr_info("Detected soc subtype: %s\n",
at91_get_soc_subtype(&at91_soc_initdata));
if (!at91_soc_is_enabled())
- panic("AT91: Soc not enabled");
+ panic(pr_fmt("Soc not enabled"));
if (at91_boot_soc.map_io)
at91_boot_soc.map_io();
}
-void __iomem *at91_shdwc_base = NULL;
-
-static void at91sam9_poweroff(void)
-{
- at91_shdwc_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
-}
-
-void __init at91_ioremap_shdwc(u32 base_addr)
-{
- at91_shdwc_base = ioremap(base_addr, 16);
- if (!at91_shdwc_base)
- panic("Impossible to ioremap at91_shdwc_base\n");
- pm_power_off = at91sam9_poweroff;
-}
-
-void __iomem *at91_rstc_base;
-
-void __init at91_ioremap_rstc(u32 base_addr)
-{
- at91_rstc_base = ioremap(base_addr, 16);
- if (!at91_rstc_base)
- panic("Impossible to ioremap at91_rstc_base\n");
-}
-
void __iomem *at91_matrix_base;
EXPORT_SYMBOL_GPL(at91_matrix_base);
@@ -348,42 +326,15 @@ void __init at91_ioremap_matrix(u32 base_addr)
{
at91_matrix_base = ioremap(base_addr, 512);
if (!at91_matrix_base)
- panic("Impossible to ioremap at91_matrix_base\n");
+ panic(pr_fmt("Impossible to ioremap at91_matrix_base\n"));
}
#if defined(CONFIG_OF) && !defined(CONFIG_ARCH_AT91X40)
-static struct of_device_id rstc_ids[] = {
- { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart },
- { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
- { /*sentinel*/ }
-};
-
-static void at91_dt_rstc(void)
-{
- struct device_node *np;
- const struct of_device_id *of_id;
-
- np = of_find_matching_node(NULL, rstc_ids);
- if (!np)
- panic("unable to find compatible rstc node in dtb\n");
-
- at91_rstc_base = of_iomap(np, 0);
- if (!at91_rstc_base)
- panic("unable to map rstc cpu registers\n");
-
- of_id = of_match_node(rstc_ids, np);
- if (!of_id)
- panic("AT91: rtsc no restart function available\n");
-
- arm_pm_restart = of_id->data;
-
- of_node_put(np);
-}
-
static struct of_device_id ramc_ids[] = {
{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
+ { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
{ /*sentinel*/ }
};
@@ -391,100 +342,29 @@ static void at91_dt_ramc(void)
{
struct device_node *np;
const struct of_device_id *of_id;
+ int idx = 0;
+ const void *standby = NULL;
- np = of_find_matching_node(NULL, ramc_ids);
- if (!np)
- panic("unable to find compatible ram controller node in dtb\n");
-
- at91_ramc_base[0] = of_iomap(np, 0);
- if (!at91_ramc_base[0])
- panic("unable to map ramc[0] cpu registers\n");
- /* the controller may have 2 banks */
- at91_ramc_base[1] = of_iomap(np, 1);
-
- of_id = of_match_node(ramc_ids, np);
- if (!of_id)
- pr_warn("AT91: ramc no standby function available\n");
- else
- at91_pm_set_standby(of_id->data);
-
- of_node_put(np);
-}
-
-static struct of_device_id shdwc_ids[] = {
- { .compatible = "atmel,at91sam9260-shdwc", },
- { .compatible = "atmel,at91sam9rl-shdwc", },
- { .compatible = "atmel,at91sam9x5-shdwc", },
- { /*sentinel*/ }
-};
-
-static const char *shdwc_wakeup_modes[] = {
- [AT91_SHDW_WKMODE0_NONE] = "none",
- [AT91_SHDW_WKMODE0_HIGH] = "high",
- [AT91_SHDW_WKMODE0_LOW] = "low",
- [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
-};
-
-const int at91_dtget_shdwc_wakeup_mode(struct device_node *np)
-{
- const char *pm;
- int err, i;
+ for_each_matching_node_and_match(np, ramc_ids, &of_id) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx])
+ panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
- err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
- if (err < 0)
- return AT91_SHDW_WKMODE0_ANYLEVEL;
+ if (!standby)
+ standby = of_id->data;
- for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
- if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
- return i;
-
- return -ENODEV;
-}
-
-static void at91_dt_shdwc(void)
-{
- struct device_node *np;
- int wakeup_mode;
- u32 reg;
- u32 mode = 0;
-
- np = of_find_matching_node(NULL, shdwc_ids);
- if (!np) {
- pr_debug("AT91: unable to find compatible shutdown (shdwc) controller node in dtb\n");
- return;
+ idx++;
}
- at91_shdwc_base = of_iomap(np, 0);
- if (!at91_shdwc_base)
- panic("AT91: unable to map shdwc cpu registers\n");
+ if (!idx)
+ panic(pr_fmt("unable to find compatible ram controller node in dtb\n"));
- wakeup_mode = at91_dtget_shdwc_wakeup_mode(np);
- if (wakeup_mode < 0) {
- pr_warn("AT91: shdwc unknown wakeup mode\n");
- goto end;
- }
-
- if (!of_property_read_u32(np, "atmel,wakeup-counter", &reg)) {
- if (reg > AT91_SHDW_CPTWK0_MAX) {
- pr_warn("AT91: shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
- reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
- reg = AT91_SHDW_CPTWK0_MAX;
- }
- mode |= AT91_SHDW_CPTWK0_(reg);
+ if (!standby) {
+ pr_warn("ramc no standby function available\n");
+ return;
}
- if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
- mode |= AT91_SHDW_RTCWKEN;
-
- if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
- mode |= AT91_SHDW_RTTWKEN;
-
- at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode);
-
-end:
- pm_power_off = at91sam9_poweroff;
-
- of_node_put(np);
+ at91_pm_set_standby(standby);
}
void __init at91rm9200_dt_initialize(void)
@@ -503,9 +383,7 @@ void __init at91rm9200_dt_initialize(void)
void __init at91_dt_initialize(void)
{
- at91_dt_rstc();
at91_dt_ramc();
- at91_dt_shdwc();
/* Init clock subsystem */
at91_dt_clock_init();
@@ -533,3 +411,13 @@ void __init at91_initialize(unsigned long main_clock)
pinctrl_provide_dummies();
}
+
+void __init at91_register_devices(void)
+{
+ at91_boot_soc.register_devices();
+}
+
+void __init at91_init_time(void)
+{
+ at91_boot_soc.init_time();
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index a1e1482c6da8..2886b83dd0df 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -11,7 +11,9 @@ struct at91_init_soc {
void (*map_io)(void);
void (*ioremap_registers)(void);
void (*register_clocks)(void);
+ void (*register_devices)(void);
void (*init)(void);
+ void (*init_time)(void);
};
extern struct at91_init_soc at91_boot_soc;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index e7189dcc9309..11ccf0b4e5c2 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -25,7 +25,6 @@ config ARCH_OMAP4
bool "TI OMAP4"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
select ARM_CPU_SUSPEND if PM
select ARM_ERRATA_720789
@@ -44,7 +43,6 @@ config SOC_OMAP5
bool "TI OMAP5"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARM_CPU_SUSPEND if PM
select ARM_GIC
select HAVE_ARM_SCU if SMP
@@ -56,14 +54,12 @@ config SOC_AM33XX
bool "TI AM33XX"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARM_CPU_SUSPEND if PM
config SOC_AM43XX
bool "TI AM43x"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARM_GIC
select MACH_OMAP_GENERIC
select MIGHT_HAVE_CACHE_L2X0
@@ -72,7 +68,6 @@ config SOC_DRA7XX
bool "TI DRA7XX"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARM_CPU_SUSPEND if PM
select ARM_GIC
select HAVE_ARM_ARCH_TIMER
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index d95d0ef1354a..d21a3048d06b 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -625,7 +625,6 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_3430sdp_init,
.init_late = omap3430_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 0d499a1878f6..212c3160de18 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -142,7 +142,6 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
.map_io = omap3_map_io,
.init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = am3517_crane_init,
.init_late = am35xx_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4f9383cecf76..1c091b3fa312 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -366,7 +366,6 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
.map_io = omap3_map_io,
.init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = am3517_evm_init,
.init_late = am35xx_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 018353d88b96..c6df8eec4553 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -766,7 +766,6 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = cm_t35_init,
.init_late = omap35xx_init_late,
.init_time = omap3_sync32k_timer_init,
@@ -779,7 +778,6 @@ MACHINE_START(CM_T3730, "Compulab CM-T3730")
.map_io = omap3_map_io,
.init_early = omap3630_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = cm_t3730_init,
.init_late = omap3630_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 4eb5e6f2f7f5..8a2c1677964c 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -329,7 +329,6 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
.map_io = omap3_map_io,
.init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = cm_t3517_init,
.init_late = am35xx_init_late,
.init_time = omap3_gptimer_timer_init,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index cdc4fb9960a9..d8e4f346936a 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -647,7 +647,6 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = devkit8000_init,
.init_late = omap35xx_init_late,
.init_time = omap3_secure_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 9480997ba616..495305903401 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -27,7 +27,7 @@
#define gic_of_init NULL
#endif
-static struct of_device_id omap_dt_match_table[] __initdata = {
+static const struct of_device_id omap_dt_match_table[] __initconst = {
{ .compatible = "simple-bus", },
{ .compatible = "ti,omap-infra", },
{ }
@@ -43,7 +43,7 @@ static void __init omap_generic_init(void)
}
#ifdef CONFIG_SOC_OMAP2420
-static const char *omap242x_boards_compat[] __initconst = {
+static const char *const omap242x_boards_compat[] __initconst = {
"ti,omap2420",
NULL,
};
@@ -52,8 +52,6 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap242x_map_io,
.init_early = omap2420_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap2_intc_handle_irq,
.init_machine = omap_generic_init,
.init_time = omap2_sync32k_timer_init,
.dt_compat = omap242x_boards_compat,
@@ -62,7 +60,7 @@ MACHINE_END
#endif
#ifdef CONFIG_SOC_OMAP2430
-static const char *omap243x_boards_compat[] __initconst = {
+static const char *const omap243x_boards_compat[] __initconst = {
"ti,omap2430",
NULL,
};
@@ -71,8 +69,6 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap243x_map_io,
.init_early = omap2430_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap2_intc_handle_irq,
.init_machine = omap_generic_init,
.init_time = omap2_sync32k_timer_init,
.dt_compat = omap243x_boards_compat,
@@ -81,7 +77,7 @@ MACHINE_END
#endif
#ifdef CONFIG_ARCH_OMAP3
-static const char *omap3_boards_compat[] __initconst = {
+static const char *const omap3_boards_compat[] __initconst = {
"ti,omap3430",
"ti,omap3",
NULL,
@@ -91,8 +87,6 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_generic_init,
.init_late = omap3_init_late,
.init_time = omap3_sync32k_timer_init,
@@ -100,7 +94,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
.restart = omap3xxx_restart,
MACHINE_END
-static const char *omap36xx_boards_compat[] __initconst = {
+static const char *const omap36xx_boards_compat[] __initconst = {
"ti,omap36xx",
NULL,
};
@@ -109,8 +103,6 @@ DT_MACHINE_START(OMAP36XX_DT, "Generic OMAP36xx (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap3630_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_generic_init,
.init_late = omap3_init_late,
.init_time = omap3_sync32k_timer_init,
@@ -118,7 +110,7 @@ DT_MACHINE_START(OMAP36XX_DT, "Generic OMAP36xx (Flattened Device Tree)")
.restart = omap3xxx_restart,
MACHINE_END
-static const char *omap3_gp_boards_compat[] __initconst = {
+static const char *const omap3_gp_boards_compat[] __initconst = {
"ti,omap3-beagle",
"timll,omap3-devkit8000",
NULL,
@@ -128,8 +120,6 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_generic_init,
.init_late = omap3_init_late,
.init_time = omap3_secure_sync32k_timer_init,
@@ -137,7 +127,7 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
.restart = omap3xxx_restart,
MACHINE_END
-static const char *am3517_boards_compat[] __initconst = {
+static const char *const am3517_boards_compat[] __initconst = {
"ti,am3517",
NULL,
};
@@ -146,8 +136,6 @@ DT_MACHINE_START(AM3517_DT, "Generic AM3517 (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = omap3_map_io,
.init_early = am35xx_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_generic_init,
.init_late = omap3_init_late,
.init_time = omap3_gptimer_timer_init,
@@ -157,7 +145,7 @@ MACHINE_END
#endif
#ifdef CONFIG_SOC_AM33XX
-static const char *am33xx_boards_compat[] __initconst = {
+static const char *const am33xx_boards_compat[] __initconst = {
"ti,am33xx",
NULL,
};
@@ -166,8 +154,6 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
.reserve = omap_reserve,
.map_io = am33xx_map_io,
.init_early = am33xx_init_early,
- .init_irq = omap_intc_of_init,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_generic_init,
.init_late = am33xx_init_late,
.init_time = omap3_gptimer_timer_init,
@@ -177,7 +163,7 @@ MACHINE_END
#endif
#ifdef CONFIG_ARCH_OMAP4
-static const char *omap4_boards_compat[] __initconst = {
+static const char *const omap4_boards_compat[] __initconst = {
"ti,omap4460",
"ti,omap4430",
"ti,omap4",
@@ -199,7 +185,7 @@ MACHINE_END
#endif
#ifdef CONFIG_SOC_OMAP5
-static const char *omap5_boards_compat[] __initconst = {
+static const char *const omap5_boards_compat[] __initconst = {
"ti,omap5432",
"ti,omap5430",
"ti,omap5",
@@ -221,7 +207,7 @@ MACHINE_END
#endif
#ifdef CONFIG_SOC_AM43XX
-static const char *am43_boards_compat[] __initconst = {
+static const char *const am43_boards_compat[] __initconst = {
"ti,am4372",
"ti,am43",
NULL,
@@ -240,7 +226,7 @@ MACHINE_END
#endif
#ifdef CONFIG_SOC_DRA7XX
-static const char *dra74x_boards_compat[] __initconst = {
+static const char *const dra74x_boards_compat[] __initconst = {
"ti,dra742",
"ti,dra7",
NULL,
@@ -259,7 +245,7 @@ DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
.restart = omap44xx_restart,
MACHINE_END
-static const char *dra72x_boards_compat[] __initconst = {
+static const char *const dra72x_boards_compat[] __initconst = {
"ti,dra722",
NULL,
};
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 44a59c3abfb0..c2975af4cd5d 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -422,7 +422,6 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap_ldp_init,
.init_late = omap3430_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index e2e52031f056..81de1c68b360 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -588,7 +588,6 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
.map_io = omap3_map_io,
.init_early = omap3_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3_beagle_init,
.init_late = omap3_init_late,
.init_time = omap3_secure_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index bab51e64c4b5..6049f60a8813 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -230,7 +230,6 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3logic_init,
.init_late = omap35xx_init_late,
.init_time = omap3_sync32k_timer_init,
@@ -243,7 +242,6 @@ MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3logic_init,
.init_late = omap35xx_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index cf18340eb3bb..f32201656cf3 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -624,7 +624,6 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3pandora_init,
.init_late = omap35xx_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index a2e035e0792a..6311f4b1ee44 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -426,7 +426,6 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3_stalker_init,
.init_late = omap35xx_init_late,
.init_time = omap3_secure_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 70b904c010c6..a01993e5500f 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -388,7 +388,6 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = omap3_touchbook_init,
.init_late = omap3430_init_late,
.init_time = omap3_secure_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index f6d384111911..2dae6ccd39bb 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -564,7 +564,6 @@ MACHINE_START(OVERO, "Gumstix Overo")
.map_io = omap3_map_io,
.init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = overo_init,
.init_late = omap35xx_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index db168c9627a1..2d1e5a6beb85 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -134,7 +134,6 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
.map_io = omap3_map_io,
.init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
- .handle_irq = omap3_intc_handle_irq,
.init_machine = rx51_init,
.init_late = omap3430_init_late,
.init_time = omap3_sync32k_timer_init,
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index dc571f1d3b8a..180009343adb 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -60,7 +60,7 @@ static inline int omap3_pm_init(void)
}
#endif
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX))
int omap4_pm_init(void);
int omap4_pm_init_early(void);
#else
@@ -219,9 +219,6 @@ void omap_intc_restore_context(void);
void omap3_intc_suspend(void);
void omap3_intc_prepare_idle(void);
void omap3_intc_resume_idle(void);
-void omap2_intc_handle_irq(struct pt_regs *regs);
-void omap3_intc_handle_irq(struct pt_regs *regs);
-void omap_intc_of_init(void);
void omap_gic_of_init(void);
#ifdef CONFIG_CACHE_L2X0
@@ -229,16 +226,6 @@ extern void __iomem *omap4_get_l2cache_base(void);
#endif
struct device_node;
-#ifdef CONFIG_OF
-int __init intc_of_init(struct device_node *node,
- struct device_node *parent);
-#else
-int __init intc_of_init(struct device_node *node,
- struct device_node *parent)
-{
- return 0;
-}
-#endif
#ifdef CONFIG_SMP
extern void __iomem *omap4_get_scu_base(void);
@@ -307,7 +294,7 @@ static inline void omap4_cpu_resume(void)
#endif
-void pdata_quirks_init(struct of_device_id *);
+void pdata_quirks_init(const struct of_device_id *);
void omap_auxdata_legacy_init(struct device *dev);
void omap_pcs_legacy_init(int irq, void (*rearm)(void));
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9f42d5437fcc..4b26e5efa7f7 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1244,7 +1244,7 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
}
#ifdef CONFIG_OF
-static struct of_device_id gpmc_dt_ids[] = {
+static const struct of_device_id gpmc_dt_ids[] = {
{ .compatible = "ti,omap2420-gpmc" },
{ .compatible = "ti,omap2430-gpmc" },
{ .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 5d0667c119f6..831805e40529 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -667,6 +667,7 @@ void __init omap5_init_early(void)
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+ omap4_pm_init_early();
omap_prm_base_init();
omap_cm_base_init();
omap44xx_prm_init();
@@ -682,6 +683,8 @@ void __init omap5_init_early(void)
void __init omap5_init_late(void)
{
omap_common_late_init();
+ omap4_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
@@ -695,6 +698,7 @@ void __init dra7xx_init_early(void)
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(DRA7XX_CM_CORE_AON_BASE),
OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+ omap4_pm_init_early();
omap_prm_base_init();
omap_cm_base_init();
omap44xx_prm_init();
@@ -709,6 +713,8 @@ void __init dra7xx_init_early(void)
void __init dra7xx_init_late(void)
{
omap_common_late_init();
+ omap4_pm_init();
+ omap2_clk_enable_autoidle_all();
}
#endif
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 35b8590c322e..b2993e45e84c 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -24,8 +24,8 @@
#include <linux/of_irq.h>
#include "soc.h"
-#include "iomap.h"
#include "common.h"
+#include "../../drivers/irqchip/irqchip.h"
/* selected INTC register offsets */
@@ -41,15 +41,14 @@
#define INTC_MIR_CLEAR0 0x0088
#define INTC_MIR_SET0 0x008c
#define INTC_PENDING_IRQ0 0x0098
-/* Number of IRQ state bits in each MIR register */
-#define IRQ_BITS_PER_REG 32
+#define INTC_PENDING_IRQ1 0x00b8
+#define INTC_PENDING_IRQ2 0x00d8
+#define INTC_PENDING_IRQ3 0x00f8
+#define INTC_ILR0 0x0100
-#define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE)
-#define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE)
-#define INTCPS_SIR_IRQ_OFFSET 0x0040 /* omap2/3 active interrupt offset */
#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
+#define INTCPS_NR_ILR_REGS 128
#define INTCPS_NR_MIR_REGS 3
-#define INTCPS_NR_IRQS 96
/*
* OMAP2 has a number of different interrupt controllers, each interrupt
@@ -57,44 +56,93 @@
* fairly consistent for each bank, but not all registers are implemented
* for each bank.. when in doubt, consult the TRM.
*/
-static struct omap_irq_bank {
- void __iomem *base_reg;
- unsigned int nr_irqs;
-} __attribute__ ((aligned(4))) irq_banks[] = {
- {
- /* MPU INTC */
- .nr_irqs = 96,
- },
-};
-
-static struct irq_domain *domain;
/* Structure to save interrupt controller context */
-struct omap3_intc_regs {
+struct omap_intc_regs {
u32 sysconfig;
u32 protection;
u32 idle;
u32 threshold;
- u32 ilr[INTCPS_NR_IRQS];
+ u32 ilr[INTCPS_NR_ILR_REGS];
u32 mir[INTCPS_NR_MIR_REGS];
};
+static struct omap_intc_regs intc_context;
+
+static struct irq_domain *domain;
+static void __iomem *omap_irq_base;
+static int omap_nr_pending = 3;
+static int omap_nr_irqs = 96;
/* INTC bank register get/set */
+static void intc_writel(u32 reg, u32 val)
+{
+ writel_relaxed(val, omap_irq_base + reg);
+}
+
+static u32 intc_readl(u32 reg)
+{
+ return readl_relaxed(omap_irq_base + reg);
+}
+
+void omap_intc_save_context(void)
+{
+ int i;
+
+ intc_context.sysconfig =
+ intc_readl(INTC_SYSCONFIG);
+ intc_context.protection =
+ intc_readl(INTC_PROTECTION);
+ intc_context.idle =
+ intc_readl(INTC_IDLE);
+ intc_context.threshold =
+ intc_readl(INTC_THRESHOLD);
+
+ for (i = 0; i < omap_nr_irqs; i++)
+ intc_context.ilr[i] =
+ intc_readl((INTC_ILR0 + 0x4 * i));
+ for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
+ intc_context.mir[i] =
+ intc_readl(INTC_MIR0 + (0x20 * i));
+}
-static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
+void omap_intc_restore_context(void)
+{
+ int i;
+
+ intc_writel(INTC_SYSCONFIG, intc_context.sysconfig);
+ intc_writel(INTC_PROTECTION, intc_context.protection);
+ intc_writel(INTC_IDLE, intc_context.idle);
+ intc_writel(INTC_THRESHOLD, intc_context.threshold);
+
+ for (i = 0; i < omap_nr_irqs; i++)
+ intc_writel(INTC_ILR0 + 0x4 * i,
+ intc_context.ilr[i]);
+
+ for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
+ intc_writel(INTC_MIR0 + 0x20 * i,
+ intc_context.mir[i]);
+ /* MIRs are saved and restore with other PRCM registers */
+}
+
+void omap3_intc_prepare_idle(void)
{
- writel_relaxed(val, bank->base_reg + reg);
+ /*
+ * Disable autoidle as it can stall interrupt controller,
+ * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
+ */
+ intc_writel(INTC_SYSCONFIG, 0);
}
-static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg)
+void omap3_intc_resume_idle(void)
{
- return readl_relaxed(bank->base_reg + reg);
+ /* Re-enable autoidle */
+ intc_writel(INTC_SYSCONFIG, 1);
}
/* XXX: FIQ and additional INTC support (only MPU at the moment) */
static void omap_ack_irq(struct irq_data *d)
{
- intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL);
+ intc_writel(INTC_CONTROL, 0x1);
}
static void omap_mask_ack_irq(struct irq_data *d)
@@ -103,49 +151,88 @@ static void omap_mask_ack_irq(struct irq_data *d)
omap_ack_irq(d);
}
-static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
+static void __init omap_irq_soft_reset(void)
{
unsigned long tmp;
- tmp = intc_bank_read_reg(bank, INTC_REVISION) & 0xff;
+ tmp = intc_readl(INTC_REVISION) & 0xff;
+
pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n",
- bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
+ omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs);
- tmp = intc_bank_read_reg(bank, INTC_SYSCONFIG);
+ tmp = intc_readl(INTC_SYSCONFIG);
tmp |= 1 << 1; /* soft reset */
- intc_bank_write_reg(tmp, bank, INTC_SYSCONFIG);
+ intc_writel(INTC_SYSCONFIG, tmp);
- while (!(intc_bank_read_reg(bank, INTC_SYSSTATUS) & 0x1))
+ while (!(intc_readl(INTC_SYSSTATUS) & 0x1))
/* Wait for reset to complete */;
/* Enable autoidle */
- intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
+ intc_writel(INTC_SYSCONFIG, 1 << 0);
}
int omap_irq_pending(void)
{
+ int irq;
+
+ for (irq = 0; irq < omap_nr_irqs; irq += 32)
+ if (intc_readl(INTC_PENDING_IRQ0 +
+ ((irq >> 5) << 5)))
+ return 1;
+ return 0;
+}
+
+void omap3_intc_suspend(void)
+{
+ /* A pending interrupt would prevent OMAP from entering suspend */
+ omap_ack_irq(NULL);
+}
+
+static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
+{
+ int ret;
int i;
- for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
- struct omap_irq_bank *bank = irq_banks + i;
- int irq;
+ ret = irq_alloc_domain_generic_chips(d, 32, 1, "INTC",
+ handle_level_irq, IRQ_NOREQUEST | IRQ_NOPROBE,
+ IRQ_LEVEL, 0);
+ if (ret) {
+ pr_warn("Failed to allocate irq chips\n");
+ return ret;
+ }
+
+ for (i = 0; i < omap_nr_pending; i++) {
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_get_domain_generic_chip(d, 32 * i);
+ gc->reg_base = base;
+ ct = gc->chip_types;
+
+ ct->type = IRQ_TYPE_LEVEL_MASK;
+ ct->handler = handle_level_irq;
- for (irq = 0; irq < bank->nr_irqs; irq += 32)
- if (intc_bank_read_reg(bank, INTC_PENDING_IRQ0 +
- ((irq >> 5) << 5)))
- return 1;
+ ct->chip.irq_ack = omap_mask_ack_irq;
+ ct->chip.irq_mask = irq_gc_mask_disable_reg;
+ ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+
+ ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
+
+ ct->regs.enable = INTC_MIR_CLEAR0 + 32 * i;
+ ct->regs.disable = INTC_MIR_SET0 + 32 * i;
}
+
return 0;
}
-static __init void
-omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+static void __init omap_alloc_gc_legacy(void __iomem *base,
+ unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
gc = irq_alloc_generic_chip("INTC", 1, irq_start, base,
- handle_level_irq);
+ handle_level_irq);
ct = gc->chip_types;
ct->chip.irq_ack = omap_mask_ack_irq;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
@@ -155,96 +242,81 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
ct->regs.enable = INTC_MIR_CLEAR0;
ct->regs.disable = INTC_MIR_SET0;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-static void __init omap_init_irq(u32 base, int nr_irqs,
- struct device_node *node)
+static int __init omap_init_irq_of(struct device_node *node)
{
- void __iomem *omap_irq_base;
- unsigned long nr_of_irqs = 0;
- unsigned int nr_banks = 0;
- int i, j, irq_base;
+ int ret;
- omap_irq_base = ioremap(base, SZ_4K);
+ omap_irq_base = of_iomap(node, 0);
if (WARN_ON(!omap_irq_base))
- return;
+ return -ENOMEM;
- irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
- if (irq_base < 0) {
- pr_warn("Couldn't allocate IRQ numbers\n");
- irq_base = 0;
- }
+ domain = irq_domain_add_linear(node, omap_nr_irqs,
+ &irq_generic_chip_ops, NULL);
- domain = irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
- &irq_domain_simple_ops, NULL);
+ omap_irq_soft_reset();
- for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
- struct omap_irq_bank *bank = irq_banks + i;
+ ret = omap_alloc_gc_of(domain, omap_irq_base);
+ if (ret < 0)
+ irq_domain_remove(domain);
- bank->nr_irqs = nr_irqs;
-
- /* Static mapping, never released */
- bank->base_reg = ioremap(base, SZ_4K);
- if (!bank->base_reg) {
- pr_err("Could not ioremap irq bank%i\n", i);
- continue;
- }
+ return ret;
+}
- omap_irq_bank_init_one(bank);
+static int __init omap_init_irq_legacy(u32 base)
+{
+ int j, irq_base;
- for (j = 0; j < bank->nr_irqs; j += 32)
- omap_alloc_gc(bank->base_reg + j, j + irq_base, 32);
+ omap_irq_base = ioremap(base, SZ_4K);
+ if (WARN_ON(!omap_irq_base))
+ return -ENOMEM;
- nr_of_irqs += bank->nr_irqs;
- nr_banks++;
+ irq_base = irq_alloc_descs(-1, 0, omap_nr_irqs, 0);
+ if (irq_base < 0) {
+ pr_warn("Couldn't allocate IRQ numbers\n");
+ irq_base = 0;
}
- pr_info("Total of %ld interrupts on %d active controller%s\n",
- nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
-}
+ domain = irq_domain_add_legacy(NULL, omap_nr_irqs, irq_base, 0,
+ &irq_domain_simple_ops, NULL);
-void __init omap2_init_irq(void)
-{
- omap_init_irq(OMAP24XX_IC_BASE, 96, NULL);
-}
+ omap_irq_soft_reset();
-void __init omap3_init_irq(void)
-{
- omap_init_irq(OMAP34XX_IC_BASE, 96, NULL);
+ for (j = 0; j < omap_nr_irqs; j += 32)
+ omap_alloc_gc_legacy(omap_irq_base + j, j + irq_base, 32);
+
+ return 0;
}
-void __init ti81xx_init_irq(void)
+static int __init omap_init_irq(u32 base, struct device_node *node)
{
- omap_init_irq(OMAP34XX_IC_BASE, 128, NULL);
+ if (node)
+ return omap_init_irq_of(node);
+ else
+ return omap_init_irq_legacy(base);
}
-static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs)
+static asmlinkage void __exception_irq_entry
+omap_intc_handle_irq(struct pt_regs *regs)
{
- u32 irqnr;
+ u32 irqnr = 0;
int handled_irq = 0;
+ int i;
do {
- irqnr = readl_relaxed(base_addr + 0x98);
- if (irqnr)
- goto out;
-
- irqnr = readl_relaxed(base_addr + 0xb8);
- if (irqnr)
- goto out;
-
- irqnr = readl_relaxed(base_addr + 0xd8);
-#if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX)
- if (irqnr)
- goto out;
- irqnr = readl_relaxed(base_addr + 0xf8);
-#endif
+ for (i = 0; i < omap_nr_pending; i++) {
+ irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i));
+ if (irqnr)
+ goto out;
+ }
out:
if (!irqnr)
break;
- irqnr = readl_relaxed(base_addr + INTCPS_SIR_IRQ_OFFSET);
+ irqnr = intc_readl(INTC_SIR);
irqnr &= ACTIVEIRQ_MASK;
if (irqnr) {
@@ -261,17 +333,38 @@ out:
omap_ack_irq(NULL);
}
-asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs)
+void __init omap2_init_irq(void)
+{
+ omap_nr_irqs = 96;
+ omap_nr_pending = 3;
+ omap_init_irq(OMAP24XX_IC_BASE, NULL);
+ set_handle_irq(omap_intc_handle_irq);
+}
+
+void __init omap3_init_irq(void)
+{
+ omap_nr_irqs = 96;
+ omap_nr_pending = 3;
+ omap_init_irq(OMAP34XX_IC_BASE, NULL);
+ set_handle_irq(omap_intc_handle_irq);
+}
+
+void __init ti81xx_init_irq(void)
{
- void __iomem *base_addr = OMAP2_IRQ_BASE;
- omap_intc_handle_irq(base_addr, regs);
+ omap_nr_irqs = 96;
+ omap_nr_pending = 4;
+ omap_init_irq(OMAP34XX_IC_BASE, NULL);
+ set_handle_irq(omap_intc_handle_irq);
}
-int __init intc_of_init(struct device_node *node,
+static int __init intc_of_init(struct device_node *node,
struct device_node *parent)
{
struct resource res;
- u32 nr_irq = 96;
+ int ret;
+
+ omap_nr_pending = 3;
+ omap_nr_irqs = 96;
if (WARN_ON(!node))
return -ENODEV;
@@ -281,100 +374,20 @@ int __init intc_of_init(struct device_node *node,
return -EINVAL;
}
- if (of_property_read_u32(node, "ti,intc-size", &nr_irq))
- pr_warn("unable to get intc-size, default to %d\n", nr_irq);
-
- omap_init_irq(res.start, nr_irq, of_node_get(node));
-
- return 0;
-}
-
-static struct of_device_id irq_match[] __initdata = {
- { .compatible = "ti,omap2-intc", .data = intc_of_init, },
- { }
-};
-
-void __init omap_intc_of_init(void)
-{
- of_irq_init(irq_match);
-}
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
-static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
-
-void omap_intc_save_context(void)
-{
- int ind = 0, i = 0;
- for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
- struct omap_irq_bank *bank = irq_banks + ind;
- intc_context[ind].sysconfig =
- intc_bank_read_reg(bank, INTC_SYSCONFIG);
- intc_context[ind].protection =
- intc_bank_read_reg(bank, INTC_PROTECTION);
- intc_context[ind].idle =
- intc_bank_read_reg(bank, INTC_IDLE);
- intc_context[ind].threshold =
- intc_bank_read_reg(bank, INTC_THRESHOLD);
- for (i = 0; i < INTCPS_NR_IRQS; i++)
- intc_context[ind].ilr[i] =
- intc_bank_read_reg(bank, (0x100 + 0x4*i));
- for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
- intc_context[ind].mir[i] =
- intc_bank_read_reg(&irq_banks[0], INTC_MIR0 +
- (0x20 * i));
+ if (of_device_is_compatible(node, "ti,am33xx-intc")) {
+ omap_nr_irqs = 128;
+ omap_nr_pending = 4;
}
-}
-void omap_intc_restore_context(void)
-{
- int ind = 0, i = 0;
-
- for (ind = 0; ind < ARRAY_SIZE(irq_banks); ind++) {
- struct omap_irq_bank *bank = irq_banks + ind;
- intc_bank_write_reg(intc_context[ind].sysconfig,
- bank, INTC_SYSCONFIG);
- intc_bank_write_reg(intc_context[ind].sysconfig,
- bank, INTC_SYSCONFIG);
- intc_bank_write_reg(intc_context[ind].protection,
- bank, INTC_PROTECTION);
- intc_bank_write_reg(intc_context[ind].idle,
- bank, INTC_IDLE);
- intc_bank_write_reg(intc_context[ind].threshold,
- bank, INTC_THRESHOLD);
- for (i = 0; i < INTCPS_NR_IRQS; i++)
- intc_bank_write_reg(intc_context[ind].ilr[i],
- bank, (0x100 + 0x4*i));
- for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
- intc_bank_write_reg(intc_context[ind].mir[i],
- &irq_banks[0], INTC_MIR0 + (0x20 * i));
- }
- /* MIRs are saved and restore with other PRCM registers */
-}
+ ret = omap_init_irq(-1, of_node_get(node));
+ if (ret < 0)
+ return ret;
-void omap3_intc_suspend(void)
-{
- /* A pending interrupt would prevent OMAP from entering suspend */
- omap_ack_irq(NULL);
-}
+ set_handle_irq(omap_intc_handle_irq);
-void omap3_intc_prepare_idle(void)
-{
- /*
- * Disable autoidle as it can stall interrupt controller,
- * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
- */
- intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG);
-}
-
-void omap3_intc_resume_idle(void)
-{
- /* Re-enable autoidle */
- intc_bank_write_reg(1, &irq_banks[0], INTC_SYSCONFIG);
+ return 0;
}
-asmlinkage void __exception_irq_entry omap3_intc_handle_irq(struct pt_regs *regs)
-{
- void __iomem *base_addr = OMAP3_IRQ_BASE;
- omap_intc_handle_irq(base_addr, regs);
-}
-#endif /* CONFIG_ARCH_OMAP3 */
+IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
+IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
+IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 4001325f90fb..6944ae3674e8 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -56,6 +56,7 @@
#include "omap4-sar-layout.h"
#include "pm.h"
#include "prcm_mpu44xx.h"
+#include "prcm_mpu54xx.h"
#include "prminst44xx.h"
#include "prcm44xx.h"
#include "prm44xx.h"
@@ -68,7 +69,6 @@ struct omap4_cpu_pm_info {
void __iomem *scu_sar_addr;
void __iomem *wkup_sar_addr;
void __iomem *l2x0_sar_addr;
- void (*secondary_startup)(void);
};
/**
@@ -76,6 +76,7 @@ struct omap4_cpu_pm_info {
* @finish_suspend: CPU suspend finisher function pointer
* @resume: CPU resume function pointer
* @scu_prepare: CPU Snoop Control program function pointer
+ * @hotplug_restart: CPU restart function pointer
*
* Structure holds functions pointer for CPU low power operations like
* suspend, resume and scu programming.
@@ -84,11 +85,13 @@ struct cpu_pm_ops {
int (*finish_suspend)(unsigned long cpu_state);
void (*resume)(void);
void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
+ void (*hotplug_restart)(void);
};
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
static struct powerdomain *mpuss_pd;
static void __iomem *sar_base;
+static u32 cpu_context_offset;
static int default_finish_suspend(unsigned long cpu_state)
{
@@ -106,6 +109,7 @@ struct cpu_pm_ops omap_pm_ops = {
.finish_suspend = default_finish_suspend,
.resume = dummy_cpu_resume,
.scu_prepare = dummy_scu_prepare,
+ .hotplug_restart = dummy_cpu_resume,
};
/*
@@ -116,7 +120,8 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
- writel_relaxed(addr, pm_info->wkup_sar_addr);
+ if (pm_info->wkup_sar_addr)
+ writel_relaxed(addr, pm_info->wkup_sar_addr);
}
/*
@@ -141,7 +146,8 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
break;
}
- writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr);
+ if (pm_info->scu_sar_addr)
+ writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr);
}
/* Helper functions for MPUSS OSWR */
@@ -161,14 +167,14 @@ static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id)
if (cpu_id) {
reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST,
- OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+ cpu_context_offset);
omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST,
- OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+ cpu_context_offset);
} else {
reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST,
- OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+ cpu_context_offset);
omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST,
- OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+ cpu_context_offset);
}
}
@@ -179,7 +185,8 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
- writel_relaxed(save_state, pm_info->l2x0_sar_addr);
+ if (pm_info->l2x0_sar_addr)
+ writel_relaxed(save_state, pm_info->l2x0_sar_addr);
}
/*
@@ -189,10 +196,14 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state)
#ifdef CONFIG_CACHE_L2X0
static void __init save_l2x0_context(void)
{
- writel_relaxed(l2x0_saved_regs.aux_ctrl,
- sar_base + L2X0_AUXCTRL_OFFSET);
- writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
- sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+ void __iomem *l2x0_base = omap4_get_l2cache_base();
+
+ if (l2x0_base && sar_base) {
+ writel_relaxed(l2x0_saved_regs.aux_ctrl,
+ sar_base + L2X0_AUXCTRL_OFFSET);
+ writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+ sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+ }
}
#else
static void __init save_l2x0_context(void)
@@ -231,6 +242,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
save_state = 1;
break;
case PWRDM_POWER_RET:
+ if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
+ save_state = 0;
+ break;
+ }
default:
/*
* CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -298,12 +313,16 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
if (omap_rev() == OMAP4430_REV_ES1_0)
return -ENXIO;
+ /* Use the achievable power state for the domain */
+ power_state = pwrdm_get_valid_lp_state(pm_info->pwrdm,
+ false, power_state);
+
if (power_state == PWRDM_POWER_OFF)
cpu_state = 1;
pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
- set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
+ set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart));
omap_pm_ops.scu_prepare(cpu, power_state);
/*
@@ -319,6 +338,21 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
/*
+ * Enable Mercury Fast HG retention mode by default.
+ */
+static void enable_mercury_retention_mode(void)
+{
+ u32 reg;
+
+ reg = omap4_prcm_mpu_read_inst_reg(OMAP54XX_PRCM_MPU_DEVICE_INST,
+ OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET);
+ /* Enable HG_EN, HG_RAMPUP = fast mode */
+ reg |= BIT(24) | BIT(25);
+ omap4_prcm_mpu_write_inst_reg(reg, OMAP54XX_PRCM_MPU_DEVICE_INST,
+ OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET);
+}
+
+/*
* Initialise OMAP4 MPUSS
*/
int __init omap4_mpuss_init(void)
@@ -330,13 +364,17 @@ int __init omap4_mpuss_init(void)
return -ENODEV;
}
- sar_base = omap4_get_sar_ram_base();
+ if (cpu_is_omap44xx())
+ sar_base = omap4_get_sar_ram_base();
/* Initilaise per CPU PM information */
pm_info = &per_cpu(omap4_pm_info, 0x0);
- pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
- pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
- pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
+ if (sar_base) {
+ pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
+ pm_info->wkup_sar_addr = sar_base +
+ CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
+ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
+ }
pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
if (!pm_info->pwrdm) {
pr_err("Lookup failed for CPU0 pwrdm\n");
@@ -351,13 +389,12 @@ int __init omap4_mpuss_init(void)
pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
pm_info = &per_cpu(omap4_pm_info, 0x1);
- pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
- pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
- pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
- if (cpu_is_omap446x())
- pm_info->secondary_startup = omap4460_secondary_startup;
- else
- pm_info->secondary_startup = omap4_secondary_startup;
+ if (sar_base) {
+ pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
+ pm_info->wkup_sar_addr = sar_base +
+ CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
+ }
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
if (!pm_info->pwrdm) {
@@ -380,20 +417,27 @@ int __init omap4_mpuss_init(void)
pwrdm_clear_all_prev_pwrst(mpuss_pd);
mpuss_clear_prev_logic_pwrst();
- /* Save device type on scratchpad for low level code to use */
- if (omap_type() != OMAP2_DEVICE_TYPE_GP)
- writel_relaxed(1, sar_base + OMAP_TYPE_OFFSET);
- else
- writel_relaxed(0, sar_base + OMAP_TYPE_OFFSET);
-
- save_l2x0_context();
+ if (sar_base) {
+ /* Save device type on scratchpad for low level code to use */
+ writel_relaxed((omap_type() != OMAP2_DEVICE_TYPE_GP) ? 1 : 0,
+ sar_base + OMAP_TYPE_OFFSET);
+ save_l2x0_context();
+ }
if (cpu_is_omap44xx()) {
omap_pm_ops.finish_suspend = omap4_finish_suspend;
omap_pm_ops.resume = omap4_cpu_resume;
omap_pm_ops.scu_prepare = scu_pwrst_prepare;
+ omap_pm_ops.hotplug_restart = omap4_secondary_startup;
+ cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET;
+ } else if (soc_is_omap54xx() || soc_is_dra7xx()) {
+ cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET;
+ enable_mercury_retention_mode();
}
+ if (cpu_is_omap446x())
+ omap_pm_ops.hotplug_restart = omap4460_secondary_startup;
+
return 0;
}
diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h
index 3e97c6c8ecf1..dec2b05d184b 100644
--- a/arch/arm/mach-omap2/omap-secure.h
+++ b/arch/arm/mach-omap2/omap-secure.h
@@ -45,6 +45,7 @@
#define OMAP4_MON_L2X0_PREFETCH_INDEX 0x113
#define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX 0x109
+#define OMAP5_MON_AMBA_IF_INDEX 0x108
/* Secure PPA(Primary Protected Application) APIs */
#define OMAP4_PPA_L2_POR_INDEX 0x23
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 37843a7d3639..f961c46453b9 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -32,6 +32,7 @@
#include "soc.h"
#include "omap4-sar-layout.h"
#include "common.h"
+#include "pm.h"
#define AM43XX_NR_REG_BANKS 7
#define AM43XX_IRQS 224
@@ -381,7 +382,7 @@ static struct notifier_block irq_notifier_block = {
static void __init irq_pm_init(void)
{
/* FIXME: Remove this when MPU OSWR support is added */
- if (!soc_is_omap54xx())
+ if (!IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
cpu_pm_register_notifier(&irq_notifier_block);
}
#else
@@ -406,6 +407,7 @@ int __init omap_wakeupgen_init(void)
{
int i;
unsigned int boot_cpu = smp_processor_id();
+ u32 val;
/* Not supported on OMAP4 ES1.0 silicon */
if (omap_rev() == OMAP4430_REV_ES1_0) {
@@ -451,6 +453,22 @@ int __init omap_wakeupgen_init(void)
for (i = 0; i < max_irqs; i++)
irq_target_cpu[i] = boot_cpu;
+ /*
+ * Enables OMAP5 ES2 PM Mode using ES2_PM_MODE in AMBA_IF_MODE
+ * 0x0: ES1 behavior, CPU cores would enter and exit OFF mode together.
+ * 0x1: ES2 behavior, CPU cores are allowed to enter/exit OFF mode
+ * independently.
+ * This needs to be set one time thanks to always ON domain.
+ *
+ * We do not support ES1 behavior anymore. OMAP5 is assumed to be
+ * ES2.0, and the same is applicable for DRA7.
+ */
+ if (soc_is_omap54xx() || soc_is_dra7xx()) {
+ val = __raw_readl(wakeupgen_base + OMAP_AMBA_IF_MODE);
+ val |= BIT(5);
+ omap_smc1(OMAP5_MON_AMBA_IF_INDEX, val);
+ }
+
irq_hotplug_init();
irq_pm_init();
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h
index b0fd16f5c391..b3c8eccfae79 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.h
+++ b/arch/arm/mach-omap2/omap-wakeupgen.h
@@ -27,6 +27,7 @@
#define OMAP_WKG_ENB_E_1 0x420
#define OMAP_AUX_CORE_BOOT_0 0x800
#define OMAP_AUX_CORE_BOOT_1 0x804
+#define OMAP_AMBA_IF_MODE 0x80c
#define OMAP_PTMSYNCREQ_MASK 0xc00
#define OMAP_PTMSYNCREQ_EN 0xc04
#define OMAP_TIMESTAMPCYCLELO 0xc08
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 90c88d498485..8695fd4ea476 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -352,6 +352,16 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata),
OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata),
#endif
+#ifdef CONFIG_SOC_OMAP5
+ OF_DEV_AUXDATA("ti,omap5-padconf", 0x4a002840, "4a002840.pinmux", &pcs_pdata),
+ OF_DEV_AUXDATA("ti,omap5-padconf", 0x4ae0c840, "4ae0c840.pinmux", &pcs_pdata),
+#endif
+#ifdef CONFIG_SOC_DRA7XX
+ OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata),
+#endif
+#ifdef CONFIG_SOC_AM43XX
+ OF_DEV_AUXDATA("ti,am437-padconf", 0x44e10800, "44e10800.pinmux", &pcs_pdata),
+#endif
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu",
&omap4_iommu_pdata),
@@ -405,7 +415,7 @@ static void pdata_quirks_check(struct pdata_init *quirks)
}
}
-void __init pdata_quirks_init(struct of_device_id *omap_dt_match_table)
+void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
{
omap_sdrc_init(NULL, NULL);
pdata_quirks_check(auxdata_quirks);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index e150102d6c06..425bfcd67db6 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -101,6 +101,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
#endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
#define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0)
+#define PM_OMAP4_CPU_OSWR_DISABLE (1 << 1)
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
extern u16 pm44xx_errata;
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 0dda6cf8b855..503097c72b82 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -29,6 +29,7 @@ u16 pm44xx_errata;
struct power_state {
struct powerdomain *pwrdm;
u32 next_state;
+ u32 next_logic_state;
#ifdef CONFIG_SUSPEND
u32 saved_state;
u32 saved_logic_state;
@@ -36,6 +37,8 @@ struct power_state {
struct list_head node;
};
+static u32 cpu_suspend_state = PWRDM_POWER_OFF;
+
static LIST_HEAD(pwrst_list);
#ifdef CONFIG_SUSPEND
@@ -54,7 +57,7 @@ static int omap4_pm_suspend(void)
/* Set targeted power domain states by suspend */
list_for_each_entry(pwrst, &pwrst_list, node) {
omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
- pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF);
+ pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
}
/*
@@ -66,7 +69,7 @@ static int omap4_pm_suspend(void)
* domain CSWR is not supported by hardware.
* More details can be found in OMAP4430 TRM section 4.3.4.2.
*/
- omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
+ omap4_enter_lowpower(cpu_id, cpu_suspend_state);
/* Restore next powerdomain state */
list_for_each_entry(pwrst, &pwrst_list, node) {
@@ -112,15 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
* through hotplug path and CPU0 explicitly programmed
* further down in the code path
*/
- if (!strncmp(pwrdm->name, "cpu", 3))
+ if (!strncmp(pwrdm->name, "cpu", 3)) {
+ if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
+ cpu_suspend_state = PWRDM_POWER_RET;
return 0;
+ }
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
pwrst->pwrdm = pwrdm;
- pwrst->next_state = PWRDM_POWER_RET;
+ pwrst->next_state = pwrdm_get_valid_lp_state(pwrdm, false,
+ PWRDM_POWER_RET);
+ pwrst->next_logic_state = pwrdm_get_valid_lp_state(pwrdm, true,
+ PWRDM_POWER_OFF);
+
list_add(&pwrst->node, &pwrst_list);
return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
@@ -203,6 +213,32 @@ static inline int omap4_init_static_deps(void)
}
/**
+ * omap5_dra7_init_static_deps - Init static clkdm dependencies on OMAP5 and
+ * DRA7
+ *
+ * The dynamic dependency between MPUSS -> EMIF is broken and has
+ * not worked as expected. The hardware recommendation is to
+ * enable static dependencies for these to avoid system
+ * lock ups or random crashes.
+ */
+static inline int omap5_dra7_init_static_deps(void)
+{
+ struct clockdomain *mpuss_clkdm, *emif_clkdm;
+ int ret;
+
+ mpuss_clkdm = clkdm_lookup("mpu_clkdm");
+ emif_clkdm = clkdm_lookup("emif_clkdm");
+ if (!mpuss_clkdm || !emif_clkdm)
+ return -EINVAL;
+
+ ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
+ if (ret)
+ pr_err("Failed to add MPUSS -> EMIF wakeup dependency\n");
+
+ return ret;
+}
+
+/**
* omap4_pm_init_early - Does early initialization necessary for OMAP4+ devices
*
* Initializes basic stuff for power management functionality.
@@ -212,6 +248,9 @@ int __init omap4_pm_init_early(void)
if (cpu_is_omap446x())
pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
+ if (soc_is_omap54xx() || soc_is_dra7xx())
+ pm44xx_errata |= PM_OMAP4_CPU_OSWR_DISABLE;
+
return 0;
}
@@ -239,10 +278,14 @@ int __init omap4_pm_init(void)
goto err2;
}
- if (cpu_is_omap44xx()) {
+ if (cpu_is_omap44xx())
ret = omap4_init_static_deps();
- if (ret)
- goto err2;
+ else if (soc_is_omap54xx() || soc_is_dra7xx())
+ ret = omap5_dra7_init_static_deps();
+
+ if (ret) {
+ pr_err("Failed to initialise static dependencies.\n");
+ goto err2;
}
ret = omap4_mpuss_init();
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index faebd5f076af..7fb033eca0a5 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -546,7 +546,8 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
return -EINVAL;
for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
- ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
+ if (pwrdm->pwrdm_clkdms[i])
+ ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
return ret;
}
@@ -1080,6 +1081,82 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
}
/**
+ * pwrdm_get_valid_lp_state() - Find best match deep power state
+ * @pwrdm: power domain for which we want to find best match
+ * @is_logic_state: Are we looking for logic state match here? Should
+ * be one of PWRDM_xxx macro values
+ * @req_state: requested power state
+ *
+ * Returns: closest match for requested power state. default fallback
+ * is RET for logic state and ON for power state.
+ *
+ * This does a search from the power domain data looking for the
+ * closest valid power domain state that the hardware can achieve.
+ * PRCM definitions for PWRSTCTRL allows us to program whatever
+ * configuration we'd like, and PRCM will actually attempt such
+ * a transition, however if the powerdomain does not actually support it,
+ * we endup with a hung system. The valid power domain states are already
+ * available in our powerdomain data files. So this function tries to do
+ * the following:
+ * a) find if we have an exact match to the request - no issues.
+ * b) else find if a deeper power state is possible.
+ * c) failing which, it tries to find closest higher power state for the
+ * request.
+ */
+u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
+ bool is_logic_state, u8 req_state)
+{
+ u8 pwrdm_states = is_logic_state ? pwrdm->pwrsts_logic_ret :
+ pwrdm->pwrsts;
+ /* For logic, ret is highest and others, ON is highest */
+ u8 default_pwrst = is_logic_state ? PWRDM_POWER_RET : PWRDM_POWER_ON;
+ u8 new_pwrst;
+ bool found;
+
+ /* If it is already supported, nothing to search */
+ if (pwrdm_states & BIT(req_state))
+ return req_state;
+
+ if (!req_state)
+ goto up_search;
+
+ /*
+ * So, we dont have a exact match
+ * Can we get a deeper power state match?
+ */
+ new_pwrst = req_state - 1;
+ found = true;
+ while (!(pwrdm_states & BIT(new_pwrst))) {
+ /* No match even at OFF? Not available */
+ if (new_pwrst == PWRDM_POWER_OFF) {
+ found = false;
+ break;
+ }
+ new_pwrst--;
+ }
+
+ if (found)
+ goto done;
+
+up_search:
+ /* OK, no deeper ones, can we get a higher match? */
+ new_pwrst = req_state + 1;
+ while (!(pwrdm_states & BIT(new_pwrst))) {
+ if (new_pwrst > PWRDM_POWER_ON) {
+ WARN(1, "powerdomain: %s: Fix max powerstate to ON\n",
+ pwrdm->name);
+ return PWRDM_POWER_ON;
+ }
+
+ if (new_pwrst == default_pwrst)
+ break;
+ new_pwrst++;
+ }
+done:
+ return new_pwrst;
+}
+
+/**
* omap_set_pwrdm_state - change a powerdomain's current power state
* @pwrdm: struct powerdomain * to change the power state of
* @pwrst: power state to change to
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index f4727117f6cc..11bd4dd7d8d6 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -39,6 +39,7 @@
#define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET)
#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON)
+#define PWRSTS_INA_ON (PWRSTS_INACTIVE | PWRSTS_ON)
/*
@@ -219,6 +220,9 @@ struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
+ bool is_logic_state, u8 req_state);
+
int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
int pwrdm_read_pwrst(struct powerdomain *pwrdm);
diff --git a/arch/arm/mach-omap2/powerdomains54xx_data.c b/arch/arm/mach-omap2/powerdomains54xx_data.c
index ce1d752af991..60d7ed8ef8ca 100644
--- a/arch/arm/mach-omap2/powerdomains54xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains54xx_data.c
@@ -35,7 +35,7 @@ static struct powerdomain core_54xx_pwrdm = {
.prcm_offs = OMAP54XX_PRM_CORE_INST,
.prcm_partition = OMAP54XX_PRM_PARTITION,
.pwrsts = PWRSTS_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 5,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* core_nret_bank */
@@ -107,8 +107,8 @@ static struct powerdomain cpu0_54xx_pwrdm = {
.voltdm = { .name = "mpu" },
.prcm_offs = OMAP54XX_PRCM_MPU_PRM_C0_INST,
.prcm_partition = OMAP54XX_PRCM_MPU_PARTITION,
- .pwrsts = PWRSTS_OFF_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts = PWRSTS_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu0_l1 */
@@ -124,8 +124,8 @@ static struct powerdomain cpu1_54xx_pwrdm = {
.voltdm = { .name = "mpu" },
.prcm_offs = OMAP54XX_PRCM_MPU_PRM_C1_INST,
.prcm_partition = OMAP54XX_PRCM_MPU_PARTITION,
- .pwrsts = PWRSTS_OFF_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts = PWRSTS_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu1_l1 */
@@ -158,7 +158,7 @@ static struct powerdomain mpu_54xx_pwrdm = {
.prcm_offs = OMAP54XX_PRM_MPU_INST,
.prcm_partition = OMAP54XX_PRM_PARTITION,
.pwrsts = PWRSTS_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* mpu_l2 */
diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c
index 48151d1cfde0..287a2037aa16 100644
--- a/arch/arm/mach-omap2/powerdomains7xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains7xx_data.c
@@ -160,8 +160,8 @@ static struct powerdomain core_7xx_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = DRA7XX_PRM_CORE_INST,
.prcm_partition = DRA7XX_PRM_PARTITION,
- .pwrsts = PWRSTS_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts = PWRSTS_INA_ON,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 5,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* core_nret_bank */
@@ -193,8 +193,8 @@ static struct powerdomain cpu0_7xx_pwrdm = {
.name = "cpu0_pwrdm",
.prcm_offs = DRA7XX_MPU_PRCM_PRM_C0_INST,
.prcm_partition = DRA7XX_MPU_PRCM_PARTITION,
- .pwrsts = PWRSTS_OFF_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts = PWRSTS_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu0_l1 */
@@ -209,8 +209,8 @@ static struct powerdomain cpu1_7xx_pwrdm = {
.name = "cpu1_pwrdm",
.prcm_offs = DRA7XX_MPU_PRCM_PRM_C1_INST,
.prcm_partition = DRA7XX_MPU_PRCM_PARTITION,
- .pwrsts = PWRSTS_OFF_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts = PWRSTS_RET_ON,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu1_l1 */
@@ -243,7 +243,7 @@ static struct powerdomain mpu_7xx_pwrdm = {
.prcm_offs = DRA7XX_PRM_MPU_INST,
.prcm_partition = DRA7XX_PRM_PARTITION,
.pwrsts = PWRSTS_RET_ON,
- .pwrsts_logic_ret = PWRSTS_OFF_RET,
+ .pwrsts_logic_ret = PWRSTS_RET,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* mpu_l2 */
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index 2458be6fc67b..e0088e0508f8 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/of_irq.h>
#include "soc.h"
#include "common.h"
@@ -649,6 +650,11 @@ int __init omap3xxx_prm_init(void)
return prm_register(&omap3xxx_prm_ll_data);
}
+static struct of_device_id omap3_prm_dt_match_table[] = {
+ { .compatible = "ti,omap3-prm" },
+ { }
+};
+
static int omap3xxx_prm_late_init(void)
{
int ret;
@@ -656,6 +662,18 @@ static int omap3xxx_prm_late_init(void)
if (!(prm_features & PRM_HAS_IO_WAKEUP))
return 0;
+ if (of_have_populated_dt()) {
+ struct device_node *np;
+ int irq_num;
+
+ np = of_find_matching_node(NULL, omap3_prm_dt_match_table);
+ if (np) {
+ irq_num = of_irq_get(np, 0);
+ if (irq_num >= 0)
+ omap3_prcm_irq_setup.irq = irq_num;
+ }
+ }
+
omap3xxx_prm_enable_io_wakeup();
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
if (!ret)
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index a7f6ea27180a..0958d070d3db 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/of_irq.h>
#include "soc.h"
@@ -32,7 +33,6 @@
/* Static data */
static const struct omap_prcm_irq omap4_prcm_irqs[] = {
- OMAP_PRCM_IRQ("wkup", 0, 0),
OMAP_PRCM_IRQ("io", 9, 1),
};
@@ -154,21 +154,36 @@ void omap4_prm_vp_clear_txdone(u8 vp_id)
u32 omap4_prm_vcvp_read(u8 offset)
{
+ s32 inst = omap4_prmst_get_prm_dev_inst();
+
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return 0;
+
return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
- OMAP4430_PRM_DEVICE_INST, offset);
+ inst, offset);
}
void omap4_prm_vcvp_write(u32 val, u8 offset)
{
+ s32 inst = omap4_prmst_get_prm_dev_inst();
+
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return;
+
omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
- OMAP4430_PRM_DEVICE_INST, offset);
+ inst, offset);
}
u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
{
+ s32 inst = omap4_prmst_get_prm_dev_inst();
+
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return 0;
+
return omap4_prminst_rmw_inst_reg_bits(mask, bits,
OMAP4430_PRM_PARTITION,
- OMAP4430_PRM_DEVICE_INST,
+ inst,
offset);
}
@@ -275,14 +290,18 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask)
void omap44xx_prm_reconfigure_io_chain(void)
{
int i = 0;
+ s32 inst = omap4_prmst_get_prm_dev_inst();
+
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return;
/* Trigger WUCLKIN enable */
omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
OMAP4430_WUCLK_CTRL_MASK,
- OMAP4430_PRM_DEVICE_INST,
+ inst,
OMAP4_PRM_IO_PMCTRL_OFFSET);
omap_test_timeout(
- (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ (((omap4_prm_read_inst_reg(inst,
OMAP4_PRM_IO_PMCTRL_OFFSET) &
OMAP4430_WUCLK_STATUS_MASK) >>
OMAP4430_WUCLK_STATUS_SHIFT) == 1),
@@ -292,10 +311,10 @@ void omap44xx_prm_reconfigure_io_chain(void)
/* Trigger WUCLKIN disable */
omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
- OMAP4430_PRM_DEVICE_INST,
+ inst,
OMAP4_PRM_IO_PMCTRL_OFFSET);
omap_test_timeout(
- (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ (((omap4_prm_read_inst_reg(inst,
OMAP4_PRM_IO_PMCTRL_OFFSET) &
OMAP4430_WUCLK_STATUS_MASK) >>
OMAP4430_WUCLK_STATUS_SHIFT) == 0),
@@ -316,9 +335,14 @@ void omap44xx_prm_reconfigure_io_chain(void)
*/
static void __init omap44xx_prm_enable_io_wakeup(void)
{
+ s32 inst = omap4_prmst_get_prm_dev_inst();
+
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return;
+
omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
OMAP4430_GLOBAL_WUEN_MASK,
- OMAP4430_PRM_DEVICE_INST,
+ inst,
OMAP4_PRM_IO_PMCTRL_OFFSET);
}
@@ -333,8 +357,13 @@ static u32 omap44xx_prm_read_reset_sources(void)
struct prm_reset_src_map *p;
u32 r = 0;
u32 v;
+ s32 inst = omap4_prmst_get_prm_dev_inst();
- v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ if (inst == PRM_INSTANCE_UNKNOWN)
+ return 0;
+
+
+ v = omap4_prm_read_inst_reg(inst,
OMAP4_RM_RSTST);
p = omap44xx_prm_reset_src_map;
@@ -664,17 +693,56 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
int __init omap44xx_prm_init(void)
{
- if (cpu_is_omap44xx())
+ if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx())
prm_features |= PRM_HAS_IO_WAKEUP;
return prm_register(&omap44xx_prm_ll_data);
}
+static struct of_device_id omap_prm_dt_match_table[] = {
+ { .compatible = "ti,omap4-prm" },
+ { .compatible = "ti,omap5-prm" },
+ { .compatible = "ti,dra7-prm" },
+ { }
+};
+
static int omap44xx_prm_late_init(void)
{
+ struct device_node *np;
+ int irq_num;
+
if (!(prm_features & PRM_HAS_IO_WAKEUP))
return 0;
+ /* OMAP4+ is DT only now */
+ if (!of_have_populated_dt())
+ return 0;
+
+ np = of_find_matching_node(NULL, omap_prm_dt_match_table);
+
+ if (!np) {
+ /* Default loaded up with OMAP4 values */
+ if (!cpu_is_omap44xx())
+ return 0;
+ } else {
+ irq_num = of_irq_get(np, 0);
+ /*
+ * Already have OMAP4 IRQ num. For all other platforms, we need
+ * IRQ numbers from DT
+ */
+ if (irq_num < 0 && !cpu_is_omap44xx()) {
+ if (irq_num == -EPROBE_DEFER)
+ return irq_num;
+
+ /* Have nothing to do */
+ return 0;
+ }
+
+ /* Once OMAP4 DT is filled as well */
+ if (irq_num >= 0)
+ omap4_prcm_irq_setup.irq = irq_num;
+ }
+
omap44xx_prm_enable_io_wakeup();
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 76ca320f007c..74054b813600 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -467,7 +467,7 @@ int prm_unregister(struct prm_ll_data *pld)
return 0;
}
-static struct of_device_id omap_prcm_dt_match_table[] = {
+static const struct of_device_id omap_prcm_dt_match_table[] = {
{ .compatible = "ti,am3-prcm" },
{ .compatible = "ti,am3-scrm" },
{ .compatible = "ti,am4-prcm" },
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index 69f0dd08629c..225e0258d76d 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -31,6 +31,8 @@
static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
+static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
+
/**
* omap_prm_base_init - Populates the prm partitions
*
@@ -43,6 +45,24 @@ void omap_prm_base_init(void)
_prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
}
+s32 omap4_prmst_get_prm_dev_inst(void)
+{
+ if (prm_dev_inst != PRM_INSTANCE_UNKNOWN)
+ return prm_dev_inst;
+
+ /* This cannot be done way early at boot.. as things are not setup */
+ if (cpu_is_omap44xx())
+ prm_dev_inst = OMAP4430_PRM_DEVICE_INST;
+ else if (soc_is_omap54xx())
+ prm_dev_inst = OMAP54XX_PRM_DEVICE_INST;
+ else if (soc_is_dra7xx())
+ prm_dev_inst = DRA7XX_PRM_DEVICE_INST;
+ else if (soc_is_am43xx())
+ prm_dev_inst = AM43XX_PRM_DEVICE_INST;
+
+ return prm_dev_inst;
+}
+
/* Read a register in a PRM instance */
u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
{
@@ -169,28 +189,18 @@ int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
void omap4_prminst_global_warm_sw_reset(void)
{
u32 v;
- s16 dev_inst;
+ s32 inst = omap4_prmst_get_prm_dev_inst();
- if (cpu_is_omap44xx())
- dev_inst = OMAP4430_PRM_DEVICE_INST;
- else if (soc_is_omap54xx())
- dev_inst = OMAP54XX_PRM_DEVICE_INST;
- else if (soc_is_dra7xx())
- dev_inst = DRA7XX_PRM_DEVICE_INST;
- else if (soc_is_am43xx())
- dev_inst = AM43XX_PRM_DEVICE_INST;
- else
+ if (inst == PRM_INSTANCE_UNKNOWN)
return;
- v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, dev_inst,
+ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst,
OMAP4_PRM_RSTCTRL_OFFSET);
v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
- dev_inst,
- OMAP4_PRM_RSTCTRL_OFFSET);
+ inst, OMAP4_PRM_RSTCTRL_OFFSET);
/* OCP barrier */
v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
- dev_inst,
- OMAP4_PRM_RSTCTRL_OFFSET);
+ inst, OMAP4_PRM_RSTCTRL_OFFSET);
}
diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
index a2ede2d65481..583aa3774571 100644
--- a/arch/arm/mach-omap2/prminst44xx.h
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -12,6 +12,9 @@
#ifndef __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
#define __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
+#define PRM_INSTANCE_UNKNOWN -1
+extern s32 omap4_prmst_get_prm_dev_inst(void);
+
/*
* In an ideal world, we would not export these low-level functions,
* but this will probably take some time to fix properly
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 43d03fbf4c0b..4f61148ec168 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -141,7 +141,7 @@ static struct property device_disabled = {
.value = "disabled",
};
-static struct of_device_id omap_timer_match[] __initdata = {
+static const struct of_device_id omap_timer_match[] __initconst = {
{ .compatible = "ti,omap2420-timer", },
{ .compatible = "ti,omap3430-timer", },
{ .compatible = "ti,omap4430-timer", },
@@ -162,7 +162,7 @@ static struct of_device_id omap_timer_match[] __initdata = {
* the timer node in device-tree as disabled, to prevent the kernel from
* registering this timer as a platform device and so no one else can use it.
*/
-static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
+static struct device_node * __init omap_get_timer_dt(const struct of_device_id *match,
const char *property)
{
struct device_node *np;
@@ -388,7 +388,7 @@ static u64 notrace dmtimer_read_sched_clock(void)
return 0;
}
-static struct of_device_id omap_counter_match[] __initdata = {
+static const struct of_device_id omap_counter_match[] __initconst = {
{ .compatible = "ti,omap-counter32k", },
{ }
};
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 8c96307d7363..a76d03fd577b 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -119,13 +119,7 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
init.ops = &system_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
- /*
- * CLK_IGNORE_UNUSED is used to avoid ddrck switch off.
- * TODO : we should implement a driver supporting at91 ddr controller
- * (see drivers/memory) which would request and enable the ddrck clock.
- * When this is done we will be able to remove CLK_IGNORE_UNUSED flag.
- */
- init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
+ init.flags = CLK_SET_RATE_PARENT;
sys->id = id;
sys->hw.init = &init;
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cfd6519df661..82a2ebe41e27 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -120,6 +120,10 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
help
Use ARM global timer clock source as sched_clock
+config ATMEL_PIT
+ select CLKSRC_OF if OF
+ def_bool SOC_AT91SAM9 || SOC_SAMA5
+
config CLKSRC_METAG_GENERIC
def_bool y if METAG
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7fd9fd1dff42..e566f6c7ded4 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
+obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
new file mode 100644
index 000000000000..d5289098b3df
--- /dev/null
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -0,0 +1,296 @@
+/*
+ * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
+ *
+ * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+ * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
+ * Converted to ClockSource/ClockEvents by David Brownell.
+ *
+ * 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 pr_fmt(fmt) "AT91: PIT: " fmt
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#define AT91_PIT_MR 0x00 /* Mode Register */
+#define AT91_PIT_PITIEN BIT(25) /* Timer Interrupt Enable */
+#define AT91_PIT_PITEN BIT(24) /* Timer Enabled */
+#define AT91_PIT_PIV GENMASK(19, 0) /* Periodic Interval Value */
+
+#define AT91_PIT_SR 0x04 /* Status Register */
+#define AT91_PIT_PITS BIT(0) /* Timer Status */
+
+#define AT91_PIT_PIVR 0x08 /* Periodic Interval Value Register */
+#define AT91_PIT_PIIR 0x0c /* Periodic Interval Image Register */
+#define AT91_PIT_PICNT GENMASK(31, 20) /* Interval Counter */
+#define AT91_PIT_CPIV GENMASK(19, 0) /* Inverval Value */
+
+#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
+#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
+
+struct pit_data {
+ struct clock_event_device clkevt;
+ struct clocksource clksrc;
+
+ void __iomem *base;
+ u32 cycle;
+ u32 cnt;
+ unsigned int irq;
+ struct clk *mck;
+};
+
+static inline struct pit_data *clksrc_to_pit_data(struct clocksource *clksrc)
+{
+ return container_of(clksrc, struct pit_data, clksrc);
+}
+
+static inline struct pit_data *clkevt_to_pit_data(struct clock_event_device *clkevt)
+{
+ return container_of(clkevt, struct pit_data, clkevt);
+}
+
+static inline unsigned int pit_read(void __iomem *base, unsigned int reg_offset)
+{
+ return __raw_readl(base + reg_offset);
+}
+
+static inline void pit_write(void __iomem *base, unsigned int reg_offset, unsigned long value)
+{
+ __raw_writel(value, base + reg_offset);
+}
+
+/*
+ * Clocksource: just a monotonic counter of MCK/16 cycles.
+ * We don't care whether or not PIT irqs are enabled.
+ */
+static cycle_t read_pit_clk(struct clocksource *cs)
+{
+ struct pit_data *data = clksrc_to_pit_data(cs);
+ unsigned long flags;
+ u32 elapsed;
+ u32 t;
+
+ raw_local_irq_save(flags);
+ elapsed = data->cnt;
+ t = pit_read(data->base, AT91_PIT_PIIR);
+ raw_local_irq_restore(flags);
+
+ elapsed += PIT_PICNT(t) * data->cycle;
+ elapsed += PIT_CPIV(t);
+ return elapsed;
+}
+
+/*
+ * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
+ */
+static void
+pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+ struct pit_data *data = clkevt_to_pit_data(dev);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* update clocksource counter */
+ data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
+ pit_write(data->base, AT91_PIT_MR,
+ (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ BUG();
+ /* FALLTHROUGH */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ /* disable irq, leaving the clocksource active */
+ pit_write(data->base, AT91_PIT_MR,
+ (data->cycle - 1) | AT91_PIT_PITEN);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
+{
+ struct pit_data *data = clkevt_to_pit_data(cedev);
+
+ /* Disable timer */
+ pit_write(data->base, AT91_PIT_MR, 0);
+}
+
+static void at91sam926x_pit_reset(struct pit_data *data)
+{
+ /* Disable timer and irqs */
+ pit_write(data->base, AT91_PIT_MR, 0);
+
+ /* Clear any pending interrupts, wait for PIT to stop counting */
+ while (PIT_CPIV(pit_read(data->base, AT91_PIT_PIVR)) != 0)
+ cpu_relax();
+
+ /* Start PIT but don't enable IRQ */
+ pit_write(data->base, AT91_PIT_MR,
+ (data->cycle - 1) | AT91_PIT_PITEN);
+}
+
+static void at91sam926x_pit_resume(struct clock_event_device *cedev)
+{
+ struct pit_data *data = clkevt_to_pit_data(cedev);
+
+ at91sam926x_pit_reset(data);
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
+{
+ struct pit_data *data = dev_id;
+
+ /*
+ * irqs should be disabled here, but as the irq is shared they are only
+ * guaranteed to be off if the timer irq is registered first.
+ */
+ WARN_ON_ONCE(!irqs_disabled());
+
+ /* The PIT interrupt may be disabled, and is shared */
+ if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) &&
+ (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) {
+ unsigned nr_ticks;
+
+ /* Get number of ticks performed before irq, and ack it */
+ nr_ticks = PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
+ do {
+ data->cnt += data->cycle;
+ data->clkevt.event_handler(&data->clkevt);
+ nr_ticks--;
+ } while (nr_ticks);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * Set up both clocksource and clockevent support.
+ */
+static void __init at91sam926x_pit_common_init(struct pit_data *data)
+{
+ unsigned long pit_rate;
+ unsigned bits;
+ int ret;
+
+ /*
+ * Use our actual MCK to figure out how many MCK/16 ticks per
+ * 1/HZ period (instead of a compile-time constant LATCH).
+ */
+ pit_rate = clk_get_rate(data->mck) / 16;
+ data->cycle = DIV_ROUND_CLOSEST(pit_rate, HZ);
+ WARN_ON(((data->cycle - 1) & ~AT91_PIT_PIV) != 0);
+
+ /* Initialize and enable the timer */
+ at91sam926x_pit_reset(data);
+
+ /*
+ * Register clocksource. The high order bits of PIV are unused,
+ * so this isn't a 32-bit counter unless we get clockevent irqs.
+ */
+ bits = 12 /* PICNT */ + ilog2(data->cycle) /* PIV */;
+ data->clksrc.mask = CLOCKSOURCE_MASK(bits);
+ data->clksrc.name = "pit";
+ data->clksrc.rating = 175;
+ data->clksrc.read = read_pit_clk,
+ data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ clocksource_register_hz(&data->clksrc, pit_rate);
+
+ /* Set up irq handler */
+ ret = request_irq(data->irq, at91sam926x_pit_interrupt,
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
+ "at91_tick", data);
+ if (ret)
+ panic(pr_fmt("Unable to setup IRQ\n"));
+
+ /* Set up and register clockevents */
+ data->clkevt.name = "pit";
+ data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+ data->clkevt.shift = 32;
+ data->clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, data->clkevt.shift);
+ data->clkevt.rating = 100;
+ data->clkevt.cpumask = cpumask_of(0);
+
+ data->clkevt.set_mode = pit_clkevt_mode;
+ data->clkevt.resume = at91sam926x_pit_resume;
+ data->clkevt.suspend = at91sam926x_pit_suspend;
+ clockevents_register_device(&data->clkevt);
+}
+
+static void __init at91sam926x_pit_dt_init(struct device_node *node)
+{
+ struct pit_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ panic(pr_fmt("Unable to allocate memory\n"));
+
+ data->base = of_iomap(node, 0);
+ if (!data->base)
+ panic(pr_fmt("Could not map PIT address\n"));
+
+ data->mck = of_clk_get(node, 0);
+ if (IS_ERR(data->mck))
+ /* Fallback on clkdev for !CCF-based boards */
+ data->mck = clk_get(NULL, "mck");
+
+ if (IS_ERR(data->mck))
+ panic(pr_fmt("Unable to get mck clk\n"));
+
+ /* Get the interrupts property */
+ data->irq = irq_of_parse_and_map(node, 0);
+ if (!data->irq)
+ panic(pr_fmt("Unable to get IRQ from DT\n"));
+
+ at91sam926x_pit_common_init(data);
+}
+CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
+ at91sam926x_pit_dt_init);
+
+static void __iomem *pit_base_addr;
+
+void __init at91sam926x_pit_init(int irq)
+{
+ struct pit_data *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ panic(pr_fmt("Unable to allocate memory\n"));
+
+ data->base = pit_base_addr;
+
+ data->mck = clk_get(NULL, "mck");
+ if (IS_ERR(data->mck))
+ panic(pr_fmt("Unable to get mck clk\n"));
+
+ data->irq = irq;
+
+ at91sam926x_pit_common_init(data);
+}
+
+void __init at91sam926x_ioremap_pit(u32 addr)
+{
+ if (of_have_populated_dt())
+ return;
+
+ pit_base_addr = ioremap(addr, 16);
+
+ if (!pit_base_addr)
+ panic(pr_fmt("Impossible to ioremap PIT\n"));
+}
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index fd89ca982748..7072c2892d63 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -376,4 +376,13 @@ config EDAC_OCTEON_PCI
Support for error detection and correction on the
Cavium Octeon family of SOCs.
+config EDAC_ALTERA_MC
+ tristate "Altera SDRAM Memory Controller EDAC"
+ depends on EDAC_MM_EDAC && ARCH_SOCFPGA
+ help
+ Support for error detection and correction on the
+ Altera SDRAM memory controller. Note that the
+ preloader must initialize the SDRAM before loading
+ the kernel.
+
endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index c479a24d8f77..359aa499b200 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -65,3 +65,5 @@ obj-$(CONFIG_EDAC_OCTEON_PC) += octeon_edac-pc.o
obj-$(CONFIG_EDAC_OCTEON_L2C) += octeon_edac-l2c.o
obj-$(CONFIG_EDAC_OCTEON_LMC) += octeon_edac-lmc.o
obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o
+
+obj-$(CONFIG_EDAC_ALTERA_MC) += altera_edac.o
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
new file mode 100644
index 000000000000..3c4929fda9d5
--- /dev/null
+++ b/drivers/edac/altera_edac.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright Altera Corporation (C) 2014. All rights reserved.
+ * Copyright 2011-2012 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Adapted from the highbank_mc_edac driver.
+ */
+
+#include <linux/ctype.h>
+#include <linux/edac.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "altera_edac"
+#define EDAC_VERSION "1"
+
+/* SDRAM Controller CtrlCfg Register */
+#define CTLCFG_OFST 0x00
+
+/* SDRAM Controller CtrlCfg Register Bit Masks */
+#define CTLCFG_ECC_EN 0x400
+#define CTLCFG_ECC_CORR_EN 0x800
+#define CTLCFG_GEN_SB_ERR 0x2000
+#define CTLCFG_GEN_DB_ERR 0x4000
+
+#define CTLCFG_ECC_AUTO_EN (CTLCFG_ECC_EN | \
+ CTLCFG_ECC_CORR_EN)
+
+/* SDRAM Controller Address Width Register */
+#define DRAMADDRW_OFST 0x2C
+
+/* SDRAM Controller Address Widths Field Register */
+#define DRAMADDRW_COLBIT_MASK 0x001F
+#define DRAMADDRW_COLBIT_SHIFT 0
+#define DRAMADDRW_ROWBIT_MASK 0x03E0
+#define DRAMADDRW_ROWBIT_SHIFT 5
+#define DRAMADDRW_BANKBIT_MASK 0x1C00
+#define DRAMADDRW_BANKBIT_SHIFT 10
+#define DRAMADDRW_CSBIT_MASK 0xE000
+#define DRAMADDRW_CSBIT_SHIFT 13
+
+/* SDRAM Controller Interface Data Width Register */
+#define DRAMIFWIDTH_OFST 0x30
+
+/* SDRAM Controller Interface Data Width Defines */
+#define DRAMIFWIDTH_16B_ECC 24
+#define DRAMIFWIDTH_32B_ECC 40
+
+/* SDRAM Controller DRAM Status Register */
+#define DRAMSTS_OFST 0x38
+
+/* SDRAM Controller DRAM Status Register Bit Masks */
+#define DRAMSTS_SBEERR 0x04
+#define DRAMSTS_DBEERR 0x08
+#define DRAMSTS_CORR_DROP 0x10
+
+/* SDRAM Controller DRAM IRQ Register */
+#define DRAMINTR_OFST 0x3C
+
+/* SDRAM Controller DRAM IRQ Register Bit Masks */
+#define DRAMINTR_INTREN 0x01
+#define DRAMINTR_SBEMASK 0x02
+#define DRAMINTR_DBEMASK 0x04
+#define DRAMINTR_CORRDROPMASK 0x08
+#define DRAMINTR_INTRCLR 0x10
+
+/* SDRAM Controller Single Bit Error Count Register */
+#define SBECOUNT_OFST 0x40
+
+/* SDRAM Controller Single Bit Error Count Register Bit Masks */
+#define SBECOUNT_MASK 0x0F
+
+/* SDRAM Controller Double Bit Error Count Register */
+#define DBECOUNT_OFST 0x44
+
+/* SDRAM Controller Double Bit Error Count Register Bit Masks */
+#define DBECOUNT_MASK 0x0F
+
+/* SDRAM Controller ECC Error Address Register */
+#define ERRADDR_OFST 0x48
+
+/* SDRAM Controller ECC Error Address Register Bit Masks */
+#define ERRADDR_MASK 0xFFFFFFFF
+
+/* Altera SDRAM Memory Controller data */
+struct altr_sdram_mc_data {
+ struct regmap *mc_vbase;
+};
+
+static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id)
+{
+ struct mem_ctl_info *mci = dev_id;
+ struct altr_sdram_mc_data *drvdata = mci->pvt_info;
+ u32 status, err_count, err_addr;
+
+ /* Error Address is shared by both SBE & DBE */
+ regmap_read(drvdata->mc_vbase, ERRADDR_OFST, &err_addr);
+
+ regmap_read(drvdata->mc_vbase, DRAMSTS_OFST, &status);
+
+ if (status & DRAMSTS_DBEERR) {
+ regmap_read(drvdata->mc_vbase, DBECOUNT_OFST, &err_count);
+ panic("\nEDAC: [%d Uncorrectable errors @ 0x%08X]\n",
+ err_count, err_addr);
+ }
+ if (status & DRAMSTS_SBEERR) {
+ regmap_read(drvdata->mc_vbase, SBECOUNT_OFST, &err_count);
+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count,
+ err_addr >> PAGE_SHIFT,
+ err_addr & ~PAGE_MASK, 0,
+ 0, 0, -1, mci->ctl_name, "");
+ }
+
+ regmap_write(drvdata->mc_vbase, DRAMINTR_OFST,
+ (DRAMINTR_INTRCLR | DRAMINTR_INTREN));
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_EDAC_DEBUG
+static ssize_t altr_sdr_mc_err_inject_write(struct file *file,
+ const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct mem_ctl_info *mci = file->private_data;
+ struct altr_sdram_mc_data *drvdata = mci->pvt_info;
+ u32 *ptemp;
+ dma_addr_t dma_handle;
+ u32 reg, read_reg;
+
+ ptemp = dma_alloc_coherent(mci->pdev, 16, &dma_handle, GFP_KERNEL);
+ if (!ptemp) {
+ dma_free_coherent(mci->pdev, 16, ptemp, dma_handle);
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Inject: Buffer Allocation error\n");
+ return -ENOMEM;
+ }
+
+ regmap_read(drvdata->mc_vbase, CTLCFG_OFST, &read_reg);
+ read_reg &= ~(CTLCFG_GEN_SB_ERR | CTLCFG_GEN_DB_ERR);
+
+ /* Error are injected by writing a word while the SBE or DBE
+ * bit in the CTLCFG register is set. Reading the word will
+ * trigger the SBE or DBE error and the corresponding IRQ.
+ */
+ if (count == 3) {
+ edac_printk(KERN_ALERT, EDAC_MC,
+ "Inject Double bit error\n");
+ regmap_write(drvdata->mc_vbase, CTLCFG_OFST,
+ (read_reg | CTLCFG_GEN_DB_ERR));
+ } else {
+ edac_printk(KERN_ALERT, EDAC_MC,
+ "Inject Single bit error\n");
+ regmap_write(drvdata->mc_vbase, CTLCFG_OFST,
+ (read_reg | CTLCFG_GEN_SB_ERR));
+ }
+
+ ptemp[0] = 0x5A5A5A5A;
+ ptemp[1] = 0xA5A5A5A5;
+
+ /* Clear the error injection bits */
+ regmap_write(drvdata->mc_vbase, CTLCFG_OFST, read_reg);
+ /* Ensure it has been written out */
+ wmb();
+
+ /*
+ * To trigger the error, we need to read the data back
+ * (the data was written with errors above).
+ * The ACCESS_ONCE macros and printk are used to prevent the
+ * the compiler optimizing these reads out.
+ */
+ reg = ACCESS_ONCE(ptemp[0]);
+ read_reg = ACCESS_ONCE(ptemp[1]);
+ /* Force Read */
+ rmb();
+
+ edac_printk(KERN_ALERT, EDAC_MC, "Read Data [0x%X, 0x%X]\n",
+ reg, read_reg);
+
+ dma_free_coherent(mci->pdev, 16, ptemp, dma_handle);
+
+ return count;
+}
+
+static const struct file_operations altr_sdr_mc_debug_inject_fops = {
+ .open = simple_open,
+ .write = altr_sdr_mc_err_inject_write,
+ .llseek = generic_file_llseek,
+};
+
+static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+{
+ if (mci->debugfs)
+ debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
+ &altr_sdr_mc_debug_inject_fops);
+}
+#else
+static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+{}
+#endif
+
+/* Get total memory size in bytes */
+static u32 altr_sdram_get_total_mem_size(struct regmap *mc_vbase)
+{
+ u32 size, read_reg, row, bank, col, cs, width;
+
+ if (regmap_read(mc_vbase, DRAMADDRW_OFST, &read_reg) < 0)
+ return 0;
+
+ if (regmap_read(mc_vbase, DRAMIFWIDTH_OFST, &width) < 0)
+ return 0;
+
+ col = (read_reg & DRAMADDRW_COLBIT_MASK) >>
+ DRAMADDRW_COLBIT_SHIFT;
+ row = (read_reg & DRAMADDRW_ROWBIT_MASK) >>
+ DRAMADDRW_ROWBIT_SHIFT;
+ bank = (read_reg & DRAMADDRW_BANKBIT_MASK) >>
+ DRAMADDRW_BANKBIT_SHIFT;
+ cs = (read_reg & DRAMADDRW_CSBIT_MASK) >>
+ DRAMADDRW_CSBIT_SHIFT;
+
+ /* Correct for ECC as its not addressible */
+ if (width == DRAMIFWIDTH_32B_ECC)
+ width = 32;
+ if (width == DRAMIFWIDTH_16B_ECC)
+ width = 16;
+
+ /* calculate the SDRAM size base on this info */
+ size = 1 << (row + bank + col);
+ size = size * cs * (width / 8);
+ return size;
+}
+
+static int altr_sdram_probe(struct platform_device *pdev)
+{
+ struct edac_mc_layer layers[2];
+ struct mem_ctl_info *mci;
+ struct altr_sdram_mc_data *drvdata;
+ struct regmap *mc_vbase;
+ struct dimm_info *dimm;
+ u32 read_reg, mem_size;
+ int irq;
+ int res = 0;
+
+ /* Validate the SDRAM controller has ECC enabled */
+ /* Grab the register range from the sdr controller in device tree */
+ mc_vbase = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "altr,sdr-syscon");
+ if (IS_ERR(mc_vbase)) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "regmap for altr,sdr-syscon lookup failed.\n");
+ return -ENODEV;
+ }
+
+ if (regmap_read(mc_vbase, CTLCFG_OFST, &read_reg) ||
+ ((read_reg & CTLCFG_ECC_AUTO_EN) != CTLCFG_ECC_AUTO_EN)) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "No ECC/ECC disabled [0x%08X]\n", read_reg);
+ return -ENODEV;
+ }
+
+ /* Grab memory size from device tree. */
+ mem_size = altr_sdram_get_total_mem_size(mc_vbase);
+ if (!mem_size) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Unable to calculate memory size\n");
+ return -ENODEV;
+ }
+
+ /* Ensure the SDRAM Interrupt is disabled and cleared */
+ if (regmap_write(mc_vbase, DRAMINTR_OFST, DRAMINTR_INTRCLR)) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Error clearing SDRAM ECC IRQ\n");
+ return -ENODEV;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ edac_printk(KERN_ERR, EDAC_MC,
+ "No irq %d in DT\n", irq);
+ return -ENODEV;
+ }
+
+ layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
+ layers[0].size = 1;
+ layers[0].is_virt_csrow = true;
+ layers[1].type = EDAC_MC_LAYER_CHANNEL;
+ layers[1].size = 1;
+ layers[1].is_virt_csrow = false;
+ mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
+ sizeof(struct altr_sdram_mc_data));
+ if (!mci)
+ return -ENOMEM;
+
+ mci->pdev = &pdev->dev;
+ drvdata = mci->pvt_info;
+ drvdata->mc_vbase = mc_vbase;
+ platform_set_drvdata(pdev, mci);
+
+ if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
+ res = -ENOMEM;
+ goto free;
+ }
+
+ mci->mtype_cap = MEM_FLAG_DDR3;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ mci->mod_name = EDAC_MOD_STR;
+ mci->mod_ver = EDAC_VERSION;
+ mci->ctl_name = dev_name(&pdev->dev);
+ mci->scrub_mode = SCRUB_SW_SRC;
+ mci->dev_name = dev_name(&pdev->dev);
+
+ dimm = *mci->dimms;
+ dimm->nr_pages = ((mem_size - 1) >> PAGE_SHIFT) + 1;
+ dimm->grain = 8;
+ dimm->dtype = DEV_X8;
+ dimm->mtype = MEM_DDR3;
+ dimm->edac_mode = EDAC_SECDED;
+
+ res = edac_mc_add_mc(mci);
+ if (res < 0)
+ goto err;
+
+ res = devm_request_irq(&pdev->dev, irq, altr_sdram_mc_err_handler,
+ 0, dev_name(&pdev->dev), mci);
+ if (res < 0) {
+ edac_mc_printk(mci, KERN_ERR,
+ "Unable to request irq %d\n", irq);
+ res = -ENODEV;
+ goto err2;
+ }
+
+ if (regmap_write(drvdata->mc_vbase, DRAMINTR_OFST,
+ (DRAMINTR_INTRCLR | DRAMINTR_INTREN))) {
+ edac_mc_printk(mci, KERN_ERR,
+ "Error enabling SDRAM ECC IRQ\n");
+ res = -ENODEV;
+ goto err2;
+ }
+
+ altr_sdr_mc_create_debugfs_nodes(mci);
+
+ devres_close_group(&pdev->dev, NULL);
+
+ return 0;
+
+err2:
+ edac_mc_del_mc(&pdev->dev);
+err:
+ devres_release_group(&pdev->dev, NULL);
+free:
+ edac_mc_free(mci);
+ edac_printk(KERN_ERR, EDAC_MC,
+ "EDAC Probe Failed; Error %d\n", res);
+
+ return res;
+}
+
+static int altr_sdram_remove(struct platform_device *pdev)
+{
+ struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+ edac_mc_del_mc(&pdev->dev);
+ edac_mc_free(mci);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id altr_sdram_ctrl_of_match[] = {
+ { .compatible = "altr,sdram-edac", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);
+
+static struct platform_driver altr_sdram_edac_driver = {
+ .probe = altr_sdram_probe,
+ .remove = altr_sdram_remove,
+ .driver = {
+ .name = "altr_sdram_edac",
+ .of_match_table = altr_sdram_ctrl_of_match,
+ },
+};
+
+module_platform_driver(altr_sdram_edac_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Thor Thayer");
+MODULE_DESCRIPTION("EDAC Driver for Altera SDRAM Controller");
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index fab81a143bd7..6d91c27fd4c8 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -7,6 +7,16 @@ menuconfig MEMORY
if MEMORY
+config ATMEL_SDRAMC
+ bool "Atmel (Multi-port DDR-)SDRAM Controller"
+ default y
+ depends on ARCH_AT91 && OF
+ help
+ This driver is for Atmel SDRAM Controller or Atmel Multi-port
+ DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
+ Starting with the at91sam9g45, this controller supports SDR, DDR and
+ LP-DDR memories.
+
config TI_AEMIF
tristate "Texas Instruments AEMIF driver"
depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 4055c47f45ab..c32d31981be3 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -5,6 +5,7 @@
ifeq ($(CONFIG_DDR),y)
obj-$(CONFIG_OF) += of_memory.o
endif
+obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
obj-$(CONFIG_TI_EMIF) += emif.o
obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c
new file mode 100644
index 000000000000..fed04e8efe75
--- /dev/null
+++ b/drivers/memory/atmel-sdramc.c
@@ -0,0 +1,98 @@
+/*
+ * Atmel (Multi-port DDR-)SDRAM Controller driver
+ *
+ * Copyright (C) 2014 Atmel
+ *
+ * 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 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+struct at91_ramc_caps {
+ bool has_ddrck;
+ bool has_mpddr_clk;
+};
+
+static const struct at91_ramc_caps at91rm9200_caps = { };
+
+static const struct at91_ramc_caps at91sam9g45_caps = {
+ .has_ddrck = 1,
+ .has_mpddr_clk = 0,
+};
+
+static const struct at91_ramc_caps sama5d3_caps = {
+ .has_ddrck = 1,
+ .has_mpddr_clk = 1,
+};
+
+static const struct of_device_id atmel_ramc_of_match[] = {
+ { .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, },
+ { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, },
+ { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, },
+ { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, atmel_ramc_of_match);
+
+static int atmel_ramc_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ const struct at91_ramc_caps *caps;
+ struct clk *clk;
+
+ match = of_match_device(atmel_ramc_of_match, &pdev->dev);
+ caps = match->data;
+
+ if (caps->has_ddrck) {
+ clk = devm_clk_get(&pdev->dev, "ddrck");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clk_prepare_enable(clk);
+ }
+
+ if (caps->has_mpddr_clk) {
+ clk = devm_clk_get(&pdev->dev, "mpddr");
+ if (IS_ERR(clk)) {
+ pr_err("AT91 RAMC: couldn't get mpddr clock\n");
+ return PTR_ERR(clk);
+ }
+ clk_prepare_enable(clk);
+ }
+
+ return 0;
+}
+
+static struct platform_driver atmel_ramc_driver = {
+ .probe = atmel_ramc_probe,
+ .driver = {
+ .name = "atmel-ramc",
+ .owner = THIS_MODULE,
+ .of_match_table = atmel_ramc_of_match,
+ },
+};
+
+static int __init atmel_ramc_init(void)
+{
+ return platform_driver_register(&atmel_ramc_driver);
+}
+module_init(atmel_ramc_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
+MODULE_DESCRIPTION("Atmel (Multi-port DDR-)SDRAM Controller");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523bbebf..81b445122eea 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -6,15 +6,33 @@ menuconfig POWER_RESET
Say Y here to enable board reset and power off
+if POWER_RESET
+
config POWER_RESET_AS3722
bool "ams AS3722 power-off driver"
- depends on MFD_AS3722 && POWER_RESET
+ depends on MFD_AS3722
help
This driver supports turning off board via a ams AS3722 power-off.
+config POWER_RESET_AT91_POWEROFF
+ bool "Atmel AT91 poweroff driver"
+ depends on ARCH_AT91
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports poweroff for Atmel AT91SAM9 and SAMA5
+ SoCs
+
+config POWER_RESET_AT91_RESET
+ bool "Atmel AT91 reset driver"
+ depends on ARCH_AT91
+ default SOC_AT91SAM9 || SOC_SAMA5
+ help
+ This driver supports restart for Atmel AT91SAM9 and SAMA5
+ SoCs
+
config POWER_RESET_AXXIA
bool "LSI Axxia reset driver"
- depends on POWER_RESET && ARCH_AXXIA
+ depends on ARCH_AXXIA
help
This driver supports restart for Axxia SoC.
@@ -33,7 +51,7 @@ config POWER_RESET_BRCMSTB
config POWER_RESET_GPIO
bool "GPIO power-off driver"
- depends on OF_GPIO && POWER_RESET
+ depends on OF_GPIO
help
This driver supports turning off your board via a GPIO line.
If your board needs a GPIO high/low to power down, say Y and
@@ -47,13 +65,13 @@ config POWER_RESET_HISI
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
- depends on POWER_RESET && ARCH_QCOM
+ depends on ARCH_QCOM
help
Power off and restart support for Qualcomm boards.
config POWER_RESET_QNAP
bool "QNAP power-off driver"
- depends on OF_GPIO && POWER_RESET && PLAT_ORION
+ depends on OF_GPIO && PLAT_ORION
help
This driver supports turning off QNAP NAS devices by sending
commands to the microcontroller which controls the main power.
@@ -71,14 +89,13 @@ config POWER_RESET_RESTART
config POWER_RESET_SUN6I
bool "Allwinner A31 SoC reset driver"
depends on ARCH_SUNXI
- depends on POWER_RESET
help
Reboot support for the Allwinner A31 SoCs.
config POWER_RESET_VEXPRESS
bool "ARM Versatile Express power-off and reset driver"
depends on ARM || ARM64
- depends on POWER_RESET && VEXPRESS_CONFIG
+ depends on VEXPRESS_CONFIG
help
Power off and reset support for the ARM Ltd. Versatile
Express boards.
@@ -86,7 +103,6 @@ config POWER_RESET_VEXPRESS
config POWER_RESET_XGENE
bool "APM SoC X-Gene reset driver"
depends on ARM64
- depends on POWER_RESET
help
Reboot support for the APM SoC X-Gene Eval boards.
@@ -97,3 +113,4 @@ config POWER_RESET_KEYSTONE
help
Reboot support for the KEYSTONE SoCs.
+endif
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a42e70edd037..4433a753fd93 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,4 +1,6 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
+obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c
new file mode 100644
index 000000000000..c61000333bb9
--- /dev/null
+++ b/drivers/power/reset/at91-poweroff.c
@@ -0,0 +1,156 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * Copyright (C) 2014 Free Electrons
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
+#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
+#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
+#define AT91_SHDW_WKMODE0 GENMASK(2, 0) /* Wake-up 0 Mode Selection */
+#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
+#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
+#define AT91_SHDW_RTTWKEN BIT(16) /* Real Time Timer Wake-up Enable */
+#define AT91_SHDW_RTCWKEN BIT(17) /* Real Time Clock Wake-up Enable */
+
+#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
+#define AT91_SHDW_WAKEUP0 BIT(0) /* Wake-up 0 Status */
+#define AT91_SHDW_RTTWK BIT(16) /* Real-time Timer Wake-up */
+#define AT91_SHDW_RTCWK BIT(17) /* Real-time Clock Wake-up [SAM9RL] */
+
+enum wakeup_type {
+ AT91_SHDW_WKMODE0_NONE = 0,
+ AT91_SHDW_WKMODE0_HIGH = 1,
+ AT91_SHDW_WKMODE0_LOW = 2,
+ AT91_SHDW_WKMODE0_ANYLEVEL = 3,
+};
+
+static const char *shdwc_wakeup_modes[] = {
+ [AT91_SHDW_WKMODE0_NONE] = "none",
+ [AT91_SHDW_WKMODE0_HIGH] = "high",
+ [AT91_SHDW_WKMODE0_LOW] = "low",
+ [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
+};
+
+static void __iomem *at91_shdwc_base;
+
+static void __init at91_wakeup_status(void)
+{
+ u32 reg = readl(at91_shdwc_base + AT91_SHDW_SR);
+ char *reason = "unknown";
+
+ /* Simple power-on, just bail out */
+ if (!reg)
+ return;
+
+ if (reg & AT91_SHDW_RTTWK)
+ reason = "RTT";
+ else if (reg & AT91_SHDW_RTCWK)
+ reason = "RTC";
+
+ pr_info("AT91: Wake-Up source: %s\n", reason);
+}
+
+static void at91_poweroff(void)
+{
+ writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
+}
+
+const enum wakeup_type at91_poweroff_get_wakeup_mode(struct device_node *np)
+{
+ const char *pm;
+ int err, i;
+
+ err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
+ if (err < 0)
+ return AT91_SHDW_WKMODE0_ANYLEVEL;
+
+ for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
+ if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
+ return i;
+
+ return -ENODEV;
+}
+
+static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ enum wakeup_type wakeup_mode;
+ u32 mode = 0, tmp;
+
+ wakeup_mode = at91_poweroff_get_wakeup_mode(np);
+ if (wakeup_mode < 0) {
+ dev_warn(&pdev->dev, "shdwc unknown wakeup mode\n");
+ return;
+ }
+
+ if (!of_property_read_u32(np, "atmel,wakeup-counter", &tmp)) {
+ if (tmp > AT91_SHDW_CPTWK0_MAX) {
+ dev_warn(&pdev->dev,
+ "shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
+ tmp, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
+ tmp = AT91_SHDW_CPTWK0_MAX;
+ }
+ mode |= AT91_SHDW_CPTWK0_(tmp);
+ }
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
+ mode |= AT91_SHDW_RTCWKEN;
+
+ if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
+ mode |= AT91_SHDW_RTTWKEN;
+
+ writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
+}
+
+static int at91_poweroff_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_shdwc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_shdwc_base);
+ }
+
+ at91_wakeup_status();
+
+ if (pdev->dev.of_node)
+ at91_poweroff_dt_set_wakeup_mode(pdev);
+
+ pm_power_off = at91_poweroff;
+
+ return 0;
+}
+
+static struct of_device_id at91_poweroff_of_match[] = {
+ { .compatible = "atmel,at91sam9260-shdwc", },
+ { .compatible = "atmel,at91sam9rl-shdwc", },
+ { .compatible = "atmel,at91sam9x5-shdwc", },
+ { /*sentinel*/ }
+};
+
+static struct platform_driver at91_poweroff_driver = {
+ .probe = at91_poweroff_probe,
+ .driver = {
+ .name = "at91-poweroff",
+ .of_match_table = at91_poweroff_of_match,
+ },
+};
+module_platform_driver(at91_poweroff_driver);
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
new file mode 100644
index 000000000000..3611806c9cfd
--- /dev/null
+++ b/drivers/power/reset/at91-reset.c
@@ -0,0 +1,252 @@
+/*
+ * Atmel AT91 SAM9 SoCs reset code
+ *
+ * Copyright (C) 2007 Atmel Corporation.
+ * Copyright (C) BitBox Ltd 2010
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
+ * Copyright (C) 2014 Free Electrons
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91sam9_sdramc.h>
+
+#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
+#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
+#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
+#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
+#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
+
+#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
+#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
+#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
+#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
+#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
+#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
+#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
+#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
+
+enum reset_type {
+ RESET_TYPE_GENERAL = 0,
+ RESET_TYPE_WAKEUP = 1,
+ RESET_TYPE_WATCHDOG = 2,
+ RESET_TYPE_SOFTWARE = 3,
+ RESET_TYPE_USER = 4,
+};
+
+static void __iomem *at91_ramc_base[2], *at91_rstc_base;
+
+/*
+* unless the SDRAM is cleanly shutdown before we hit the
+* reset register it can be left driving the data bus and
+* killing the chance of a subsequent boot from NAND
+*/
+static void at91sam9260_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ /* Align to cache lines */
+ ".balign 32\n\t"
+
+ /* Disable SDRAM accesses */
+ "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
+
+ /* Power down SDRAM */
+ "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
+
+ /* Reset CPU */
+ "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ "b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
+}
+
+static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
+{
+ asm volatile(
+ /*
+ * Test wether we have a second RAM controller to care
+ * about.
+ *
+ * First, test that we can dereference the virtual address.
+ */
+ "cmp %1, #0\n\t"
+ "beq 1f\n\t"
+
+ /* Then, test that the RAM controller is enabled */
+ "ldr r0, [%1]\n\t"
+ "cmp r0, #0\n\t"
+
+ /* Align to cache lines */
+ ".balign 32\n\t"
+
+ /* Disable SDRAM0 accesses */
+ "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ /* Power down SDRAM0 */
+ " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ /* Disable SDRAM1 accesses */
+ " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ /* Power down SDRAM1 */
+ " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+ /* Reset CPU */
+ " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
+
+ " b .\n\t"
+ :
+ : "r" (at91_ramc_base[0]),
+ "r" (at91_ramc_base[1]),
+ "r" (at91_rstc_base),
+ "r" (1),
+ "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
+ "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
+ : "r0");
+}
+
+static void __init at91_reset_status(struct platform_device *pdev)
+{
+ u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
+ char *reason;
+
+ switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
+ case RESET_TYPE_GENERAL:
+ reason = "general reset";
+ break;
+ case RESET_TYPE_WAKEUP:
+ reason = "wakeup";
+ break;
+ case RESET_TYPE_WATCHDOG:
+ reason = "watchdog reset";
+ break;
+ case RESET_TYPE_SOFTWARE:
+ reason = "software reset";
+ break;
+ case RESET_TYPE_USER:
+ reason = "user reset";
+ break;
+ default:
+ reason = "unknown reset";
+ break;
+ }
+
+ pr_info("AT91: Starting after %s\n", reason);
+}
+
+static struct of_device_id at91_ramc_of_match[] = {
+ { .compatible = "atmel,at91sam9260-sdramc", },
+ { .compatible = "atmel,at91sam9g45-ddramc", },
+ { .compatible = "atmel,sama5d3-ddramc", },
+ { /* sentinel */ }
+};
+
+static struct of_device_id at91_reset_of_match[] = {
+ { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
+ { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static int at91_reset_of_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct device_node *np;
+ int idx = 0;
+
+ at91_rstc_base = of_iomap(pdev->dev.of_node, 0);
+ if (!at91_rstc_base) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return -ENODEV;
+ }
+
+ for_each_matching_node(np, at91_ramc_of_match) {
+ at91_ramc_base[idx] = of_iomap(np, 0);
+ if (!at91_ramc_base[idx]) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return -ENODEV;
+ }
+ idx++;
+ }
+
+ match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
+ arm_pm_restart = match->data;
+
+ return 0;
+}
+
+static int at91_reset_platform_probe(struct platform_device *pdev)
+{
+ const struct platform_device_id *match;
+ struct resource *res;
+ int idx = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(at91_rstc_base)) {
+ dev_err(&pdev->dev, "Could not map reset controller address\n");
+ return PTR_ERR(at91_rstc_base);
+ }
+
+ for (idx = 0; idx < 2; idx++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
+ at91_ramc_base[idx] = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (IS_ERR(at91_ramc_base[idx])) {
+ dev_err(&pdev->dev, "Could not map ram controller address\n");
+ return PTR_ERR(at91_ramc_base[idx]);
+ }
+ }
+
+ match = platform_get_device_id(pdev);
+ arm_pm_restart = (void (*)(enum reboot_mode, const char*))
+ match->driver_data;
+
+ return 0;
+}
+
+static int at91_reset_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (pdev->dev.of_node)
+ ret = at91_reset_of_probe(pdev);
+ else
+ ret = at91_reset_platform_probe(pdev);
+
+ if (ret)
+ return ret;
+
+ at91_reset_status(pdev);
+
+ return 0;
+}
+
+static struct platform_device_id at91_reset_plat_match[] = {
+ { "at91-sam9260-reset", (unsigned long)at91sam9260_restart },
+ { "at91-sam9g45-reset", (unsigned long)at91sam9g45_restart },
+ { /* sentinel */ }
+};
+
+static struct platform_driver at91_reset_driver = {
+ .probe = at91_reset_probe,
+ .driver = {
+ .name = "at91-reset",
+ .of_match_table = at91_reset_of_match,
+ },
+ .id_table = at91_reset_plat_match,
+};
+module_platform_driver(at91_reset_driver);