Skip to content

Commit c5b7cd9

Browse files
claudiubezneapH5
authored andcommitted
reset: rzg2l-usbphy-ctrl: Add suspend/resume support
The RZ/G2L USBPHY control driver is also used on the RZ/G3S SoC. The RZ/G3S SoC supports a power-saving mode in which power to most USB components (including the USBPHY control block) is turned off. Because of this, the USBPHY control block needs to be reconfigured when returning from power-saving mode. Add suspend/resume support to handle runtime suspend/resume of the device, assert/deassert the reset signal, and reinitialize the USBPHY control block. Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
1 parent 2289ccd commit c5b7cd9

1 file changed

Lines changed: 84 additions & 15 deletions

File tree

drivers/reset/reset-rzg2l-usbphy-ctrl.c

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct rzg2l_usbphy_ctrl_priv {
3636
struct reset_control *rstc;
3737
void __iomem *base;
3838
struct platform_device *vdev;
39+
struct regmap_field *pwrrdy;
3940

4041
spinlock_t lock;
4142
};
@@ -92,6 +93,19 @@ static int rzg2l_usbphy_ctrl_status(struct reset_controller_dev *rcdev,
9293
return !!(readl(priv->base + RESET) & port_mask);
9394
}
9495

96+
/* put pll and phy into reset state */
97+
static void rzg2l_usbphy_ctrl_init(struct rzg2l_usbphy_ctrl_priv *priv)
98+
{
99+
unsigned long flags;
100+
u32 val;
101+
102+
spin_lock_irqsave(&priv->lock, flags);
103+
val = readl(priv->base + RESET);
104+
val |= RESET_SEL_PLLRESET | RESET_PLLRESET | PHY_RESET_PORT2 | PHY_RESET_PORT1;
105+
writel(val, priv->base + RESET);
106+
spin_unlock_irqrestore(&priv->lock, flags);
107+
}
108+
95109
#define RZG2L_USBPHY_CTRL_PWRRDY 1
96110

97111
static const struct of_device_id rzg2l_usbphy_ctrl_match_table[] = {
@@ -131,9 +145,9 @@ static void rzg2l_usbphy_ctrl_pwrrdy_off(void *data)
131145
rzg2l_usbphy_ctrl_set_pwrrdy(data, false);
132146
}
133147

134-
static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev)
148+
static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev,
149+
struct rzg2l_usbphy_ctrl_priv *priv)
135150
{
136-
struct regmap_field *pwrrdy;
137151
struct reg_field field;
138152
struct regmap *regmap;
139153
const int *data;
@@ -158,15 +172,15 @@ static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev)
158172
field.lsb = __ffs(args[1]);
159173
field.msb = __fls(args[1]);
160174

161-
pwrrdy = devm_regmap_field_alloc(dev, regmap, field);
162-
if (IS_ERR(pwrrdy))
163-
return PTR_ERR(pwrrdy);
175+
priv->pwrrdy = devm_regmap_field_alloc(dev, regmap, field);
176+
if (IS_ERR(priv->pwrrdy))
177+
return PTR_ERR(priv->pwrrdy);
164178

165179
ret = rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, true);
166180
if (ret)
167181
return ret;
168182

169-
return devm_add_action_or_reset(dev, rzg2l_usbphy_ctrl_pwrrdy_off, pwrrdy);
183+
return devm_add_action_or_reset(dev, rzg2l_usbphy_ctrl_pwrrdy_off, priv->pwrrdy);
170184
}
171185

172186
static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
@@ -175,9 +189,7 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
175189
struct rzg2l_usbphy_ctrl_priv *priv;
176190
struct platform_device *vdev;
177191
struct regmap *regmap;
178-
unsigned long flags;
179192
int error;
180-
u32 val;
181193

182194
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
183195
if (!priv)
@@ -191,7 +203,7 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
191203
if (IS_ERR(regmap))
192204
return PTR_ERR(regmap);
193205

194-
error = rzg2l_usbphy_ctrl_pwrrdy_init(dev);
206+
error = rzg2l_usbphy_ctrl_pwrrdy_init(dev, priv);
195207
if (error)
196208
return error;
197209

@@ -214,12 +226,7 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
214226
goto err_pm_disable_reset_deassert;
215227
}
216228

217-
/* put pll and phy into reset state */
218-
spin_lock_irqsave(&priv->lock, flags);
219-
val = readl(priv->base + RESET);
220-
val |= RESET_SEL_PLLRESET | RESET_PLLRESET | PHY_RESET_PORT2 | PHY_RESET_PORT1;
221-
writel(val, priv->base + RESET);
222-
spin_unlock_irqrestore(&priv->lock, flags);
229+
rzg2l_usbphy_ctrl_init(priv);
223230

224231
priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
225232
priv->rcdev.of_reset_n_cells = 1;
@@ -266,10 +273,72 @@ static void rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
266273
reset_control_assert(priv->rstc);
267274
}
268275

276+
static int rzg2l_usbphy_ctrl_suspend(struct device *dev)
277+
{
278+
struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(dev);
279+
u32 val;
280+
int ret;
281+
282+
val = readl(priv->base + RESET);
283+
if (!(val & PHY_RESET_PORT2) || !(val & PHY_RESET_PORT1))
284+
WARN(1, "Suspend with resets de-asserted\n");
285+
286+
pm_runtime_put_sync(dev);
287+
288+
ret = reset_control_assert(priv->rstc);
289+
if (ret)
290+
goto rpm_resume;
291+
292+
ret = rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, false);
293+
if (ret)
294+
goto reset_deassert;
295+
296+
return 0;
297+
298+
reset_deassert:
299+
reset_control_deassert(priv->rstc);
300+
rpm_resume:
301+
pm_runtime_resume_and_get(dev);
302+
return ret;
303+
}
304+
305+
static int rzg2l_usbphy_ctrl_resume(struct device *dev)
306+
{
307+
struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(dev);
308+
int ret;
309+
310+
ret = rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, true);
311+
if (ret)
312+
return ret;
313+
314+
ret = reset_control_deassert(priv->rstc);
315+
if (ret)
316+
goto pwrrdy_off;
317+
318+
ret = pm_runtime_resume_and_get(dev);
319+
if (ret)
320+
goto reset_assert;
321+
322+
rzg2l_usbphy_ctrl_init(priv);
323+
324+
return 0;
325+
326+
reset_assert:
327+
reset_control_assert(priv->rstc);
328+
pwrrdy_off:
329+
rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, false);
330+
return ret;
331+
}
332+
333+
static DEFINE_SIMPLE_DEV_PM_OPS(rzg2l_usbphy_ctrl_pm_ops,
334+
rzg2l_usbphy_ctrl_suspend,
335+
rzg2l_usbphy_ctrl_resume);
336+
269337
static struct platform_driver rzg2l_usbphy_ctrl_driver = {
270338
.driver = {
271339
.name = "rzg2l_usbphy_ctrl",
272340
.of_match_table = rzg2l_usbphy_ctrl_match_table,
341+
.pm = pm_ptr(&rzg2l_usbphy_ctrl_pm_ops),
273342
},
274343
.probe = rzg2l_usbphy_ctrl_probe,
275344
.remove = rzg2l_usbphy_ctrl_remove,

0 commit comments

Comments
 (0)