diff options
author | Olof Johansson <olof@lixom.net> | 2017-04-19 10:03:33 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2017-04-19 10:03:33 -0400 |
commit | 1bbecc8cd0a4192ec2a30f6cb3e6f4bd166f576a (patch) | |
tree | b02abf10a7aad5eccbaa9d2d586ddeaeca2a75f6 | |
parent | d7718c147a89783ec3bf1735f724ca32174393dd (diff) | |
parent | b32de9dd38fcf9063e993dcdd64cc64ad344d3ac (diff) |
Merge tag 'at91-ab-4.12-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux into next/soc
SoC for 4.12:
- huge PM cleanup
- Move SoC detection to its own driver
* tag 'at91-ab-4.12-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
ARM: at91: move SoC detection to its own driver
ARM: at91: pm: correct typo
ARM: at91: pm: Remove at91_pm_set_standby
ARM: at91: pm: Merge all at91sam9*_pm_init
ARM: at91: pm: Tie the USB clock mask to the pmc
ARM: at91: pm: Tie the memory controller type to the ramc id
ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories.
ARM: at91: pm: Simplify at91rm9200_standby
ARM: at91: pm: Use struct at91_pm_data in pm_suspend.S
ARM: at91: pm: Move global variables into at91_pm_data
ARM: at91: pm: Move at91_ramc_read/write to pm.c
ARM: at91: pm: Cleanup headers
MAINTAINERS: Add memory drivers to AT91 entry
MAINTAINERS: Update AT91 entry
ARM: at91: pm: cpu_idle: switch DDR to power-down mode
Revert "ARM: at91/dt: sama5d2: Use new compatible for ohci node"
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/sama5d2.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile | 34 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9.c | 91 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm.c | 215 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm_data-offsets.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm_suspend.S | 31 | ||||
-rw-r--r-- | arch/arm/mach-at91/sama5.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-at91/soc.c | 142 | ||||
-rw-r--r-- | drivers/soc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/atmel/Kconfig | 6 | ||||
-rw-r--r-- | drivers/soc/atmel/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/atmel/soc.c | 231 | ||||
-rw-r--r-- | drivers/soc/atmel/soc.h (renamed from arch/arm/mach-at91/soc.h) | 0 |
18 files changed, 433 insertions, 436 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8cd40d7063b2..f79067d79dfc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1104,7 +1104,6 @@ F: drivers/*/*aspeed* | |||
1104 | ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT | 1104 | ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT |
1105 | M: Nicolas Ferre <nicolas.ferre@microchip.com> | 1105 | M: Nicolas Ferre <nicolas.ferre@microchip.com> |
1106 | M: Alexandre Belloni <alexandre.belloni@free-electrons.com> | 1106 | M: Alexandre Belloni <alexandre.belloni@free-electrons.com> |
1107 | M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com> | ||
1108 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 1107 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
1109 | W: http://www.linux4sam.org | 1108 | W: http://www.linux4sam.org |
1110 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git | 1109 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git |
@@ -1116,6 +1115,7 @@ F: arch/arm/boot/dts/at91*.dtsi | |||
1116 | F: arch/arm/boot/dts/sama*.dts | 1115 | F: arch/arm/boot/dts/sama*.dts |
1117 | F: arch/arm/boot/dts/sama*.dtsi | 1116 | F: arch/arm/boot/dts/sama*.dtsi |
1118 | F: arch/arm/include/debug/at91.S | 1117 | F: arch/arm/include/debug/at91.S |
1118 | F: drivers/memory/atmel* | ||
1119 | 1119 | ||
1120 | ARM/ATMEL AT91 Clock Support | 1120 | ARM/ATMEL AT91 Clock Support |
1121 | M: Boris Brezillon <boris.brezillon@free-electrons.com> | 1121 | M: Boris Brezillon <boris.brezillon@free-electrons.com> |
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 22332be72140..528b4e9c6d3d 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi | |||
@@ -266,7 +266,7 @@ | |||
266 | }; | 266 | }; |
267 | 267 | ||
268 | usb1: ohci@00400000 { | 268 | usb1: ohci@00400000 { |
269 | compatible = "atmel,sama5d2-ohci", "usb-ohci"; | 269 | compatible = "atmel,at91rm9200-ohci", "usb-ohci"; |
270 | reg = <0x00400000 0x100000>; | 270 | reg = <0x00400000 0x100000>; |
271 | interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; | 271 | interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; |
272 | clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; | 272 | clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; |
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index c5bbf8bb8c0f..cfd8f60a9268 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -1,7 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | obj-y := soc.o | ||
5 | 4 | ||
6 | # CPU-specific support | 5 | # CPU-specific support |
7 | obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o | 6 | obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o |
@@ -18,3 +17,36 @@ endif | |||
18 | ifeq ($(CONFIG_PM_DEBUG),y) | 17 | ifeq ($(CONFIG_PM_DEBUG),y) |
19 | CFLAGS_pm.o += -DDEBUG | 18 | CFLAGS_pm.o += -DDEBUG |
20 | endif | 19 | endif |
20 | |||
21 | # Default sed regexp - multiline due to syntax constraints | ||
22 | define sed-y | ||
23 | "/^->/{s:->#\(.*\):/* \1 */:; \ | ||
24 | s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ | ||
25 | s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ | ||
26 | s:->::; p;}" | ||
27 | endef | ||
28 | |||
29 | # Use filechk to avoid rebuilds when a header changes, but the resulting file | ||
30 | # does not | ||
31 | define filechk_offsets | ||
32 | (set -e; \ | ||
33 | echo "#ifndef $2"; \ | ||
34 | echo "#define $2"; \ | ||
35 | echo "/*"; \ | ||
36 | echo " * DO NOT MODIFY."; \ | ||
37 | echo " *"; \ | ||
38 | echo " * This file was generated by Kbuild"; \ | ||
39 | echo " */"; \ | ||
40 | echo ""; \ | ||
41 | sed -ne $(sed-y); \ | ||
42 | echo ""; \ | ||
43 | echo "#endif" ) | ||
44 | endef | ||
45 | |||
46 | arch/arm/mach-at91/pm_data-offsets.s: arch/arm/mach-at91/pm_data-offsets.c | ||
47 | $(call if_changed_dep,cc_s_c) | ||
48 | |||
49 | include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE | ||
50 | $(call filechk,offsets,__PM_DATA_OFFSETS_H__) | ||
51 | |||
52 | arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h | ||
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index d068ec3cd1f6..656ad409a253 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c | |||
@@ -14,23 +14,10 @@ | |||
14 | #include <asm/mach/arch.h> | 14 | #include <asm/mach/arch.h> |
15 | 15 | ||
16 | #include "generic.h" | 16 | #include "generic.h" |
17 | #include "soc.h" | ||
18 | |||
19 | static const struct at91_soc rm9200_socs[] = { | ||
20 | AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), | ||
21 | { /* sentinel */ }, | ||
22 | }; | ||
23 | 17 | ||
24 | static void __init at91rm9200_dt_device_init(void) | 18 | static void __init at91rm9200_dt_device_init(void) |
25 | { | 19 | { |
26 | struct soc_device *soc; | 20 | of_platform_default_populate(NULL, NULL, NULL); |
27 | struct device *soc_dev = NULL; | ||
28 | |||
29 | soc = at91_soc_init(rm9200_socs); | ||
30 | if (soc != NULL) | ||
31 | soc_dev = soc_device_to_device(soc); | ||
32 | |||
33 | of_platform_default_populate(NULL, NULL, soc_dev); | ||
34 | 21 | ||
35 | at91rm9200_pm_init(); | 22 | at91rm9200_pm_init(); |
36 | } | 23 | } |
diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c index ba28e9cc584d..3dbdef4d3cbf 100644 --- a/arch/arm/mach-at91/at91sam9.c +++ b/arch/arm/mach-at91/at91sam9.c | |||
@@ -14,60 +14,12 @@ | |||
14 | #include <asm/system_misc.h> | 14 | #include <asm/system_misc.h> |
15 | 15 | ||
16 | #include "generic.h" | 16 | #include "generic.h" |
17 | #include "soc.h" | ||
18 | 17 | ||
19 | static const struct at91_soc at91sam9_socs[] = { | 18 | static void __init at91sam9_init(void) |
20 | AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL), | ||
21 | AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL), | ||
22 | AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL), | ||
23 | AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL), | ||
24 | AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL), | ||
25 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH, | ||
26 | "at91sam9m11", "at91sam9g45"), | ||
27 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH, | ||
28 | "at91sam9m10", "at91sam9g45"), | ||
29 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH, | ||
30 | "at91sam9g46", "at91sam9g45"), | ||
31 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH, | ||
32 | "at91sam9g45", "at91sam9g45"), | ||
33 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH, | ||
34 | "at91sam9g15", "at91sam9x5"), | ||
35 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH, | ||
36 | "at91sam9g35", "at91sam9x5"), | ||
37 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH, | ||
38 | "at91sam9x35", "at91sam9x5"), | ||
39 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH, | ||
40 | "at91sam9g25", "at91sam9x5"), | ||
41 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH, | ||
42 | "at91sam9x25", "at91sam9x5"), | ||
43 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH, | ||
44 | "at91sam9cn12", "at91sam9n12"), | ||
45 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH, | ||
46 | "at91sam9n12", "at91sam9n12"), | ||
47 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH, | ||
48 | "at91sam9cn11", "at91sam9n12"), | ||
49 | AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), | ||
50 | AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), | ||
51 | AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), | ||
52 | { /* sentinel */ }, | ||
53 | }; | ||
54 | |||
55 | static void __init at91sam9_common_init(void) | ||
56 | { | 19 | { |
57 | struct soc_device *soc; | 20 | of_platform_default_populate(NULL, NULL, NULL); |
58 | struct device *soc_dev = NULL; | ||
59 | |||
60 | soc = at91_soc_init(at91sam9_socs); | ||
61 | if (soc != NULL) | ||
62 | soc_dev = soc_device_to_device(soc); | ||
63 | 21 | ||
64 | of_platform_default_populate(NULL, NULL, soc_dev); | 22 | at91sam9_pm_init(); |
65 | } | ||
66 | |||
67 | static void __init at91sam9_dt_device_init(void) | ||
68 | { | ||
69 | at91sam9_common_init(); | ||
70 | at91sam9260_pm_init(); | ||
71 | } | 23 | } |
72 | 24 | ||
73 | static const char *const at91_dt_board_compat[] __initconst = { | 25 | static const char *const at91_dt_board_compat[] __initconst = { |
@@ -77,41 +29,6 @@ static const char *const at91_dt_board_compat[] __initconst = { | |||
77 | 29 | ||
78 | DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9") | 30 | DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9") |
79 | /* Maintainer: Atmel */ | 31 | /* Maintainer: Atmel */ |
80 | .init_machine = at91sam9_dt_device_init, | 32 | .init_machine = at91sam9_init, |
81 | .dt_compat = at91_dt_board_compat, | 33 | .dt_compat = at91_dt_board_compat, |
82 | MACHINE_END | 34 | MACHINE_END |
83 | |||
84 | static void __init at91sam9g45_dt_device_init(void) | ||
85 | { | ||
86 | at91sam9_common_init(); | ||
87 | at91sam9g45_pm_init(); | ||
88 | } | ||
89 | |||
90 | static const char *const at91sam9g45_board_compat[] __initconst = { | ||
91 | "atmel,at91sam9g45", | ||
92 | NULL | ||
93 | }; | ||
94 | |||
95 | DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45") | ||
96 | /* Maintainer: Atmel */ | ||
97 | .init_machine = at91sam9g45_dt_device_init, | ||
98 | .dt_compat = at91sam9g45_board_compat, | ||
99 | MACHINE_END | ||
100 | |||
101 | static void __init at91sam9x5_dt_device_init(void) | ||
102 | { | ||
103 | at91sam9_common_init(); | ||
104 | at91sam9x5_pm_init(); | ||
105 | } | ||
106 | |||
107 | static const char *const at91sam9x5_board_compat[] __initconst = { | ||
108 | "atmel,at91sam9x5", | ||
109 | "atmel,at91sam9n12", | ||
110 | NULL | ||
111 | }; | ||
112 | |||
113 | DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9") | ||
114 | /* Maintainer: Atmel */ | ||
115 | .init_machine = at91sam9x5_dt_device_init, | ||
116 | .dt_compat = at91sam9x5_board_compat, | ||
117 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 28ca57a2060f..f1ead0f13c19 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
@@ -13,15 +13,11 @@ | |||
13 | 13 | ||
14 | #ifdef CONFIG_PM | 14 | #ifdef CONFIG_PM |
15 | extern void __init at91rm9200_pm_init(void); | 15 | extern void __init at91rm9200_pm_init(void); |
16 | extern void __init at91sam9260_pm_init(void); | 16 | extern void __init at91sam9_pm_init(void); |
17 | extern void __init at91sam9g45_pm_init(void); | ||
18 | extern void __init at91sam9x5_pm_init(void); | ||
19 | extern void __init sama5_pm_init(void); | 17 | extern void __init sama5_pm_init(void); |
20 | #else | 18 | #else |
21 | static inline void __init at91rm9200_pm_init(void) { } | 19 | static inline void __init at91rm9200_pm_init(void) { } |
22 | static inline void __init at91sam9260_pm_init(void) { } | 20 | static inline void __init at91sam9_pm_init(void) { } |
23 | static inline void __init at91sam9g45_pm_init(void) { } | ||
24 | static inline void __init at91sam9x5_pm_init(void) { } | ||
25 | static inline void __init sama5_pm_init(void) { } | 21 | static inline void __init sama5_pm_init(void) { } |
26 | #endif | 22 | #endif |
27 | 23 | ||
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 3d89b7905bd9..2cd27c830ab6 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
@@ -10,35 +10,22 @@ | |||
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/suspend.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/proc_fs.h> | ||
17 | #include <linux/genalloc.h> | 13 | #include <linux/genalloc.h> |
18 | #include <linux/interrupt.h> | 14 | #include <linux/io.h> |
19 | #include <linux/sysfs.h> | 15 | #include <linux/of_address.h> |
20 | #include <linux/module.h> | ||
21 | #include <linux/of.h> | 16 | #include <linux/of.h> |
22 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
23 | #include <linux/of_address.h> | 18 | #include <linux/suspend.h> |
24 | #include <linux/platform_device.h> | 19 | |
25 | #include <linux/platform_data/atmel.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/clk/at91_pmc.h> | 20 | #include <linux/clk/at91_pmc.h> |
28 | 21 | ||
29 | #include <asm/irq.h> | ||
30 | #include <linux/atomic.h> | ||
31 | #include <asm/mach/time.h> | ||
32 | #include <asm/mach/irq.h> | ||
33 | #include <asm/fncpy.h> | ||
34 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/fncpy.h> | ||
35 | #include <asm/system_misc.h> | 24 | #include <asm/system_misc.h> |
36 | 25 | ||
37 | #include "generic.h" | 26 | #include "generic.h" |
38 | #include "pm.h" | 27 | #include "pm.h" |
39 | 28 | ||
40 | static void __iomem *pmc; | ||
41 | |||
42 | /* | 29 | /* |
43 | * FIXME: this is needed to communicate between the pinctrl driver and | 30 | * FIXME: this is needed to communicate between the pinctrl driver and |
44 | * the PM implementation in the machine. Possibly part of the PM | 31 | * the PM implementation in the machine. Possibly part of the PM |
@@ -50,12 +37,13 @@ extern void at91_pinctrl_gpio_suspend(void); | |||
50 | extern void at91_pinctrl_gpio_resume(void); | 37 | extern void at91_pinctrl_gpio_resume(void); |
51 | #endif | 38 | #endif |
52 | 39 | ||
53 | static struct { | 40 | static struct at91_pm_data pm_data; |
54 | unsigned long uhp_udp_mask; | ||
55 | int memctrl; | ||
56 | } at91_pm_data; | ||
57 | 41 | ||
58 | static void __iomem *at91_ramc_base[2]; | 42 | #define at91_ramc_read(id, field) \ |
43 | __raw_readl(pm_data.ramc[id] + field) | ||
44 | |||
45 | #define at91_ramc_write(id, field, value) \ | ||
46 | __raw_writel(value, pm_data.ramc[id] + field) | ||
59 | 47 | ||
60 | static int at91_pm_valid_state(suspend_state_t state) | 48 | static int at91_pm_valid_state(suspend_state_t state) |
61 | { | 49 | { |
@@ -91,10 +79,10 @@ static int at91_pm_verify_clocks(void) | |||
91 | unsigned long scsr; | 79 | unsigned long scsr; |
92 | int i; | 80 | int i; |
93 | 81 | ||
94 | scsr = readl(pmc + AT91_PMC_SCSR); | 82 | scsr = readl(pm_data.pmc + AT91_PMC_SCSR); |
95 | 83 | ||
96 | /* USB must not be using PLLB */ | 84 | /* USB must not be using PLLB */ |
97 | if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { | 85 | if ((scsr & pm_data.uhp_udp_mask) != 0) { |
98 | pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); | 86 | pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); |
99 | return 0; | 87 | return 0; |
100 | } | 88 | } |
@@ -105,7 +93,7 @@ static int at91_pm_verify_clocks(void) | |||
105 | 93 | ||
106 | if ((scsr & (AT91_PMC_PCK0 << i)) == 0) | 94 | if ((scsr & (AT91_PMC_PCK0 << i)) == 0) |
107 | continue; | 95 | continue; |
108 | css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; | 96 | css = readl(pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; |
109 | if (css != AT91_PMC_CSS_SLOW) { | 97 | if (css != AT91_PMC_CSS_SLOW) { |
110 | pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); | 98 | pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); |
111 | return 0; | 99 | return 0; |
@@ -131,25 +119,18 @@ int at91_suspend_entering_slow_clock(void) | |||
131 | } | 119 | } |
132 | EXPORT_SYMBOL(at91_suspend_entering_slow_clock); | 120 | EXPORT_SYMBOL(at91_suspend_entering_slow_clock); |
133 | 121 | ||
134 | static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0, | 122 | static void (*at91_suspend_sram_fn)(struct at91_pm_data *); |
135 | void __iomem *ramc1, int memctrl); | 123 | extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data); |
136 | |||
137 | extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0, | ||
138 | void __iomem *ramc1, int memctrl); | ||
139 | extern u32 at91_pm_suspend_in_sram_sz; | 124 | extern u32 at91_pm_suspend_in_sram_sz; |
140 | 125 | ||
141 | static void at91_pm_suspend(suspend_state_t state) | 126 | static void at91_pm_suspend(suspend_state_t state) |
142 | { | 127 | { |
143 | unsigned int pm_data = at91_pm_data.memctrl; | 128 | pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0; |
144 | |||
145 | pm_data |= (state == PM_SUSPEND_MEM) ? | ||
146 | AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; | ||
147 | 129 | ||
148 | flush_cache_all(); | 130 | flush_cache_all(); |
149 | outer_disable(); | 131 | outer_disable(); |
150 | 132 | ||
151 | at91_suspend_sram_fn(pmc, at91_ramc_base[0], | 133 | at91_suspend_sram_fn(&pm_data); |
152 | at91_ramc_base[1], pm_data); | ||
153 | 134 | ||
154 | outer_resume(); | 135 | outer_resume(); |
155 | } | 136 | } |
@@ -224,12 +205,6 @@ static struct platform_device at91_cpuidle_device = { | |||
224 | .name = "cpuidle-at91", | 205 | .name = "cpuidle-at91", |
225 | }; | 206 | }; |
226 | 207 | ||
227 | static void at91_pm_set_standby(void (*at91_standby)(void)) | ||
228 | { | ||
229 | if (at91_standby) | ||
230 | at91_cpuidle_device.dev.platform_data = at91_standby; | ||
231 | } | ||
232 | |||
233 | /* | 208 | /* |
234 | * The AT91RM9200 goes into self-refresh mode with this command, and will | 209 | * The AT91RM9200 goes into self-refresh mode with this command, and will |
235 | * terminate self-refresh automatically on the next SDRAM access. | 210 | * terminate self-refresh automatically on the next SDRAM access. |
@@ -241,20 +216,15 @@ static void at91_pm_set_standby(void (*at91_standby)(void)) | |||
241 | */ | 216 | */ |
242 | static void at91rm9200_standby(void) | 217 | static void at91rm9200_standby(void) |
243 | { | 218 | { |
244 | u32 lpr = at91_ramc_read(0, AT91_MC_SDRAMC_LPR); | ||
245 | |||
246 | asm volatile( | 219 | asm volatile( |
247 | "b 1f\n\t" | 220 | "b 1f\n\t" |
248 | ".align 5\n\t" | 221 | ".align 5\n\t" |
249 | "1: mcr p15, 0, %0, c7, c10, 4\n\t" | 222 | "1: mcr p15, 0, %0, c7, c10, 4\n\t" |
250 | " str %0, [%1, %2]\n\t" | 223 | " str %2, [%1, %3]\n\t" |
251 | " str %3, [%1, %4]\n\t" | ||
252 | " mcr p15, 0, %0, c7, c0, 4\n\t" | 224 | " mcr p15, 0, %0, c7, c0, 4\n\t" |
253 | " str %5, [%1, %2]" | ||
254 | : | 225 | : |
255 | : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91_MC_SDRAMC_LPR), | 226 | : "r" (0), "r" (pm_data.ramc[0]), |
256 | "r" (1), "r" (AT91_MC_SDRAMC_SRR), | 227 | "r" (1), "r" (AT91_MC_SDRAMC_SRR)); |
257 | "r" (lpr)); | ||
258 | } | 228 | } |
259 | 229 | ||
260 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to | 230 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to |
@@ -265,12 +235,27 @@ static void at91_ddr_standby(void) | |||
265 | /* Those two values allow us to delay self-refresh activation | 235 | /* Those two values allow us to delay self-refresh activation |
266 | * to the maximum. */ | 236 | * to the maximum. */ |
267 | u32 lpr0, lpr1 = 0; | 237 | u32 lpr0, lpr1 = 0; |
238 | u32 mdr, saved_mdr0, saved_mdr1 = 0; | ||
268 | u32 saved_lpr0, saved_lpr1 = 0; | 239 | u32 saved_lpr0, saved_lpr1 = 0; |
269 | 240 | ||
270 | if (at91_ramc_base[1]) { | 241 | /* LPDDR1 --> force DDR2 mode during self-refresh */ |
242 | saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR); | ||
243 | if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) { | ||
244 | mdr = saved_mdr0 & ~AT91_DDRSDRC_MD; | ||
245 | mdr |= AT91_DDRSDRC_MD_DDR2; | ||
246 | at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr); | ||
247 | } | ||
248 | |||
249 | if (pm_data.ramc[1]) { | ||
271 | saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); | 250 | saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); |
272 | lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; | 251 | lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; |
273 | lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; | 252 | lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; |
253 | saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR); | ||
254 | if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) { | ||
255 | mdr = saved_mdr1 & ~AT91_DDRSDRC_MD; | ||
256 | mdr |= AT91_DDRSDRC_MD_DDR2; | ||
257 | at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr); | ||
258 | } | ||
274 | } | 259 | } |
275 | 260 | ||
276 | saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); | 261 | saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); |
@@ -279,14 +264,33 @@ static void at91_ddr_standby(void) | |||
279 | 264 | ||
280 | /* self-refresh mode now */ | 265 | /* self-refresh mode now */ |
281 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); | 266 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); |
282 | if (at91_ramc_base[1]) | 267 | if (pm_data.ramc[1]) |
283 | at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); | 268 | at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); |
284 | 269 | ||
285 | cpu_do_idle(); | 270 | cpu_do_idle(); |
286 | 271 | ||
272 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0); | ||
287 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); | 273 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); |
288 | if (at91_ramc_base[1]) | 274 | if (pm_data.ramc[1]) { |
275 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1); | ||
289 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); | 276 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); |
277 | } | ||
278 | } | ||
279 | |||
280 | static void sama5d3_ddr_standby(void) | ||
281 | { | ||
282 | u32 lpr0; | ||
283 | u32 saved_lpr0; | ||
284 | |||
285 | saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); | ||
286 | lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; | ||
287 | lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN; | ||
288 | |||
289 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); | ||
290 | |||
291 | cpu_do_idle(); | ||
292 | |||
293 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); | ||
290 | } | 294 | } |
291 | 295 | ||
292 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to | 296 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to |
@@ -297,7 +301,7 @@ static void at91sam9_sdram_standby(void) | |||
297 | u32 lpr0, lpr1 = 0; | 301 | u32 lpr0, lpr1 = 0; |
298 | u32 saved_lpr0, saved_lpr1 = 0; | 302 | u32 saved_lpr0, saved_lpr1 = 0; |
299 | 303 | ||
300 | if (at91_ramc_base[1]) { | 304 | if (pm_data.ramc[1]) { |
301 | saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); | 305 | saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); |
302 | lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; | 306 | lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; |
303 | lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; | 307 | lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; |
@@ -309,21 +313,33 @@ static void at91sam9_sdram_standby(void) | |||
309 | 313 | ||
310 | /* self-refresh mode now */ | 314 | /* self-refresh mode now */ |
311 | at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); | 315 | at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); |
312 | if (at91_ramc_base[1]) | 316 | if (pm_data.ramc[1]) |
313 | at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); | 317 | at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); |
314 | 318 | ||
315 | cpu_do_idle(); | 319 | cpu_do_idle(); |
316 | 320 | ||
317 | at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); | 321 | at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); |
318 | if (at91_ramc_base[1]) | 322 | if (pm_data.ramc[1]) |
319 | at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); | 323 | at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); |
320 | } | 324 | } |
321 | 325 | ||
326 | struct ramc_info { | ||
327 | void (*idle)(void); | ||
328 | unsigned int memctrl; | ||
329 | }; | ||
330 | |||
331 | static const struct ramc_info ramc_infos[] __initconst = { | ||
332 | { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC}, | ||
333 | { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC}, | ||
334 | { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, | ||
335 | { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, | ||
336 | }; | ||
337 | |||
322 | static const struct of_device_id const ramc_ids[] __initconst = { | 338 | static const struct of_device_id const ramc_ids[] __initconst = { |
323 | { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, | 339 | { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] }, |
324 | { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, | 340 | { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] }, |
325 | { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, | 341 | { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] }, |
326 | { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, | 342 | { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] }, |
327 | { /*sentinel*/ } | 343 | { /*sentinel*/ } |
328 | }; | 344 | }; |
329 | 345 | ||
@@ -332,15 +348,18 @@ static __init void at91_dt_ramc(void) | |||
332 | struct device_node *np; | 348 | struct device_node *np; |
333 | const struct of_device_id *of_id; | 349 | const struct of_device_id *of_id; |
334 | int idx = 0; | 350 | int idx = 0; |
335 | const void *standby = NULL; | 351 | void *standby = NULL; |
352 | const struct ramc_info *ramc; | ||
336 | 353 | ||
337 | for_each_matching_node_and_match(np, ramc_ids, &of_id) { | 354 | for_each_matching_node_and_match(np, ramc_ids, &of_id) { |
338 | at91_ramc_base[idx] = of_iomap(np, 0); | 355 | pm_data.ramc[idx] = of_iomap(np, 0); |
339 | if (!at91_ramc_base[idx]) | 356 | if (!pm_data.ramc[idx]) |
340 | panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); | 357 | panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); |
341 | 358 | ||
359 | ramc = of_id->data; | ||
342 | if (!standby) | 360 | if (!standby) |
343 | standby = of_id->data; | 361 | standby = ramc->idle; |
362 | pm_data.memctrl = ramc->memctrl; | ||
344 | 363 | ||
345 | idx++; | 364 | idx++; |
346 | } | 365 | } |
@@ -353,7 +372,7 @@ static __init void at91_dt_ramc(void) | |||
353 | return; | 372 | return; |
354 | } | 373 | } |
355 | 374 | ||
356 | at91_pm_set_standby(standby); | 375 | at91_cpuidle_device.dev.platform_data = standby; |
357 | } | 376 | } |
358 | 377 | ||
359 | static void at91rm9200_idle(void) | 378 | static void at91rm9200_idle(void) |
@@ -362,12 +381,12 @@ static void at91rm9200_idle(void) | |||
362 | * Disable the processor clock. The processor will be automatically | 381 | * Disable the processor clock. The processor will be automatically |
363 | * re-enabled by an interrupt or by a reset. | 382 | * re-enabled by an interrupt or by a reset. |
364 | */ | 383 | */ |
365 | writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); | 384 | writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); |
366 | } | 385 | } |
367 | 386 | ||
368 | static void at91sam9_idle(void) | 387 | static void at91sam9_idle(void) |
369 | { | 388 | { |
370 | writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); | 389 | writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); |
371 | cpu_do_idle(); | 390 | cpu_do_idle(); |
372 | } | 391 | } |
373 | 392 | ||
@@ -417,31 +436,46 @@ static void __init at91_pm_sram_init(void) | |||
417 | &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); | 436 | &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); |
418 | } | 437 | } |
419 | 438 | ||
439 | struct pmc_info { | ||
440 | unsigned long uhp_udp_mask; | ||
441 | }; | ||
442 | |||
443 | static const struct pmc_info pmc_infos[] __initconst = { | ||
444 | { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP }, | ||
445 | { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP }, | ||
446 | { .uhp_udp_mask = AT91SAM926x_PMC_UHP }, | ||
447 | }; | ||
448 | |||
420 | static const struct of_device_id atmel_pmc_ids[] __initconst = { | 449 | static const struct of_device_id atmel_pmc_ids[] __initconst = { |
421 | { .compatible = "atmel,at91rm9200-pmc" }, | 450 | { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] }, |
422 | { .compatible = "atmel,at91sam9260-pmc" }, | 451 | { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] }, |
423 | { .compatible = "atmel,at91sam9g45-pmc" }, | 452 | { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] }, |
424 | { .compatible = "atmel,at91sam9n12-pmc" }, | 453 | { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] }, |
425 | { .compatible = "atmel,at91sam9x5-pmc" }, | 454 | { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] }, |
426 | { .compatible = "atmel,sama5d3-pmc" }, | 455 | { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] }, |
427 | { .compatible = "atmel,sama5d2-pmc" }, | 456 | { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] }, |
428 | { /* sentinel */ }, | 457 | { /* sentinel */ }, |
429 | }; | 458 | }; |
430 | 459 | ||
431 | static void __init at91_pm_init(void (*pm_idle)(void)) | 460 | static void __init at91_pm_init(void (*pm_idle)(void)) |
432 | { | 461 | { |
433 | struct device_node *pmc_np; | 462 | struct device_node *pmc_np; |
463 | const struct of_device_id *of_id; | ||
464 | const struct pmc_info *pmc; | ||
434 | 465 | ||
435 | if (at91_cpuidle_device.dev.platform_data) | 466 | if (at91_cpuidle_device.dev.platform_data) |
436 | platform_device_register(&at91_cpuidle_device); | 467 | platform_device_register(&at91_cpuidle_device); |
437 | 468 | ||
438 | pmc_np = of_find_matching_node(NULL, atmel_pmc_ids); | 469 | pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id); |
439 | pmc = of_iomap(pmc_np, 0); | 470 | pm_data.pmc = of_iomap(pmc_np, 0); |
440 | if (!pmc) { | 471 | if (!pm_data.pmc) { |
441 | pr_err("AT91: PM not supported, PMC not found\n"); | 472 | pr_err("AT91: PM not supported, PMC not found\n"); |
442 | return; | 473 | return; |
443 | } | 474 | } |
444 | 475 | ||
476 | pmc = of_id->data; | ||
477 | pm_data.uhp_udp_mask = pmc->uhp_udp_mask; | ||
478 | |||
445 | if (pm_idle) | 479 | if (pm_idle) |
446 | arm_pm_idle = pm_idle; | 480 | arm_pm_idle = pm_idle; |
447 | 481 | ||
@@ -462,40 +496,17 @@ void __init at91rm9200_pm_init(void) | |||
462 | */ | 496 | */ |
463 | at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0); | 497 | at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0); |
464 | 498 | ||
465 | at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; | ||
466 | at91_pm_data.memctrl = AT91_MEMCTRL_MC; | ||
467 | |||
468 | at91_pm_init(at91rm9200_idle); | 499 | at91_pm_init(at91rm9200_idle); |
469 | } | 500 | } |
470 | 501 | ||
471 | void __init at91sam9260_pm_init(void) | 502 | void __init at91sam9_pm_init(void) |
472 | { | ||
473 | at91_dt_ramc(); | ||
474 | at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; | ||
475 | at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; | ||
476 | at91_pm_init(at91sam9_idle); | ||
477 | } | ||
478 | |||
479 | void __init at91sam9g45_pm_init(void) | ||
480 | { | ||
481 | at91_dt_ramc(); | ||
482 | at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; | ||
483 | at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; | ||
484 | at91_pm_init(at91sam9_idle); | ||
485 | } | ||
486 | |||
487 | void __init at91sam9x5_pm_init(void) | ||
488 | { | 503 | { |
489 | at91_dt_ramc(); | 504 | at91_dt_ramc(); |
490 | at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; | ||
491 | at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; | ||
492 | at91_pm_init(at91sam9_idle); | 505 | at91_pm_init(at91sam9_idle); |
493 | } | 506 | } |
494 | 507 | ||
495 | void __init sama5_pm_init(void) | 508 | void __init sama5_pm_init(void) |
496 | { | 509 | { |
497 | at91_dt_ramc(); | 510 | at91_dt_ramc(); |
498 | at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; | ||
499 | at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; | ||
500 | at91_pm_init(NULL); | 511 | at91_pm_init(NULL); |
501 | } | 512 | } |
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index bf980c6ef294..fc0f7d048187 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h | |||
@@ -17,24 +17,20 @@ | |||
17 | #include <soc/at91/at91sam9_ddrsdr.h> | 17 | #include <soc/at91/at91sam9_ddrsdr.h> |
18 | #include <soc/at91/at91sam9_sdramc.h> | 18 | #include <soc/at91/at91sam9_sdramc.h> |
19 | 19 | ||
20 | #ifndef __ASSEMBLY__ | ||
21 | #define at91_ramc_read(id, field) \ | ||
22 | __raw_readl(at91_ramc_base[id] + field) | ||
23 | |||
24 | #define at91_ramc_write(id, field, value) \ | ||
25 | __raw_writel(value, at91_ramc_base[id] + field) | ||
26 | #endif | ||
27 | |||
28 | #define AT91_MEMCTRL_MC 0 | 20 | #define AT91_MEMCTRL_MC 0 |
29 | #define AT91_MEMCTRL_SDRAMC 1 | 21 | #define AT91_MEMCTRL_SDRAMC 1 |
30 | #define AT91_MEMCTRL_DDRSDR 2 | 22 | #define AT91_MEMCTRL_DDRSDR 2 |
31 | 23 | ||
32 | #define AT91_PM_MEMTYPE_MASK 0x0f | ||
33 | |||
34 | #define AT91_PM_MODE_OFFSET 4 | ||
35 | #define AT91_PM_MODE_MASK 0x01 | ||
36 | #define AT91_PM_MODE(x) (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET) | ||
37 | |||
38 | #define AT91_PM_SLOW_CLOCK 0x01 | 24 | #define AT91_PM_SLOW_CLOCK 0x01 |
39 | 25 | ||
26 | #ifndef __ASSEMBLY__ | ||
27 | struct at91_pm_data { | ||
28 | void __iomem *pmc; | ||
29 | void __iomem *ramc[2]; | ||
30 | unsigned long uhp_udp_mask; | ||
31 | unsigned int memctrl; | ||
32 | unsigned int mode; | ||
33 | }; | ||
34 | #endif | ||
35 | |||
40 | #endif | 36 | #endif |
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c new file mode 100644 index 000000000000..30302cb16df0 --- /dev/null +++ b/arch/arm/mach-at91/pm_data-offsets.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <linux/stddef.h> | ||
2 | #include <linux/kbuild.h> | ||
3 | #include "pm.h" | ||
4 | |||
5 | int main(void) | ||
6 | { | ||
7 | DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc)); | ||
8 | DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc[0])); | ||
9 | DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1])); | ||
10 | DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl)); | ||
11 | DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode)); | ||
12 | return 0; | ||
13 | } | ||
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index a25defda3d22..96781daa671a 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2006 Savin Zlobec | 4 | * Copyright (C) 2006 Savin Zlobec |
5 | * | 5 | * |
6 | * AT91SAM9 support: | 6 | * AT91SAM9 support: |
7 | * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee | 7 | * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
15 | #include <linux/clk/at91_pmc.h> | 15 | #include <linux/clk/at91_pmc.h> |
16 | #include "pm.h" | 16 | #include "pm.h" |
17 | #include "generated/at91_pm_data-offsets.h" | ||
17 | 18 | ||
18 | #define SRAMC_SELF_FRESH_ACTIVE 0x01 | 19 | #define SRAMC_SELF_FRESH_ACTIVE 0x01 |
19 | #define SRAMC_SELF_FRESH_EXIT 0x00 | 20 | #define SRAMC_SELF_FRESH_EXIT 0x00 |
@@ -72,13 +73,9 @@ tmp2 .req r5 | |||
72 | .arm | 73 | .arm |
73 | 74 | ||
74 | /* | 75 | /* |
75 | * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc, | 76 | * void at91_suspend_sram_fn(struct at91_pm_data*) |
76 | * void __iomem *ramc1, int memctrl) | ||
77 | * @input param: | 77 | * @input param: |
78 | * @r0: base address of AT91_PMC | 78 | * @r0: base address of struct at91_pm_data |
79 | * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS) | ||
80 | * @r2: base address of second SDRAM Controller or 0 if not present | ||
81 | * @r3: pm information | ||
82 | */ | 79 | */ |
83 | /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ | 80 | /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ |
84 | .align 3 | 81 | .align 3 |
@@ -90,16 +87,16 @@ ENTRY(at91_pm_suspend_in_sram) | |||
90 | mov tmp1, #0 | 87 | mov tmp1, #0 |
91 | mcr p15, 0, tmp1, c7, c10, 4 | 88 | mcr p15, 0, tmp1, c7, c10, 4 |
92 | 89 | ||
93 | str r0, .pmc_base | 90 | ldr tmp1, [r0, #PM_DATA_PMC] |
94 | str r1, .sramc_base | 91 | str tmp1, .pmc_base |
95 | str r2, .sramc1_base | 92 | ldr tmp1, [r0, #PM_DATA_RAMC0] |
96 | 93 | str tmp1, .sramc_base | |
97 | and r0, r3, #AT91_PM_MEMTYPE_MASK | 94 | ldr tmp1, [r0, #PM_DATA_RAMC1] |
98 | str r0, .memtype | 95 | str tmp1, .sramc1_base |
99 | 96 | ldr tmp1, [r0, #PM_DATA_MEMCTRL] | |
100 | lsr r0, r3, #AT91_PM_MODE_OFFSET | 97 | str tmp1, .memtype |
101 | and r0, r0, #AT91_PM_MODE_MASK | 98 | ldr tmp1, [r0, #PM_DATA_MODE] |
102 | str r0, .pm_mode | 99 | str tmp1, .pm_mode |
103 | 100 | ||
104 | /* Active the self-refresh mode */ | 101 | /* Active the self-refresh mode */ |
105 | mov r0, #SRAMC_SELF_FRESH_ACTIVE | 102 | mov r0, #SRAMC_SELF_FRESH_ACTIVE |
diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index b272c45b400f..6d157d0ead8e 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c | |||
@@ -15,60 +15,10 @@ | |||
15 | #include <asm/system_misc.h> | 15 | #include <asm/system_misc.h> |
16 | 16 | ||
17 | #include "generic.h" | 17 | #include "generic.h" |
18 | #include "soc.h" | ||
19 | |||
20 | static const struct at91_soc sama5_socs[] = { | ||
21 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, | ||
22 | "sama5d21", "sama5d2"), | ||
23 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, | ||
24 | "sama5d22", "sama5d2"), | ||
25 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, | ||
26 | "sama5d23", "sama5d2"), | ||
27 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, | ||
28 | "sama5d24", "sama5d2"), | ||
29 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, | ||
30 | "sama5d24", "sama5d2"), | ||
31 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, | ||
32 | "sama5d26", "sama5d2"), | ||
33 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, | ||
34 | "sama5d27", "sama5d2"), | ||
35 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, | ||
36 | "sama5d27", "sama5d2"), | ||
37 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, | ||
38 | "sama5d28", "sama5d2"), | ||
39 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, | ||
40 | "sama5d28", "sama5d2"), | ||
41 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, | ||
42 | "sama5d31", "sama5d3"), | ||
43 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, | ||
44 | "sama5d33", "sama5d3"), | ||
45 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH, | ||
46 | "sama5d34", "sama5d3"), | ||
47 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH, | ||
48 | "sama5d35", "sama5d3"), | ||
49 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH, | ||
50 | "sama5d36", "sama5d3"), | ||
51 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH, | ||
52 | "sama5d41", "sama5d4"), | ||
53 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH, | ||
54 | "sama5d42", "sama5d4"), | ||
55 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH, | ||
56 | "sama5d43", "sama5d4"), | ||
57 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, | ||
58 | "sama5d44", "sama5d4"), | ||
59 | { /* sentinel */ }, | ||
60 | }; | ||
61 | 18 | ||
62 | static void __init sama5_dt_device_init(void) | 19 | static void __init sama5_dt_device_init(void) |
63 | { | 20 | { |
64 | struct soc_device *soc; | 21 | of_platform_default_populate(NULL, NULL, NULL); |
65 | struct device *soc_dev = NULL; | ||
66 | |||
67 | soc = at91_soc_init(sama5_socs); | ||
68 | if (soc != NULL) | ||
69 | soc_dev = soc_device_to_device(soc); | ||
70 | |||
71 | of_platform_default_populate(NULL, NULL, soc_dev); | ||
72 | sama5_pm_init(); | 22 | sama5_pm_init(); |
73 | } | 23 | } |
74 | 24 | ||
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c deleted file mode 100644 index c6fda75ddb89..000000000000 --- a/arch/arm/mach-at91/soc.c +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Atmel | ||
3 | * | ||
4 | * Alexandre Belloni <alexandre.belloni@free-electrons.com | ||
5 | * Boris Brezillon <boris.brezillon@free-electrons.com | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "AT91: " fmt | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/sys_soc.h> | ||
21 | |||
22 | #include "soc.h" | ||
23 | |||
24 | #define AT91_DBGU_CIDR 0x40 | ||
25 | #define AT91_DBGU_EXID 0x44 | ||
26 | #define AT91_CHIPID_CIDR 0x00 | ||
27 | #define AT91_CHIPID_EXID 0x04 | ||
28 | #define AT91_CIDR_VERSION(x) ((x) & 0x1f) | ||
29 | #define AT91_CIDR_EXT BIT(31) | ||
30 | #define AT91_CIDR_MATCH_MASK 0x7fffffe0 | ||
31 | |||
32 | static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid) | ||
33 | { | ||
34 | struct device_node *np; | ||
35 | void __iomem *regs; | ||
36 | |||
37 | np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu"); | ||
38 | if (!np) | ||
39 | np = of_find_compatible_node(NULL, NULL, | ||
40 | "atmel,at91sam9260-dbgu"); | ||
41 | if (!np) | ||
42 | return -ENODEV; | ||
43 | |||
44 | regs = of_iomap(np, 0); | ||
45 | of_node_put(np); | ||
46 | |||
47 | if (!regs) { | ||
48 | pr_warn("Could not map DBGU iomem range"); | ||
49 | return -ENXIO; | ||
50 | } | ||
51 | |||
52 | *cidr = readl(regs + AT91_DBGU_CIDR); | ||
53 | *exid = readl(regs + AT91_DBGU_EXID); | ||
54 | |||
55 | iounmap(regs); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) | ||
61 | { | ||
62 | struct device_node *np; | ||
63 | void __iomem *regs; | ||
64 | |||
65 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); | ||
66 | if (!np) | ||
67 | return -ENODEV; | ||
68 | |||
69 | regs = of_iomap(np, 0); | ||
70 | of_node_put(np); | ||
71 | |||
72 | if (!regs) { | ||
73 | pr_warn("Could not map DBGU iomem range"); | ||
74 | return -ENXIO; | ||
75 | } | ||
76 | |||
77 | *cidr = readl(regs + AT91_CHIPID_CIDR); | ||
78 | *exid = readl(regs + AT91_CHIPID_EXID); | ||
79 | |||
80 | iounmap(regs); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | struct soc_device * __init at91_soc_init(const struct at91_soc *socs) | ||
86 | { | ||
87 | struct soc_device_attribute *soc_dev_attr; | ||
88 | const struct at91_soc *soc; | ||
89 | struct soc_device *soc_dev; | ||
90 | u32 cidr, exid; | ||
91 | int ret; | ||
92 | |||
93 | /* | ||
94 | * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more | ||
95 | * in the dbgu device but in the chipid device whose purpose is only | ||
96 | * to expose these two registers. | ||
97 | */ | ||
98 | ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid); | ||
99 | if (ret) | ||
100 | ret = at91_get_cidr_exid_from_chipid(&cidr, &exid); | ||
101 | if (ret) { | ||
102 | if (ret == -ENODEV) | ||
103 | pr_warn("Could not find identification node"); | ||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | for (soc = socs; soc->name; soc++) { | ||
108 | if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) | ||
109 | continue; | ||
110 | |||
111 | if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | if (!soc->name) { | ||
116 | pr_warn("Could not find matching SoC description\n"); | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
121 | if (!soc_dev_attr) | ||
122 | return NULL; | ||
123 | |||
124 | soc_dev_attr->family = soc->family; | ||
125 | soc_dev_attr->soc_id = soc->name; | ||
126 | soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", | ||
127 | AT91_CIDR_VERSION(cidr)); | ||
128 | soc_dev = soc_device_register(soc_dev_attr); | ||
129 | if (IS_ERR(soc_dev)) { | ||
130 | kfree(soc_dev_attr->revision); | ||
131 | kfree(soc_dev_attr); | ||
132 | pr_warn("Could not register SoC device\n"); | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | if (soc->family) | ||
137 | pr_info("Detected SoC family: %s\n", soc->family); | ||
138 | pr_info("Detected SoC: %s, revision %X\n", soc->name, | ||
139 | AT91_CIDR_VERSION(cidr)); | ||
140 | |||
141 | return soc_dev; | ||
142 | } | ||
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index f09023f7ab11..45e5b13a3c02 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | menu "SOC (System On Chip) specific Drivers" | 1 | menu "SOC (System On Chip) specific Drivers" |
2 | 2 | ||
3 | source "drivers/soc/atmel/Kconfig" | ||
3 | source "drivers/soc/bcm/Kconfig" | 4 | source "drivers/soc/bcm/Kconfig" |
4 | source "drivers/soc/fsl/Kconfig" | 5 | source "drivers/soc/fsl/Kconfig" |
5 | source "drivers/soc/mediatek/Kconfig" | 6 | source "drivers/soc/mediatek/Kconfig" |
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 05eae52a30b4..3467de7d3890 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for the Linux Kernel SOC specific device drivers. | 2 | # Makefile for the Linux Kernel SOC specific device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_ARCH_AT91) += atmel/ | ||
5 | obj-y += bcm/ | 6 | obj-y += bcm/ |
6 | obj-$(CONFIG_ARCH_DOVE) += dove/ | 7 | obj-$(CONFIG_ARCH_DOVE) += dove/ |
7 | obj-$(CONFIG_MACH_DOVE) += dove/ | 8 | obj-$(CONFIG_MACH_DOVE) += dove/ |
diff --git a/drivers/soc/atmel/Kconfig b/drivers/soc/atmel/Kconfig new file mode 100644 index 000000000000..6242ebb41abb --- /dev/null +++ b/drivers/soc/atmel/Kconfig | |||
@@ -0,0 +1,6 @@ | |||
1 | config AT91_SOC_ID | ||
2 | bool "SoC bus for Atmel ARM SoCs" | ||
3 | depends on ARCH_AT91 || COMPILE_TEST | ||
4 | default ARCH_AT91 | ||
5 | help | ||
6 | Include support for the SoC bus on the Atmel ARM SoCs. | ||
diff --git a/drivers/soc/atmel/Makefile b/drivers/soc/atmel/Makefile new file mode 100644 index 000000000000..2d92f32e4ea5 --- /dev/null +++ b/drivers/soc/atmel/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_AT91_SOC_ID) += soc.o | |||
diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c new file mode 100644 index 000000000000..4790094b498e --- /dev/null +++ b/drivers/soc/atmel/soc.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Atmel | ||
3 | * | ||
4 | * Alexandre Belloni <alexandre.belloni@free-electrons.com | ||
5 | * Boris Brezillon <boris.brezillon@free-electrons.com | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "AT91: " fmt | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/sys_soc.h> | ||
21 | |||
22 | #include "soc.h" | ||
23 | |||
24 | #define AT91_DBGU_CIDR 0x40 | ||
25 | #define AT91_DBGU_EXID 0x44 | ||
26 | #define AT91_CHIPID_CIDR 0x00 | ||
27 | #define AT91_CHIPID_EXID 0x04 | ||
28 | #define AT91_CIDR_VERSION(x) ((x) & 0x1f) | ||
29 | #define AT91_CIDR_EXT BIT(31) | ||
30 | #define AT91_CIDR_MATCH_MASK 0x7fffffe0 | ||
31 | |||
32 | static const struct at91_soc __initconst socs[] = { | ||
33 | #ifdef CONFIG_SOC_AT91RM9200 | ||
34 | AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), | ||
35 | #endif | ||
36 | #ifdef CONFIG_SOC_AT91SAM9 | ||
37 | AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL), | ||
38 | AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL), | ||
39 | AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL), | ||
40 | AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL), | ||
41 | AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL), | ||
42 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH, | ||
43 | "at91sam9m11", "at91sam9g45"), | ||
44 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH, | ||
45 | "at91sam9m10", "at91sam9g45"), | ||
46 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH, | ||
47 | "at91sam9g46", "at91sam9g45"), | ||
48 | AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH, | ||
49 | "at91sam9g45", "at91sam9g45"), | ||
50 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH, | ||
51 | "at91sam9g15", "at91sam9x5"), | ||
52 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH, | ||
53 | "at91sam9g35", "at91sam9x5"), | ||
54 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH, | ||
55 | "at91sam9x35", "at91sam9x5"), | ||
56 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH, | ||
57 | "at91sam9g25", "at91sam9x5"), | ||
58 | AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH, | ||
59 | "at91sam9x25", "at91sam9x5"), | ||
60 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH, | ||
61 | "at91sam9cn12", "at91sam9n12"), | ||
62 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH, | ||
63 | "at91sam9n12", "at91sam9n12"), | ||
64 | AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH, | ||
65 | "at91sam9cn11", "at91sam9n12"), | ||
66 | AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), | ||
67 | AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), | ||
68 | AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), | ||
69 | #endif | ||
70 | #ifdef CONFIG_SOC_SAMA5 | ||
71 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, | ||
72 | "sama5d21", "sama5d2"), | ||
73 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, | ||
74 | "sama5d22", "sama5d2"), | ||
75 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, | ||
76 | "sama5d23", "sama5d2"), | ||
77 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, | ||
78 | "sama5d24", "sama5d2"), | ||
79 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, | ||
80 | "sama5d24", "sama5d2"), | ||
81 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, | ||
82 | "sama5d26", "sama5d2"), | ||
83 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, | ||
84 | "sama5d27", "sama5d2"), | ||
85 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, | ||
86 | "sama5d27", "sama5d2"), | ||
87 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, | ||
88 | "sama5d28", "sama5d2"), | ||
89 | AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, | ||
90 | "sama5d28", "sama5d2"), | ||
91 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, | ||
92 | "sama5d31", "sama5d3"), | ||
93 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, | ||
94 | "sama5d33", "sama5d3"), | ||
95 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH, | ||
96 | "sama5d34", "sama5d3"), | ||
97 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH, | ||
98 | "sama5d35", "sama5d3"), | ||
99 | AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH, | ||
100 | "sama5d36", "sama5d3"), | ||
101 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH, | ||
102 | "sama5d41", "sama5d4"), | ||
103 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH, | ||
104 | "sama5d42", "sama5d4"), | ||
105 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH, | ||
106 | "sama5d43", "sama5d4"), | ||
107 | AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, | ||
108 | "sama5d44", "sama5d4"), | ||
109 | #endif | ||
110 | { /* sentinel */ }, | ||
111 | }; | ||
112 | |||
113 | static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid) | ||
114 | { | ||
115 | struct device_node *np; | ||
116 | void __iomem *regs; | ||
117 | |||
118 | np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu"); | ||
119 | if (!np) | ||
120 | np = of_find_compatible_node(NULL, NULL, | ||
121 | "atmel,at91sam9260-dbgu"); | ||
122 | if (!np) | ||
123 | return -ENODEV; | ||
124 | |||
125 | regs = of_iomap(np, 0); | ||
126 | of_node_put(np); | ||
127 | |||
128 | if (!regs) { | ||
129 | pr_warn("Could not map DBGU iomem range"); | ||
130 | return -ENXIO; | ||
131 | } | ||
132 | |||
133 | *cidr = readl(regs + AT91_DBGU_CIDR); | ||
134 | *exid = readl(regs + AT91_DBGU_EXID); | ||
135 | |||
136 | iounmap(regs); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) | ||
142 | { | ||
143 | struct device_node *np; | ||
144 | void __iomem *regs; | ||
145 | |||
146 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); | ||
147 | if (!np) | ||
148 | return -ENODEV; | ||
149 | |||
150 | regs = of_iomap(np, 0); | ||
151 | of_node_put(np); | ||
152 | |||
153 | if (!regs) { | ||
154 | pr_warn("Could not map DBGU iomem range"); | ||
155 | return -ENXIO; | ||
156 | } | ||
157 | |||
158 | *cidr = readl(regs + AT91_CHIPID_CIDR); | ||
159 | *exid = readl(regs + AT91_CHIPID_EXID); | ||
160 | |||
161 | iounmap(regs); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | struct soc_device * __init at91_soc_init(const struct at91_soc *socs) | ||
167 | { | ||
168 | struct soc_device_attribute *soc_dev_attr; | ||
169 | const struct at91_soc *soc; | ||
170 | struct soc_device *soc_dev; | ||
171 | u32 cidr, exid; | ||
172 | int ret; | ||
173 | |||
174 | /* | ||
175 | * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more | ||
176 | * in the dbgu device but in the chipid device whose purpose is only | ||
177 | * to expose these two registers. | ||
178 | */ | ||
179 | ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid); | ||
180 | if (ret) | ||
181 | ret = at91_get_cidr_exid_from_chipid(&cidr, &exid); | ||
182 | if (ret) { | ||
183 | if (ret == -ENODEV) | ||
184 | pr_warn("Could not find identification node"); | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | for (soc = socs; soc->name; soc++) { | ||
189 | if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) | ||
190 | continue; | ||
191 | |||
192 | if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) | ||
193 | break; | ||
194 | } | ||
195 | |||
196 | if (!soc->name) { | ||
197 | pr_warn("Could not find matching SoC description\n"); | ||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
202 | if (!soc_dev_attr) | ||
203 | return NULL; | ||
204 | |||
205 | soc_dev_attr->family = soc->family; | ||
206 | soc_dev_attr->soc_id = soc->name; | ||
207 | soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", | ||
208 | AT91_CIDR_VERSION(cidr)); | ||
209 | soc_dev = soc_device_register(soc_dev_attr); | ||
210 | if (IS_ERR(soc_dev)) { | ||
211 | kfree(soc_dev_attr->revision); | ||
212 | kfree(soc_dev_attr); | ||
213 | pr_warn("Could not register SoC device\n"); | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | if (soc->family) | ||
218 | pr_info("Detected SoC family: %s\n", soc->family); | ||
219 | pr_info("Detected SoC: %s, revision %X\n", soc->name, | ||
220 | AT91_CIDR_VERSION(cidr)); | ||
221 | |||
222 | return soc_dev; | ||
223 | } | ||
224 | |||
225 | static int __init atmel_soc_device_init(void) | ||
226 | { | ||
227 | at91_soc_init(socs); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | subsys_initcall(atmel_soc_device_init); | ||
diff --git a/arch/arm/mach-at91/soc.h b/drivers/soc/atmel/soc.h index 228efded5085..228efded5085 100644 --- a/arch/arm/mach-at91/soc.h +++ b/drivers/soc/atmel/soc.h | |||