Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * System controller support for Armada 370, 375 and XP platforms.
0004  *
0005  * Copyright (C) 2012 Marvell
0006  *
0007  * Lior Amsalem <alior@marvell.com>
0008  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0009  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
0010  *
0011  * The Armada 370, 375 and Armada XP SoCs have a range of
0012  * miscellaneous registers, that do not belong to a particular device,
0013  * but rather provide system-level features. This basic
0014  * system-controller driver provides a device tree binding for those
0015  * registers, and implements utility functions offering various
0016  * features related to those registers.
0017  *
0018  * For now, the feature set is limited to restarting the platform by a
0019  * soft-reset, but it might be extended in the future.
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     { /* end of list */ },
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          * Enable soft reset to assert RSTOUTn.
0098          */
0099         writel(mvebu_sc->rstoutn_mask_reset_out_en,
0100             system_controller_base +
0101             mvebu_sc->rstoutn_mask_offset);
0102         /*
0103          * Assert soft reset.
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);