aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2014-08-25 09:35:26 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2014-08-25 09:35:26 -0400
commite657ce689a85ff1c887b8020282e5b2ab1411ded (patch)
treeb9e9195aeaeb77fc7fa730eac0ce98bcbe267dea
parent39333610ba3b1e076ac1ceccca34de037a413a03 (diff)
parentae499f0fadaf28bf3138676fa2d3f6cf7d57556a (diff)
Merge tag 'at91-drivers-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux
Pull AT91 reset, poweroff and ram drivers from Maxime Ripard: "This tag holds the various new drivers introduced to move code that used to be in mach-at91 over to the proper frameworks. These files are the reboot and poweroff code for all AT91 SoCs but the RM9200, and the ram controller driver is not doing much at the time, except for grabing the RAM clock in order to leave it always enabled." Conflicts: arch/arm/mach-at91/Kconfig
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.txt1
-rw-r--r--arch/arm/mach-at91/Kconfig4
-rw-r--r--arch/arm/mach-at91/setup.c1
-rw-r--r--drivers/clk/at91/clk-system.c8
-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
11 files changed, 551 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index 16f60b41c147..33bcf8b57798 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -61,6 +61,7 @@ RAMC SDRAM/DDR Controller required properties:
61- compatible: Should be "atmel,at91rm9200-sdramc", 61- compatible: Should be "atmel,at91rm9200-sdramc",
62 "atmel,at91sam9260-sdramc", 62 "atmel,at91sam9260-sdramc",
63 "atmel,at91sam9g45-ddramc", 63 "atmel,at91sam9g45-ddramc",
64 "atmel,sama5d3-ddramc",
64- reg: Should contain registers location and length 65- reg: Should contain registers location and length
65 For at91sam9263 and at91sam9g45 you must specify 2 entries. 66 For at91sam9263 and at91sam9g45 you must specify 2 entries.
66 67
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index dd28e1fedbdc..6aa7ab47205e 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -53,6 +53,8 @@ config SOC_AT91SAM9
53 select ATMEL_AIC_IRQ if !OLD_IRQ_AT91 53 select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
54 select CPU_ARM926T 54 select CPU_ARM926T
55 select GENERIC_CLOCKEVENTS 55 select GENERIC_CLOCKEVENTS
56 select MEMORY if USE_OF
57 select ATMEL_SDRAMC if USE_OF
56 58
57config SOC_SAMA5 59config SOC_SAMA5
58 bool 60 bool
@@ -61,6 +63,8 @@ config SOC_SAMA5
61 select CPU_V7 63 select CPU_V7
62 select GENERIC_CLOCKEVENTS 64 select GENERIC_CLOCKEVENTS
63 select USE_OF 65 select USE_OF
66 select MEMORY
67 select ATMEL_SDRAMC
64 68
65menu "Atmel AT91 System-on-Chip" 69menu "Atmel AT91 System-on-Chip"
66 70
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 0bf893a574f9..1174b5fe74d8 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -385,6 +385,7 @@ static struct of_device_id ramc_ids[] = {
385 { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, 385 { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
386 { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, 386 { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
387 { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, 387 { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
388 { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
388 { /*sentinel*/ } 389 { /*sentinel*/ }
389}; 390};
390 391
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,
119 init.ops = &system_ops; 119 init.ops = &system_ops;
120 init.parent_names = &parent_name; 120 init.parent_names = &parent_name;
121 init.num_parents = 1; 121 init.num_parents = 1;
122 /* 122 init.flags = CLK_SET_RATE_PARENT;
123 * CLK_IGNORE_UNUSED is used to avoid ddrck switch off.
124 * TODO : we should implement a driver supporting at91 ddr controller
125 * (see drivers/memory) which would request and enable the ddrck clock.
126 * When this is done we will be able to remove CLK_IGNORE_UNUSED flag.
127 */
128 init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
129 123
130 sys->id = id; 124 sys->id = id;
131 sys->hw.init = &init; 125 sys->hw.init = &init;
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
7 7
8if MEMORY 8if MEMORY
9 9
10config ATMEL_SDRAMC
11 bool "Atmel (Multi-port DDR-)SDRAM Controller"
12 default y
13 depends on ARCH_AT91 && OF
14 help
15 This driver is for Atmel SDRAM Controller or Atmel Multi-port
16 DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
17 Starting with the at91sam9g45, this controller supports SDR, DDR and
18 LP-DDR memories.
19
10config TI_AEMIF 20config TI_AEMIF
11 tristate "Texas Instruments AEMIF driver" 21 tristate "Texas Instruments AEMIF driver"
12 depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF 22 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 @@
5ifeq ($(CONFIG_DDR),y) 5ifeq ($(CONFIG_DDR),y)
6obj-$(CONFIG_OF) += of_memory.o 6obj-$(CONFIG_OF) += of_memory.o
7endif 7endif
8obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
8obj-$(CONFIG_TI_AEMIF) += ti-aemif.o 9obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
9obj-$(CONFIG_TI_EMIF) += emif.o 10obj-$(CONFIG_TI_EMIF) += emif.o
10obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o 11obj-$(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 @@
1/*
2 * Atmel (Multi-port DDR-)SDRAM Controller driver
3 *
4 * Copyright (C) 2014 Atmel
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <linux/clk.h>
21#include <linux/err.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of_platform.h>
25#include <linux/platform_device.h>
26
27struct at91_ramc_caps {
28 bool has_ddrck;
29 bool has_mpddr_clk;
30};
31
32static const struct at91_ramc_caps at91rm9200_caps = { };
33
34static const struct at91_ramc_caps at91sam9g45_caps = {
35 .has_ddrck = 1,
36 .has_mpddr_clk = 0,
37};
38
39static const struct at91_ramc_caps sama5d3_caps = {
40 .has_ddrck = 1,
41 .has_mpddr_clk = 1,
42};
43
44static const struct of_device_id atmel_ramc_of_match[] = {
45 { .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, },
46 { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, },
47 { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, },
48 { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
49 {},
50};
51MODULE_DEVICE_TABLE(of, atmel_ramc_of_match);
52
53static int atmel_ramc_probe(struct platform_device *pdev)
54{
55 const struct of_device_id *match;
56 const struct at91_ramc_caps *caps;
57 struct clk *clk;
58
59 match = of_match_device(atmel_ramc_of_match, &pdev->dev);
60 caps = match->data;
61
62 if (caps->has_ddrck) {
63 clk = devm_clk_get(&pdev->dev, "ddrck");
64 if (IS_ERR(clk))
65 return PTR_ERR(clk);
66 clk_prepare_enable(clk);
67 }
68
69 if (caps->has_mpddr_clk) {
70 clk = devm_clk_get(&pdev->dev, "mpddr");
71 if (IS_ERR(clk)) {
72 pr_err("AT91 RAMC: couldn't get mpddr clock\n");
73 return PTR_ERR(clk);
74 }
75 clk_prepare_enable(clk);
76 }
77
78 return 0;
79}
80
81static struct platform_driver atmel_ramc_driver = {
82 .probe = atmel_ramc_probe,
83 .driver = {
84 .name = "atmel-ramc",
85 .owner = THIS_MODULE,
86 .of_match_table = atmel_ramc_of_match,
87 },
88};
89
90static int __init atmel_ramc_init(void)
91{
92 return platform_driver_register(&atmel_ramc_driver);
93}
94module_init(atmel_ramc_init);
95
96MODULE_LICENSE("GPL v2");
97MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
98MODULE_DESCRIPTION("Atmel (Multi-port DDR-)SDRAM Controller");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523bbebf..c1c046d0464e 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -6,15 +6,33 @@ menuconfig POWER_RESET
6 6
7 Say Y here to enable board reset and power off 7 Say Y here to enable board reset and power off
8 8
9if POWER_RESET
10
9config POWER_RESET_AS3722 11config POWER_RESET_AS3722
10 bool "ams AS3722 power-off driver" 12 bool "ams AS3722 power-off driver"
11 depends on MFD_AS3722 && POWER_RESET 13 depends on MFD_AS3722
12 help 14 help
13 This driver supports turning off board via a ams AS3722 power-off. 15 This driver supports turning off board via a ams AS3722 power-off.
14 16
17config POWER_RESET_AT91_POWEROFF
18 bool "Atmel AT91 poweroff driver"
19 depends on MACH_AT91
20 default SOC_AT91SAM9 || SOC_SAMA5
21 help
22 This driver supports poweroff for Atmel AT91SAM9 and SAMA5
23 SoCs
24
25config POWER_RESET_AT91_RESET
26 bool "Atmel AT91 reset driver"
27 depends on MACH_AT91
28 default SOC_AT91SAM9 || SOC_SAMA5
29 help
30 This driver supports restart for Atmel AT91SAM9 and SAMA5
31 SoCs
32
15config POWER_RESET_AXXIA 33config POWER_RESET_AXXIA
16 bool "LSI Axxia reset driver" 34 bool "LSI Axxia reset driver"
17 depends on POWER_RESET && ARCH_AXXIA 35 depends on ARCH_AXXIA
18 help 36 help
19 This driver supports restart for Axxia SoC. 37 This driver supports restart for Axxia SoC.
20 38
@@ -33,7 +51,7 @@ config POWER_RESET_BRCMSTB
33 51
34config POWER_RESET_GPIO 52config POWER_RESET_GPIO
35 bool "GPIO power-off driver" 53 bool "GPIO power-off driver"
36 depends on OF_GPIO && POWER_RESET 54 depends on OF_GPIO
37 help 55 help
38 This driver supports turning off your board via a GPIO line. 56 This driver supports turning off your board via a GPIO line.
39 If your board needs a GPIO high/low to power down, say Y and 57 If your board needs a GPIO high/low to power down, say Y and
@@ -47,13 +65,13 @@ config POWER_RESET_HISI
47 65
48config POWER_RESET_MSM 66config POWER_RESET_MSM
49 bool "Qualcomm MSM power-off driver" 67 bool "Qualcomm MSM power-off driver"
50 depends on POWER_RESET && ARCH_QCOM 68 depends on ARCH_QCOM
51 help 69 help
52 Power off and restart support for Qualcomm boards. 70 Power off and restart support for Qualcomm boards.
53 71
54config POWER_RESET_QNAP 72config POWER_RESET_QNAP
55 bool "QNAP power-off driver" 73 bool "QNAP power-off driver"
56 depends on OF_GPIO && POWER_RESET && PLAT_ORION 74 depends on OF_GPIO && PLAT_ORION
57 help 75 help
58 This driver supports turning off QNAP NAS devices by sending 76 This driver supports turning off QNAP NAS devices by sending
59 commands to the microcontroller which controls the main power. 77 commands to the microcontroller which controls the main power.
@@ -71,14 +89,13 @@ config POWER_RESET_RESTART
71config POWER_RESET_SUN6I 89config POWER_RESET_SUN6I
72 bool "Allwinner A31 SoC reset driver" 90 bool "Allwinner A31 SoC reset driver"
73 depends on ARCH_SUNXI 91 depends on ARCH_SUNXI
74 depends on POWER_RESET
75 help 92 help
76 Reboot support for the Allwinner A31 SoCs. 93 Reboot support for the Allwinner A31 SoCs.
77 94
78config POWER_RESET_VEXPRESS 95config POWER_RESET_VEXPRESS
79 bool "ARM Versatile Express power-off and reset driver" 96 bool "ARM Versatile Express power-off and reset driver"
80 depends on ARM || ARM64 97 depends on ARM || ARM64
81 depends on POWER_RESET && VEXPRESS_CONFIG 98 depends on VEXPRESS_CONFIG
82 help 99 help
83 Power off and reset support for the ARM Ltd. Versatile 100 Power off and reset support for the ARM Ltd. Versatile
84 Express boards. 101 Express boards.
@@ -86,7 +103,6 @@ config POWER_RESET_VEXPRESS
86config POWER_RESET_XGENE 103config POWER_RESET_XGENE
87 bool "APM SoC X-Gene reset driver" 104 bool "APM SoC X-Gene reset driver"
88 depends on ARM64 105 depends on ARM64
89 depends on POWER_RESET
90 help 106 help
91 Reboot support for the APM SoC X-Gene Eval boards. 107 Reboot support for the APM SoC X-Gene Eval boards.
92 108
@@ -97,3 +113,4 @@ config POWER_RESET_KEYSTONE
97 help 113 help
98 Reboot support for the KEYSTONE SoCs. 114 Reboot support for the KEYSTONE SoCs.
99 115
116endif
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 @@
1obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o 1obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
2obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
3obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
2obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 4obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
3obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o 5obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
4obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 6obj-$(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..40bf42d146f1
--- /dev/null
+++ b/drivers/power/reset/at91-poweroff.c
@@ -0,0 +1,156 @@
1/*
2 * Atmel AT91 SAM9 SoCs reset code
3 *
4 * Copyright (C) 2007 Atmel Corporation.
5 * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
6 * Copyright (C) 2014 Free Electrons
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/io.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/printk.h>
18
19#define AT91_SHDW_CR 0x00 /* Shut Down Control Register */
20#define AT91_SHDW_SHDW BIT(0) /* Shut Down command */
21#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
22
23#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */
24#define AT91_SHDW_WKMODE0 GENMASK(2, 0) /* Wake-up 0 Mode Selection */
25#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */
26#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
27#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
28#define AT91_SHDW_RTTWKEN BIT(16) /* Real Time Timer Wake-up Enable */
29#define AT91_SHDW_RTCWKEN BIT(17) /* Real Time Clock Wake-up Enable */
30
31#define AT91_SHDW_SR 0x08 /* Shut Down Status Register */
32#define AT91_SHDW_WAKEUP0 BIT(0) /* Wake-up 0 Status */
33#define AT91_SHDW_RTTWK BIT(16) /* Real-time Timer Wake-up */
34#define AT91_SHDW_RTCWK BIT(17) /* Real-time Clock Wake-up [SAM9RL] */
35
36enum wakeup_type {
37 AT91_SHDW_WKMODE0_NONE = 0,
38 AT91_SHDW_WKMODE0_HIGH = 1,
39 AT91_SHDW_WKMODE0_LOW = 2,
40 AT91_SHDW_WKMODE0_ANYLEVEL = 3,
41};
42
43static const char *shdwc_wakeup_modes[] = {
44 [AT91_SHDW_WKMODE0_NONE] = "none",
45 [AT91_SHDW_WKMODE0_HIGH] = "high",
46 [AT91_SHDW_WKMODE0_LOW] = "low",
47 [AT91_SHDW_WKMODE0_ANYLEVEL] = "any",
48};
49
50static void __iomem *at91_shdwc_base;
51
52static void __init at91_wakeup_status(void)
53{
54 u32 reg = readl(at91_shdwc_base);
55 char *reason = "unknown";
56
57 /* Simple power-on, just bail out */
58 if (!reg)
59 return;
60
61 if (reg & AT91_SHDW_RTTWK)
62 reason = "RTT";
63 else if (reg & AT91_SHDW_RTCWK)
64 reason = "RTC";
65
66 pr_info("AT91: Wake-Up source: %s\n", reason);
67}
68
69static void at91_poweroff(void)
70{
71 writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, at91_shdwc_base + AT91_SHDW_CR);
72}
73
74const enum wakeup_type at91_poweroff_get_wakeup_mode(struct device_node *np)
75{
76 const char *pm;
77 int err, i;
78
79 err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
80 if (err < 0)
81 return AT91_SHDW_WKMODE0_ANYLEVEL;
82
83 for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
84 if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
85 return i;
86
87 return -ENODEV;
88}
89
90static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
91{
92 struct device_node *np = pdev->dev.of_node;
93 enum wakeup_type wakeup_mode;
94 u32 mode = 0, tmp;
95
96 wakeup_mode = at91_poweroff_get_wakeup_mode(np);
97 if (wakeup_mode < 0) {
98 dev_warn(&pdev->dev, "shdwc unknown wakeup mode\n");
99 return;
100 }
101
102 if (!of_property_read_u32(np, "atmel,wakeup-counter", &tmp)) {
103 if (tmp > AT91_SHDW_CPTWK0_MAX) {
104 dev_warn(&pdev->dev,
105 "shdwc wakeup counter 0x%x > 0x%x reduce it to 0x%x\n",
106 tmp, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
107 tmp = AT91_SHDW_CPTWK0_MAX;
108 }
109 mode |= AT91_SHDW_CPTWK0_(tmp);
110 }
111
112 if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
113 mode |= AT91_SHDW_RTCWKEN;
114
115 if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
116 mode |= AT91_SHDW_RTTWKEN;
117
118 writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR);
119}
120
121static int at91_poweroff_probe(struct platform_device *pdev)
122{
123 struct resource *res;
124
125 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
126 at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res);
127 if (IS_ERR(at91_shdwc_base)) {
128 dev_err(&pdev->dev, "Could not map reset controller address\n");
129 return PTR_ERR(at91_shdwc_base);
130 }
131
132 at91_wakeup_status();
133
134 if (pdev->dev.of_node)
135 at91_poweroff_dt_set_wakeup_mode(pdev);
136
137 pm_power_off = at91_poweroff;
138
139 return 0;
140}
141
142static struct of_device_id at91_poweroff_of_match[] = {
143 { .compatible = "atmel,at91sam9260-shdwc", },
144 { .compatible = "atmel,at91sam9rl-shdwc", },
145 { .compatible = "atmel,at91sam9x5-shdwc", },
146 { /*sentinel*/ }
147};
148
149static struct platform_driver at91_poweroff_driver = {
150 .probe = at91_poweroff_probe,
151 .driver = {
152 .name = "at91-poweroff",
153 .of_match_table = at91_poweroff_of_match,
154 },
155};
156module_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 @@
1/*
2 * Atmel AT91 SAM9 SoCs reset code
3 *
4 * Copyright (C) 2007 Atmel Corporation.
5 * Copyright (C) BitBox Ltd 2010
6 * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
7 * Copyright (C) 2014 Free Electrons
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/io.h>
15#include <linux/module.h>
16#include <linux/of_address.h>
17#include <linux/platform_device.h>
18#include <linux/reboot.h>
19
20#include <asm/system_misc.h>
21
22#include <mach/at91sam9_ddrsdr.h>
23#include <mach/at91sam9_sdramc.h>
24
25#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
26#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
27#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
28#define AT91_RSTC_EXTRST BIT(3) /* External Reset */
29#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
30
31#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
32#define AT91_RSTC_URSTS BIT(0) /* User Reset Status */
33#define AT91_RSTC_RSTTYP GENMASK(10, 8) /* Reset Type */
34#define AT91_RSTC_NRSTL BIT(16) /* NRST Pin Level */
35#define AT91_RSTC_SRCMP BIT(17) /* Software Reset Command in Progress */
36
37#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
38#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
39#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
40#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
41
42enum reset_type {
43 RESET_TYPE_GENERAL = 0,
44 RESET_TYPE_WAKEUP = 1,
45 RESET_TYPE_WATCHDOG = 2,
46 RESET_TYPE_SOFTWARE = 3,
47 RESET_TYPE_USER = 4,
48};
49
50static void __iomem *at91_ramc_base[2], *at91_rstc_base;
51
52/*
53* unless the SDRAM is cleanly shutdown before we hit the
54* reset register it can be left driving the data bus and
55* killing the chance of a subsequent boot from NAND
56*/
57static void at91sam9260_restart(enum reboot_mode mode, const char *cmd)
58{
59 asm volatile(
60 /* Align to cache lines */
61 ".balign 32\n\t"
62
63 /* Disable SDRAM accesses */
64 "str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
65
66 /* Power down SDRAM */
67 "str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
68
69 /* Reset CPU */
70 "str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
71
72 "b .\n\t"
73 :
74 : "r" (at91_ramc_base[0]),
75 "r" (at91_rstc_base),
76 "r" (1),
77 "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
78 "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
79}
80
81static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
82{
83 asm volatile(
84 /*
85 * Test wether we have a second RAM controller to care
86 * about.
87 *
88 * First, test that we can dereference the virtual address.
89 */
90 "cmp %1, #0\n\t"
91 "beq 1f\n\t"
92
93 /* Then, test that the RAM controller is enabled */
94 "ldr r0, [%1]\n\t"
95 "cmp r0, #0\n\t"
96
97 /* Align to cache lines */
98 ".balign 32\n\t"
99
100 /* Disable SDRAM0 accesses */
101 "1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
102 /* Power down SDRAM0 */
103 " str %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
104 /* Disable SDRAM1 accesses */
105 " strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
106 /* Power down SDRAM1 */
107 " strne %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
108 /* Reset CPU */
109 " str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
110
111 " b .\n\t"
112 :
113 : "r" (at91_ramc_base[0]),
114 "r" (at91_ramc_base[1]),
115 "r" (at91_rstc_base),
116 "r" (1),
117 "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
118 "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
119 : "r0");
120}
121
122static void __init at91_reset_status(struct platform_device *pdev)
123{
124 u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
125 char *reason;
126
127 switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
128 case RESET_TYPE_GENERAL:
129 reason = "general reset";
130 break;
131 case RESET_TYPE_WAKEUP:
132 reason = "wakeup";
133 break;
134 case RESET_TYPE_WATCHDOG:
135 reason = "watchdog reset";
136 break;
137 case RESET_TYPE_SOFTWARE:
138 reason = "software reset";
139 break;
140 case RESET_TYPE_USER:
141 reason = "user reset";
142 break;
143 default:
144 reason = "unknown reset";
145 break;
146 }
147
148 pr_info("AT91: Starting after %s\n", reason);
149}
150
151static struct of_device_id at91_ramc_of_match[] = {
152 { .compatible = "atmel,at91sam9260-sdramc", },
153 { .compatible = "atmel,at91sam9g45-ddramc", },
154 { .compatible = "atmel,sama5d3-ddramc", },
155 { /* sentinel */ }
156};
157
158static struct of_device_id at91_reset_of_match[] = {
159 { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
160 { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
161 { /* sentinel */ }
162};
163
164static int at91_reset_of_probe(struct platform_device *pdev)
165{
166 const struct of_device_id *match;
167 struct device_node *np;
168 int idx = 0;
169
170 at91_rstc_base = of_iomap(pdev->dev.of_node, 0);
171 if (!at91_rstc_base) {
172 dev_err(&pdev->dev, "Could not map reset controller address\n");
173 return -ENODEV;
174 }
175
176 for_each_matching_node(np, at91_ramc_of_match) {
177 at91_ramc_base[idx] = of_iomap(np, 0);
178 if (!at91_ramc_base[idx]) {
179 dev_err(&pdev->dev, "Could not map ram controller address\n");
180 return -ENODEV;
181 }
182 idx++;
183 }
184
185 match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
186 arm_pm_restart = match->data;
187
188 return 0;
189}
190
191static int at91_reset_platform_probe(struct platform_device *pdev)
192{
193 const struct platform_device_id *match;
194 struct resource *res;
195 int idx = 0;
196
197 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
198 at91_rstc_base = devm_ioremap_resource(&pdev->dev, res);
199 if (IS_ERR(at91_rstc_base)) {
200 dev_err(&pdev->dev, "Could not map reset controller address\n");
201 return PTR_ERR(at91_rstc_base);
202 }
203
204 for (idx = 0; idx < 2; idx++) {
205 res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
206 at91_ramc_base[idx] = devm_ioremap(&pdev->dev, res->start,
207 resource_size(res));
208 if (IS_ERR(at91_ramc_base[idx])) {
209 dev_err(&pdev->dev, "Could not map ram controller address\n");
210 return PTR_ERR(at91_ramc_base[idx]);
211 }
212 }
213
214 match = platform_get_device_id(pdev);
215 arm_pm_restart = (void (*)(enum reboot_mode, const char*))
216 match->driver_data;
217
218 return 0;
219}
220
221static int at91_reset_probe(struct platform_device *pdev)
222{
223 int ret;
224
225 if (pdev->dev.of_node)
226 ret = at91_reset_of_probe(pdev);
227 else
228 ret = at91_reset_platform_probe(pdev);
229
230 if (ret)
231 return ret;
232
233 at91_reset_status(pdev);
234
235 return 0;
236}
237
238static struct platform_device_id at91_reset_plat_match[] = {
239 { "at91-sam9260-reset", (unsigned long)at91sam9260_restart },
240 { "at91-sam9g45-reset", (unsigned long)at91sam9g45_restart },
241 { /* sentinel */ }
242};
243
244static struct platform_driver at91_reset_driver = {
245 .probe = at91_reset_probe,
246 .driver = {
247 .name = "at91-reset",
248 .of_match_table = at91_reset_of_match,
249 },
250 .id_table = at91_reset_plat_match,
251};
252module_platform_driver(at91_reset_driver);