All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7
@ 2023-06-22 13:06 Eugen Hristev
  2023-06-22 13:07 ` [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Eugen Hristev
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Eugen Hristev @ 2023-06-22 13:06 UTC (permalink / raw)
  To: marex; +Cc: u-boot, eugen.hristev, Sergiu Moga, Mihai Sain

From: Sergiu Moga <sergiu.moga@microchip.com>

In order to have USB functionality, drivers for SAMA7's
USB 2.0 PHY's have been added. There is one driver
for UTMI clock's SFR and RESET required functionalities and
one for its three possible subclocks of the phy's themselves.
In order for this layout to properly work in conjunction with
CCF and DT, the former driver will also act as a clock provider
for the three phy's with the help of a custom hook into the
driver's of_xlate method.

Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
Tested-by: Mihai Sain <mihai.sain@microchip.com>
---

v1 -> v2:
- use *_bulk API's


v2 -> v3:
- use if (CONFIG_IS_ENABLED(...))

v3->v4:
- none


 drivers/phy/Kconfig              |  10 ++
 drivers/phy/Makefile             |   1 +
 drivers/phy/phy-sama7-usb.c      |  90 +++++++++++++
 drivers/phy/phy-sama7-utmi-clk.c | 216 +++++++++++++++++++++++++++++++
 4 files changed, 317 insertions(+)
 create mode 100644 drivers/phy/phy-sama7-usb.c
 create mode 100644 drivers/phy/phy-sama7-utmi-clk.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 7a2d54f71d21..999f9793fa3f 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -281,6 +281,16 @@ config PHY_XILINX_ZYNQMP
 	  Enable this to support ZynqMP High Speed Gigabit Transceiver
 	  that is part of ZynqMP SoC.
 
+config PHY_MICROCHIP_SAMA7_USB
+       tristate "Microchip SAMA7 USB 2.0 PHY"
+       depends on PHY && ARCH_AT91
+       help
+	 Enable this to support SAMA7 USB 2.0 PHY.
+
+	 The USB 2.0 PHY integrates high-speed, full-speed and low-speed
+	 termination and signal switching. With a single resistor, it
+	 requires minimal external components.
+
 source "drivers/phy/rockchip/Kconfig"
 source "drivers/phy/cadence/Kconfig"
 source "drivers/phy/ti/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index aca365d219c4..0b609768774a 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
 obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o
 obj-$(CONFIG_PHY_IMX8MQ_USB) += phy-imx8mq-usb.o
 obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o
+obj-$(CONFIG_PHY_MICROCHIP_SAMA7_USB)  += phy-sama7-utmi-clk.o phy-sama7-usb.o
 obj-y += cadence/
 obj-y += ti/
 obj-y += qcom/
diff --git a/drivers/phy/phy-sama7-usb.c b/drivers/phy/phy-sama7-usb.c
new file mode 100644
index 000000000000..200324d81281
--- /dev/null
+++ b/drivers/phy/phy-sama7-usb.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Atmel/Microchip USB PHY's.
+ *
+ * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Sergiu Moga <sergiu.moga@microchip.com>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <syscon.h>
+#include <regmap.h>
+#include <mach/sama7-sfr.h>
+
+struct sama7_usb_phy {
+	struct clk *uclk;
+	struct regmap *sfr;
+	int port;
+};
+
+static int sama7_usb_phy_init(struct phy *phy)
+{
+	struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev);
+	int port = sama7_phy->port;
+
+	regmap_update_bits(sama7_phy->sfr, SAMA7_SFR_UTMI0R(port),
+			   SAMA7_SFR_UTMI_RX_TX_PREEM_AMP_TUNE_1X,
+			   SAMA7_SFR_UTMI_RX_TX_PREEM_AMP_TUNE_1X);
+
+	regmap_update_bits(sama7_phy->sfr, SAMA7_SFR_UTMI0R(port),
+			   SAMA7_SFR_UTMI_RX_VBUS,
+			   SAMA7_SFR_UTMI_RX_VBUS);
+
+	return 0;
+}
+
+static int sama7_phy_power_on(struct phy *phy)
+{
+	struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev);
+
+	clk_prepare_enable(sama7_phy->uclk);
+
+	return 0;
+}
+
+static int sama7_phy_power_off(struct phy *phy)
+{
+	struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev);
+
+	clk_disable_unprepare(sama7_phy->uclk);
+
+	return 0;
+}
+
+static int sama7_usb_phy_probe(struct udevice *dev)
+{
+	struct sama7_usb_phy *sama7_phy = dev_get_priv(dev);
+
+	sama7_phy->uclk = devm_clk_get(dev, "utmi_clk");
+	if (IS_ERR(sama7_phy->uclk))
+		return PTR_ERR(sama7_phy->uclk);
+
+	sama7_phy->sfr = syscon_regmap_lookup_by_phandle(dev, "sfr-phandle");
+	if (IS_ERR(sama7_phy->sfr))
+		return PTR_ERR(sama7_phy->sfr);
+
+	return dev_read_u32(dev, "reg", &sama7_phy->port);
+}
+
+static const struct phy_ops sama7_usb_phy_ops = {
+	.init = sama7_usb_phy_init,
+	.power_on = sama7_phy_power_on,
+	.power_off = sama7_phy_power_off,
+};
+
+static const struct udevice_id sama7_usb_phy_of_match[] = {
+	{ .compatible = "microchip,sama7g5-usb-phy", },
+	{ },
+};
+
+U_BOOT_DRIVER(sama7_usb_phy_driver) = {
+	.name = "sama7-usb-phy",
+	.id = UCLASS_PHY,
+	.of_match = sama7_usb_phy_of_match,
+	.ops = &sama7_usb_phy_ops,
+	.probe = sama7_usb_phy_probe,
+	.priv_auto = sizeof(struct sama7_usb_phy),
+};
diff --git a/drivers/phy/phy-sama7-utmi-clk.c b/drivers/phy/phy-sama7-utmi-clk.c
new file mode 100644
index 000000000000..2371b4341cd5
--- /dev/null
+++ b/drivers/phy/phy-sama7-utmi-clk.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Atmel/Microchip USB PHY's.
+ *
+ * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Sergiu Moga <sergiu.moga@microchip.com>
+ */
+
+#include <dm.h>
+#include <linux/clk-provider.h>
+#include <syscon.h>
+#include <regmap.h>
+#include <mach/sama7-sfr.h>
+#include <reset.h>
+#include <dt-bindings/clk/at91.h>
+
+struct sama7_utmi_clk {
+	struct clk		uclk;
+	struct regmap		*regmap_sfr;
+	struct reset_ctl	*reset;
+	u8 id;
+};
+
+#define to_sama7_utmi_clk(_c) container_of(_c, struct sama7_utmi_clk, uclk)
+
+#define UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI "sama7-utmi-clk"
+#define UBOOT_DM_MICROCHIP_SAMA7G5_UTMI "sama7-utmi"
+#define USB_RESET_NAME_MAX_LEN 16
+
+#define AT91_TO_CLK_ID(_t, _i)		(((_t) << 8) | ((_i) & 0xff))
+
+/*
+ * UTMI clock description
+ * @n:	clock name
+ * @p:	clock parent name
+ * @id: clock id in RSTC_GRSTR
+ */
+static struct {
+	const char *n;
+	const char *p;
+	u8 id;
+} sama7_utmick[] = {
+	{ .n = "utmi1",	.p = "utmick", .id = 0, },
+	{ .n = "utmi2",	.p = "utmi1",  .id = 1, },
+	{ .n = "utmi3",	.p = "utmi1",  .id = 2, },
+};
+
+static int sama7_utmi_clk_enable(struct clk *clk)
+{
+	int ret;
+
+	struct sama7_utmi_clk *utmi = to_sama7_utmi_clk(clk);
+	u8 id = utmi->id;
+
+	ret = reset_assert(utmi->reset);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(utmi->regmap_sfr, SAMA7_SFR_UTMI0R(id),
+				 SAMA7_SFR_UTMI_COMMONON, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(utmi->reset);
+	if (ret)
+		return ret;
+
+	/* Datasheet states a minimum of 45 us before any USB operation */
+	udelay(50);
+
+	return 0;
+}
+
+static int sama7_utmi_clk_disable(struct clk *clk)
+{
+	int ret;
+	struct sama7_utmi_clk *utmi = to_sama7_utmi_clk(clk);
+	u8 id = utmi->id;
+
+	ret = reset_assert(utmi->reset);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(utmi->regmap_sfr, SAMA7_SFR_UTMI0R(id),
+			   SAMA7_SFR_UTMI_COMMONON, SAMA7_SFR_UTMI_COMMONON);
+
+	return 0;
+}
+
+static ulong sama7_utmi_clk_get_rate(struct clk *clk)
+{
+	/* Return utmick's rate: 480MHz */
+	return clk_get_parent_rate(clk);
+}
+
+static const struct clk_ops sama7_utmi_clk_ops = {
+	.enable = sama7_utmi_clk_enable,
+	.disable = sama7_utmi_clk_disable,
+	.get_rate = sama7_utmi_clk_get_rate,
+};
+
+static struct clk*
+sama7_utmi_clk_register(struct regmap *regmap_sfr, struct reset_ctl *reset,
+			const char *name, const char *parent_name, u8 id)
+{
+	struct clk *clk;
+	struct sama7_utmi_clk *utmi_clk;
+	int ret;
+
+	if (!regmap_sfr || !reset || !name || !parent_name)
+		return ERR_PTR(-EINVAL);
+
+	utmi_clk = kzalloc(sizeof(*utmi_clk), GFP_KERNEL);
+	if (!utmi_clk)
+		return ERR_PTR(-ENOMEM);
+
+	utmi_clk->reset = reset;
+	utmi_clk->regmap_sfr = regmap_sfr;
+	utmi_clk->id = id;
+
+	clk = &utmi_clk->uclk;
+	ret = clk_register(clk, UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI,
+			   name, parent_name);
+	if (ret) {
+		kfree(utmi_clk);
+		clk = ERR_PTR(ret);
+	}
+
+	clk_dm(AT91_TO_CLK_ID(USB_UTMI, utmi_clk->id), clk);
+
+	return clk;
+}
+
+static int sama7_utmi_probe(struct udevice *dev)
+{
+	struct clk *utmi_parent_clk, *utmi_clk[ARRAY_SIZE(sama7_utmick)];
+	char name[USB_RESET_NAME_MAX_LEN];
+	struct sama7_utmi_clk *uclk;
+	struct reset_ctl *phy_reset;
+	struct regmap *regmap_sfr;
+	int ret, i, j;
+
+	utmi_parent_clk = devm_clk_get(dev, "utmi_clk");
+	if (IS_ERR(utmi_parent_clk))
+		return PTR_ERR(utmi_parent_clk);
+
+	regmap_sfr = syscon_regmap_lookup_by_phandle(dev, "sfr-phandle");
+	if (IS_ERR(regmap_sfr))
+		return PTR_ERR(regmap_sfr);
+
+	for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) {
+		snprintf(name, sizeof(name), "usb%d_reset", i);
+		phy_reset = devm_reset_control_get(dev, name);
+		if (IS_ERR(phy_reset)) {
+			ret = PTR_ERR(phy_reset);
+			goto err_uclk_register;
+		}
+
+		utmi_clk[i] = sama7_utmi_clk_register(regmap_sfr, phy_reset,
+						      sama7_utmick[i].n,
+						      sama7_utmick[i].p,
+						      sama7_utmick[i].id);
+		if (IS_ERR(utmi_clk[i])) {
+			ret = PTR_ERR(utmi_clk[i]);
+			goto err_uclk_register;
+		}
+	}
+
+	return 0;
+
+err_uclk_register:
+	for (j = 0; j < i; j++) {
+		uclk = to_sama7_utmi_clk(utmi_clk[j]);
+		kfree(uclk);
+	}
+
+	return ret;
+};
+
+static const struct udevice_id sama7_utmi_clk_dt_ids[] = {
+	{ .compatible = "microchip,sama7g5-utmi-clk", },
+	{ /* sentinel */},
+};
+
+static int utmi_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	if (args->args_count != 1) {
+		debug("UTMI: clk: Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	clk->id = AT91_TO_CLK_ID(USB_UTMI, args->args[0]);
+
+	return 0;
+}
+
+static const struct clk_ops sama7_utmi_ops = {
+	.of_xlate	= utmi_clk_of_xlate,
+	.enable		= ccf_clk_enable,
+	.disable	= ccf_clk_disable,
+};
+
+U_BOOT_DRIVER(microhip_sama7g5_utmi_clk) = {
+	.name = UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI,
+	.id = UCLASS_CLK,
+	.ops = &sama7_utmi_clk_ops,
+};
+
+U_BOOT_DRIVER(microhip_sama7g5_utmi) = {
+	.name = UBOOT_DM_MICROCHIP_SAMA7G5_UTMI,
+	.of_match = sama7_utmi_clk_dt_ids,
+	.id = UCLASS_CLK,
+	.ops = &sama7_utmi_ops,
+	.probe = sama7_utmi_probe,
+};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM
  2023-06-22 13:06 [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Eugen Hristev
@ 2023-06-22 13:07 ` Eugen Hristev
  2023-06-22 15:19   ` Marek Vasut
  2023-06-22 13:07 ` [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality Eugen Hristev
  2023-06-22 15:14 ` [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Marek Vasut
  2 siblings, 1 reply; 6+ messages in thread
From: Eugen Hristev @ 2023-06-22 13:07 UTC (permalink / raw)
  To: marex; +Cc: u-boot, eugen.hristev, Sergiu Moga

From: Sergiu Moga <sergiu.moga@microchip.com>

Register the OHCI driver into DM by properly initializing the required
clocks and pins required by the DT node of OHCI. In order for the VBUS
to stay enabled, a `child_pre_probe` method has been added to overcome
the DM core disabling it in `usb_scan_device`: when the generic
`device_probe` method is called, the pinctrl is processed once again,
undoing whatever changes have been made in our driver's probe method.

Furthermore, enable CONFIG_DM_GPIO whenever this driver and CONFIG_DM_USB
are selected.

Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
---


v1 -> v2:
- squashed 3/4 into this patch
- removed bool clocked
- use *_blk API's
- select DM_GPIO in Kconfig if DM_USB enabled
- use dev_read_u32_default



v2 -> v3:
- check value of dev_read_addr
- clk_disable in case of failure after at91_start_hc


v3->v4:
none

 drivers/usb/host/Kconfig     |   1 +
 drivers/usb/host/ohci-at91.c | 159 +++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a883babf4c2..e9551a74bb23 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -437,6 +437,7 @@ config USB_ATMEL
 	depends on ARCH_AT91
 	select SYS_USB_OHCI_CPU_INIT
 	select USB_OHCI_NEW
+	select DM_GPIO if DM_USB
 
 choice
 	prompt "Clock for OHCI"
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 9b955c1bd678..92d0ab7184c4 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -5,6 +5,9 @@
  */
 
 #include <common.h>
+
+#if !(CONFIG_IS_ENABLED(DM_USB))
+
 #include <asm/arch/clk.h>
 
 int usb_cpu_init(void)
@@ -62,3 +65,159 @@ int usb_cpu_init_fail(void)
 {
 	return usb_cpu_stop();
 }
+
+#else
+
+#include <clk.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <usb.h>
+#include "ohci.h"
+
+#define AT91_MAX_USBH_PORTS        3
+
+#define at91_for_each_port(index, ports)					\
+		for ((index) = 0;						\
+		     (index) < min_t(u32, AT91_MAX_USBH_PORTS, (ports));	\
+		     (index)++)
+
+struct at91_usbh_data {
+	enum usb_init_type init_type;
+	struct gpio_desc vbus_pin[AT91_MAX_USBH_PORTS];
+	u32 ports;				/* number of ports on root hub */
+};
+
+struct ohci_at91_priv {
+	ohci_t ohci;
+	struct clk_bulk clks;
+};
+
+static int at91_start_clock(struct ohci_at91_priv *ohci_at91)
+{
+	return clk_enable_bulk(&ohci_at91->clks);
+}
+
+static int at91_stop_clock(struct ohci_at91_priv *ohci_at91)
+{
+	return clk_disable_bulk(&ohci_at91->clks);
+}
+
+static void ohci_at91_set_power(struct at91_usbh_data *pdata, int port,
+				bool enable)
+{
+	if (!dm_gpio_is_valid(&pdata->vbus_pin[port]))
+		return;
+
+	if (enable)
+		dm_gpio_set_dir_flags(&pdata->vbus_pin[port],
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	else
+		dm_gpio_set_dir_flags(&pdata->vbus_pin[port], 0);
+}
+
+static int at91_start_hc(struct udevice *dev)
+{
+	struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
+
+	return at91_start_clock(ohci_at91);
+}
+
+static int at91_stop_hc(struct udevice *dev)
+{
+	struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
+
+	return at91_stop_clock(ohci_at91);
+}
+
+static int ohci_atmel_deregister(struct udevice *dev)
+{
+	struct at91_usbh_data *pdata = dev_get_plat(dev);
+	int ret, i;
+
+	ret = at91_stop_hc(dev);
+	if (ret)
+		return ret;
+
+	at91_for_each_port(i, pdata->ports)
+		ohci_at91_set_power(pdata, i, false);
+
+	return ohci_deregister(dev);
+}
+
+static int ohci_atmel_child_pre_probe(struct udevice *dev)
+{
+	struct udevice *ohci_controller = dev_get_parent(dev);
+	struct at91_usbh_data *pdata = dev_get_plat(ohci_controller);
+	int i;
+
+	at91_for_each_port(i, pdata->ports)
+		ohci_at91_set_power(pdata, i, true);
+
+	return 0;
+}
+
+static int ohci_atmel_probe(struct udevice *dev)
+{
+	struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
+	struct at91_usbh_data *pdata = dev_get_plat(dev);
+	struct ohci_regs *regs;
+	int ret;
+	u32 i;
+
+	regs = (struct ohci_regs *)dev_read_addr(dev);
+	if (IS_ERR(regs)) {
+		ret = PTR_ERR(regs);
+		goto fail;
+	}
+
+	pdata->ports = dev_read_u32_default(dev, "num-ports", 3);
+
+	at91_for_each_port(i, pdata->ports)
+		gpio_request_by_name(dev, "atmel,vbus-gpio", i,
+				     &pdata->vbus_pin[i], GPIOD_IS_OUT |
+				     GPIOD_IS_OUT_ACTIVE);
+
+	ret = clk_get_bulk(dev, &ohci_at91->clks);
+	if (ret)
+		goto fail;
+
+	ret = clk_enable_bulk(&ohci_at91->clks);
+	if (ret)
+		goto fail;
+
+	ret = at91_start_hc(dev);
+	if (ret)
+		goto fail;
+
+	return ohci_register(dev, regs);
+
+fail:
+	at91_for_each_port(i, pdata->ports)
+		if (dm_gpio_is_valid(&pdata->vbus_pin[i]))
+			gpio_free(pdata->vbus_pin[i].offset);
+
+	clk_disable_bulk(&ohci_at91->clks);
+
+	return ret;
+}
+
+static const struct udevice_id ohci_usb_ids[] = {
+	{ .compatible = "atmel,at91rm9200-ohci", },
+	{ .compatible = "microchip,sama7g5-ohci", },
+	{ }
+};
+
+U_BOOT_DRIVER(ohci_atmel) = {
+	.name		 = "ohci_atmel",
+	.id		 = UCLASS_USB,
+	.of_match	 = ohci_usb_ids,
+	.probe		 = ohci_atmel_probe,
+	.remove		 = ohci_atmel_deregister,
+	.child_pre_probe = ohci_atmel_child_pre_probe,
+	.ops		 = &ohci_usb_ops,
+	.plat_auto	 = sizeof(struct at91_usbh_data),
+	.priv_auto	 = sizeof(struct ohci_at91_priv),
+	.flags		 = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+#endif /* CONFIG_IS_ENABLED(DM_USB) */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality
  2023-06-22 13:06 [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Eugen Hristev
  2023-06-22 13:07 ` [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Eugen Hristev
@ 2023-06-22 13:07 ` Eugen Hristev
  2023-06-22 15:24   ` Marek Vasut
  2023-06-22 15:14 ` [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Marek Vasut
  2 siblings, 1 reply; 6+ messages in thread
From: Eugen Hristev @ 2023-06-22 13:07 UTC (permalink / raw)
  To: marex; +Cc: u-boot, eugen.hristev, Sergiu Moga, Mihai Sain

From: Sergiu Moga <sergiu.moga@microchip.com>

Add the ability to enable/disable whatever USB PHY's are
passed to the AT91 OHCI driver through DT.

Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
Tested-by: Mihai Sain <mihai.sain@microchip.com>
Reviewed-by: Marek Vasut <marex@denx.de>
[eugen.hristev@collabora.com: disable PHYs in at91_start_clock if
clk_enable_bulk fails]
Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
---


v1 -> v2:
- use *_bulk API's


v2 -> v3:
- use if (CONFIG_IS_ENABLED(...))

v3 -> v4
[eugen.hristev@collabora.com: disable PHYs in at91_start_clock if
clk_enable_bulk fails]

 drivers/usb/host/ohci-at91.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 92d0ab7184c4..3d4f31d240aa 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -73,6 +73,7 @@ int usb_cpu_init_fail(void)
 #include <asm/gpio.h>
 #include <usb.h>
 #include "ohci.h"
+#include <generic-phy.h>
 
 #define AT91_MAX_USBH_PORTS        3
 
@@ -90,15 +91,36 @@ struct at91_usbh_data {
 struct ohci_at91_priv {
 	ohci_t ohci;
 	struct clk_bulk clks;
+	struct phy_bulk phys;
 };
 
 static int at91_start_clock(struct ohci_at91_priv *ohci_at91)
 {
-	return clk_enable_bulk(&ohci_at91->clks);
+	int ret;
+
+	if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) {
+		ret = generic_phy_power_on_bulk(&ohci_at91->phys);
+		if (ret)
+			return ret;
+	}
+
+	ret = clk_enable_bulk(&ohci_at91->clks);
+	if (ret)
+		generic_phy_power_off_bulk(&ohci_at91->phys);
+
+	return ret;
 }
 
 static int at91_stop_clock(struct ohci_at91_priv *ohci_at91)
 {
+	if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) {
+		int ret;
+
+		ret = generic_phy_power_off_bulk(&ohci_at91->phys);
+		if (ret)
+			return ret;
+	}
+
 	return clk_disable_bulk(&ohci_at91->clks);
 }
 
@@ -185,6 +207,16 @@ static int ohci_atmel_probe(struct udevice *dev)
 	if (ret)
 		goto fail;
 
+	if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) {
+		ret = generic_phy_get_bulk(dev, &ohci_at91->phys);
+		if (ret)
+			goto fail;
+
+		ret = generic_phy_init_bulk(&ohci_at91->phys);
+		if (ret)
+			goto fail;
+	}
+
 	ret = at91_start_hc(dev);
 	if (ret)
 		goto fail;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7
  2023-06-22 13:06 [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Eugen Hristev
  2023-06-22 13:07 ` [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Eugen Hristev
  2023-06-22 13:07 ` [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality Eugen Hristev
@ 2023-06-22 15:14 ` Marek Vasut
  2 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2023-06-22 15:14 UTC (permalink / raw)
  To: Eugen Hristev; +Cc: u-boot, Sergiu Moga, Mihai Sain

On 6/22/23 15:06, Eugen Hristev wrote:
> From: Sergiu Moga <sergiu.moga@microchip.com>
> 
> In order to have USB functionality, drivers for SAMA7's
> USB 2.0 PHY's have been added. There is one driver
> for UTMI clock's SFR and RESET required functionalities and
> one for its three possible subclocks of the phy's themselves.
> In order for this layout to properly work in conjunction with
> CCF and DT, the former driver will also act as a clock provider
> for the three phy's with the help of a custom hook into the
> driver's of_xlate method.
> 
> Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
> Tested-by: Mihai Sain <mihai.sain@microchip.com>

Reviewed-by: Marek Vasut <marex@denx.de>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM
  2023-06-22 13:07 ` [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Eugen Hristev
@ 2023-06-22 15:19   ` Marek Vasut
  0 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2023-06-22 15:19 UTC (permalink / raw)
  To: Eugen Hristev; +Cc: u-boot, Sergiu Moga

On 6/22/23 15:07, Eugen Hristev wrote:
> From: Sergiu Moga <sergiu.moga@microchip.com>
> 
> Register the OHCI driver into DM by properly initializing the required
> clocks and pins required by the DT node of OHCI. In order for the VBUS
> to stay enabled, a `child_pre_probe` method has been added to overcome
> the DM core disabling it in `usb_scan_device`: when the generic
> `device_probe` method is called, the pinctrl is processed once again,
> undoing whatever changes have been made in our driver's probe method.
> 
> Furthermore, enable CONFIG_DM_GPIO whenever this driver and CONFIG_DM_USB
> are selected.
> 
> Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>

Reviewed-by: Marek Vasut <marex@denx.de>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality
  2023-06-22 13:07 ` [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality Eugen Hristev
@ 2023-06-22 15:24   ` Marek Vasut
  0 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2023-06-22 15:24 UTC (permalink / raw)
  To: Eugen Hristev; +Cc: u-boot, Sergiu Moga, Mihai Sain

On 6/22/23 15:07, Eugen Hristev wrote:
> From: Sergiu Moga <sergiu.moga@microchip.com>
> 
> Add the ability to enable/disable whatever USB PHY's are
> passed to the AT91 OHCI driver through DT.
> 
> Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
> Tested-by: Mihai Sain <mihai.sain@microchip.com>
> Reviewed-by: Marek Vasut <marex@denx.de>
> [eugen.hristev@collabora.com: disable PHYs in at91_start_clock if
> clk_enable_bulk fails]
> Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
> ---
> 
> 
> v1 -> v2:
> - use *_bulk API's
> 
> 
> v2 -> v3:
> - use if (CONFIG_IS_ENABLED(...))
> 
> v3 -> v4
> [eugen.hristev@collabora.com: disable PHYs in at91_start_clock if
> clk_enable_bulk fails]
> 
>   drivers/usb/host/ohci-at91.c | 34 +++++++++++++++++++++++++++++++++-
>   1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
> index 92d0ab7184c4..3d4f31d240aa 100644
> --- a/drivers/usb/host/ohci-at91.c
> +++ b/drivers/usb/host/ohci-at91.c
> @@ -73,6 +73,7 @@ int usb_cpu_init_fail(void)
>   #include <asm/gpio.h>
>   #include <usb.h>
>   #include "ohci.h"
> +#include <generic-phy.h>
>   
>   #define AT91_MAX_USBH_PORTS        3
>   
> @@ -90,15 +91,36 @@ struct at91_usbh_data {
>   struct ohci_at91_priv {
>   	ohci_t ohci;
>   	struct clk_bulk clks;
> +	struct phy_bulk phys;
>   };
>   
>   static int at91_start_clock(struct ohci_at91_priv *ohci_at91)
>   {
> -	return clk_enable_bulk(&ohci_at91->clks);
> +	int ret;
> +
> +	if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) {
> +		ret = generic_phy_power_on_bulk(&ohci_at91->phys);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = clk_enable_bulk(&ohci_at91->clks);
> +	if (ret)
> +		generic_phy_power_off_bulk(&ohci_at91->phys);

A fail path (goto err;) would be nicer here.

> +	return ret;
>   }
>   
>   static int at91_stop_clock(struct ohci_at91_priv *ohci_at91)
>   {
> +	if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) {
> +		int ret;
> +
> +		ret = generic_phy_power_off_bulk(&ohci_at91->phys);
> +		if (ret)
> +			return ret;

Shouldn't this one ignore the return value and instead proceed to 
disable clock below ?

> +	}
> +
>   	return clk_disable_bulk(&ohci_at91->clks);
>   }

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-06-22 15:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-22 13:06 [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Eugen Hristev
2023-06-22 13:07 ` [PATCH v4 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Eugen Hristev
2023-06-22 15:19   ` Marek Vasut
2023-06-22 13:07 ` [PATCH v4 3/3] usb: ohci-at91: Add USB PHY functionality Eugen Hristev
2023-06-22 15:24   ` Marek Vasut
2023-06-22 15:14 ` [PATCH v4 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.