Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for_5.5/driver-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into arm/drivers

* 'for_5.5/driver-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone:
memory: emif: remove set but not used variables 'cs1_used' and 'custom_configs'
soc: ti: omap-prm: fix return value check in omap_prm_probe()
soc: ti: omap-prm: add omap5 PRM data
soc: ti: omap-prm: add am4 PRM data
soc: ti: omap-prm: add dra7 PRM data
soc: ti: omap-prm: add data for am33xx
soc: ti: omap-prm: add omap4 PRM data
soc: ti: omap-prm: add support for denying idle for reset clockdomain
soc: ti: omap-prm: poll for reset complete during de-assert
soc: ti: add initial PRM driver with reset control support
dt-bindings: omap: add new binding for PRM instances

Link: https://lore.kernel.org/r/1572372856-20598-1-git-send-email-santosh.shilimkar@oracle.com
Signed-off-by: Olof Johansson <olof@lixom.net>

+444 -4
+29
Documentation/devicetree/bindings/arm/omap/prm-inst.txt
··· 1 + OMAP PRM instance bindings 2 + 3 + Power and Reset Manager is an IP block on OMAP family of devices which 4 + handle the power domains and their current state, and provide reset 5 + handling for the domains and/or separate IP blocks under the power domain 6 + hierarchy. 7 + 8 + Required properties: 9 + - compatible: Must contain one of the following: 10 + "ti,am3-prm-inst" 11 + "ti,am4-prm-inst" 12 + "ti,omap4-prm-inst" 13 + "ti,omap5-prm-inst" 14 + "ti,dra7-prm-inst" 15 + and additionally must contain: 16 + "ti,omap-prm-inst" 17 + - reg: Contains PRM instance register address range 18 + (base address and length) 19 + 20 + Optional properties: 21 + - #reset-cells: Should be 1 if the PRM instance in question supports resets. 22 + 23 + Example: 24 + 25 + prm_dsp2: prm@1b00 { 26 + compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst"; 27 + reg = <0x1b00 0x40>; 28 + #reset-cells = <1>; 29 + };
+1
arch/arm/mach-omap2/Kconfig
··· 109 109 select TI_SYSC 110 110 select OMAP_IRQCHIP 111 111 select CLKSRC_TI_32K 112 + select ARCH_HAS_RESET_CONTROLLER 112 113 help 113 114 Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 114 115
+1 -4
drivers/memory/emif.c
··· 1613 1613 static int get_emif_reg_values(struct emif_data *emif, u32 freq, 1614 1614 struct emif_regs *regs) 1615 1615 { 1616 - u32 cs1_used, ip_rev, phy_type; 1616 + u32 ip_rev, phy_type; 1617 1617 u32 cl, type; 1618 1618 const struct lpddr2_timings *timings; 1619 1619 const struct lpddr2_min_tck *min_tck; ··· 1621 1621 const struct lpddr2_addressing *addressing; 1622 1622 struct emif_data *emif_for_calc; 1623 1623 struct device *dev; 1624 - const struct emif_custom_configs *custom_configs; 1625 1624 1626 1625 dev = emif->dev; 1627 1626 /* ··· 1638 1639 1639 1640 device_info = emif_for_calc->plat_data->device_info; 1640 1641 type = device_info->type; 1641 - cs1_used = device_info->cs1_used; 1642 1642 ip_rev = emif_for_calc->plat_data->ip_rev; 1643 1643 phy_type = emif_for_calc->plat_data->phy_type; 1644 1644 1645 1645 min_tck = emif_for_calc->plat_data->min_tck; 1646 - custom_configs = emif_for_calc->plat_data->custom_configs; 1647 1646 1648 1647 set_ddr_clk_period(freq); 1649 1648
+1
drivers/soc/ti/Makefile
··· 6 6 knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o 7 7 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o 8 8 obj-$(CONFIG_AMX3_PM) += pm33xx.o 9 + obj-$(CONFIG_ARCH_OMAP2PLUS) += omap_prm.o 9 10 obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o 10 11 obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o 11 12 obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
+391
drivers/soc/ti/omap_prm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * OMAP2+ PRM driver 4 + * 5 + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ 6 + * Tero Kristo <t-kristo@ti.com> 7 + */ 8 + 9 + #include <linux/kernel.h> 10 + #include <linux/device.h> 11 + #include <linux/io.h> 12 + #include <linux/iopoll.h> 13 + #include <linux/of.h> 14 + #include <linux/of_device.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/reset-controller.h> 17 + #include <linux/delay.h> 18 + 19 + #include <linux/platform_data/ti-prm.h> 20 + 21 + struct omap_rst_map { 22 + s8 rst; 23 + s8 st; 24 + }; 25 + 26 + struct omap_prm_data { 27 + u32 base; 28 + const char *name; 29 + const char *clkdm_name; 30 + u16 rstctrl; 31 + u16 rstst; 32 + const struct omap_rst_map *rstmap; 33 + u8 flags; 34 + }; 35 + 36 + struct omap_prm { 37 + const struct omap_prm_data *data; 38 + void __iomem *base; 39 + }; 40 + 41 + struct omap_reset_data { 42 + struct reset_controller_dev rcdev; 43 + struct omap_prm *prm; 44 + u32 mask; 45 + spinlock_t lock; 46 + struct clockdomain *clkdm; 47 + struct device *dev; 48 + }; 49 + 50 + #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev) 51 + 52 + #define OMAP_MAX_RESETS 8 53 + #define OMAP_RESET_MAX_WAIT 10000 54 + 55 + #define OMAP_PRM_HAS_RSTCTRL BIT(0) 56 + #define OMAP_PRM_HAS_RSTST BIT(1) 57 + #define OMAP_PRM_HAS_NO_CLKDM BIT(2) 58 + 59 + #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) 60 + 61 + static const struct omap_rst_map rst_map_0[] = { 62 + { .rst = 0, .st = 0 }, 63 + { .rst = -1 }, 64 + }; 65 + 66 + static const struct omap_rst_map rst_map_01[] = { 67 + { .rst = 0, .st = 0 }, 68 + { .rst = 1, .st = 1 }, 69 + { .rst = -1 }, 70 + }; 71 + 72 + static const struct omap_rst_map rst_map_012[] = { 73 + { .rst = 0, .st = 0 }, 74 + { .rst = 1, .st = 1 }, 75 + { .rst = 2, .st = 2 }, 76 + { .rst = -1 }, 77 + }; 78 + 79 + static const struct omap_prm_data omap4_prm_data[] = { 80 + { .name = "tesla", .base = 0x4a306400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 81 + { .name = "core", .base = 0x4a306700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", .rstmap = rst_map_012 }, 82 + { .name = "ivahd", .base = 0x4a306f00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 }, 83 + { .name = "device", .base = 0x4a307b00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 84 + { }, 85 + }; 86 + 87 + static const struct omap_prm_data omap5_prm_data[] = { 88 + { .name = "dsp", .base = 0x4ae06400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 89 + { .name = "core", .base = 0x4ae06700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu", .rstmap = rst_map_012 }, 90 + { .name = "iva", .base = 0x4ae07200, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 }, 91 + { .name = "device", .base = 0x4ae07c00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 92 + { }, 93 + }; 94 + 95 + static const struct omap_prm_data dra7_prm_data[] = { 96 + { .name = "dsp1", .base = 0x4ae06400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 97 + { .name = "ipu", .base = 0x4ae06500, .rstctrl = 0x10, .rstst = 0x14, .clkdm_name = "ipu1", .rstmap = rst_map_012 }, 98 + { .name = "core", .base = 0x4ae06700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu2", .rstmap = rst_map_012 }, 99 + { .name = "iva", .base = 0x4ae06f00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 }, 100 + { .name = "dsp2", .base = 0x4ae07b00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 101 + { .name = "eve1", .base = 0x4ae07b40, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 102 + { .name = "eve2", .base = 0x4ae07b80, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 103 + { .name = "eve3", .base = 0x4ae07bc0, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 104 + { .name = "eve4", .base = 0x4ae07c00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 105 + { }, 106 + }; 107 + 108 + static const struct omap_rst_map am3_per_rst_map[] = { 109 + { .rst = 1 }, 110 + { .rst = -1 }, 111 + }; 112 + 113 + static const struct omap_rst_map am3_wkup_rst_map[] = { 114 + { .rst = 3, .st = 5 }, 115 + { .rst = -1 }, 116 + }; 117 + 118 + static const struct omap_prm_data am3_prm_data[] = { 119 + { .name = "per", .base = 0x44e00c00, .rstctrl = 0x0, .rstmap = am3_per_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp" }, 120 + { .name = "wkup", .base = 0x44e00d00, .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 121 + { .name = "device", .base = 0x44e00f00, .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 122 + { .name = "gfx", .base = 0x44e01100, .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3" }, 123 + { }, 124 + }; 125 + 126 + static const struct omap_rst_map am4_per_rst_map[] = { 127 + { .rst = 1, .st = 0 }, 128 + { .rst = -1 }, 129 + }; 130 + 131 + static const struct omap_rst_map am4_device_rst_map[] = { 132 + { .rst = 0, .st = 1 }, 133 + { .rst = 1, .st = 0 }, 134 + { .rst = -1 }, 135 + }; 136 + 137 + static const struct omap_prm_data am4_prm_data[] = { 138 + { .name = "gfx", .base = 0x44df0400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3" }, 139 + { .name = "per", .base = 0x44df0800, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map, .clkdm_name = "pruss_ocp" }, 140 + { .name = "wkup", .base = 0x44df2000, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_NO_CLKDM }, 141 + { .name = "device", .base = 0x44df4000, .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 142 + { }, 143 + }; 144 + 145 + static const struct of_device_id omap_prm_id_table[] = { 146 + { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data }, 147 + { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data }, 148 + { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data }, 149 + { .compatible = "ti,am3-prm-inst", .data = am3_prm_data }, 150 + { .compatible = "ti,am4-prm-inst", .data = am4_prm_data }, 151 + { }, 152 + }; 153 + 154 + static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id) 155 + { 156 + if (reset->mask & BIT(id)) 157 + return true; 158 + 159 + return false; 160 + } 161 + 162 + static int omap_reset_get_st_bit(struct omap_reset_data *reset, 163 + unsigned long id) 164 + { 165 + const struct omap_rst_map *map = reset->prm->data->rstmap; 166 + 167 + while (map->rst >= 0) { 168 + if (map->rst == id) 169 + return map->st; 170 + 171 + map++; 172 + } 173 + 174 + return id; 175 + } 176 + 177 + static int omap_reset_status(struct reset_controller_dev *rcdev, 178 + unsigned long id) 179 + { 180 + struct omap_reset_data *reset = to_omap_reset_data(rcdev); 181 + u32 v; 182 + int st_bit = omap_reset_get_st_bit(reset, id); 183 + bool has_rstst = reset->prm->data->rstst || 184 + (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); 185 + 186 + /* Check if we have rstst */ 187 + if (!has_rstst) 188 + return -ENOTSUPP; 189 + 190 + /* Check if hw reset line is asserted */ 191 + v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 192 + if (v & BIT(id)) 193 + return 1; 194 + 195 + /* 196 + * Check reset status, high value means reset sequence has been 197 + * completed successfully so we can return 0 here (reset deasserted) 198 + */ 199 + v = readl_relaxed(reset->prm->base + reset->prm->data->rstst); 200 + v >>= st_bit; 201 + v &= 1; 202 + 203 + return !v; 204 + } 205 + 206 + static int omap_reset_assert(struct reset_controller_dev *rcdev, 207 + unsigned long id) 208 + { 209 + struct omap_reset_data *reset = to_omap_reset_data(rcdev); 210 + u32 v; 211 + unsigned long flags; 212 + 213 + /* assert the reset control line */ 214 + spin_lock_irqsave(&reset->lock, flags); 215 + v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 216 + v |= 1 << id; 217 + writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); 218 + spin_unlock_irqrestore(&reset->lock, flags); 219 + 220 + return 0; 221 + } 222 + 223 + static int omap_reset_deassert(struct reset_controller_dev *rcdev, 224 + unsigned long id) 225 + { 226 + struct omap_reset_data *reset = to_omap_reset_data(rcdev); 227 + u32 v; 228 + int st_bit; 229 + bool has_rstst; 230 + unsigned long flags; 231 + struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev); 232 + int ret = 0; 233 + 234 + has_rstst = reset->prm->data->rstst || 235 + (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); 236 + 237 + if (has_rstst) { 238 + st_bit = omap_reset_get_st_bit(reset, id); 239 + 240 + /* Clear the reset status by writing 1 to the status bit */ 241 + v = 1 << st_bit; 242 + writel_relaxed(v, reset->prm->base + reset->prm->data->rstst); 243 + } 244 + 245 + if (reset->clkdm) 246 + pdata->clkdm_deny_idle(reset->clkdm); 247 + 248 + /* de-assert the reset control line */ 249 + spin_lock_irqsave(&reset->lock, flags); 250 + v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 251 + v &= ~(1 << id); 252 + writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); 253 + spin_unlock_irqrestore(&reset->lock, flags); 254 + 255 + if (!has_rstst) 256 + goto exit; 257 + 258 + /* wait for the status to be set */ 259 + ret = readl_relaxed_poll_timeout(reset->prm->base + 260 + reset->prm->data->rstst, 261 + v, v & BIT(st_bit), 1, 262 + OMAP_RESET_MAX_WAIT); 263 + if (ret) 264 + pr_err("%s: timedout waiting for %s:%lu\n", __func__, 265 + reset->prm->data->name, id); 266 + 267 + exit: 268 + if (reset->clkdm) 269 + pdata->clkdm_allow_idle(reset->clkdm); 270 + 271 + return ret; 272 + } 273 + 274 + static const struct reset_control_ops omap_reset_ops = { 275 + .assert = omap_reset_assert, 276 + .deassert = omap_reset_deassert, 277 + .status = omap_reset_status, 278 + }; 279 + 280 + static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev, 281 + const struct of_phandle_args *reset_spec) 282 + { 283 + struct omap_reset_data *reset = to_omap_reset_data(rcdev); 284 + 285 + if (!_is_valid_reset(reset, reset_spec->args[0])) 286 + return -EINVAL; 287 + 288 + return reset_spec->args[0]; 289 + } 290 + 291 + static int omap_prm_reset_init(struct platform_device *pdev, 292 + struct omap_prm *prm) 293 + { 294 + struct omap_reset_data *reset; 295 + const struct omap_rst_map *map; 296 + struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev); 297 + char buf[32]; 298 + 299 + /* 300 + * Check if we have controllable resets. If either rstctrl is non-zero 301 + * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register 302 + * for the domain. 303 + */ 304 + if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL)) 305 + return 0; 306 + 307 + /* Check if we have the pdata callbacks in place */ 308 + if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle || 309 + !pdata->clkdm_allow_idle) 310 + return -EINVAL; 311 + 312 + map = prm->data->rstmap; 313 + if (!map) 314 + return -EINVAL; 315 + 316 + reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL); 317 + if (!reset) 318 + return -ENOMEM; 319 + 320 + reset->rcdev.owner = THIS_MODULE; 321 + reset->rcdev.ops = &omap_reset_ops; 322 + reset->rcdev.of_node = pdev->dev.of_node; 323 + reset->rcdev.nr_resets = OMAP_MAX_RESETS; 324 + reset->rcdev.of_xlate = omap_prm_reset_xlate; 325 + reset->rcdev.of_reset_n_cells = 1; 326 + reset->dev = &pdev->dev; 327 + spin_lock_init(&reset->lock); 328 + 329 + reset->prm = prm; 330 + 331 + sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name : 332 + prm->data->name); 333 + 334 + if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) { 335 + reset->clkdm = pdata->clkdm_lookup(buf); 336 + if (!reset->clkdm) 337 + return -EINVAL; 338 + } 339 + 340 + while (map->rst >= 0) { 341 + reset->mask |= BIT(map->rst); 342 + map++; 343 + } 344 + 345 + return devm_reset_controller_register(&pdev->dev, &reset->rcdev); 346 + } 347 + 348 + static int omap_prm_probe(struct platform_device *pdev) 349 + { 350 + struct resource *res; 351 + const struct omap_prm_data *data; 352 + struct omap_prm *prm; 353 + const struct of_device_id *match; 354 + 355 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 356 + if (!res) 357 + return -ENODEV; 358 + 359 + match = of_match_device(omap_prm_id_table, &pdev->dev); 360 + if (!match) 361 + return -ENOTSUPP; 362 + 363 + prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL); 364 + if (!prm) 365 + return -ENOMEM; 366 + 367 + data = match->data; 368 + 369 + while (data->base != res->start) { 370 + if (!data->base) 371 + return -EINVAL; 372 + data++; 373 + } 374 + 375 + prm->data = data; 376 + 377 + prm->base = devm_ioremap_resource(&pdev->dev, res); 378 + if (IS_ERR(prm->base)) 379 + return PTR_ERR(prm->base); 380 + 381 + return omap_prm_reset_init(pdev, prm); 382 + } 383 + 384 + static struct platform_driver omap_prm_driver = { 385 + .probe = omap_prm_probe, 386 + .driver = { 387 + .name = KBUILD_MODNAME, 388 + .of_match_table = omap_prm_id_table, 389 + }, 390 + }; 391 + builtin_platform_driver(omap_prm_driver);
+21
include/linux/platform_data/ti-prm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * TI PRM (Power & Reset Manager) platform data 4 + * 5 + * Copyright (C) 2019 Texas Instruments, Inc. 6 + * 7 + * Tero Kristo <t-kristo@ti.com> 8 + */ 9 + 10 + #ifndef _LINUX_PLATFORM_DATA_TI_PRM_H 11 + #define _LINUX_PLATFORM_DATA_TI_PRM_H 12 + 13 + struct clockdomain; 14 + 15 + struct ti_prm_platform_data { 16 + void (*clkdm_deny_idle)(struct clockdomain *clkdm); 17 + void (*clkdm_allow_idle)(struct clockdomain *clkdm); 18 + struct clockdomain * (*clkdm_lookup)(const char *name); 19 + }; 20 + 21 + #endif /* _LINUX_PLATFORM_DATA_TI_PRM_H */