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

soc: ti: omap-prm: add support for denying idle for reset clockdomain

TI SoCs hardware reset signals require the parent clockdomain to be
in force wakeup mode while de-asserting the reset, otherwise it may
never complete. To support this, add pdata hooks to control the
clockdomain directly.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>

authored by

Tero Kristo and committed by
Santosh Shilimkar
d30cd83f c5117a78

+55 -2
+34 -2
drivers/soc/ti/omap_prm.c
··· 16 16 #include <linux/reset-controller.h> 17 17 #include <linux/delay.h> 18 18 19 + #include <linux/platform_data/ti-prm.h> 20 + 19 21 struct omap_rst_map { 20 22 s8 rst; 21 23 s8 st; ··· 26 24 struct omap_prm_data { 27 25 u32 base; 28 26 const char *name; 27 + const char *clkdm_name; 29 28 u16 rstctrl; 30 29 u16 rstst; 31 30 const struct omap_rst_map *rstmap; ··· 43 40 struct omap_prm *prm; 44 41 u32 mask; 45 42 spinlock_t lock; 43 + struct clockdomain *clkdm; 44 + struct device *dev; 46 45 }; 47 46 48 47 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev) ··· 54 49 55 50 #define OMAP_PRM_HAS_RSTCTRL BIT(0) 56 51 #define OMAP_PRM_HAS_RSTST BIT(1) 52 + #define OMAP_PRM_HAS_NO_CLKDM BIT(2) 57 53 58 54 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) 59 55 ··· 139 133 int st_bit; 140 134 bool has_rstst; 141 135 unsigned long flags; 136 + struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev); 137 + int ret = 0; 142 138 143 139 has_rstst = reset->prm->data->rstst || 144 140 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); ··· 153 145 writel_relaxed(v, reset->prm->base + reset->prm->data->rstst); 154 146 } 155 147 148 + if (reset->clkdm) 149 + pdata->clkdm_deny_idle(reset->clkdm); 150 + 156 151 /* de-assert the reset control line */ 157 152 spin_lock_irqsave(&reset->lock, flags); 158 153 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); ··· 164 153 spin_unlock_irqrestore(&reset->lock, flags); 165 154 166 155 if (!has_rstst) 167 - return 0; 156 + goto exit; 168 157 169 158 /* wait for the status to be set */ 170 159 ret = readl_relaxed_poll_timeout(reset->prm->base + ··· 175 164 pr_err("%s: timedout waiting for %s:%lu\n", __func__, 176 165 reset->prm->data->name, id); 177 166 178 - return 0; 167 + exit: 168 + if (reset->clkdm) 169 + pdata->clkdm_allow_idle(reset->clkdm); 170 + 171 + return ret; 179 172 } 180 173 181 174 static const struct reset_control_ops omap_reset_ops = { ··· 204 189 { 205 190 struct omap_reset_data *reset; 206 191 const struct omap_rst_map *map; 192 + struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev); 193 + char buf[32]; 207 194 208 195 /* 209 196 * Check if we have controllable resets. If either rstctrl is non-zero ··· 214 197 */ 215 198 if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL)) 216 199 return 0; 200 + 201 + /* Check if we have the pdata callbacks in place */ 202 + if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle || 203 + !pdata->clkdm_allow_idle) 204 + return -EINVAL; 217 205 218 206 map = prm->data->rstmap; 219 207 if (!map) ··· 234 212 reset->rcdev.nr_resets = OMAP_MAX_RESETS; 235 213 reset->rcdev.of_xlate = omap_prm_reset_xlate; 236 214 reset->rcdev.of_reset_n_cells = 1; 215 + reset->dev = &pdev->dev; 237 216 spin_lock_init(&reset->lock); 238 217 239 218 reset->prm = prm; 219 + 220 + sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name : 221 + prm->data->name); 222 + 223 + if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) { 224 + reset->clkdm = pdata->clkdm_lookup(buf); 225 + if (!reset->clkdm) 226 + return -EINVAL; 227 + } 240 228 241 229 while (map->rst >= 0) { 242 230 reset->mask |= BIT(map->rst);
+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 */