diff options
Diffstat (limited to 'arch/arm/mach-mvebu/system-controller.c')
-rw-r--r-- | arch/arm/mach-mvebu/system-controller.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c new file mode 100644 index 000000000000..b8079df8c986 --- /dev/null +++ b/arch/arm/mach-mvebu/system-controller.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * System controller support for Armada 370 and XP platforms. | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell | ||
5 | * | ||
6 | * Lior Amsalem <alior@marvell.com> | ||
7 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
8 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public | ||
11 | * License version 2. This program is licensed "as is" without any | ||
12 | * warranty of any kind, whether express or implied. | ||
13 | * | ||
14 | * The Armada 370 and Armada XP SoCs both have a range of | ||
15 | * miscellaneous registers, that do not belong to a particular device, | ||
16 | * but rather provide system-level features. This basic | ||
17 | * system-controller driver provides a device tree binding for those | ||
18 | * registers, and implements utility functions offering various | ||
19 | * features related to those registers. | ||
20 | * | ||
21 | * For now, the feature set is limited to restarting the platform by a | ||
22 | * soft-reset, but it might be extended in the future. | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/of_address.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | static void __iomem *system_controller_base; | ||
31 | |||
32 | struct mvebu_system_controller { | ||
33 | u32 rstoutn_mask_offset; | ||
34 | u32 system_soft_reset_offset; | ||
35 | |||
36 | u32 rstoutn_mask_reset_out_en; | ||
37 | u32 system_soft_reset; | ||
38 | }; | ||
39 | static struct mvebu_system_controller *mvebu_sc; | ||
40 | |||
41 | const struct mvebu_system_controller armada_370_xp_system_controller = { | ||
42 | .rstoutn_mask_offset = 0x60, | ||
43 | .system_soft_reset_offset = 0x64, | ||
44 | .rstoutn_mask_reset_out_en = 0x1, | ||
45 | .system_soft_reset = 0x1, | ||
46 | }; | ||
47 | |||
48 | const struct mvebu_system_controller orion_system_controller = { | ||
49 | .rstoutn_mask_offset = 0x108, | ||
50 | .system_soft_reset_offset = 0x10c, | ||
51 | .rstoutn_mask_reset_out_en = 0x4, | ||
52 | .system_soft_reset = 0x1, | ||
53 | }; | ||
54 | |||
55 | static struct of_device_id of_system_controller_table[] = { | ||
56 | { | ||
57 | .compatible = "marvell,orion-system-controller", | ||
58 | .data = (void *) &orion_system_controller, | ||
59 | }, { | ||
60 | .compatible = "marvell,armada-370-xp-system-controller", | ||
61 | .data = (void *) &armada_370_xp_system_controller, | ||
62 | }, | ||
63 | { /* end of list */ }, | ||
64 | }; | ||
65 | |||
66 | void mvebu_restart(char mode, const char *cmd) | ||
67 | { | ||
68 | if (!system_controller_base) { | ||
69 | pr_err("Cannot restart, system-controller not available: check the device tree\n"); | ||
70 | } else { | ||
71 | /* | ||
72 | * Enable soft reset to assert RSTOUTn. | ||
73 | */ | ||
74 | writel(mvebu_sc->rstoutn_mask_reset_out_en, | ||
75 | system_controller_base + | ||
76 | mvebu_sc->rstoutn_mask_offset); | ||
77 | /* | ||
78 | * Assert soft reset. | ||
79 | */ | ||
80 | writel(mvebu_sc->system_soft_reset, | ||
81 | system_controller_base + | ||
82 | mvebu_sc->system_soft_reset_offset); | ||
83 | } | ||
84 | |||
85 | while (1) | ||
86 | ; | ||
87 | } | ||
88 | |||
89 | static int __init mvebu_system_controller_init(void) | ||
90 | { | ||
91 | struct device_node *np; | ||
92 | |||
93 | np = of_find_matching_node(NULL, of_system_controller_table); | ||
94 | if (np) { | ||
95 | const struct of_device_id *match = | ||
96 | of_match_node(of_system_controller_table, np); | ||
97 | BUG_ON(!match); | ||
98 | system_controller_base = of_iomap(np, 0); | ||
99 | mvebu_sc = (struct mvebu_system_controller *)match->data; | ||
100 | } | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | arch_initcall(mvebu_system_controller_init); | ||