From: Sergiu Moga <sergiu.moga@microchip.com>
To: <eugen.hristev@microchip.com>, <durai.manickamkr@microchip.com>,
<sandeep.sheriker@microchip.com>, <greg@embeddedgreg.com>,
<nicolas.ferre@microchip.com>, <ludovic.desroches@microchip.com>,
<lukma@denx.de>, <seanga2@gmail.com>, <marex@denx.de>,
<sergiu.moga@microchip.com>, <michael@walle.cc>, <hs@denx.de>,
<claudiu.beznea@microchip.com>,
<balamanikandan.gunasundar@microchip.com>,
<michael@amarulasolutions.com>,
<dario.binacchi@amarulasolutions.com>,
<cristian.birsan@microchip.com>, <peng.fan@nxp.com>,
<mihai.sain@microchip.com>, <weijie.gao@mediatek.com>,
<sumit.garg@linaro.org>, <jim.t90615@gmail.com>,
<michal.simek@amd.com>, <sjg@chromium.org>, <j-keerthy@ti.com>,
<ashok.reddy.soma@xilinx.com>
Cc: <u-boot@lists.denx.de>
Subject: [PATCH v4 12/19] phy: at91: Add support for the USB 2.0 PHY's of SAMA7
Date: Mon, 19 Dec 2022 10:46:20 +0200 [thread overview]
Message-ID: <20221219084626.34606-13-sergiu.moga@microchip.com> (raw)
In-Reply-To: <20221219084626.34606-1-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 -> v3:
- No change
v3 -> v4:
- Remove unnecessary `sama7_phy->sfr = NULL;` in sama7 usb phy driver
drivers/phy/Kconfig | 10 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-sama7-usb.c | 90 ++++++++++++++
drivers/phy/phy-sama7-utmi-clk.c | 202 +++++++++++++++++++++++++++++++
4 files changed, 303 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 cf4d5908d7..9fbb956783 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 a3b9f3c5b1..9d50affd47 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 0000000000..e941354f5f
--- /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;
+};
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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 0000000000..ab9fddccf6
--- /dev/null
+++ b/drivers/phy/phy-sama7-utmi-clk.c
@@ -0,0 +1,202 @@
+// 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 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(UTMI, utmi_clk->id), clk);
+
+ return clk;
+}
+
+static int sama7_utmi_probe(struct udevice *dev)
+{
+ struct clk *utmi_parent_clk, *utmi_clk;
+ struct regmap *regmap_sfr;
+ struct reset_ctl *phy_reset;
+ int i;
+ char name[16];
+
+ 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))
+ return PTR_ERR(phy_reset);
+
+ utmi_clk = 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))
+ return PTR_ERR(utmi_clk);
+ }
+
+ return 0;
+};
+
+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(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
next prev parent reply other threads:[~2022-12-19 8:50 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-19 8:46 [PATCH v4 00/19] Add USB on SAM9X60, SAMA7G5 and SAMA5D2 boards Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 01/19] ARM: dts: sam9x60: Add OHCI and EHCI DT nodes Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 02/19] clk: at91: Add support for sam9x60 USB clock Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 03/19] clk: at91: sam9x60: Register the required clocks for USB Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 04/19] clk: at91: pmc: export clock setup to pmc Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 05/19] clk: at91: sam9x60: Add initial setup of UPLL and USBCK rates Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 06/19] usb: ohci-at91: Enable OHCI functionality and register into DM Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 07/19] dt-bindings: reset: add sama7g5 definitions Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 08/19] dt-bindings: clk: at91: Define additional UTMI related clocks Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 09/19] ARM: dts: at91: sama7: Add USB related DT nodes Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 10/19] ARM: at91: add sama7 SFR definitions Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 11/19] reset: at91: Add reset driver for basic assert/deassert operations Sergiu Moga
2022-12-19 8:46 ` Sergiu Moga [this message]
2022-12-19 8:46 ` [PATCH v4 13/19] usb: ohci-at91: Add USB PHY functionality Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 14/19] ARM: dts: at91: sama5d2_icp: Add pinctrl nodes for USB related DT nodes Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 15/19] ARM: dts: at91: sama5d27_wlsom1_ek: Add pinctrl nodes for USB " Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 16/19] configs: at91: sam9x60ek: Add required configs for the USB command Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 17/19] configs: at91: sama5d2: Enable OHCI/EHCI related configs Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 18/19] configs: at91: sama7: Enable USB and RESET functionality Sergiu Moga
2022-12-19 8:46 ` [PATCH v4 19/19] usb: ohci-at91: Add `ohci_t` field in `ohci_at91_priv` Sergiu Moga
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221219084626.34606-13-sergiu.moga@microchip.com \
--to=sergiu.moga@microchip.com \
--cc=ashok.reddy.soma@xilinx.com \
--cc=balamanikandan.gunasundar@microchip.com \
--cc=claudiu.beznea@microchip.com \
--cc=cristian.birsan@microchip.com \
--cc=dario.binacchi@amarulasolutions.com \
--cc=durai.manickamkr@microchip.com \
--cc=eugen.hristev@microchip.com \
--cc=greg@embeddedgreg.com \
--cc=hs@denx.de \
--cc=j-keerthy@ti.com \
--cc=jim.t90615@gmail.com \
--cc=ludovic.desroches@microchip.com \
--cc=lukma@denx.de \
--cc=marex@denx.de \
--cc=michael@amarulasolutions.com \
--cc=michael@walle.cc \
--cc=michal.simek@amd.com \
--cc=mihai.sain@microchip.com \
--cc=nicolas.ferre@microchip.com \
--cc=peng.fan@nxp.com \
--cc=sandeep.sheriker@microchip.com \
--cc=seanga2@gmail.com \
--cc=sjg@chromium.org \
--cc=sumit.garg@linaro.org \
--cc=u-boot@lists.denx.de \
--cc=weijie.gao@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox