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 02/19] clk: at91: Add support for sam9x60 USB clock
Date: Mon, 19 Dec 2022 10:46:10 +0200 [thread overview]
Message-ID: <20221219084626.34606-3-sergiu.moga@microchip.com> (raw)
In-Reply-To: <20221219084626.34606-1-sergiu.moga@microchip.com>
Implement sam9x60 USB clock driver. This clock has
three parents: PLLA, UPLL and MAINXTAL. The driver is
aware of the three possible parents with the help of the
two mux tables provied to the driver during the registration
of the clock.
Signed-off-by: Sergiu Moga <sergiu.moga@microchip.com>
---
v1 -> v4:
- No change
drivers/clk/at91/Kconfig | 7 ++
drivers/clk/at91/Makefile | 1 +
drivers/clk/at91/clk-sam9x60-usb.c | 156 +++++++++++++++++++++++++++++
drivers/clk/at91/pmc.h | 11 ++
4 files changed, 175 insertions(+)
create mode 100644 drivers/clk/at91/clk-sam9x60-usb.c
diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig
index 4abc8026b4..4563892647 100644
--- a/drivers/clk/at91/Kconfig
+++ b/drivers/clk/at91/Kconfig
@@ -61,3 +61,10 @@ config AT91_SAM9X60_PLL
help
This option is used to enable the AT91 SAM9X60's PLL clock
driver.
+
+config AT91_SAM9X60_USB
+ bool "USB Clock support for SAM9X60 SoCs"
+ depends on CLK_AT91
+ help
+ This option is used to enable the AT91 SAM9X60's USB clock
+ driver.
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 580b406d7b..e53dcb4ca7 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -9,6 +9,7 @@ obj-y += clk-peripheral.o
obj-$(CONFIG_AT91_GENERIC_CLK) += clk-generic.o
obj-$(CONFIG_AT91_UTMI) += clk-utmi.o
obj-$(CONFIG_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o
+obj-$(CONFIG_AT91_SAM9X60_USB) += clk-sam9x60-usb.o
obj-$(CONFIG_SAMA7G5) += sama7g5.o
obj-$(CONFIG_SAM9X60) += sam9x60.o
else
diff --git a/drivers/clk/at91/clk-sam9x60-usb.c b/drivers/clk/at91/clk-sam9x60-usb.c
new file mode 100644
index 0000000000..0ccdc1494d
--- /dev/null
+++ b/drivers/clk/at91/clk-sam9x60-usb.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SAM9X60's USB Clock support.
+ *
+ * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Sergiu Moga <sergiu.moga@microchip.com>
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <linux/clk-provider.h>
+
+#include "pmc.h"
+
+#define UBOOT_DM_CLK_AT91_SAM9X60_USB "at91-sam9x60-usb-clk"
+
+struct sam9x60_usb {
+ const struct clk_usbck_layout *layout;
+ void __iomem *base;
+ struct clk clk;
+ const u32 *clk_mux_table;
+ const u32 *mux_table;
+ const char * const *parent_names;
+ u32 num_parents;
+ u8 id;
+};
+
+#define to_sam9x60_usb(_clk) container_of(_clk, struct sam9x60_usb, clk)
+#define USB_MAX_DIV 15
+
+static int sam9x60_usb_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct sam9x60_usb *usb = to_sam9x60_usb(clk);
+ u32 val, index;
+
+ index = at91_clk_mux_val_to_index(usb->clk_mux_table, usb->num_parents,
+ parent->id);
+ if (index < 0)
+ return index;
+
+ index = at91_clk_mux_index_to_val(usb->mux_table, usb->num_parents,
+ index);
+ if (index < 0)
+ return index;
+
+ pmc_read(usb->base, usb->layout->offset, &val);
+ val &= ~usb->layout->usbs_mask;
+ val |= index << (ffs(usb->layout->usbs_mask - 1));
+ pmc_write(usb->base, usb->layout->offset, val);
+
+ return 0;
+}
+
+static ulong sam9x60_usb_clk_get_rate(struct clk *clk)
+{
+ struct sam9x60_usb *usb = to_sam9x60_usb(clk);
+ ulong parent_rate = clk_get_parent_rate(clk);
+ u32 val, usbdiv;
+
+ if (!parent_rate)
+ return 0;
+
+ pmc_read(usb->base, usb->layout->offset, &val);
+ usbdiv = (val & usb->layout->usbdiv_mask) >>
+ (ffs(usb->layout->usbdiv_mask) - 1);
+ return parent_rate / (usbdiv + 1);
+}
+
+static ulong sam9x60_usb_clk_set_rate(struct clk *clk, ulong rate)
+{
+ struct sam9x60_usb *usb = to_sam9x60_usb(clk);
+ ulong parent_rate = clk_get_parent_rate(clk);
+ u32 usbdiv, val;
+
+ if (!parent_rate)
+ return 0;
+
+ usbdiv = DIV_ROUND_CLOSEST(parent_rate, rate);
+ if (usbdiv > USB_MAX_DIV + 1 || !usbdiv)
+ return 0;
+
+ pmc_read(usb->base, usb->layout->offset, &val);
+ val &= usb->layout->usbdiv_mask;
+ val |= (usbdiv - 1) << (ffs(usb->layout->usbdiv_mask) - 1);
+ pmc_write(usb->base, usb->layout->offset, val);
+
+ return parent_rate / usbdiv;
+}
+
+static const struct clk_ops sam9x60_usb_ops = {
+ .set_parent = sam9x60_usb_clk_set_parent,
+ .set_rate = sam9x60_usb_clk_set_rate,
+ .get_rate = sam9x60_usb_clk_get_rate,
+};
+
+struct clk *
+sam9x60_clk_register_usb(void __iomem *base, const char *name,
+ const char * const *parent_names, u8 num_parents,
+ const struct clk_usbck_layout *usbck_layout,
+ const u32 *clk_mux_table, const u32 *mux_table, u8 id)
+{
+ struct sam9x60_usb *usb;
+ struct clk *clk;
+ int ret;
+ u32 val, index;
+
+ if (!base || !name || !parent_names || !num_parents ||
+ !clk_mux_table || !mux_table)
+ return ERR_PTR(-EINVAL);
+
+ usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+ if (!usb)
+ return ERR_PTR(-ENOMEM);
+
+ usb->id = id;
+ usb->base = base;
+ usb->layout = usbck_layout;
+ usb->parent_names = parent_names;
+ usb->num_parents = num_parents;
+ usb->clk_mux_table = clk_mux_table;
+ usb->mux_table = mux_table;
+
+ clk = &usb->clk;
+ clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT;
+
+ pmc_read(usb->base, usb->layout->offset, &val);
+
+ val = (val & usb->layout->usbs_mask) >>
+ (ffs(usb->layout->usbs_mask) - 1);
+
+ index = at91_clk_mux_val_to_index(usb->mux_table, usb->num_parents,
+ val);
+
+ if (index < 0) {
+ kfree(usb);
+ return ERR_PTR(index);
+ }
+
+ ret = clk_register(clk, UBOOT_DM_CLK_AT91_SAM9X60_USB, name,
+ parent_names[index]);
+ if (ret) {
+ kfree(usb);
+ clk = ERR_PTR(ret);
+ }
+
+ return clk;
+}
+
+U_BOOT_DRIVER(at91_sam9x60_usb_clk) = {
+ .name = UBOOT_DM_CLK_AT91_SAM9X60_USB,
+ .id = UCLASS_CLK,
+ .ops = &sam9x60_usb_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 2b4dd9a3d9..17793b8802 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -71,6 +71,12 @@ struct clk_pcr_layout {
u32 pid_mask;
};
+struct clk_usbck_layout {
+ u32 offset;
+ u32 usbs_mask;
+ u32 usbdiv_mask;
+};
+
extern const struct clk_programmable_layout at91rm9200_programmable_layout;
extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
@@ -87,6 +93,11 @@ struct clk *at91_clk_sam9x5_main(void __iomem *reg, const char *name,
const char * const *parent_names, int num_parents,
const u32 *mux_table, int type);
struct clk *
+sam9x60_clk_register_usb(void __iomem *base, const char *name,
+ const char * const *parent_names, u8 num_parents,
+ const struct clk_usbck_layout *usbck_layout,
+ const u32 *clk_mux_table, const u32 *mux_table, u8 id);
+struct clk *
sam9x60_clk_register_div_pll(void __iomem *base, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_characteristics *characteristics,
--
2.34.1
next prev parent reply other threads:[~2022-12-19 8:47 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 ` Sergiu Moga [this message]
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 ` [PATCH v4 12/19] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Sergiu Moga
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-3-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