diff mbox

[U-Boot,2/5] ARM: OMAP5: Add Pipe3 PHY driver

Message ID 1383749246-30895-3-git-send-email-rogerq@ti.com
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

Roger Quadros Nov. 6, 2013, 2:47 p.m. UTC
Pipe3 PHY is used by SATA, USB3 and PCIe modules. This is
a driver for the Pipe3 PHY.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/cpu/armv7/omap-common/Makefile    |   4 +
 arch/arm/cpu/armv7/omap-common/pipe3-phy.c | 233 +++++++++++++++++++++++++++++
 arch/arm/cpu/armv7/omap-common/pipe3-phy.h |  36 +++++
 3 files changed, 273 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/omap-common/pipe3-phy.c
 create mode 100644 arch/arm/cpu/armv7/omap-common/pipe3-phy.h

Comments

Tom Rini Nov. 6, 2013, 9:48 p.m. UTC | #1
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 11/06/2013 09:47 AM, Roger Quadros wrote:
> Pipe3 PHY is used by SATA, USB3 and PCIe modules. This is
> a driver for the Pipe3 PHY.
> 
> Signed-off-by: Roger Quadros <rogerq@ti.com>
[snip]
> +#define perror(fmt, args...) printf("%s: " fmt, __func__ , ##args)

Please use the debug macro.

[snip[
> +	perror("%s: No DPLL configuration for %u Hz SYS CLK\n",
> +							__func__, rate);

Indent is wrong, we do like the kernel (and checkpatch.pl is in tools/
and will catch these).  Thanks.

Code itself seems fine tho, thanks.

- -- 
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJSerkvAAoJENk4IS6UOR1WoscQAJPuEI2msKOndDsaVdQcD8oQ
zy2H6hXl4o9FwZd9B6Q3xigjUcjJ9a/g8dBxEprB96pv+8s52R5QUfvP88kFrAJ7
Nq/Yb0EeHVNmsQoOAaFrmeYd6iJ+XFJv93G0bD1cSVTPoynnIl0kyeicN8rf2lNV
ZbU8qdxyYwxK3BaBMyh+jarCx+glXmDuQgcRMJ8t7KWOKKvOpiVzpksoZvoSucrN
gIKfxyPbvUSEFwx95oN0VfAvAhOzrnHF1ghp7CSnatVWuqGWpseqqIC0oosRe1ob
GFUOxWYK3jUIwE8KYgbcHl0Zie7jEWegYOlkOxurivRZS8AcOoi9IycJlTGGO/vX
REgdHSKm6O5NxHBW6X6rBrL44YuR0WnVKmBLVeGcGxqSfpgkXRG+6Pa8XBSmYDgU
k26tb2JXSkpUwMRu9omKn96nbaWAAo3IUnB/ErWuPjvhADRZcERYH1UdNnSY3BvW
PsgeUEL7j67/s9EHShwtPLBRN22CJVgefnV1oxBgK7I1IZkgiUS3EVN53Z/edFTw
XKR+sN8SRM9pAV4DzGVElK5njdoy11ez9Xc1cG7lenLJJv1MTCo1NVqG136NvldS
OURc8Hp0G92OBGUBts5gDDeJTgn1fEnfSizZZ9JJP8B2I7WXV41rzGvswHR12tgE
EP0V6CqWSWjeOoj9DFhS
=tTZq
-----END PGP SIGNATURE-----
Roger Quadros Nov. 7, 2013, 12:23 p.m. UTC | #2
On 11/06/2013 11:48 PM, Tom Rini wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 11/06/2013 09:47 AM, Roger Quadros wrote:
>> Pipe3 PHY is used by SATA, USB3 and PCIe modules. This is
>> a driver for the Pipe3 PHY.
>>
>> Signed-off-by: Roger Quadros <rogerq@ti.com>
> [snip]
>> +#define perror(fmt, args...) printf("%s: " fmt, __func__ , ##args)
> 
> Please use the debug macro.
> 
But I want the message to be printed and not hidden if DEBUG is not defined.

> [snip[
>> +	perror("%s: No DPLL configuration for %u Hz SYS CLK\n",
>> +							__func__, rate);
> 
> Indent is wrong, we do like the kernel (and checkpatch.pl is in tools/
> and will catch these).  Thanks.

you mean the function arguments '__func__' and 'rate' should be on the
same line where perror is?

cheers,
-roger
Tom Rini Nov. 11, 2013, 1:52 p.m. UTC | #3
On Thu, Nov 07, 2013 at 02:23:32PM +0200, Roger Quadros wrote:
> On 11/06/2013 11:48 PM, Tom Rini wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> > 
> > On 11/06/2013 09:47 AM, Roger Quadros wrote:
> >> Pipe3 PHY is used by SATA, USB3 and PCIe modules. This is
> >> a driver for the Pipe3 PHY.
> >>
> >> Signed-off-by: Roger Quadros <rogerq@ti.com>
> > [snip]
> >> +#define perror(fmt, args...) printf("%s: " fmt, __func__ , ##args)
> > 
> > Please use the debug macro.
> > 
> But I want the message to be printed and not hidden if DEBUG is not defined.

Then just call printf please.  Or is this kernel-adapted code?

> > [snip[
> >> +	perror("%s: No DPLL configuration for %u Hz SYS CLK\n",
> >> +							__func__, rate);
> > 
> > Indent is wrong, we do like the kernel (and checkpatch.pl is in tools/
> > and will catch these).  Thanks.
> 
> you mean the function arguments '__func__' and 'rate' should be on the
> same line where perror is?

perror("....\n",
       __func_, ...);
Roger Quadros Nov. 11, 2013, 1:57 p.m. UTC | #4
On 11/11/2013 03:52 PM, Tom Rini wrote:
> On Thu, Nov 07, 2013 at 02:23:32PM +0200, Roger Quadros wrote:
>> On 11/06/2013 11:48 PM, Tom Rini wrote:
>>> -----BEGIN PGP SIGNED MESSAGE-----
>>> Hash: SHA1
>>>
>>> On 11/06/2013 09:47 AM, Roger Quadros wrote:
>>>> Pipe3 PHY is used by SATA, USB3 and PCIe modules. This is
>>>> a driver for the Pipe3 PHY.
>>>>
>>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>> [snip]
>>>> +#define perror(fmt, args...) printf("%s: " fmt, __func__ , ##args)
>>>
>>> Please use the debug macro.
>>>
>> But I want the message to be printed and not hidden if DEBUG is not defined.
> 
> Then just call printf please.  Or is this kernel-adapted code?

OK. No this isn't in the kernel.

> 
>>> [snip[
>>>> +	perror("%s: No DPLL configuration for %u Hz SYS CLK\n",
>>>> +							__func__, rate);
>>>
>>> Indent is wrong, we do like the kernel (and checkpatch.pl is in tools/
>>> and will catch these).  Thanks.
>>
>> you mean the function arguments '__func__' and 'rate' should be on the
>> same line where perror is?
> 
> perror("....\n",
>        __func_, ...);
> 

OK. I'll wait some more time for comments on v2 before I send out a v3 with these changes.

cheers,
-roger
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile
index 75b3753..6e4a0f0 100644
--- a/arch/arm/cpu/armv7/omap-common/Makefile
+++ b/arch/arm/cpu/armv7/omap-common/Makefile
@@ -21,6 +21,10 @@  COBJS	+= vc.o
 COBJS	+= abb.o
 endif
 
+ifneq ($(CONFIG_OMAP54XX),)
+COBJS	+= pipe3-phy.o
+endif
+
 ifeq ($(CONFIG_OMAP34XX),)
 COBJS	+= boot-common.o
 SOBJS	+= lowlevel_init.o
diff --git a/arch/arm/cpu/armv7/omap-common/pipe3-phy.c b/arch/arm/cpu/armv7/omap-common/pipe3-phy.c
new file mode 100644
index 0000000..2756bed
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap-common/pipe3-phy.c
@@ -0,0 +1,233 @@ 
+/*
+ * TI PIPE3 PHY
+ *
+ * (C) Copyright 2013
+ * Texas Instruments, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <sata.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include "pipe3-phy.h"
+
+/* PLLCTRL Registers */
+#define PLL_STATUS              0x00000004
+#define PLL_GO                  0x00000008
+#define PLL_CONFIGURATION1      0x0000000C
+#define PLL_CONFIGURATION2      0x00000010
+#define PLL_CONFIGURATION3      0x00000014
+#define PLL_CONFIGURATION4      0x00000020
+
+#define PLL_REGM_MASK           0x001FFE00
+#define PLL_REGM_SHIFT          9
+#define PLL_REGM_F_MASK         0x0003FFFF
+#define PLL_REGM_F_SHIFT        0
+#define PLL_REGN_MASK           0x000001FE
+#define PLL_REGN_SHIFT          1
+#define PLL_SELFREQDCO_MASK     0x0000000E
+#define PLL_SELFREQDCO_SHIFT    1
+#define PLL_SD_MASK             0x0003FC00
+#define PLL_SD_SHIFT            10
+#define SET_PLL_GO              0x1
+#define PLL_TICOPWDN            BIT(16)
+#define PLL_LDOPWDN             BIT(15)
+#define PLL_LOCK                0x2
+#define PLL_IDLE                0x1
+
+/* PHY POWER CONTROL Register */
+#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK         0x003FC000
+#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT        0xE
+
+#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK        0xFFC00000
+#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT       0x16
+
+#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON       0x3
+#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF      0x0
+
+
+#define PLL_IDLE_TIME   100     /* in milliseconds */
+#define PLL_LOCK_TIME   100     /* in milliseconds */
+
+#define perror(fmt, args...) printf("%s: " fmt, __func__ , ##args)
+
+static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
+{
+	return __raw_readl(addr + offset);
+}
+
+static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
+		u32 data)
+{
+	__raw_writel(data, addr + offset);
+}
+
+static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3
+									*pipe3)
+{
+	u32 rate;
+	struct pipe3_dpll_map *dpll_map = pipe3->dpll_map;
+
+	rate = get_sys_clk_freq();
+
+	for (; dpll_map->rate; dpll_map++) {
+		if (rate == dpll_map->rate)
+			return &dpll_map->params;
+	}
+
+	perror("%s: No DPLL configuration for %u Hz SYS CLK\n",
+							__func__, rate);
+	return NULL;
+}
+
+
+static int omap_pipe3_wait_lock(struct omap_pipe3 *phy)
+{
+	u32 val;
+	int timeout = PLL_LOCK_TIME;
+
+	do {
+		mdelay(1);
+		val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+		if (val & PLL_LOCK)
+			break;
+	} while (--timeout);
+
+	if (!(val & PLL_LOCK)) {
+		perror("%s: DPLL failed to lock\n", __func__);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int omap_pipe3_dpll_program(struct omap_pipe3 *phy)
+{
+	u32                     val;
+	struct pipe3_dpll_params *dpll_params;
+
+	dpll_params = omap_pipe3_get_dpll_params(phy);
+	if (!dpll_params) {
+		perror("%s: Invalid DPLL parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGN_MASK;
+	val |= dpll_params->n << PLL_REGN_SHIFT;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	val &= ~PLL_SELFREQDCO_MASK;
+	val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGM_MASK;
+	val |= dpll_params->m << PLL_REGM_SHIFT;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
+	val &= ~PLL_REGM_F_MASK;
+	val |= dpll_params->mf << PLL_REGM_F_SHIFT;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
+
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
+	val &= ~PLL_SD_MASK;
+	val |= dpll_params->sd << PLL_SD_SHIFT;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
+
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
+
+	return omap_pipe3_wait_lock(phy);
+}
+
+static void omap_control_phy_power(struct omap_pipe3 *phy, int on)
+{
+	u32 val, rate;
+
+	val = readl(phy->power_reg);
+
+	rate = get_sys_clk_freq();
+	rate = rate/1000000;
+
+	if (on) {
+		val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
+				OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
+		val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
+			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+		val |= rate <<
+			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
+	} else {
+		val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
+		val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
+			OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+	}
+
+	writel(val, phy->power_reg);
+}
+
+int phy_pipe3_power_on(struct omap_pipe3 *phy)
+{
+	int ret;
+	u32 val;
+
+	/* Program the DPLL only if not locked */
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+	if (!(val & PLL_LOCK)) {
+		ret = omap_pipe3_dpll_program(phy);
+		if (ret)
+			return ret;
+	} else {
+		/* else just bring it out of IDLE mode */
+	        val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+		if (val & PLL_IDLE) {
+			val &= ~PLL_IDLE;
+			omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2,
+					val);
+			ret = omap_pipe3_wait_lock(phy);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Power up the PHY */
+	omap_control_phy_power(phy, 1);
+
+	return 0;
+}
+
+int phy_pipe3_power_off(struct omap_pipe3 *phy)
+{
+	u32 val;
+	int timeout = PLL_IDLE_TIME;
+
+	/* Power down the PHY */
+	omap_control_phy_power(phy, 0);
+
+	/* Put DPLL in IDLE mode */
+	val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	val |= PLL_IDLE;
+	omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+	/* wait for LDO and Oscillator to power down */
+	do {
+		mdelay(1);
+		val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+		if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
+			break;
+	} while (--timeout);
+
+	if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
+		perror("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
+								__func__, val);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
diff --git a/arch/arm/cpu/armv7/omap-common/pipe3-phy.h b/arch/arm/cpu/armv7/omap-common/pipe3-phy.h
new file mode 100644
index 0000000..441f49a
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap-common/pipe3-phy.h
@@ -0,0 +1,36 @@ 
+/*
+ * TI PIPE3 PHY
+ *
+ * (C) Copyright 2013
+ * Texas Instruments, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __OMAP_PIPE3_PHY_H
+#define __OMAP_PIPE3_PHY_H
+
+struct pipe3_dpll_params {
+	u16     m;
+	u8      n;
+	u8      freq:3;
+	u8      sd;
+	u32     mf;
+};
+
+struct pipe3_dpll_map {
+	unsigned long rate;
+	struct pipe3_dpll_params params;
+};
+
+struct omap_pipe3 {
+	void __iomem            *pll_ctrl_base;
+	void __iomem		*power_reg;
+	struct pipe3_dpll_map   *dpll_map;
+};
+
+
+int phy_pipe3_power_on(struct omap_pipe3 *phy);
+int phy_pipe3_power_off(struct omap_pipe3 *pipe3);
+
+#endif /* __OMAP_PIPE3_PHY_H */