Commit 2bb1acc6 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'reset-for-v6.11-2' of git://git.pengutronix.de/pza/linux into soc/drivers

Reset controller updates for v6.11, part 2

This tag adds USB VBUS regulator control for Renesas RZ/G2L SoCs,
which also touches PHY driver and device tree, and pulls in a new
regulator_hardware_enable() helper.

The Tegra BPMP reset driver can be compiled under COMPILE_TEST now.

* tag 'reset-for-v6.11-2' of git://git.pengutronix.de/pza/linux:
  arm64: dts: renesas: rz-smarc: Replace fixed regulator for USB VBUS
  phy: renesas: phy-rcar-gen3-usb2: Control VBUS for RZ/G2L SoCs
  reset: renesas: Add USB VBUS regulator device as child
  dt-bindings: reset: renesas,rzg2l-usbphy-ctrl: Document USB VBUS regulator
  reset: tegra-bpmp: allow building under COMPILE_TEST
  regulator: core: Add helper for allow HW access to enable/disable regulator

Link: https://lore.kernel.org/r/20240703100809.2773890-1-p.zabel@pengutronix.deSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents ee22fbd7 c1267e1a
......@@ -42,6 +42,12 @@ properties:
0 = Port 1 Phy reset
1 = Port 2 Phy reset
regulator-vbus:
type: object
description: USB VBUS regulator
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
......@@ -49,6 +55,7 @@ required:
- resets
- power-domains
- '#reset-cells'
- regulator-vbus
additionalProperties: false
......@@ -64,4 +71,7 @@ examples:
resets = <&cpg R9A07G044_USB_PRESETN>;
power-domains = <&cpg>;
#reset-cells = <1>;
regulator-vbus {
regulator-name = "vbus";
};
};
......@@ -227,3 +227,9 @@ directly written to the voltage selector register, use::
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
To access the hardware for enabling/disabling the regulator, consumers must
use regulator_get_exclusive(), as it can't work if there's more than one
consumer. To enable/disable regulator use::
int regulator_hardware_enable(struct regulator *regulator, bool enable);
......@@ -54,14 +54,6 @@ codec_dai: simple-audio-card,codec {
};
};
usb0_vbus_otg: regulator-usb0-vbus-otg {
compatible = "regulator-fixed";
regulator-name = "USB0_VBUS_OTG";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
vccq_sdhi1: regulator-vccq-sdhi1 {
compatible = "regulator-gpio";
regulator-name = "SDHI1 VccQ";
......@@ -139,6 +131,9 @@ &ohci1 {
&phyrst {
status = "okay";
usb0_vbus_otg: regulator-vbus {
regulator-name = "vbus";
};
};
&scif0 {
......
......@@ -188,6 +188,9 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
if (ch->soc_no_adp_ctrl) {
if (ch->vbus)
regulator_hardware_enable(ch->vbus, vbus);
vbus_ctrl_reg = USB2_VBCTRL;
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
}
......@@ -718,7 +721,10 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (channel->soc_no_adp_ctrl && channel->is_otg_channel)
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
else
channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(channel->vbus)) {
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(channel->vbus);
......
......@@ -3408,6 +3408,34 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
}
EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
/**
* regulator_hardware_enable - access the HW for enable/disable regulator
* @regulator: regulator source
* @enable: true for enable, false for disable
*
* Request that the regulator be enabled/disabled with the regulator output at
* the predefined voltage or current value.
*
* On success 0 is returned, otherwise a negative errno is returned.
*/
int regulator_hardware_enable(struct regulator *regulator, bool enable)
{
struct regulator_dev *rdev = regulator->rdev;
const struct regulator_ops *ops = rdev->desc->ops;
int ret = -EOPNOTSUPP;
if (!rdev->exclusive || !ops || !ops->enable || !ops->disable)
return ret;
if (enable)
ret = ops->enable(rdev);
else
ret = ops->disable(rdev);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_hardware_enable);
/**
* regulator_get_linear_step - return the voltage step size between VSEL values
* @regulator: regulator source
......
......@@ -3,7 +3,7 @@ obj-y += core.o
obj-y += hisilicon/
obj-y += starfive/
obj-y += sti/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
......
......@@ -10,10 +10,12 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#define RESET 0x000
#define VBENCTL 0x03c
#define RESET_SEL_PLLRESET BIT(12)
#define RESET_PLLRESET BIT(8)
......@@ -32,6 +34,7 @@ struct rzg2l_usbphy_ctrl_priv {
struct reset_controller_dev rcdev;
struct reset_control *rstc;
void __iomem *base;
struct platform_device *vdev;
spinlock_t lock;
};
......@@ -100,10 +103,19 @@ static const struct reset_control_ops rzg2l_usbphy_ctrl_reset_ops = {
.status = rzg2l_usbphy_ctrl_status,
};
static const struct regmap_config rzg2l_usb_regconf = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 1,
};
static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rzg2l_usbphy_ctrl_priv *priv;
struct platform_device *vdev;
struct regmap *regmap;
unsigned long flags;
int error;
u32 val;
......@@ -116,6 +128,10 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
regmap = devm_regmap_init_mmio(dev, priv->base + VBENCTL, &rzg2l_usb_regconf);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(priv->rstc))
return dev_err_probe(dev, PTR_ERR(priv->rstc),
......@@ -152,8 +168,22 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
if (error)
goto err_pm_runtime_put;
vdev = platform_device_alloc("rzg2l-usb-vbus-regulator", pdev->id);
if (!vdev) {
error = -ENOMEM;
goto err_pm_runtime_put;
}
vdev->dev.parent = dev;
priv->vdev = vdev;
error = platform_device_add(vdev);
if (error)
goto err_device_put;
return 0;
err_device_put:
platform_device_put(vdev);
err_pm_runtime_put:
pm_runtime_put(&pdev->dev);
err_pm_disable_reset_deassert:
......@@ -166,6 +196,7 @@ static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
{
struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(&pdev->dev);
platform_device_unregister(priv->vdev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
reset_control_assert(priv->rstc);
......
# SPDX-License-Identifier: GPL-2.0-only
config RESET_TEGRA_BPMP
def_bool TEGRA_BPMP
bool "Tegra BPMP Reset Driver" if COMPILE_TEST
default TEGRA_BPMP
......@@ -250,6 +250,7 @@ int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_mask);
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
int regulator_hardware_enable(struct regulator *regulator, bool enable);
/* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator,
......@@ -571,6 +572,12 @@ static inline int regulator_list_hardware_vsel(struct regulator *regulator,
return -EOPNOTSUPP;
}
static inline int regulator_hardware_enable(struct regulator *regulator,
bool enable)
{
return -EOPNOTSUPP;
}
static inline int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment