summaryrefslogtreecommitdiff
path: root/arch/arm/mach-sunxi
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2018-03-08 18:00:12 +0300
committerChen-Yu Tsai <wens@csie.org>2018-03-10 11:14:57 +0300
commit99e3a1e6fedd3b8713a1398772ad7da3796c6908 (patch)
treebc5616eec7576d10421dcbe24dbb8077c5025303 /arch/arm/mach-sunxi
parent8591743f12636a247bdab56c8c355ea9686f2d97 (diff)
downloadlinux-99e3a1e6fedd3b8713a1398772ad7da3796c6908.tar.xz
ARM: sunxi: mc-smp: Split out SoC-specific device node lookup sequence
The multi-cluster SMP code maps the address spaces of several hardware control blocks. The device nodes for them are SoC-specific. To help with supporting other SoCs to re-use this code, these bits should be split out to a separate function tied to the enable-method string. This patch splits out and groups the device node lookup sequence, and adds new data structures to have the newly created function tied to the enable method string. This structure can also be used to encode other differences between the SoCs. Acked-by: Maxime Ripard <maxime.ripard@bootlin.com> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Diffstat (limited to 'arch/arm/mach-sunxi')
-rw-r--r--arch/arm/mach-sunxi/mc_smp.c126
1 files changed, 86 insertions, 40 deletions
diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c
index 86e90b038555..c0246ec54a0a 100644
--- a/arch/arm/mach-sunxi/mc_smp.c
+++ b/arch/arm/mach-sunxi/mc_smp.c
@@ -684,11 +684,69 @@ static int __init sunxi_mc_smp_loopback(void)
return ret;
}
+/*
+ * This holds any device nodes that we requested resources for,
+ * so that we may easily release resources in the error path.
+ */
+struct sunxi_mc_smp_nodes {
+ struct device_node *prcm_node;
+ struct device_node *cpucfg_node;
+ struct device_node *sram_node;
+};
+
+/* This structure holds SoC-specific bits tied to an enable-method string. */
+struct sunxi_mc_smp_data {
+ const char *enable_method;
+ int (*get_smp_nodes)(struct sunxi_mc_smp_nodes *nodes);
+};
+
+static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes)
+{
+ of_node_put(nodes->prcm_node);
+ of_node_put(nodes->cpucfg_node);
+ of_node_put(nodes->sram_node);
+ memset(nodes, 0, sizeof(*nodes));
+}
+
+static int __init sun9i_a80_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes)
+{
+ nodes->prcm_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun9i-a80-prcm");
+ if (!nodes->prcm_node) {
+ pr_err("%s: PRCM not available\n", __func__);
+ return -ENODEV;
+ }
+
+ nodes->cpucfg_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun9i-a80-cpucfg");
+ if (!nodes->cpucfg_node) {
+ pr_err("%s: CPUCFG not available\n", __func__);
+ return -ENODEV;
+ }
+
+ nodes->sram_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun9i-a80-smp-sram");
+ if (!nodes->sram_node) {
+ pr_err("%s: Secure SRAM not available\n", __func__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static const struct sunxi_mc_smp_data sunxi_mc_smp_data[] __initconst = {
+ {
+ .enable_method = "allwinner,sun9i-a80-smp",
+ .get_smp_nodes = sun9i_a80_get_smp_nodes,
+ },
+};
+
static int __init sunxi_mc_smp_init(void)
{
- struct device_node *cpucfg_node, *sram_node, *node;
+ struct sunxi_mc_smp_nodes nodes = { 0 };
+ struct device_node *node;
struct resource res;
- int ret;
+ int i, ret;
/*
* Don't bother checking the "cpus" node, as an enable-method
@@ -706,8 +764,13 @@ static int __init sunxi_mc_smp_init(void)
* callbacks in smp_operations, which we would use if we were to
* use CPU_METHOD_OF_DECLARE
*/
- ret = of_property_match_string(node, "enable-method",
- "allwinner,sun9i-a80-smp");
+ for (i = 0; i < ARRAY_SIZE(sunxi_mc_smp_data); i++) {
+ ret = of_property_match_string(node, "enable-method",
+ sunxi_mc_smp_data[i].enable_method);
+ if (!ret)
+ break;
+ }
+
of_node_put(node);
if (ret)
return -ENODEV;
@@ -720,51 +783,37 @@ static int __init sunxi_mc_smp_init(void)
return -ENODEV;
}
- node = of_find_compatible_node(NULL, NULL, "allwinner,sun9i-a80-prcm");
- if (!node) {
- pr_err("%s: PRCM not available\n", __func__);
- return -ENODEV;
- }
+ /* Get needed device tree nodes */
+ ret = sunxi_mc_smp_data[i].get_smp_nodes(&nodes);
+ if (ret)
+ goto err_put_nodes;
/*
* Unfortunately we can not request the I/O region for the PRCM.
* It is shared with the PRCM clock.
*/
- prcm_base = of_iomap(node, 0);
- of_node_put(node);
+ prcm_base = of_iomap(nodes.prcm_node, 0);
if (!prcm_base) {
pr_err("%s: failed to map PRCM registers\n", __func__);
- return -ENOMEM;
- }
-
- cpucfg_node = of_find_compatible_node(NULL, NULL,
- "allwinner,sun9i-a80-cpucfg");
- if (!cpucfg_node) {
- ret = -ENODEV;
- pr_err("%s: CPUCFG not available\n", __func__);
- goto err_unmap_prcm;
+ ret = -ENOMEM;
+ goto err_put_nodes;
}
- cpucfg_base = of_io_request_and_map(cpucfg_node, 0, "sunxi-mc-smp");
+ cpucfg_base = of_io_request_and_map(nodes.cpucfg_node, 0,
+ "sunxi-mc-smp");
if (IS_ERR(cpucfg_base)) {
ret = PTR_ERR(cpucfg_base);
pr_err("%s: failed to map CPUCFG registers: %d\n",
__func__, ret);
- goto err_put_cpucfg_node;
- }
-
- sram_node = of_find_compatible_node(NULL, NULL,
- "allwinner,sun9i-a80-smp-sram");
- if (!sram_node) {
- ret = -ENODEV;
- goto err_unmap_release_cpucfg;
+ goto err_unmap_prcm;
}
- sram_b_smp_base = of_io_request_and_map(sram_node, 0, "sunxi-mc-smp");
+ sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0,
+ "sunxi-mc-smp");
if (IS_ERR(sram_b_smp_base)) {
ret = PTR_ERR(sram_b_smp_base);
pr_err("%s: failed to map secure SRAM\n", __func__);
- goto err_put_sram_node;
+ goto err_unmap_release_cpucfg;
}
/* Configure CCI-400 for boot cluster */
@@ -775,9 +824,8 @@ static int __init sunxi_mc_smp_init(void)
goto err_unmap_release_secure_sram;
}
- /* We don't need the CPUCFG and SRAM device nodes anymore */
- of_node_put(cpucfg_node);
- of_node_put(sram_node);
+ /* We don't need the device nodes anymore */
+ sunxi_mc_smp_put_nodes(&nodes);
/* Set the hardware entry point address */
writel(__pa_symbol(sunxi_mc_smp_secondary_startup),
@@ -792,18 +840,16 @@ static int __init sunxi_mc_smp_init(void)
err_unmap_release_secure_sram:
iounmap(sram_b_smp_base);
- of_address_to_resource(sram_node, 0, &res);
+ of_address_to_resource(nodes.sram_node, 0, &res);
release_mem_region(res.start, resource_size(&res));
-err_put_sram_node:
- of_node_put(sram_node);
err_unmap_release_cpucfg:
iounmap(cpucfg_base);
- of_address_to_resource(cpucfg_node, 0, &res);
+ of_address_to_resource(nodes.cpucfg_node, 0, &res);
release_mem_region(res.start, resource_size(&res));
-err_put_cpucfg_node:
- of_node_put(cpucfg_node);
err_unmap_prcm:
iounmap(prcm_base);
+err_put_nodes:
+ sunxi_mc_smp_put_nodes(&nodes);
return ret;
}