0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/kernel.h>
0023 #include <linux/init.h>
0024 #include <linux/of_address.h>
0025 #include <linux/io.h>
0026 #include <linux/reboot.h>
0027 #include "common.h"
0028 #include "mvebu-soc-id.h"
0029 #include "pmsu.h"
0030
0031 #define ARMADA_375_CRYPT0_ENG_TARGET 41
0032 #define ARMADA_375_CRYPT0_ENG_ATTR 1
0033
0034 static void __iomem *system_controller_base;
0035 static phys_addr_t system_controller_phys_base;
0036
0037 struct mvebu_system_controller {
0038 u32 rstoutn_mask_offset;
0039 u32 system_soft_reset_offset;
0040
0041 u32 rstoutn_mask_reset_out_en;
0042 u32 system_soft_reset;
0043
0044 u32 resume_boot_addr;
0045
0046 u32 dev_id;
0047 u32 rev_id;
0048 };
0049 static struct mvebu_system_controller *mvebu_sc;
0050
0051 static const struct mvebu_system_controller armada_370_xp_system_controller = {
0052 .rstoutn_mask_offset = 0x60,
0053 .system_soft_reset_offset = 0x64,
0054 .rstoutn_mask_reset_out_en = 0x1,
0055 .system_soft_reset = 0x1,
0056 .dev_id = 0x38,
0057 .rev_id = 0x3c,
0058 };
0059
0060 static const struct mvebu_system_controller armada_375_system_controller = {
0061 .rstoutn_mask_offset = 0x54,
0062 .system_soft_reset_offset = 0x58,
0063 .rstoutn_mask_reset_out_en = 0x1,
0064 .system_soft_reset = 0x1,
0065 .resume_boot_addr = 0xd4,
0066 .dev_id = 0x38,
0067 .rev_id = 0x3c,
0068 };
0069
0070 static const struct mvebu_system_controller orion_system_controller = {
0071 .rstoutn_mask_offset = 0x108,
0072 .system_soft_reset_offset = 0x10c,
0073 .rstoutn_mask_reset_out_en = 0x4,
0074 .system_soft_reset = 0x1,
0075 };
0076
0077 static const struct of_device_id of_system_controller_table[] = {
0078 {
0079 .compatible = "marvell,orion-system-controller",
0080 .data = (void *) &orion_system_controller,
0081 }, {
0082 .compatible = "marvell,armada-370-xp-system-controller",
0083 .data = (void *) &armada_370_xp_system_controller,
0084 }, {
0085 .compatible = "marvell,armada-375-system-controller",
0086 .data = (void *) &armada_375_system_controller,
0087 },
0088 { },
0089 };
0090
0091 void mvebu_restart(enum reboot_mode mode, const char *cmd)
0092 {
0093 if (!system_controller_base) {
0094 pr_err("Cannot restart, system-controller not available: check the device tree\n");
0095 } else {
0096
0097
0098
0099 writel(mvebu_sc->rstoutn_mask_reset_out_en,
0100 system_controller_base +
0101 mvebu_sc->rstoutn_mask_offset);
0102
0103
0104
0105 writel(mvebu_sc->system_soft_reset,
0106 system_controller_base +
0107 mvebu_sc->system_soft_reset_offset);
0108 }
0109
0110 while (1)
0111 ;
0112 }
0113
0114 int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
0115 {
0116 if (of_machine_is_compatible("marvell,armada380") &&
0117 system_controller_base) {
0118 *dev = readl(system_controller_base + mvebu_sc->dev_id) >> 16;
0119 *rev = (readl(system_controller_base + mvebu_sc->rev_id) >> 8)
0120 & 0xF;
0121 return 0;
0122 } else
0123 return -ENODEV;
0124 }
0125
0126 #if defined(CONFIG_SMP) && defined(CONFIG_MACH_MVEBU_V7)
0127 static void mvebu_armada375_smp_wa_init(void)
0128 {
0129 u32 dev, rev;
0130 phys_addr_t resume_addr_reg;
0131
0132 if (mvebu_get_soc_id(&dev, &rev) != 0)
0133 return;
0134
0135 if (rev != ARMADA_375_Z1_REV)
0136 return;
0137
0138 resume_addr_reg = system_controller_phys_base +
0139 mvebu_sc->resume_boot_addr;
0140 mvebu_setup_boot_addr_wa(ARMADA_375_CRYPT0_ENG_TARGET,
0141 ARMADA_375_CRYPT0_ENG_ATTR,
0142 resume_addr_reg);
0143 }
0144
0145 void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
0146 {
0147 BUG_ON(system_controller_base == NULL);
0148 BUG_ON(mvebu_sc->resume_boot_addr == 0);
0149
0150 if (of_machine_is_compatible("marvell,armada375"))
0151 mvebu_armada375_smp_wa_init();
0152
0153 writel(__pa_symbol(boot_addr), system_controller_base +
0154 mvebu_sc->resume_boot_addr);
0155 }
0156 #endif
0157
0158 static int __init mvebu_system_controller_init(void)
0159 {
0160 const struct of_device_id *match;
0161 struct device_node *np;
0162
0163 np = of_find_matching_node_and_match(NULL, of_system_controller_table,
0164 &match);
0165 if (np) {
0166 struct resource res;
0167 system_controller_base = of_iomap(np, 0);
0168 of_address_to_resource(np, 0, &res);
0169 system_controller_phys_base = res.start;
0170 mvebu_sc = (struct mvebu_system_controller *)match->data;
0171 of_node_put(np);
0172 }
0173
0174 return 0;
0175 }
0176
0177 early_initcall(mvebu_system_controller_init);