1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 4 */ 5 6 #include <linux/bitfield.h> 7 #include <linux/bitops.h> 8 #include <linux/clk.h> 9 #include <linux/delay.h> 10 #include <linux/genalloc.h> 11 #include <linux/io.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 #include <linux/property.h> 16 #include <linux/regmap.h> 17 #include <linux/remoteproc.h> 18 #include <linux/reset.h> 19 #include <linux/sizes.h> 20 21 #include "remoteproc_internal.h" 22 23 #define AO_REMAP_REG0 0x0 24 #define AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU GENMASK(3, 0) 25 26 #define AO_REMAP_REG1 0x4 27 #define AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR BIT(4) 28 #define AO_REMAP_REG1_REMAP_AHB_SRAM_BITS_17_14_FOR_MEDIA_CPU GENMASK(3, 0) 29 30 #define AO_CPU_CNTL 0x0 31 #define AO_CPU_CNTL_AHB_SRAM_BITS_31_20 GENMASK(28, 16) 32 #define AO_CPU_CNTL_HALT BIT(9) 33 #define AO_CPU_CNTL_UNKNONWN BIT(8) 34 #define AO_CPU_CNTL_RUN BIT(0) 35 36 #define AO_CPU_STAT 0x4 37 38 #define AO_SECURE_REG0 0x0 39 #define AO_SECURE_REG0_AHB_SRAM_BITS_19_12 GENMASK(15, 8) 40 41 /* Only bits [31:20] and [17:14] are usable, all other bits must be zero */ 42 #define MESON_AO_RPROC_SRAM_USABLE_BITS 0xfff3c000ULL 43 44 #define MESON_AO_RPROC_MEMORY_OFFSET 0x10000000 45 46 struct meson_mx_ao_arc_rproc_priv { 47 void __iomem *remap_base; 48 void __iomem *cpu_base; 49 unsigned long sram_va; 50 phys_addr_t sram_pa; 51 size_t sram_size; 52 struct gen_pool *sram_pool; 53 struct reset_control *arc_reset; 54 struct clk *arc_pclk; 55 struct regmap *secbus2_regmap; 56 }; 57 58 static int meson_mx_ao_arc_rproc_start(struct rproc *rproc) 59 { 60 struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; 61 phys_addr_t translated_sram_addr; 62 u32 tmp; 63 int ret; 64 65 ret = clk_prepare_enable(priv->arc_pclk); 66 if (ret) 67 return ret; 68 69 tmp = FIELD_PREP(AO_REMAP_REG0_REMAP_AHB_SRAM_BITS_17_14_FOR_ARM_CPU, 70 priv->sram_pa >> 14); 71 writel(tmp, priv->remap_base + AO_REMAP_REG0); 72 73 /* 74 * The SRAM content as seen by the ARC core always starts at 0x0 75 * regardless of the value given here (this was discovered by trial and 76 * error). For SoCs older than Meson6 we probably have to set 77 * AO_REMAP_REG1_MOVE_AHB_SRAM_TO_0X0_INSTEAD_OF_DDR to achieve the 78 * same. (At least) For Meson8 and newer that bit must not be set. 79 */ 80 writel(0x0, priv->remap_base + AO_REMAP_REG1); 81 82 regmap_update_bits(priv->secbus2_regmap, AO_SECURE_REG0, 83 AO_SECURE_REG0_AHB_SRAM_BITS_19_12, 84 FIELD_PREP(AO_SECURE_REG0_AHB_SRAM_BITS_19_12, 85 priv->sram_pa >> 12)); 86 87 ret = reset_control_reset(priv->arc_reset); 88 if (ret) { 89 clk_disable_unprepare(priv->arc_pclk); 90 return ret; 91 } 92 93 usleep_range(10, 100); 94 95 /* 96 * Convert from 0xd9000000 to 0xc9000000 as the vendor driver does. 97 * This only seems to be relevant for the AO_CPU_CNTL register. It is 98 * unknown why this is needed. 99 */ 100 translated_sram_addr = priv->sram_pa - MESON_AO_RPROC_MEMORY_OFFSET; 101 102 tmp = FIELD_PREP(AO_CPU_CNTL_AHB_SRAM_BITS_31_20, 103 translated_sram_addr >> 20); 104 tmp |= AO_CPU_CNTL_UNKNONWN | AO_CPU_CNTL_RUN; 105 writel(tmp, priv->cpu_base + AO_CPU_CNTL); 106 107 usleep_range(20, 200); 108 109 return 0; 110 } 111 112 static int meson_mx_ao_arc_rproc_stop(struct rproc *rproc) 113 { 114 struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; 115 116 writel(AO_CPU_CNTL_HALT, priv->cpu_base + AO_CPU_CNTL); 117 118 clk_disable_unprepare(priv->arc_pclk); 119 120 return 0; 121 } 122 123 static void *meson_mx_ao_arc_rproc_da_to_va(struct rproc *rproc, u64 da, 124 size_t len, bool *is_iomem) 125 { 126 struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; 127 128 /* The memory from the ARC core's perspective always starts at 0x0. */ 129 if ((da + len) > priv->sram_size) 130 return NULL; 131 132 return (void *)priv->sram_va + da; 133 } 134 135 static struct rproc_ops meson_mx_ao_arc_rproc_ops = { 136 .start = meson_mx_ao_arc_rproc_start, 137 .stop = meson_mx_ao_arc_rproc_stop, 138 .da_to_va = meson_mx_ao_arc_rproc_da_to_va, 139 .get_boot_addr = rproc_elf_get_boot_addr, 140 .load = rproc_elf_load_segments, 141 .sanity_check = rproc_elf_sanity_check, 142 }; 143 144 static int meson_mx_ao_arc_rproc_probe(struct platform_device *pdev) 145 { 146 struct meson_mx_ao_arc_rproc_priv *priv; 147 struct device *dev = &pdev->dev; 148 const char *fw_name = NULL; 149 struct rproc *rproc; 150 int ret; 151 152 device_property_read_string(dev, "firmware-name", &fw_name); 153 154 rproc = devm_rproc_alloc(dev, "meson-mx-ao-arc", 155 &meson_mx_ao_arc_rproc_ops, fw_name, 156 sizeof(*priv)); 157 if (!rproc) 158 return -ENOMEM; 159 160 rproc->has_iommu = false; 161 priv = rproc->priv; 162 163 priv->sram_pool = of_gen_pool_get(dev->of_node, "sram", 0); 164 if (!priv->sram_pool) { 165 dev_err(dev, "Could not get SRAM pool\n"); 166 return -ENODEV; 167 } 168 169 priv->sram_size = gen_pool_avail(priv->sram_pool); 170 171 priv->sram_va = gen_pool_alloc(priv->sram_pool, priv->sram_size); 172 if (!priv->sram_va) { 173 dev_err(dev, "Could not alloc memory in SRAM pool\n"); 174 return -ENOMEM; 175 } 176 177 priv->sram_pa = gen_pool_virt_to_phys(priv->sram_pool, priv->sram_va); 178 if (priv->sram_pa & ~MESON_AO_RPROC_SRAM_USABLE_BITS) { 179 dev_err(dev, "SRAM address contains unusable bits\n"); 180 ret = -EINVAL; 181 goto err_free_genpool; 182 } 183 184 priv->secbus2_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, 185 "amlogic,secbus2"); 186 if (IS_ERR(priv->secbus2_regmap)) { 187 dev_err(dev, "Failed to find SECBUS2 regmap\n"); 188 ret = PTR_ERR(priv->secbus2_regmap); 189 goto err_free_genpool; 190 } 191 192 priv->remap_base = devm_platform_ioremap_resource_byname(pdev, "remap"); 193 if (IS_ERR(priv->remap_base)) { 194 ret = PTR_ERR(priv->remap_base); 195 goto err_free_genpool; 196 } 197 198 priv->cpu_base = devm_platform_ioremap_resource_byname(pdev, "cpu"); 199 if (IS_ERR(priv->cpu_base)) { 200 ret = PTR_ERR(priv->cpu_base); 201 goto err_free_genpool; 202 } 203 204 priv->arc_reset = devm_reset_control_get_exclusive(dev, NULL); 205 if (IS_ERR(priv->arc_reset)) { 206 dev_err(dev, "Failed to get ARC reset\n"); 207 ret = PTR_ERR(priv->arc_reset); 208 goto err_free_genpool; 209 } 210 211 priv->arc_pclk = devm_clk_get(dev, NULL); 212 if (IS_ERR(priv->arc_pclk)) { 213 dev_err(dev, "Failed to get the ARC PCLK\n"); 214 ret = PTR_ERR(priv->arc_pclk); 215 goto err_free_genpool; 216 } 217 218 platform_set_drvdata(pdev, rproc); 219 220 ret = rproc_add(rproc); 221 if (ret) 222 goto err_free_genpool; 223 224 return 0; 225 226 err_free_genpool: 227 gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size); 228 return ret; 229 } 230 231 static void meson_mx_ao_arc_rproc_remove(struct platform_device *pdev) 232 { 233 struct rproc *rproc = platform_get_drvdata(pdev); 234 struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; 235 236 rproc_del(rproc); 237 gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size); 238 } 239 240 static const struct of_device_id meson_mx_ao_arc_rproc_match[] = { 241 { .compatible = "amlogic,meson8-ao-arc" }, 242 { .compatible = "amlogic,meson8b-ao-arc" }, 243 { /* sentinel */ } 244 }; 245 MODULE_DEVICE_TABLE(of, meson_mx_ao_arc_rproc_match); 246 247 static struct platform_driver meson_mx_ao_arc_rproc_driver = { 248 .probe = meson_mx_ao_arc_rproc_probe, 249 .remove_new = meson_mx_ao_arc_rproc_remove, 250 .driver = { 251 .name = "meson-mx-ao-arc-rproc", 252 .of_match_table = meson_mx_ao_arc_rproc_match, 253 }, 254 }; 255 module_platform_driver(meson_mx_ao_arc_rproc_driver); 256 257 MODULE_DESCRIPTION("Amlogic Meson6/8/8b/8m2 AO ARC remote processor driver"); 258 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 259 MODULE_LICENSE("GPL v2"); 260