Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1359552 > unrolled thread
| Started by | David Lechner <david@lechnology.com> |
|---|---|
| First post | 2016-03-17 04:40 +0100 |
| Last post | 2016-03-23 18:30 +0100 |
| Articles | 20 on this page of 22 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH v2 00/11] da8xx USB clocks David Lechner <david@lechnology.com> - 2016-03-17 04:40 +0100
[PATCH v2 07/11] ARM: davinci: da8xx: Add USB PHY platform declaration David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
[PATCH v2 10/11] usb: musb: da8xx: Use devm in probe David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
Re: [PATCH v2 10/11] usb: musb: da8xx: Use devm in probe Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> - 2016-03-17 12:10 +0100
[PATCH v2 02/11] ARM: davinci: add set_parent callback for mux clocks David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
[PATCH v2 01/11] ARM: davinci: defined missing CFGCHIP2_REFFREQ_* macros for MUSB PHY David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
[PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
Re: [PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> - 2016-03-17 14:00 +0100
Re: [PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach Alan Stern <stern@rowland.harvard.edu> - 2016-03-17 19:10 +0100
[PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> - 2016-03-17 13:20 +0100
Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks Sekhar Nori <nsekhar@ti.com> - 2016-03-23 18:00 +0100
Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks David Lechner <david@lechnology.com> - 2016-03-23 18:50 +0100
Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks Sekhar Nori <nsekhar@ti.com> - 2016-03-23 19:00 +0100
[PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 David Lechner <david@lechnology.com> - 2016-03-17 04:50 +0100
Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 Sekhar Nori <nsekhar@ti.com> - 2016-03-23 17:00 +0100
Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 David Lechner <david@lechnology.com> - 2016-03-23 18:30 +0100
Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 Sekhar Nori <nsekhar@ti.com> - 2016-03-23 18:40 +0100
Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 David Lechner <david@lechnology.com> - 2016-03-23 19:40 +0100
Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 Sekhar Nori <nsekhar@ti.com> - 2016-03-24 14:50 +0100
Re: [PATCH v2 00/11] da8xx USB clocks Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> - 2016-03-17 14:40 +0100
Re: [PATCH v2 00/11] da8xx USB clocks Sekhar Nori <nsekhar@ti.com> - 2016-03-23 18:30 +0100
Page 1 of 2 [1] 2 Next page →
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:40 +0100 |
| Subject | [PATCH v2 00/11] da8xx USB clocks |
| Message-ID | <rdwWZ-1LR-3@gated-at.bofh.it> |
OK, ready for round two. I've added a new callback in the davinci clocks so that they can properly handle clock muxing. The clock functions are pretty much the same as in the previous patch set other than clk_set_parent() now works. The next new thing is a phy driver for the CFGCHIP2 register that controls the SoC USB PHY (both USB 1.1 and USB 2.0). The ohci and musb drivers have been updated to use this new phy driver. David Lechner (10): ARM: davinci: add set_parent callback for mux clocks ARM: davinci: da850: use clk->set_parent for async3 ARM: davinci: da8xx: add usb phy clocks dt-bindings: Add bindings for phy-da8xx-usb phy: da8xx-usb: new driver for DA8XX SoC USB PHY ARM: davinci: da8xx: Add USB PHY platform declaration ARM: dt: da850: Add usb phy node usb: ohci-da8xx: Remove code that references mach usb: musb: da8xx: Use devm in probe usb: musb: da8xx: Remove mach code Petr Kulhavy (1): ARM: davinci: defined missing CFGCHIP2_REFFREQ_* macros for MUSB PHY .../devicetree/bindings/phy/phy-da8xx-usb.txt | 34 +++ arch/arm/boot/dts/da850.dtsi | 6 + arch/arm/mach-davinci/board-da830-evm.c | 12 - arch/arm/mach-davinci/board-omapl138-hawk.c | 7 - arch/arm/mach-davinci/clock.c | 17 +- arch/arm/mach-davinci/clock.h | 1 + arch/arm/mach-davinci/da830.c | 143 ++++++++++ arch/arm/mach-davinci/da850.c | 231 ++++++++++++---- arch/arm/mach-davinci/include/mach/da8xx.h | 1 + arch/arm/mach-davinci/usb.c | 24 +- drivers/phy/Kconfig | 9 + drivers/phy/Makefile | 1 + drivers/phy/phy-da8xx-usb.c | 295 +++++++++++++++++++++ drivers/usb/host/ohci-da8xx.c | 90 +++---- drivers/usb/musb/da8xx.c | 150 +++-------- include/linux/platform_data/usb-davinci.h | 6 + 16 files changed, 799 insertions(+), 228 deletions(-) create mode 100644 Documentation/devicetree/bindings/phy/phy-da8xx-usb.txt create mode 100644 drivers/phy/phy-da8xx-usb.c -- 1.9.1
[toc] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 07/11] ARM: davinci: da8xx: Add USB PHY platform declaration |
| Message-ID | <rdx6F-1Ps-1@gated-at.bofh.it> |
| In reply to | #1359552 |
There is now a proper phy driver for the DA8XX SoC USB PHY. This adds the
platform device declarations needed to use it.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: This is new patch in v2.
arch/arm/mach-davinci/include/mach/da8xx.h | 1 +
arch/arm/mach-davinci/usb.c | 24 +++++++++++++++++++++++-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index f9f9713..049d26f 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -88,6 +88,7 @@ int da850_register_edma(struct edma_rsv_info *rsv[2]);
int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
int da8xx_register_spi_bus(int instance, unsigned num_chipselect);
int da8xx_register_watchdog(void);
+int da8xx_register_usbphy(void);
int da8xx_register_usb20(unsigned mA, unsigned potpgt);
int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
int da8xx_register_emac(void);
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index b0a6b52..6a0802e 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -4,7 +4,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-
+#include <linux/phy/phy.h>
#include <linux/usb/musb.h>
#include <mach/common.h>
@@ -18,6 +18,28 @@
#define DA8XX_USB0_BASE 0x01e00000
#define DA8XX_USB1_BASE 0x01e25000
+#ifdef CONFIG_ARCH_DAVINCI_DA8XX
+static struct resource da8xx_usbphy_resources[] = {
+ [0] = {
+ .start = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG,
+ .end = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device da8xx_usbphy = {
+ .name = "da8xx-usbphy",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(da8xx_usbphy_resources),
+ .resource = da8xx_usbphy_resources,
+};
+
+int __init da8xx_register_usbphy(void)
+{
+ return platform_device_register(&da8xx_usbphy);
+}
+#endif /* CONFIG_ARCH_DAVINCI_DA8XX */
+
#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
static struct musb_hdrc_eps_bits musb_eps[] = {
{ "ep1_tx", 8, },
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 10/11] usb: musb: da8xx: Use devm in probe |
| Message-ID | <rdx6G-1Ps-9@gated-at.bofh.it> |
| In reply to | #1359552 |
Simplify things a bit by using devm functions where possible.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: This is part of a previous patch that was split. No changes from
previous version.
drivers/usb/musb/da8xx.c | 28 ++++++++--------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index b03d3b8..50f07a5 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -489,32 +489,27 @@ static int da8xx_probe(struct platform_device *pdev)
struct platform_device *musb;
struct da8xx_glue *glue;
struct platform_device_info pinfo;
- struct clk *clk;
+ int ret;
- int ret = -ENOMEM;
-
- glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(&pdev->dev, "failed to allocate glue context\n");
- goto err0;
+ return -ENOMEM;
}
- clk = clk_get(&pdev->dev, "usb20");
- if (IS_ERR(clk)) {
+ glue->clk = devm_clk_get(&pdev->dev, "usb20");
+ if (IS_ERR(glue->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
- ret = PTR_ERR(clk);
- goto err3;
+ return PTR_ERR(glue->clk);
}
- ret = clk_enable(clk);
+ ret = clk_enable(glue->clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n");
goto err4;
}
glue->dev = &pdev->dev;
- glue->clk = clk;
-
pdata->platform_ops = &da8xx_ops;
glue->phy = usb_phy_generic_register();
@@ -557,15 +552,10 @@ err6:
usb_phy_generic_unregister(glue->phy);
err5:
- clk_disable(clk);
+ clk_disable(glue->clk);
err4:
- clk_put(clk);
-
-err3:
- kfree(glue);
-err0:
return ret;
}
@@ -576,8 +566,6 @@ static int da8xx_remove(struct platform_device *pdev)
platform_device_unregister(glue->musb);
usb_phy_generic_unregister(glue->phy);
clk_disable(glue->clk);
- clk_put(glue->clk);
- kfree(glue);
return 0;
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
|---|---|
| Date | 2016-03-17 12:10 +0100 |
| Subject | Re: [PATCH v2 10/11] usb: musb: da8xx: Use devm in probe |
| Message-ID | <rdDYu-6EU-5@gated-at.bofh.it> |
| In reply to | #1359557 |
Hello.
On 3/17/2016 5:26 AM, David Lechner wrote:
> Simplify things a bit by using devm functions where possible.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>
> v2 changes: This is part of a previous patch that was split. No changes from
> previous version.
>
>
> drivers/usb/musb/da8xx.c | 28 ++++++++--------------------
> 1 file changed, 8 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
> index b03d3b8..50f07a5 100644
> --- a/drivers/usb/musb/da8xx.c
> +++ b/drivers/usb/musb/da8xx.c
> @@ -489,32 +489,27 @@ static int da8xx_probe(struct platform_device *pdev)
> struct platform_device *musb;
> struct da8xx_glue *glue;
> struct platform_device_info pinfo;
> - struct clk *clk;
I wouldn't remove this variable to minimize the patch.
[...]
MBR, Sergei
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 02/11] ARM: davinci: add set_parent callback for mux clocks |
| Message-ID | <rdx6G-1Ps-13@gated-at.bofh.it> |
| In reply to | #1359552 |
Introduce a set_parent callback that will be used for mux clocks, such as
the USB PHY muxes and the async3 clock domain mux.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: This is a new patch in v2.
arch/arm/mach-davinci/clock.c | 17 ++++++++++++++++-
arch/arm/mach-davinci/clock.h | 1 +
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 3424eac6..3143e8b 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -195,6 +195,13 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
return -EINVAL;
mutex_lock(&clocks_mutex);
+ if (clk->set_parent) {
+ int ret = clk->set_parent(clk, parent);
+ if (ret) {
+ mutex_unlock(&clocks_mutex);
+ return ret;
+ }
+ }
clk->parent = parent;
list_del_init(&clk->childnode);
list_add(&clk->childnode, &clk->parent->children);
@@ -224,8 +231,16 @@ int clk_register(struct clk *clk)
mutex_lock(&clocks_mutex);
list_add_tail(&clk->node, &clocks);
- if (clk->parent)
+ if (clk->parent) {
+ if (clk->set_parent) {
+ int ret = clk->set_parent(clk, clk->parent);
+ if (ret) {
+ mutex_unlock(&clocks_mutex);
+ return ret;
+ }
+ }
list_add_tail(&clk->childnode, &clk->parent->children);
+ }
mutex_unlock(&clocks_mutex);
/* If rate is already set, use it */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 1e4e836..e2a5437 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -106,6 +106,7 @@ struct clk {
int (*reset) (struct clk *clk, bool reset);
void (*clk_enable) (struct clk *clk);
void (*clk_disable) (struct clk *clk);
+ int (*set_parent) (struct clk *clk, struct clk *parent);
};
/* Clock flags: SoC-specific flags start at BIT(16) */
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 01/11] ARM: davinci: defined missing CFGCHIP2_REFFREQ_* macros for MUSB PHY |
| Message-ID | <rdx6G-1Ps-21@gated-at.bofh.it> |
| In reply to | #1359552 |
From: Petr Kulhavy <petr@barix.com> Only few MUSB PHY reference clock frequencies were defined. This patch defines macros for the missing frequencies: 19.2MHz, 38.4MHz, 13MHz, 26MHz, 20MHz, 40MHz Signed-off-by: Petr Kulhavy <petr@barix.com>. Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: Bin Liu <b-liu@ti.com> --- v2 changes: None. include/linux/platform_data/usb-davinci.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/platform_data/usb-davinci.h b/include/linux/platform_data/usb-davinci.h index e0bc4ab..961d3dc 100644 --- a/include/linux/platform_data/usb-davinci.h +++ b/include/linux/platform_data/usb-davinci.h @@ -33,6 +33,12 @@ #define CFGCHIP2_REFFREQ_12MHZ (1 << 0) #define CFGCHIP2_REFFREQ_24MHZ (2 << 0) #define CFGCHIP2_REFFREQ_48MHZ (3 << 0) +#define CFGCHIP2_REFFREQ_19_2MHZ (4 << 0) +#define CFGCHIP2_REFFREQ_38_4MHZ (5 << 0) +#define CFGCHIP2_REFFREQ_13MHZ (6 << 0) +#define CFGCHIP2_REFFREQ_26MHZ (7 << 0) +#define CFGCHIP2_REFFREQ_20MHZ (8 << 0) +#define CFGCHIP2_REFFREQ_40MHZ (9 << 0) struct da8xx_ohci_root_hub; -- 1.9.1
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach |
| Message-ID | <rdx6H-1Ps-31@gated-at.bofh.it> |
| In reply to | #1359552 |
Including mach/* is frowned upon in device drivers, so get rid of it.
This replaces usb20_clk and code that pokes CFGCHIP2 with a proper phy
driver.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: Uses the new phy driver instead of using a second clock.
drivers/usb/host/ohci-da8xx.c | 90 +++++++++++++++++++++----------------------
1 file changed, 44 insertions(+), 46 deletions(-)
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index e5c33bc..c648674 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -15,58 +15,40 @@
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-
-#include <mach/da8xx.h>
+#include <linux/phy/phy.h>
#include <linux/platform_data/usb-davinci.h>
#ifndef CONFIG_ARCH_DAVINCI_DA8XX
#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
#endif
-#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)
-
static struct clk *usb11_clk;
-static struct clk *usb20_clk;
+static struct phy *usb11_phy;
/* Over-current indicator change bitmask */
static volatile u16 ocic_mask;
-static void ohci_da8xx_clock(int on)
+static int ohci_da8xx_enable(void)
{
- u32 cfgchip2;
-
- cfgchip2 = __raw_readl(CFGCHIP2);
- if (on) {
- clk_enable(usb11_clk);
-
- /*
- * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we
- * need to enable the USB 2.0 module clocking, start its PHY,
- * and not allow it to stop the clock during USB 2.0 suspend.
- */
- if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) {
- clk_enable(usb20_clk);
-
- cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
- cfgchip2 |= CFGCHIP2_PHY_PLLON;
- __raw_writel(cfgchip2, CFGCHIP2);
-
- pr_info("Waiting for USB PHY clock good...\n");
- while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD))
- cpu_relax();
- }
+ int ret;
- /* Enable USB 1.1 PHY */
- cfgchip2 |= CFGCHIP2_USB1SUSPENDM;
- } else {
- clk_disable(usb11_clk);
- if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX))
- clk_disable(usb20_clk);
+ ret = clk_prepare_enable(usb11_clk);
+ if (ret)
+ return ret;
- /* Disable USB 1.1 PHY */
- cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM;
+ ret = phy_power_on(usb11_phy);
+ if (ret) {
+ clk_disable_unprepare(usb11_clk);
+ return ret;
}
- __raw_writel(cfgchip2, CFGCHIP2);
+
+ return 0;
+}
+
+static void ohci_da8xx_disable(void)
+{
+ phy_power_off(usb11_phy);
+ clk_disable_unprepare(usb11_clk);
}
/*
@@ -92,7 +74,9 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
dev_dbg(dev, "starting USB controller\n");
- ohci_da8xx_clock(1);
+ result = ohci_da8xx_enable();
+ if (result < 0)
+ return result;
/*
* DA8xx only have 1 port connected to the pins but the HC root hub
@@ -101,8 +85,10 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
ohci->num_ports = 1;
result = ohci_init(ohci);
- if (result < 0)
+ if (result < 0) {
+ ohci_da8xx_disable();
return result;
+ }
/*
* Since we're providing a board-specific root hub port power control
@@ -129,7 +115,7 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
static void ohci_da8xx_stop(struct usb_hcd *hcd)
{
ohci_stop(hcd);
- ohci_da8xx_clock(0);
+ ohci_da8xx_disable();
}
static int ohci_da8xx_start(struct usb_hcd *hcd)
@@ -301,12 +287,18 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
return -ENODEV;
usb11_clk = devm_clk_get(&pdev->dev, "usb11");
- if (IS_ERR(usb11_clk))
+ if (IS_ERR(usb11_clk)) {
+ if (PTR_ERR(usb11_clk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get clock.\n");
return PTR_ERR(usb11_clk);
+ }
- usb20_clk = devm_clk_get(&pdev->dev, "usb20");
- if (IS_ERR(usb20_clk))
- return PTR_ERR(usb20_clk);
+ usb11_phy = devm_phy_get(&pdev->dev, "usbphy");
+ if (IS_ERR(usb11_phy)) {
+ if (PTR_ERR(usb11_phy) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get phy.\n");
+ return PTR_ERR(usb11_phy);
+ }
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd)
@@ -316,6 +308,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
hcd->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(hcd->regs)) {
error = PTR_ERR(hcd->regs);
+ dev_err(&pdev->dev, "failed to map ohci.\n");
goto err;
}
hcd->rsrc_start = mem->start;
@@ -397,7 +390,7 @@ static int ohci_da8xx_suspend(struct platform_device *pdev,
if (ret)
return ret;
- ohci_da8xx_clock(0);
+ ohci_da8xx_disable();
hcd->state = HC_STATE_SUSPENDED;
return ret;
@@ -407,14 +400,19 @@ static int ohci_da8xx_resume(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
- ohci_da8xx_clock(1);
+ ret = ohci_da8xx_enable();
+ if (ret)
+ return ret;
+
dev->dev.power.power_state = PMSG_ON;
usb_hcd_resume_root_hub(hcd);
+
return 0;
}
#endif
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
|---|---|
| Date | 2016-03-17 14:00 +0100 |
| Subject | Re: [PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach |
| Message-ID | <rdFGX-7xG-17@gated-at.bofh.it> |
| In reply to | #1359563 |
On 3/17/2016 5:26 AM, David Lechner wrote:
> Including mach/* is frowned upon in device drivers, so get rid of it.
>
> This replaces usb20_clk and code that pokes CFGCHIP2 with a proper phy
> driver.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>
> v2 changes: Uses the new phy driver instead of using a second clock.
>
>
> drivers/usb/host/ohci-da8xx.c | 90 +++++++++++++++++++++----------------------
> 1 file changed, 44 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
> index e5c33bc..c648674 100644
> --- a/drivers/usb/host/ohci-da8xx.c
> +++ b/drivers/usb/host/ohci-da8xx.c
> @@ -15,58 +15,40 @@
> #include <linux/jiffies.h>
> #include <linux/platform_device.h>
> #include <linux/clk.h>
> -
> -#include <mach/da8xx.h>
> +#include <linux/phy/phy.h>
> #include <linux/platform_data/usb-davinci.h>
>
> #ifndef CONFIG_ARCH_DAVINCI_DA8XX
> #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
> #endif
>
> -#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)
> -
> static struct clk *usb11_clk;
> -static struct clk *usb20_clk;
> +static struct phy *usb11_phy;
>
> /* Over-current indicator change bitmask */
> static volatile u16 ocic_mask;
>
> -static void ohci_da8xx_clock(int on)
> +static int ohci_da8xx_enable(void)
> {
[...]
> + ret = clk_prepare_enable(usb11_clk);
> + if (ret)
> + return ret;
>
> - /* Disable USB 1.1 PHY */
> - cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM;
> + ret = phy_power_on(usb11_phy);
Aren't you supposed to call phy_init() first?
> + if (ret) {
> + clk_disable_unprepare(usb11_clk);
> + return ret;
> }
> - __raw_writel(cfgchip2, CFGCHIP2);
> +
> + return 0;
> +}
> +
> +static void ohci_da8xx_disable(void)
> +{
> + phy_power_off(usb11_phy);
... and phy_exit() after that?
> + clk_disable_unprepare(usb11_clk);
> }
>
> /*
[...]
MBR, Sergei
[toc] | [prev] | [next] | [standalone]
| From | Alan Stern <stern@rowland.harvard.edu> |
|---|---|
| Date | 2016-03-17 19:10 +0100 |
| Subject | Re: [PATCH v2 09/11] usb: ohci-da8xx: Remove code that references mach |
| Message-ID | <rdKwY-2ml-33@gated-at.bofh.it> |
| In reply to | #1359563 |
On Wed, 16 Mar 2016, David Lechner wrote: > Including mach/* is frowned upon in device drivers, so get rid of it. > > This replaces usb20_clk and code that pokes CFGCHIP2 with a proper phy > driver. > > Signed-off-by: David Lechner <david@lechnology.com> > --- > > v2 changes: Uses the new phy driver instead of using a second clock. Acked-by: Alan Stern <stern@rowland.harvard.edu>
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks |
| Message-ID | <rdx6H-1Ps-29@gated-at.bofh.it> |
| In reply to | #1359552 |
Up to this point, the USB phy clock configuration was handled manually in
the board files and in the usb drivers. This adds proper clocks so that
the usb drivers can use clk_get and clk_enable and not have to worry about
the details. Also, the related code is removed from the board files.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: Move clock mux code to set_parent callback. Also fixed some other
issues from feedback on the previous patch.
arch/arm/mach-davinci/board-da830-evm.c | 12 ---
arch/arm/mach-davinci/board-omapl138-hawk.c | 7 --
arch/arm/mach-davinci/da830.c | 143 ++++++++++++++++++++++++++++
arch/arm/mach-davinci/da850.c | 143 ++++++++++++++++++++++++++++
4 files changed, 286 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 3d8cf8c..f3a8cc9 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -115,18 +115,6 @@ static __init void da830_evm_usb_init(void)
*/
cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
- /* USB2.0 PHY reference clock is 24 MHz */
- cfgchip2 &= ~CFGCHIP2_REFFREQ;
- cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
-
- /*
- * Select internal reference clock for USB 2.0 PHY
- * and use it as a clock source for USB 1.1 PHY
- * (this is the default setting anyway).
- */
- cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX;
- cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX;
-
/*
* We have to override VBUS/ID signals when MUSB is configured into the
* host-only mode -- ID pin will float if no cable is connected, so the
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index ee62486..d27e753 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -251,13 +251,6 @@ static __init void omapl138_hawk_usb_init(void)
return;
}
- /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
-
- cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
- cfgchip2 &= ~CFGCHIP2_REFFREQ;
- cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
- __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
ret = gpio_request_one(DA850_USB1_VBUS_PIN,
GPIOF_DIR_OUT, "USB1 VBUS");
if (ret < 0) {
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 7187e7f..ee942b0 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
#include <asm/mach/map.h>
@@ -346,6 +347,12 @@ static struct clk i2c1_clk = {
.gpsc = 1,
};
+static struct clk usb_ref_clk = {
+ .name = "usb_ref_clk",
+ .rate = 48000000,
+ .set_rate = davinci_simple_set_rate,
+};
+
static struct clk usb11_clk = {
.name = "usb11",
.parent = &pll0_sysclk4,
@@ -353,6 +360,139 @@ static struct clk usb11_clk = {
.gpsc = 1,
};
+static void usb20_phy_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+ /*
+ * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
+ * host may use the PLL clock without USB 2.0 OTG being used.
+ */
+ val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
+ val |= CFGCHIP2_PHY_PLLON;
+
+ writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+ pr_info("Waiting for USB 2.0 PHY clock good...\n");
+ while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
+ & CFGCHIP2_PHYCLKGD))
+ cpu_relax();
+}
+
+static void usb20_phy_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+ val |= CFGCHIP2_PHYPWRDN;
+ writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+}
+
+static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 __iomem *cfgchip2;
+ u32 val;
+
+ /*
+ * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
+ * da8xx_syscfg0_base is initialized.
+ */
+ cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
+ val = readl(cfgchip2);
+
+ /* Set the mux depending on the parent clock. */
+ if (parent == &pll0_aux_clk)
+ val |= CFGCHIP2_USB2PHYCLKMUX;
+ else if (parent == &usb_ref_clk)
+ val &= ~CFGCHIP2_USB2PHYCLKMUX;
+ else {
+ pr_err("Bad parent on USB 2.0 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ /* reference frequency also comes from parent clock */
+ val &= ~CFGCHIP2_REFFREQ;
+ switch (clk_get_rate(parent)) {
+ case 12000000:
+ val |= CFGCHIP2_REFFREQ_12MHZ;
+ break;
+ case 13000000:
+ val |= CFGCHIP2_REFFREQ_13MHZ;
+ break;
+ case 19200000:
+ val |= CFGCHIP2_REFFREQ_19_2MHZ;
+ break;
+ case 20000000:
+ val |= CFGCHIP2_REFFREQ_20MHZ;
+ break;
+ case 24000000:
+ val |= CFGCHIP2_REFFREQ_24MHZ;
+ break;
+ case 26000000:
+ val |= CFGCHIP2_REFFREQ_26MHZ;
+ break;
+ case 38400000:
+ val |= CFGCHIP2_REFFREQ_38_4MHZ;
+ break;
+ case 40000000:
+ val |= CFGCHIP2_REFFREQ_40MHZ;
+ break;
+ case 48000000:
+ val |= CFGCHIP2_REFFREQ_48MHZ;
+ break;
+ default:
+ pr_err("Bad parent clock rate on USB 2.0 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ writel(val, cfgchip2);
+
+ return 0;
+}
+
+static struct clk usb20_phy_clk = {
+ .name = "usb20_phy",
+ .parent = &pll0_aux_clk,
+ .clk_enable = usb20_phy_clk_enable,
+ .clk_disable = usb20_phy_clk_disable,
+ .set_parent = usb20_phy_clk_set_parent,
+};
+
+static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 __iomem *cfgchip2;
+ u32 val;
+
+ /*
+ * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
+ * da8xx_syscfg0_base is initialized.
+ */
+ cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
+ val = readl(cfgchip2);
+
+ /* Set the USB 1.1 PHY clock mux based on the parent clock. */
+ if (parent == &usb20_phy_clk)
+ val &= ~CFGCHIP2_USB1PHYCLKMUX;
+ else if (parent == &usb_ref_clk)
+ val |= CFGCHIP2_USB1PHYCLKMUX;
+ else {
+ pr_err("Bad parent on USB 1.1 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ writel(val, cfgchip2);
+
+ return 0;
+}
+
+static struct clk usb11_phy_clk = {
+ .name = "usb11_phy",
+ .parent = &usb20_phy_clk,
+ .set_parent = usb11_phy_clk_set_parent,
+};
+
static struct clk emif3_clk = {
.name = "emif3",
.parent = &pll0_sysclk5,
@@ -420,7 +560,10 @@ static struct clk_lookup da830_clks[] = {
CLK("davinci_mdio.0", "fck", &emac_clk),
CLK(NULL, "gpio", &gpio_clk),
CLK("i2c_davinci.2", NULL, &i2c1_clk),
+ CLK(NULL, "usb_ref_clk", &usb_ref_clk),
CLK(NULL, "usb11", &usb11_clk),
+ CLK(NULL, "usb20_phy", &usb20_phy_clk),
+ CLK(NULL, "usb11_phy", &usb11_phy_clk),
CLK(NULL, "emif3", &emif3_clk),
CLK(NULL, "arm", &arm_clk),
CLK(NULL, "rmii", &rmii_clk),
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 8c8f31e..8089a82 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -19,6 +19,7 @@
#include <linux/cpufreq.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
#include <asm/mach/map.h>
@@ -360,6 +361,12 @@ static struct clk aemif_clk = {
.flags = ALWAYS_ENABLED,
};
+static struct clk usb_ref_clk = {
+ .name = "usb_ref_clk",
+ .rate = 48000000,
+ .set_rate = davinci_simple_set_rate,
+};
+
static struct clk usb11_clk = {
.name = "usb11",
.parent = &pll0_sysclk4,
@@ -374,6 +381,139 @@ static struct clk usb20_clk = {
.gpsc = 1,
};
+static void usb20_phy_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+ /*
+ * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
+ * host may use the PLL clock without USB 2.0 OTG being used.
+ */
+ val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
+ val |= CFGCHIP2_PHY_PLLON;
+
+ writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+ pr_info("Waiting for USB 2.0 PHY clock good...\n");
+ while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
+ & CFGCHIP2_PHYCLKGD))
+ cpu_relax();
+}
+
+static void usb20_phy_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+ val |= CFGCHIP2_PHYPWRDN;
+ writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+}
+
+static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 __iomem *cfgchip2;
+ u32 val;
+
+ /*
+ * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
+ * da8xx_syscfg0_base is initialized.
+ */
+ cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
+ val = readl(cfgchip2);
+
+ /* Set the mux depending on the parent clock. */
+ if (parent == &pll0_aux_clk)
+ val |= CFGCHIP2_USB2PHYCLKMUX;
+ else if (parent == &usb_ref_clk)
+ val &= ~CFGCHIP2_USB2PHYCLKMUX;
+ else {
+ pr_err("Bad parent on USB 2.0 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ /* reference frequency also comes from parent clock */
+ val &= ~CFGCHIP2_REFFREQ;
+ switch (clk_get_rate(parent)) {
+ case 12000000:
+ val |= CFGCHIP2_REFFREQ_12MHZ;
+ break;
+ case 13000000:
+ val |= CFGCHIP2_REFFREQ_13MHZ;
+ break;
+ case 19200000:
+ val |= CFGCHIP2_REFFREQ_19_2MHZ;
+ break;
+ case 20000000:
+ val |= CFGCHIP2_REFFREQ_20MHZ;
+ break;
+ case 24000000:
+ val |= CFGCHIP2_REFFREQ_24MHZ;
+ break;
+ case 26000000:
+ val |= CFGCHIP2_REFFREQ_26MHZ;
+ break;
+ case 38400000:
+ val |= CFGCHIP2_REFFREQ_38_4MHZ;
+ break;
+ case 40000000:
+ val |= CFGCHIP2_REFFREQ_40MHZ;
+ break;
+ case 48000000:
+ val |= CFGCHIP2_REFFREQ_48MHZ;
+ break;
+ default:
+ pr_err("Bad parent clock rate on USB 2.0 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ writel(val, cfgchip2);
+
+ return 0;
+}
+
+static struct clk usb20_phy_clk = {
+ .name = "usb20_phy",
+ .parent = &pll0_aux_clk,
+ .clk_enable = usb20_phy_clk_enable,
+ .clk_disable = usb20_phy_clk_disable,
+ .set_parent = usb20_phy_clk_set_parent,
+};
+
+static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 __iomem *cfgchip2;
+ u32 val;
+
+ /*
+ * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
+ * da8xx_syscfg0_base is initialized.
+ */
+ cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
+ val = readl(cfgchip2);
+
+ /* Set the USB 1.1 PHY clock mux based on the parent clock. */
+ if (parent == &usb20_phy_clk)
+ val &= ~CFGCHIP2_USB1PHYCLKMUX;
+ else if (parent == &usb_ref_clk)
+ val |= CFGCHIP2_USB1PHYCLKMUX;
+ else {
+ pr_err("Bad parent on USB 1.1 PHY clock.\n");
+ return -EINVAL;
+ }
+
+ writel(val, cfgchip2);
+
+ return 0;
+}
+
+static struct clk usb11_phy_clk = {
+ .name = "usb11_phy",
+ .parent = &usb20_phy_clk,
+ .set_parent = usb11_phy_clk_set_parent,
+};
+
static struct clk spi0_clk = {
.name = "spi0",
.parent = &pll0_sysclk2,
@@ -493,8 +633,11 @@ static struct clk_lookup da850_clks[] = {
CLK("da830-mmc.0", NULL, &mmcsd0_clk),
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
CLK(NULL, "aemif", &aemif_clk),
+ CLK(NULL, "usb_ref_clk", &usb_ref_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK(NULL, "usb20", &usb20_clk),
+ CLK(NULL, "usb20_phy", &usb20_phy_clk),
+ CLK(NULL, "usb11_phy", &usb11_phy_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
CLK("spi_davinci.1", NULL, &spi1_clk),
CLK("vpif", NULL, &vpif_clk),
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
|---|---|
| Date | 2016-03-17 13:20 +0100 |
| Subject | Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks |
| Message-ID | <rdF4d-7ki-3@gated-at.bofh.it> |
| In reply to | #1359564 |
On 3/17/2016 5:26 AM, David Lechner wrote:
> Up to this point, the USB phy clock configuration was handled manually in
> the board files and in the usb drivers. This adds proper clocks so that
> the usb drivers can use clk_get and clk_enable and not have to worry about
> the details. Also, the related code is removed from the board files.
>
> Signed-off-by: David Lechner <david@lechnology.com>
[...]
> diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
> index 7187e7f..ee942b0 100644
> --- a/arch/arm/mach-davinci/da830.c
> +++ b/arch/arm/mach-davinci/da830.c
[...]
> @@ -346,6 +347,12 @@ static struct clk i2c1_clk = {
> .gpsc = 1,
> };
>
> +static struct clk usb_ref_clk = {
> + .name = "usb_ref_clk",
I'd leave out "_clk" for consistency.
[...]
> @@ -353,6 +360,139 @@ static struct clk usb11_clk = {
[...]
> +static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> + u32 __iomem *cfgchip2;
> + u32 val;
> +
> + /*
> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
> + * da8xx_syscfg0_base is initialized.
> + */
> + cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
You should be able to use IO_ADDRESS(), no?
[...]
> @@ -420,7 +560,10 @@ static struct clk_lookup da830_clks[] = {
> CLK("davinci_mdio.0", "fck", &emac_clk),
> CLK(NULL, "gpio", &gpio_clk),
> CLK("i2c_davinci.2", NULL, &i2c1_clk),
> + CLK(NULL, "usb_ref_clk", &usb_ref_clk),
I'd leave out "_clk" agai.
> CLK(NULL, "usb11", &usb11_clk),
> + CLK(NULL, "usb20_phy", &usb20_phy_clk),
> + CLK(NULL, "usb11_phy", &usb11_phy_clk),
> CLK(NULL, "emif3", &emif3_clk),
> CLK(NULL, "arm", &arm_clk),
> CLK(NULL, "rmii", &rmii_clk),
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 8c8f31e..8089a82 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
Same comments on this file...
MBR, Sergei
[toc] | [prev] | [next] | [standalone]
| From | Sekhar Nori <nsekhar@ti.com> |
|---|---|
| Date | 2016-03-23 18:00 +0100 |
| Subject | Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks |
| Message-ID | <rfUiu-6gL-15@gated-at.bofh.it> |
| In reply to | #1359564 |
On Thursday 17 March 2016 07:56 AM, David Lechner wrote:
> Up to this point, the USB phy clock configuration was handled manually in
> the board files and in the usb drivers. This adds proper clocks so that
> the usb drivers can use clk_get and clk_enable and not have to worry about
> the details. Also, the related code is removed from the board files.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>
> v2 changes: Move clock mux code to set_parent callback. Also fixed some other
> issues from feedback on the previous patch.
>
>
> arch/arm/mach-davinci/board-da830-evm.c | 12 ---
> arch/arm/mach-davinci/board-omapl138-hawk.c | 7 --
> arch/arm/mach-davinci/da830.c | 143 ++++++++++++++++++++++++++++
> arch/arm/mach-davinci/da850.c | 143 ++++++++++++++++++++++++++++
> 4 files changed, 286 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
> index 3d8cf8c..f3a8cc9 100644
> --- a/arch/arm/mach-davinci/board-da830-evm.c
> +++ b/arch/arm/mach-davinci/board-da830-evm.c
> @@ -115,18 +115,6 @@ static __init void da830_evm_usb_init(void)
> */
> cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
>
> - /* USB2.0 PHY reference clock is 24 MHz */
> - cfgchip2 &= ~CFGCHIP2_REFFREQ;
> - cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
> -
> - /*
> - * Select internal reference clock for USB 2.0 PHY
> - * and use it as a clock source for USB 1.1 PHY
> - * (this is the default setting anyway).
> - */
> - cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX;
> - cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX;
> -
> /*
> * We have to override VBUS/ID signals when MUSB is configured into the
> * host-only mode -- ID pin will float if no cable is connected, so the
> diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
> index ee62486..d27e753 100644
> --- a/arch/arm/mach-davinci/board-omapl138-hawk.c
> +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
> @@ -251,13 +251,6 @@ static __init void omapl138_hawk_usb_init(void)
> return;
> }
>
> - /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
> -
> - cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> - cfgchip2 &= ~CFGCHIP2_REFFREQ;
> - cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
> - __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> -
> ret = gpio_request_one(DA850_USB1_VBUS_PIN,
> GPIOF_DIR_OUT, "USB1 VBUS");
> if (ret < 0) {
> diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
> index 7187e7f..ee942b0 100644
> --- a/arch/arm/mach-davinci/da830.c
> +++ b/arch/arm/mach-davinci/da830.c
> @@ -12,6 +12,7 @@
> #include <linux/init.h>
> #include <linux/clk.h>
> #include <linux/platform_data/gpio-davinci.h>
> +#include <linux/platform_data/usb-davinci.h>
>
> #include <asm/mach/map.h>
>
> @@ -346,6 +347,12 @@ static struct clk i2c1_clk = {
> .gpsc = 1,
> };
>
> +static struct clk usb_ref_clk = {
> + .name = "usb_ref_clk",
> + .rate = 48000000,
> + .set_rate = davinci_simple_set_rate,
> +};
can we call this usb_refclkin so it matches the TRM name? Also, should
this node be not be coming through individual board files as the rate
depends on what is connected to the usb_refclkin pin? Or is the
expectation that boards will call clk_set_rate() on this clock to the
correct value? If yes, I think it is misleading to populate the .rate here.
> +
> static struct clk usb11_clk = {
> .name = "usb11",
> .parent = &pll0_sysclk4,
> @@ -353,6 +360,139 @@ static struct clk usb11_clk = {
> .gpsc = 1,
> };
>
> +static void usb20_phy_clk_enable(struct clk *clk)
> +{
> + u32 val;
> +
> + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> +
> + /*
> + * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
> + * host may use the PLL clock without USB 2.0 OTG being used.
> + */
> + val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
> + val |= CFGCHIP2_PHY_PLLON;
> +
> + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> +
> + pr_info("Waiting for USB 2.0 PHY clock good...\n");
> + while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
> + & CFGCHIP2_PHYCLKGD))
> + cpu_relax();
I guess this is copying some earlier code, but still, it will be nice to
see a timeout mechanism here, rather than loop endlessly.
> +}
> +
> +static void usb20_phy_clk_disable(struct clk *clk)
> +{
> + u32 val;
> +
> + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> + val |= CFGCHIP2_PHYPWRDN;
> + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> +}
> +
> +static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> + u32 __iomem *cfgchip2;
> + u32 val;
> +
> + /*
> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
> + * da8xx_syscfg0_base is initialized.
> + */
> + cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
Again, not sure if this is juts a theoretical possibility. If yes, I
would rather see you bail out if syscfg0_base is not initialized by the
time you get here than do an ioremap() again.
> + val = readl(cfgchip2);
> +
> + /* Set the mux depending on the parent clock. */
> + if (parent == &pll0_aux_clk)
> + val |= CFGCHIP2_USB2PHYCLKMUX;
> + else if (parent == &usb_ref_clk)
> + val &= ~CFGCHIP2_USB2PHYCLKMUX;
> + else {
> + pr_err("Bad parent on USB 2.0 PHY clock.\n");
> + return -EINVAL;
> + }
> +
> + /* reference frequency also comes from parent clock */
> + val &= ~CFGCHIP2_REFFREQ;
> + switch (clk_get_rate(parent)) {
> + case 12000000:
> + val |= CFGCHIP2_REFFREQ_12MHZ;
> + break;
> + case 13000000:
> + val |= CFGCHIP2_REFFREQ_13MHZ;
> + break;
> + case 19200000:
> + val |= CFGCHIP2_REFFREQ_19_2MHZ;
> + break;
> + case 20000000:
> + val |= CFGCHIP2_REFFREQ_20MHZ;
> + break;
> + case 24000000:
> + val |= CFGCHIP2_REFFREQ_24MHZ;
> + break;
> + case 26000000:
> + val |= CFGCHIP2_REFFREQ_26MHZ;
> + break;
> + case 38400000:
> + val |= CFGCHIP2_REFFREQ_38_4MHZ;
> + break;
> + case 40000000:
> + val |= CFGCHIP2_REFFREQ_40MHZ;
> + break;
> + case 48000000:
> + val |= CFGCHIP2_REFFREQ_48MHZ;
> + break;
> + default:
> + pr_err("Bad parent clock rate on USB 2.0 PHY clock.\n");
> + return -EINVAL;
> + }
> +
> + writel(val, cfgchip2);
> +
> + return 0;
> +}
> +
> +static struct clk usb20_phy_clk = {
> + .name = "usb20_phy",
> + .parent = &pll0_aux_clk,
> + .clk_enable = usb20_phy_clk_enable,
> + .clk_disable = usb20_phy_clk_disable,
> + .set_parent = usb20_phy_clk_set_parent,
> +};
I hope you have checked that all boards in mainline use the AUXCLK as
the reference USB 2.0 frequency?
> +
> +static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> + u32 __iomem *cfgchip2;
> + u32 val;
> +
> + /*
> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
> + * da8xx_syscfg0_base is initialized.
> + */
> + cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
> + val = readl(cfgchip2);
> +
> + /* Set the USB 1.1 PHY clock mux based on the parent clock. */
> + if (parent == &usb20_phy_clk)
> + val &= ~CFGCHIP2_USB1PHYCLKMUX;
> + else if (parent == &usb_ref_clk)
> + val |= CFGCHIP2_USB1PHYCLKMUX;
> + else {
> + pr_err("Bad parent on USB 1.1 PHY clock.\n");
> + return -EINVAL;
> + }
> +
> + writel(val, cfgchip2);
> +
> + return 0;
> +}
> +
> +static struct clk usb11_phy_clk = {
> + .name = "usb11_phy",
> + .parent = &usb20_phy_clk,
> + .set_parent = usb11_phy_clk_set_parent,
> +};
Same thing here. I hope all current boards use USB2.0 clk as reference
for USB 1.1 phy
> +
> static struct clk emif3_clk = {
> .name = "emif3",
> .parent = &pll0_sysclk5,
> @@ -420,7 +560,10 @@ static struct clk_lookup da830_clks[] = {
> CLK("davinci_mdio.0", "fck", &emac_clk),
> CLK(NULL, "gpio", &gpio_clk),
> CLK("i2c_davinci.2", NULL, &i2c1_clk),
> + CLK(NULL, "usb_ref_clk", &usb_ref_clk),
> CLK(NULL, "usb11", &usb11_clk),
> + CLK(NULL, "usb20_phy", &usb20_phy_clk),
> + CLK(NULL, "usb11_phy", &usb11_phy_clk),
> CLK(NULL, "emif3", &emif3_clk),
> CLK(NULL, "arm", &arm_clk),
> CLK(NULL, "rmii", &rmii_clk),
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 8c8f31e..8089a82 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -19,6 +19,7 @@
> #include <linux/cpufreq.h>
> #include <linux/regulator/consumer.h>
> #include <linux/platform_data/gpio-davinci.h>
> +#include <linux/platform_data/usb-davinci.h>
>
> #include <asm/mach/map.h>
>
> @@ -360,6 +361,12 @@ static struct clk aemif_clk = {
> .flags = ALWAYS_ENABLED,
> };
>
> +static struct clk usb_ref_clk = {
> + .name = "usb_ref_clk",
> + .rate = 48000000,
> + .set_rate = davinci_simple_set_rate,
> +};
> +
> static struct clk usb11_clk = {
> .name = "usb11",
> .parent = &pll0_sysclk4,
> @@ -374,6 +381,139 @@ static struct clk usb20_clk = {
> .gpsc = 1,
> };
>
> +static void usb20_phy_clk_enable(struct clk *clk)
> +{
> + u32 val;
> +
> + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> +
> + /*
> + * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
> + * host may use the PLL clock without USB 2.0 OTG being used.
> + */
> + val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
> + val |= CFGCHIP2_PHY_PLLON;
> +
> + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
> +
> + pr_info("Waiting for USB 2.0 PHY clock good...\n");
> + while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
> + & CFGCHIP2_PHYCLKGD))
> + cpu_relax();
> +}
Looks like this is pretty much going to be the same code repeated for
DA850 and DA830. So can we move these to a common file like da8xx-usb.c?
You can even register these USB clocks from that file by using
clkdev_add() and clk_register(). This way they can remain to be file local.
Thanks,
Sekhar
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-23 18:50 +0100 |
| Subject | Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks |
| Message-ID | <rfV4S-6Vm-9@gated-at.bofh.it> |
| In reply to | #1363557 |
On 03/23/2016 11:56 AM, Sekhar Nori wrote:
>>
>> +static struct clk usb_ref_clk = {
>> + .name = "usb_ref_clk",
>> + .rate = 48000000,
>> + .set_rate = davinci_simple_set_rate,
>> +};
>
> can we call this usb_refclkin so it matches the TRM name? Also, should
> this node be not be coming through individual board files as the rate
> depends on what is connected to the usb_refclkin pin? Or is the
> expectation that boards will call clk_set_rate() on this clock to the
> correct value? If yes, I think it is misleading to populate the .rate here.
You are right. When I did this, I was looking at USB 1.1 only, which
MUST be 48MHz. However, this can be used for USB 2.0 which can accept a
number of rates.
However, even the main reference oscillator in da850.c has the rate hard
coded in da850.c (DA850_REF_FREQ).
The clock initialization will fail if a clock does not have a parent or
a rate, so we have to give it a default rate since it is an external
clock and has no parent. So, I think 48MHz makes sense for a default
value. Most boards will probably not be using this clock anyway, but
rather the PLL in the USB 2.0 PHY.
>> +
>> + pr_info("Waiting for USB 2.0 PHY clock good...\n");
>> + while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
>> + & CFGCHIP2_PHYCLKGD))
>> + cpu_relax();
>
> I guess this is copying some earlier code, but still, it will be nice to
> see a timeout mechanism here, rather than loop endlessly.
Do you have a suggestion on how to do this?
>> +
>> + /*
>> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
>> + * da8xx_syscfg0_base is initialized.
>> + */
>> + cfgchip2 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG, 4);
>
> Again, not sure if this is juts a theoretical possibility. If yes, I
> would rather see you bail out if syscfg0_base is not initialized by the
> time you get here than do an ioremap() again.
>
Will rework clock registration so that this is not necessary.
>> +
>> +static struct clk usb20_phy_clk = {
>> + .name = "usb20_phy",
>> + .parent = &pll0_aux_clk,
>> + .clk_enable = usb20_phy_clk_enable,
>> + .clk_disable = usb20_phy_clk_disable,
>> + .set_parent = usb20_phy_clk_set_parent,
>> +};
>
> I hope you have checked that all boards in mainline use the AUXCLK as
> the reference USB 2.0 frequency?
>
After sending this patch set, I realized that I missed updating existing
boards. Will include this in v3.
>> +
>> +static struct clk usb11_phy_clk = {
>> + .name = "usb11_phy",
>> + .parent = &usb20_phy_clk,
>> + .set_parent = usb11_phy_clk_set_parent,
>> +};
>
> Same thing here. I hope all current boards use USB2.0 clk as reference
> for USB 1.1 phy
>
Ditto. Will check on this.
>> +static void usb20_phy_clk_enable(struct clk *clk)
>> +{
>> + u32 val;
>> +
>> + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
>> +
>> + /*
>> + * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
>> + * host may use the PLL clock without USB 2.0 OTG being used.
>> + */
>> + val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
>> + val |= CFGCHIP2_PHY_PLLON;
>> +
>> + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
>> +
>> + pr_info("Waiting for USB 2.0 PHY clock good...\n");
>> + while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
>> + & CFGCHIP2_PHYCLKGD))
>> + cpu_relax();
>> +}
>
> Looks like this is pretty much going to be the same code repeated for
> DA850 and DA830. So can we move these to a common file like da8xx-usb.c?
> You can even register these USB clocks from that file by using
> clkdev_add() and clk_register(). This way they can remain to be file local.
>
I knew someone was going to say that. ;-) Thanks for the suggestion of
clkdev_add() and clk_register(), I had not considered that but it sounds
like a good idea and will take care of the ioremap problem too.
[toc] | [prev] | [next] | [standalone]
| From | Sekhar Nori <nsekhar@ti.com> |
|---|---|
| Date | 2016-03-23 19:00 +0100 |
| Subject | Re: [PATCH v2 04/11] ARM: davinci: da8xx: add usb phy clocks |
| Message-ID | <rfVex-6Z8-7@gated-at.bofh.it> |
| In reply to | #1363585 |
On Wednesday 23 March 2016 11:15 PM, David Lechner wrote:
> On 03/23/2016 11:56 AM, Sekhar Nori wrote:
>>>
>>> +static struct clk usb_ref_clk = {
>>> + .name = "usb_ref_clk",
>>> + .rate = 48000000,
>>> + .set_rate = davinci_simple_set_rate,
>>> +};
>>
>> can we call this usb_refclkin so it matches the TRM name? Also, should
>> this node be not be coming through individual board files as the rate
>> depends on what is connected to the usb_refclkin pin? Or is the
>> expectation that boards will call clk_set_rate() on this clock to the
>> correct value? If yes, I think it is misleading to populate the .rate
>> here.
>
> You are right. When I did this, I was looking at USB 1.1 only, which
> MUST be 48MHz. However, this can be used for USB 2.0 which can accept a
> number of rates.
>
> However, even the main reference oscillator in da850.c has the rate hard
> coded in da850.c (DA850_REF_FREQ).
:)
>
> The clock initialization will fail if a clock does not have a parent or
> a rate, so we have to give it a default rate since it is an external
> clock and has no parent. So, I think 48MHz makes sense for a default
> value. Most boards will probably not be using this clock anyway, but
> rather the PLL in the USB 2.0 PHY.
Alright, I guess the only change is to call it usb_refclkin
>
>
>>> +
>>> + pr_info("Waiting for USB 2.0 PHY clock good...\n");
>>> + while (!(readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG))
>>> + & CFGCHIP2_PHYCLKGD))
>>> + cpu_relax();
>>
>> I guess this is copying some earlier code, but still, it will be nice to
>> see a timeout mechanism here, rather than loop endlessly.
>
> Do you have a suggestion on how to do this?
Simplest would be to use a udelay(1) inside the loop and count a
specific number of times (sufficiently large to not cause false
negatives and sufficiently small so as to not appear that board is
frozen forever).
Thanks,
Sekhar
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-17 04:50 +0100 |
| Subject | [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rdx6H-1Ps-33@gated-at.bofh.it> |
| In reply to | #1359552 |
The da850 family of processors has an async3 clock domain that can be
muxed to either pll0_sysclk2 or pll1_sysclk2. Now that the davinci clocks
have a set_parent callback, we can use this to control the async3 mux
instead of a stand-alone function.
This adds a new async3_clk and sets the appropriate child clocks. The
default is use to pll1_sysclk2 since it is not affected by processor
frequency scaling.
Signed-off-by: David Lechner <david@lechnology.com>
---
v2 changes: This is a new patch in v2.
arch/arm/mach-davinci/da850.c | 88 ++++++++++++++++++++-----------------------
1 file changed, 40 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 97d8779..8c8f31e 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -34,9 +34,6 @@
#include "clock.h"
#include "mux.h"
-/* SoC specific clock flags */
-#define DA850_CLK_ASYNC3 BIT(16)
-
#define DA850_PLL1_BASE 0x01e1a000
#define DA850_TIMER64P2_BASE 0x01f0c000
#define DA850_TIMER64P3_BASE 0x01f0d000
@@ -161,6 +158,39 @@ static struct clk pll1_sysclk3 = {
.div_reg = PLLDIV3,
};
+static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 __iomem *cfgchip3;
+ u32 val;
+
+ /*
+ * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
+ * da8xx_syscfg0_base is initialized.
+ */
+ cfgchip3 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP3_REG, 4);
+ val = readl(cfgchip3);
+
+ /* Set the USB 1.1 PHY clock mux based on the parent clock. */
+ if (parent == &pll0_sysclk2)
+ val &= ~CFGCHIP3_ASYNC3_CLKSRC;
+ else if (parent == &pll1_sysclk2)
+ val |= CFGCHIP3_ASYNC3_CLKSRC;
+ else {
+ pr_err("Bad parent on async3 clock mux.\n");
+ return -EINVAL;
+ }
+
+ writel(val, cfgchip3);
+
+ return 0;
+}
+
+static struct clk async3_clk = {
+ .name = "async3",
+ .parent = &pll1_sysclk2,
+ .set_parent = da850_async3_set_parent,
+};
+
static struct clk i2c0_clk = {
.name = "i2c0",
.parent = &pll0_aux_clk,
@@ -234,18 +264,16 @@ static struct clk uart0_clk = {
static struct clk uart1_clk = {
.name = "uart1",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_UART1,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
static struct clk uart2_clk = {
.name = "uart2",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_UART2,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
static struct clk aintc_clk = {
@@ -300,10 +328,9 @@ static struct clk emac_clk = {
static struct clk mcasp_clk = {
.name = "mcasp",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_McASP0,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
static struct clk lcdc_clk = {
@@ -355,10 +382,9 @@ static struct clk spi0_clk = {
static struct clk spi1_clk = {
.name = "spi1",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_SPI1,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
static struct clk vpif_clk = {
@@ -386,10 +412,9 @@ static struct clk dsp_clk = {
static struct clk ehrpwm_clk = {
.name = "ehrpwm",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_PWM,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
#define DA8XX_EHRPWM_TBCLKSYNC BIT(12)
@@ -421,10 +446,9 @@ static struct clk ehrpwm_tbclk = {
static struct clk ecap_clk = {
.name = "ecap",
- .parent = &pll0_sysclk2,
+ .parent = &async3_clk,
.lpsc = DA8XX_LPSC1_ECAP,
.gpsc = 1,
- .flags = DA850_CLK_ASYNC3,
};
static struct clk_lookup da850_clks[] = {
@@ -442,6 +466,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "pll1_aux", &pll1_aux_clk),
CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
+ CLK(NULL, "async3", &async3_clk),
CLK("i2c_davinci.1", NULL, &i2c0_clk),
CLK(NULL, "timer0", &timerp64_0_clk),
CLK("davinci-wdt", NULL, &timerp64_1_clk),
@@ -909,30 +934,6 @@ static struct davinci_timer_info da850_timer_info = {
.clocksource_id = T0_TOP,
};
-static void da850_set_async3_src(int pllnum)
-{
- struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2;
- struct clk_lookup *c;
- unsigned int v;
- int ret;
-
- for (c = da850_clks; c->clk; c++) {
- clk = c->clk;
- if (clk->flags & DA850_CLK_ASYNC3) {
- ret = clk_set_parent(clk, newparent);
- WARN(ret, "DA850: unable to re-parent clock %s",
- clk->name);
- }
- }
-
- v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
- if (pllnum)
- v |= CFGCHIP3_ASYNC3_CLKSRC;
- else
- v &= ~CFGCHIP3_ASYNC3_CLKSRC;
- __raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-}
-
#ifdef CONFIG_CPU_FREQ
/*
* Notes:
@@ -1328,15 +1329,6 @@ void __init da850_init(void)
if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
return;
- /*
- * Move the clock source of Async3 domain to PLL1 SYSCLK2.
- * This helps keeping the peripherals on this domain insulated
- * from CPU frequency changes caused by DVFS. The firmware sets
- * both PLL0 and PLL1 to the same frequency so, there should not
- * be any noticeable change even in non-DVFS use cases.
- */
- da850_set_async3_src(1);
-
/* Unlock writing to PLL0 registers */
v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
v &= ~CFGCHIP0_PLL_MASTER_LOCK;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Sekhar Nori <nsekhar@ti.com> |
|---|---|
| Date | 2016-03-23 17:00 +0100 |
| Subject | Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rfTmq-5As-3@gated-at.bofh.it> |
| In reply to | #1359565 |
On Thursday 17 March 2016 07:56 AM, David Lechner wrote:
> The da850 family of processors has an async3 clock domain that can be
> muxed to either pll0_sysclk2 or pll1_sysclk2. Now that the davinci clocks
> have a set_parent callback, we can use this to control the async3 mux
> instead of a stand-alone function.
>
> This adds a new async3_clk and sets the appropriate child clocks. The
> default is use to pll1_sysclk2 since it is not affected by processor
> frequency scaling.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
> +static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
> +{
> + u32 __iomem *cfgchip3;
> + u32 val;
> +
> + /*
> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
> + * da8xx_syscfg0_base is initialized.
> + */
> + cfgchip3 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP3_REG, 4);
Is this just a theoretical possibility or have you seen this happen? I
would like to see if there are ways of avoiding this rather than throw
away usage of DA8XX_SYSCFG0_VIRT()
> + val = readl(cfgchip3);
> +
> + /* Set the USB 1.1 PHY clock mux based on the parent clock. */
Comment is wrong (copy-paste error?)
> + if (parent == &pll0_sysclk2)
> + val &= ~CFGCHIP3_ASYNC3_CLKSRC;
> + else if (parent == &pll1_sysclk2)
> + val |= CFGCHIP3_ASYNC3_CLKSRC;
> + else {
> + pr_err("Bad parent on async3 clock mux.\n");
> + return -EINVAL;
> + }
> +
> + writel(val, cfgchip3);
> +
> + return 0;
> +}
Thanks,
Sekhar
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-23 18:30 +0100 |
| Subject | Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rfULw-6Mz-1@gated-at.bofh.it> |
| In reply to | #1363508 |
On 03/23/2016 10:56 AM, Sekhar Nori wrote:
> On Thursday 17 March 2016 07:56 AM, David Lechner wrote:
>> The da850 family of processors has an async3 clock domain that can be
>> muxed to either pll0_sysclk2 or pll1_sysclk2. Now that the davinci clocks
>> have a set_parent callback, we can use this to control the async3 mux
>> instead of a stand-alone function.
>>
>> This adds a new async3_clk and sets the appropriate child clocks. The
>> default is use to pll1_sysclk2 since it is not affected by processor
>> frequency scaling.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>
>> +static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
>> +{
>> + u32 __iomem *cfgchip3;
>> + u32 val;
>> +
>> + /*
>> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called before
>> + * da8xx_syscfg0_base is initialized.
>> + */
>> + cfgchip3 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP3_REG, 4);
>
> Is this just a theoretical possibility or have you seen this happen? I
> would like to see if there are ways of avoiding this rather than throw
> away usage of DA8XX_SYSCFG0_VIRT()
Yes, it will not boot without this. The problem comes from the fact that
clocks are setup in davinci_common_init() which is called before
da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K) in da850_init()
(and da830_init()). I also tried moving the ioremap() before
davinci_common_init(), but davinci_common_init() sets up the iomem, so
that doesn't work either.
So, if you want to use DA8XX_SYSCFG0_VIRT() here, the clock init would
have to be split out from davinci_common_init() which would affect all
davinci devices.
[toc] | [prev] | [next] | [standalone]
| From | Sekhar Nori <nsekhar@ti.com> |
|---|---|
| Date | 2016-03-23 18:40 +0100 |
| Subject | Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rfUVc-6Rl-19@gated-at.bofh.it> |
| In reply to | #1363566 |
On Wednesday 23 March 2016 10:50 PM, David Lechner wrote:
> On 03/23/2016 10:56 AM, Sekhar Nori wrote:
>> On Thursday 17 March 2016 07:56 AM, David Lechner wrote:
>>> The da850 family of processors has an async3 clock domain that can be
>>> muxed to either pll0_sysclk2 or pll1_sysclk2. Now that the davinci
>>> clocks
>>> have a set_parent callback, we can use this to control the async3 mux
>>> instead of a stand-alone function.
>>>
>>> This adds a new async3_clk and sets the appropriate child clocks. The
>>> default is use to pll1_sysclk2 since it is not affected by processor
>>> frequency scaling.
>>>
>>> Signed-off-by: David Lechner <david@lechnology.com>
>>> ---
>>
>>> +static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
>>> +{
>>> + u32 __iomem *cfgchip3;
>>> + u32 val;
>>> +
>>> + /*
>>> + * Can't use DA8XX_SYSCFG0_VIRT() here since this can be called
>>> before
>>> + * da8xx_syscfg0_base is initialized.
>>> + */
>>> + cfgchip3 = ioremap(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP3_REG, 4);
>>
>> Is this just a theoretical possibility or have you seen this happen? I
>> would like to see if there are ways of avoiding this rather than throw
>> away usage of DA8XX_SYSCFG0_VIRT()
>
> Yes, it will not boot without this. The problem comes from the fact that
> clocks are setup in davinci_common_init() which is called before
> da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K) in da850_init()
> (and da830_init()). I also tried moving the ioremap() before
> davinci_common_init(), but davinci_common_init() sets up the iomem, so
> that doesn't work either.
>
> So, if you want to use DA8XX_SYSCFG0_VIRT() here, the clock init would
> have to be split out from davinci_common_init() which would affect all
> davinci devices.
Alright, I guess 'can be called' in the comment should have used
stronger language :) How about late registration of USB clocks as I
suggested. It should also help consolidate code across da830 and da850.
Thanks,
Sekhar
[toc] | [prev] | [next] | [standalone]
| From | David Lechner <david@lechnology.com> |
|---|---|
| Date | 2016-03-23 19:40 +0100 |
| Subject | Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rfVRg-7vh-17@gated-at.bofh.it> |
| In reply to | #1363579 |
On 03/23/2016 12:29 PM, Sekhar Nori wrote: > > Alright, I guess 'can be called' in the comment should have used > stronger language :) How about late registration of USB clocks as I > suggested. It should also help consolidate code across da830 and da850. > What about the new async3 clock? It will require later registration too, but it has many children that depend on it.
[toc] | [prev] | [next] | [standalone]
| From | Sekhar Nori <nsekhar@ti.com> |
|---|---|
| Date | 2016-03-24 14:50 +0100 |
| Subject | Re: [PATCH v2 03/11] ARM: davinci: da850: use clk->set_parent for async3 |
| Message-ID | <rgdOa-3jF-5@gated-at.bofh.it> |
| In reply to | #1363606 |
On Thursday 24 March 2016 12:02 AM, David Lechner wrote: > On 03/23/2016 12:29 PM, Sekhar Nori wrote: >> >> Alright, I guess 'can be called' in the comment should have used >> stronger language :) How about late registration of USB clocks as I >> suggested. It should also help consolidate code across da830 and da850. >> > > What about the new async3 clock? It will require later registration too, > but it has many children that depend on it. I guess that was the reason why it was done the way it was. Can we leave that alone for now (not use the new set_parent interface)? You don't really need that to be changed for USB functionality, right? Thanks, sekhar
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web