mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/16] Vybrid related patches
@ 2016-12-05 14:54 Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 01/16] i.MX: esdhc: Enable host->clk during initialization Andrey Smirnov
                   ` (15 more replies)
  0 siblings, 16 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Hi everyone,

Here's a second wave of Vybrid related patches that I developed
working with custom Vybrid board.

Most notable features of this patchset are:

     - CPU re-clocking for Vybrid
     - USB support on Vybrid
     - Early pinmux configuration routines for i.MX and Vybrid. An
       example of their utility is shown in the patch for i.MX6
       SabreSD board (I also have custom code using Vybrid version of
       those to read various "bootstraping" pins on my custom design)
     

Andrey Smirnov (16):
  i.MX: esdhc: Enable host->clk during initialization
  i.MX: ocotp: Add provisions for storing multiple MAC addresses
  i.MX: ocotp: Initialize OCOTP as early as possible
  i.MX: ocotp: Initialize 'sense_enable' to true on Vybrid
  i.MX: clk: Add IMX_PLLV3_SYS_VF610 subtype
  i.MX: vf610: Ramp CPU clock to maximum frequency
  i.MX: iomuxv3: Add low-level pad code to headers
  i.MX: iomuxv3: Add helper type to deconstruct iomux_v3_cfg_t values
  i.MX: iomuxv3: Add low-level pad configuration routine
  i.MX6: sabresd: Remove magic numbers in setup_uart
  i.MX: iomuxv3: Use helper functions in iomux-v3.h
  i.MX: vf610: Add low-level pin configuration helper
  i.MX: iomux-vf610: Add missing pad definitions
  i.MX: imx-usb-phy: Add VF610 OF compatiblity string
  i.MX: Default CONFI_USB_IMX_PHY to 'y' on Vybrid
  i.MX: imx-usb-misc: Add Vybrid support

 arch/arm/boards/freescale-mx6-sabresd/lowlevel.c |   9 +-
 arch/arm/mach-imx/Kconfig                        |  13 ++
 arch/arm/mach-imx/include/mach/iomux-v3.h        |  61 ++++++++
 arch/arm/mach-imx/include/mach/iomux-vf610.h     |  20 +++
 arch/arm/mach-imx/ocotp.c                        |  58 ++++++-
 drivers/clk/imx/clk-pllv3.c                      | 108 +++++++++++++
 drivers/clk/imx/clk-vf610.c                      | 187 ++++++++++++++++++++++-
 drivers/clk/imx/clk.h                            |   5 +
 drivers/mci/imx-esdhc.c                          |   7 +
 drivers/pinctrl/imx-iomux-v3.c                   |  38 +----
 drivers/pinctrl/pinctrl-vf610.c                  |  11 +-
 drivers/usb/imx/Kconfig                          |   2 +-
 drivers/usb/imx/imx-usb-misc.c                   |  28 ++++
 drivers/usb/imx/imx-usb-phy.c                    |   2 +
 14 files changed, 496 insertions(+), 53 deletions(-)

-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 01/16] i.MX: esdhc: Enable host->clk during initialization
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses Andrey Smirnov
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/mci/imx-esdhc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index d72e3f8..40a086b 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -631,6 +631,13 @@ static int fsl_esdhc_probe(struct device_d *dev)
 	if (IS_ERR(host->clk))
 		return PTR_ERR(host->clk);
 
+	ret = clk_enable(host->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clock: %s\n",
+			strerror(ret));
+		return ret;
+	}
+
 	host->dev = dev;
 	iores = dev_request_mem_resource(dev, 0);
 	if (IS_ERR(iores))
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 01/16] i.MX: esdhc: Enable host->clk during initialization Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 15:14   ` Stefan Lengfeld
  2016-12-05 14:54 ` [PATCH 03/16] i.MX: ocotp: Initialize OCOTP as early as possible Andrey Smirnov
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

i.MX SoC variants like Vybrid have more than one built-in Ethernet
interface and as a consequence support storing more than one MAC address
in OCOTP module. Add 'mac_idx' variable to allow to select which mac
address is being referred to by 'mac_addr' variable and the code to
handle it appropriately.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 50 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 68ff0ce..9a07922 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -69,12 +69,16 @@
 /* Other definitions */
 #define IMX6_OTP_DATA_ERROR_VAL		0xBADABADA
 #define DEF_RELAX			20
-#define MAC_OFFSET			(0x22 * 4)
+#define MAC_OFFSET_0			(0x22 * 4)
+#define MAC_OFFSET_1			(0x24 * 4)
+#define MAX_MAC_OFFSETS			2
 #define MAC_BYTES			8
 
 struct imx_ocotp_data {
 	int num_regs;
 	u32 (*addr_to_offset)(u32 addr);
+	u8  mac_offsets[MAX_MAC_OFFSETS];
+	u8  mac_offsets_num;
 };
 
 struct ocotp_priv {
@@ -87,6 +91,7 @@ struct ocotp_priv {
 	char ethaddr[6];
 	struct regmap_config map_config;
 	const struct imx_ocotp_data *data;
+	int  mac_offset_idx;
 };
 
 static struct ocotp_priv *imx_ocotp;
@@ -402,8 +407,10 @@ static int imx_ocotp_get_mac(struct param_d *param, void *priv)
 	struct ocotp_priv *ocotp_priv = priv;
 	char buf[8];
 	int i, ret;
+	u8  mac_offset;
 
-	ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
+	mac_offset = ocotp_priv->data->mac_offsets[ocotp_priv->mac_offset_idx];
+	ret = regmap_bulk_read(ocotp_priv->map, mac_offset, buf, MAC_BYTES);
 	if (ret < 0)
 		return ret;
 
@@ -418,18 +425,43 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv)
 	struct ocotp_priv *ocotp_priv = priv;
 	char buf[8];
 	int i, ret;
+	u8 mac_offset;
+
+	mac_offset = ocotp_priv->data->mac_offsets[ocotp_priv->mac_offset_idx];
 
 	for (i = 0; i < 6; i++)
 		buf[5 - i] = ocotp_priv->ethaddr[i];
 	buf[6] = 0; buf[7] = 0;
 
-	ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
+	ret = regmap_bulk_write(ocotp_priv->map, mac_offset, buf, MAC_BYTES);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
+static int imx_ocotp_set_mac_idx(struct param_d *param, void *priv)
+{
+	struct ocotp_priv *ocotp_priv = priv;
+	const int min = 0;
+	const int max = ocotp_priv->data->mac_offsets_num - 1;
+	int old, new, ret = 0;
+
+	old = ocotp_priv->mac_offset_idx;
+	new = clamp(old, min, max);
+
+	if (old != new) {
+		dev_err(&ocotp_priv->dev,
+			"%d is out of bounds for '%s', clamping to %d\n",
+			old, param->name, new);
+		ret = -EINVAL;
+	}
+
+	ocotp_priv->mac_offset_idx = new;
+
+	return ret;
+}
+
 static struct regmap_bus imx_ocotp_regmap_bus = {
 	.reg_write = imx_ocotp_reg_write,
 	.reg_read = imx_ocotp_reg_read,
@@ -486,9 +518,13 @@ static int imx_ocotp_probe(struct device_d *dev)
 				NULL, NULL, &priv->permanent_write_enable, NULL);
 	}
 
-	if (IS_ENABLED(CONFIG_NET))
+	if (IS_ENABLED(CONFIG_NET)) {
+		dev_add_param_int(&priv->dev, "mac_idx",
+				  imx_ocotp_set_mac_idx, NULL,
+				  &priv->mac_offset_idx, "%d", priv);
 		dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac,
 				imx_ocotp_get_mac, priv->ethaddr, priv);
+	}
 
 	dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv);
 
@@ -527,16 +563,22 @@ static u32 vf610_addr_to_offset(u32 addr)
 static struct imx_ocotp_data imx6q_ocotp_data = {
 	.num_regs = 512,
 	.addr_to_offset = imx6q_addr_to_offset,
+	.mac_offsets_num = 1,
+	.mac_offsets = { MAC_OFFSET_0 },
 };
 
 static struct imx_ocotp_data imx6sl_ocotp_data = {
 	.num_regs = 256,
 	.addr_to_offset = imx6sl_addr_to_offset,
+	.mac_offsets_num = 1,
+	.mac_offsets = { MAC_OFFSET_0 },
 };
 
 static struct imx_ocotp_data vf610_ocotp_data = {
 	.num_regs = 512,
 	.addr_to_offset = vf610_addr_to_offset,
+	.mac_offsets_num = 2,
+	.mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 },
 };
 
 static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 03/16] i.MX: ocotp: Initialize OCOTP as early as possible
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 01/16] i.MX: esdhc: Enable host->clk during initialization Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 04/16] i.MX: ocotp: Initialize 'sense_enable' to true on Vybrid Andrey Smirnov
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

On Vybrid SoC OCOTP module contains speed grading information that is
needed to correctly adjust CPU clock to its maxumum rate, so we need to
have this information handy as early as possible.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 9a07922..667555a 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -614,4 +614,4 @@ static int imx_ocotp_init(void)
 
 	return 0;
 }
-coredevice_initcall(imx_ocotp_init);
+postcore_initcall(imx_ocotp_init);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 04/16] i.MX: ocotp: Initialize 'sense_enable' to true on Vybrid
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (2 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 03/16] i.MX: ocotp: Initialize OCOTP as early as possible Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 05/16] i.MX: clk: Add IMX_PLLV3_SYS_VF610 subtype Andrey Smirnov
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Reading speed grading information (OCOTP word 0x4) only seem to work
when that data read is straigh out of a fusebox. Allow differenet SoC to
deafalut 'sense_enable' to different values and set it to true on
Vybrid.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 667555a..e9c07c2 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -79,6 +79,7 @@ struct imx_ocotp_data {
 	u32 (*addr_to_offset)(u32 addr);
 	u8  mac_offsets[MAX_MAC_OFFSETS];
 	u8  mac_offsets_num;
+	bool sense_enable;
 };
 
 struct ocotp_priv {
@@ -494,6 +495,8 @@ static int imx_ocotp_probe(struct device_d *dev)
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
+	priv->sense_enable = priv->data->sense_enable;
+
 	strcpy(priv->dev.name, "ocotp");
 	priv->dev.parent = dev;
 	register_device(&priv->dev);
@@ -565,6 +568,7 @@ static struct imx_ocotp_data imx6q_ocotp_data = {
 	.addr_to_offset = imx6q_addr_to_offset,
 	.mac_offsets_num = 1,
 	.mac_offsets = { MAC_OFFSET_0 },
+	.sense_enable = false,
 };
 
 static struct imx_ocotp_data imx6sl_ocotp_data = {
@@ -572,6 +576,7 @@ static struct imx_ocotp_data imx6sl_ocotp_data = {
 	.addr_to_offset = imx6sl_addr_to_offset,
 	.mac_offsets_num = 1,
 	.mac_offsets = { MAC_OFFSET_0 },
+	.sense_enable = false,
 };
 
 static struct imx_ocotp_data vf610_ocotp_data = {
@@ -579,6 +584,7 @@ static struct imx_ocotp_data vf610_ocotp_data = {
 	.addr_to_offset = vf610_addr_to_offset,
 	.mac_offsets_num = 2,
 	.mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 },
+	.sense_enable = true,
 };
 
 static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 05/16] i.MX: clk: Add IMX_PLLV3_SYS_VF610 subtype
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (3 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 04/16] i.MX: ocotp: Initialize 'sense_enable' to true on Vybrid Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency Andrey Smirnov
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add IMX_PLLV3_SYS_VF610 subtype to pllv3 code to be able to control and
re-clock PLL1 and PLL2 on Vybrid SoC. This commit also introduces
imx_clk_pllv3_locked which allows the user to create PLLv3 and specify
how it should be polled for "locked" status (used in .set_rate callback)

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/clk-pllv3.c | 108 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h       |   5 ++
 2 files changed, 113 insertions(+)

diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index 29c0f1c..dd924a4 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -26,6 +26,8 @@
 #define PLL_NUM_OFFSET		0x10
 #define PLL_DENOM_OFFSET	0x20
 
+#define SYS_VF610_PLL_OFFSET	0x10
+
 #define BM_PLL_POWER		(0x1 << 12)
 #define BM_PLL_ENABLE		(0x1 << 13)
 #define BM_PLL_BYPASS		(0x1 << 16)
@@ -38,6 +40,8 @@ struct clk_pllv3 {
 	u32		div_mask;
 	u32		div_shift;
 	const char	*parent;
+	void __iomem	*lock_reg;
+	u32		lock_mask;
 };
 
 #define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk)
@@ -279,6 +283,88 @@ static const struct clk_ops clk_pllv3_mlb_ops = {
 	.disable	= clk_pllv3_disable,
 };
 
+static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk,
+						     unsigned long parent_rate)
+{
+	struct clk_pllv3 *pll = to_clk_pllv3(clk);
+
+	u32 mfn = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET);
+	u32 mfd = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET);
+	u32 div = (readl(pll->base) & pll->div_mask) ? 22 : 20;
+
+	return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate,
+					   unsigned long *prate)
+{
+	unsigned long parent_rate = *prate;
+	unsigned long min_rate = parent_rate * 20;
+	unsigned long max_rate = 528000000;
+	u32 mfn, mfd = 1000000;
+	u64 temp64;
+
+	if (rate >= max_rate)
+		return max_rate;
+	else if (rate < min_rate)
+		rate = min_rate;
+
+	temp64 = (u64) (rate - 20 * parent_rate);
+	temp64 *= mfd;
+	do_div(temp64, parent_rate);
+	mfn = temp64;
+
+	return parent_rate * 20 + parent_rate / mfd * mfn;
+}
+
+static int clk_pllv3_sys_vf610_set_rate(struct clk *clk, unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct clk_pllv3 *pll = to_clk_pllv3(clk);
+	unsigned long min_rate = parent_rate * 20;
+	unsigned long max_rate = 528000000;
+	u32 val;
+	u32 mfn, mfd = 1000000;
+	u64 temp64;
+
+	if (rate < min_rate || rate > max_rate)
+		return -EINVAL;
+
+	val = readl(pll->base);
+
+	if (rate == max_rate) {
+		writel(0, pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET);
+		val |= pll->div_mask;
+		writel(val, pll->base);
+
+		return 0;
+	} else {
+		val &= ~pll->div_mask;
+	}
+
+	temp64 = (u64) (rate - 20 * parent_rate);
+	temp64 *= mfd;
+	do_div(temp64, parent_rate);
+	mfn = temp64;
+
+	writel(val, pll->base);
+	writel(mfn, pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET);
+	writel(mfd, pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET);
+
+	while (!(readl(pll->lock_reg) & pll->lock_mask))
+		;
+
+	return 0;
+}
+
+static const struct clk_ops clk_pllv3_sys_vf610_ops = {
+	.enable		= clk_pllv3_enable,
+	.disable	= clk_pllv3_disable,
+	.recalc_rate	= clk_pllv3_sys_vf610_recalc_rate,
+	.round_rate	= clk_pllv3_sys_vf610_round_rate,
+	.set_rate	= clk_pllv3_sys_vf610_set_rate,
+};
+
 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 			  const char *parent, void __iomem *base,
 			  u32 div_mask)
@@ -290,6 +376,9 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 	pll = xzalloc(sizeof(*pll));
 
 	switch (type) {
+	case IMX_PLLV3_SYS_VF610:
+		ops = &clk_pllv3_sys_vf610_ops;
+		break;
 	case IMX_PLLV3_SYS:
 		ops = &clk_pllv3_sys_ops;
 		break;
@@ -327,3 +416,22 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 
 	return &pll->clk;
 }
+
+struct clk *imx_clk_pllv3_locked(enum imx_pllv3_type type, const char *name,
+				 const char *parent, void __iomem *base,
+				 u32 div_mask, void __iomem *lock_reg, u32 lock_mask)
+{
+	struct clk *clk;
+	struct clk_pllv3 *pll;
+
+	clk = imx_clk_pllv3(type, name, parent, base, div_mask);
+	if (IS_ERR(clk))
+		return clk;
+
+	pll = to_clk_pllv3(clk);
+
+	pll->lock_reg  = lock_reg;
+	pll->lock_mask = lock_mask;
+
+	return clk;
+}
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 970f65c..0b28fb2 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -78,6 +78,7 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent,
 enum imx_pllv3_type {
 	IMX_PLLV3_GENERIC,
 	IMX_PLLV3_SYS,
+	IMX_PLLV3_SYS_VF610,
 	IMX_PLLV3_USB,
 	IMX_PLLV3_USB_VF610,
 	IMX_PLLV3_AV,
@@ -89,6 +90,10 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 			  const char *parent, void __iomem *base,
 			  u32 div_mask);
 
+struct clk *imx_clk_pllv3_locked(enum imx_pllv3_type type, const char *name,
+				 const char *parent, void __iomem *base,
+				 u32 div_mask, void __iomem *lock_reg, u32 lock_mask);
+
 struct clk *imx_clk_pfd(const char *name, const char *parent,
 			void __iomem *reg, u8 idx);
 
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (4 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 05/16] i.MX: clk: Add IMX_PLLV3_SYS_VF610 subtype Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-07 19:27   ` Sascha Hauer
  2016-12-05 14:54 ` [PATCH 07/16] i.MX: iomuxv3: Add low-level pad code to headers Andrey Smirnov
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Mask ROM leaves the CPU running at 264Mhz, so configure the clock tree
to such that CPU runs at maximum supported frequency, based on speed
grading burned into OCOTP fusebox.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/Kconfig   |  13 +++
 drivers/clk/imx/clk-vf610.c | 187 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 198 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index af533ea..1752335 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -750,6 +750,19 @@ config HABV3_IMG_CRT_DER
 
 endif
 
+config ADJUST_CPU_CLOCK
+       bool "Adjust CPU clock based on its speed grading"
+       select IMX_OCOTP
+       depends on ARCH_VF610
+       default y
+       help
+	  Some i.MX SoCs (e. g. Vybrid) are manufactured to have
+	  several variants of the same chip different only in maxumum
+	  CPU frequency supported. MaskROM on such chips plays it safe
+	  and uses the lowest possible frequency. This option
+	  configures Barebox to read chip's speed grade information
+	  and increase CPU clock to it's highest possible value.
+
 endmenu
 
 endif
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
index 04cb02f..1cf2b65 100644
--- a/drivers/clk/imx/clk-vf610.c
+++ b/drivers/clk/imx/clk-vf610.c
@@ -16,7 +16,9 @@
 #include <of_address.h>
 #include <linux/clkdev.h>
 #include <linux/clk.h>
+#include <notifier.h>
 #include <dt-bindings/clock/vf610-clock.h>
+#include <mach/vf610-regs.h>
 
 #include "clk.h"
 
@@ -76,6 +78,7 @@
 #define PLL6_CTRL		(anatop_base + 0xa0)
 #define PLL7_CTRL		(anatop_base + 0x20)
 #define ANA_MISC1		(anatop_base + 0x160)
+#define PLL_LOCK		(anatop_base + 0x2c0)
 
 static void __iomem *anatop_base;
 static void __iomem *ccm_base;
@@ -188,8 +191,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 	clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 	clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
 
-	clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
-	clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
+	clk[VF610_CLK_PLL1] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1, PLL_LOCK, BIT(6));
+	clk[VF610_CLK_PLL2] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1, PLL_LOCK, BIT(5));
+
 	clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
 	clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
 	clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
@@ -441,3 +445,182 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 }
 CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init);
+
+#ifdef CONFIG_ADJUST_CPU_CLOCK
+
+enum {
+	OCOTP_SPEED_GRADING_OFFSET = (0x4 * sizeof(uint32_t)),
+	OCOTP_SPEED_GRADING_SHIFT  = 18,
+	OCOTP_SPEED_GRADING_MASK   = 0b1111,
+
+	VF610_SPEED_500 = 0b1110,
+	VF610_SPEED_400 = 0b1001,
+	VF610_SPEED_266 = 0b0001,
+
+	DDRMC_CR117 = 0x01d4,
+	DDRMC_CR117_AXI0_FITYPEREG_SYNC = 0b01 << 16,
+};
+
+static int vf610_switch_cpu_clock_to_500mhz(void)
+{
+	int ret;
+
+	/*
+	 * When switching A5 CPU to 500Mhz we expect DDRC to be
+	 * clocked by PLL2_PFD2 and the system to be configured in
+	 * asynchronous mode.
+	 *
+	 * We also can't just use default PFD1 output of PLL1 due to
+	 * Errata e6235, so we have to re-clock the PLL itself and use
+	 * its output to clock the CPU directly.
+	 */
+
+	if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
+		pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_BUS]);
+	if (ret < 0) {
+		pr_crit("Unable to re-parent '%s'\n",
+			clk[VF610_CLK_SYS_SEL]->name);
+		return ret;
+	}
+
+	ret = clk_set_rate(clk[VF610_CLK_PLL1], 500000000);
+	if (ret < 0) {
+		pr_crit("Unable to set %s to 500Mhz %d\n",
+			clk[VF610_CLK_PLL1]->name, ret);
+		return ret;
+	}
+
+	ret = clk_set_parent(clk[VF610_CLK_PLL1_PFD_SEL], clk[VF610_CLK_PLL1_SYS]);
+	if (ret < 0) {
+		pr_crit("Unable to re-parent '%s'\n",
+			clk[VF610_CLK_PLL1_PFD_SEL]->name);
+		return ret;
+	}
+
+	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL1_PFD_SEL]);
+	if (ret < 0) {
+		pr_crit("Unable to re-parent '%s'\n",
+			clk[VF610_CLK_SYS_SEL]->name);
+		return ret;
+	}
+
+	/*
+	 * imx_clk_divider has no error path in its set_rate hook
+	 */
+	clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
+	clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
+
+	return ret;
+}
+
+static int vf610_switch_cpu_clock_to_400mhz(void)
+{
+	int ret;
+	uint32_t cr117;
+	void * __iomem ddrmc = IOMEM(VF610_DDR_BASE_ADDR);
+
+	if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
+		pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(clk[VF610_CLK_PLL2_PFD_SEL], clk[VF610_CLK_PLL2_PFD2]);
+	if (ret < 0) {
+		pr_crit("Unable to re-parent '%s'\n",
+			clk[VF610_CLK_PLL2_PFD_SEL]->name);
+		return ret;
+	}
+
+	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_PFD_SEL]);
+	if (ret < 0) {
+		pr_crit("Unable to re-parent '%s'\n",
+			clk[VF610_CLK_SYS_SEL]->name);
+		return ret;
+	}
+
+	/*
+	 * imx_clk_divider has no error path in its set_rate hook
+	 */
+	clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
+	clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
+
+	/*
+	 * Now that we are running off of the same clock as DDRMC we
+	 * shouldn't need to use clock domain corssing FIFO and
+	 * asynchronous mode and instead can swithch to sychronous
+	 * mode for AXI0 accesses
+	 */
+	cr117 =  readl(ddrmc + DDRMC_CR117);
+	cr117 |= DDRMC_CR117_AXI0_FITYPEREG_SYNC;
+	writel(cr117, ddrmc + DDRMC_CR117);
+
+	return 0;
+}
+
+static int vf610_switch_cpu_clock(void)
+{
+	int ret;
+	struct device_node *ocotp_node;
+	struct cdev *ocotp;
+	uint32_t speed_grading;
+
+	if (!of_machine_is_compatible("fsl,vf610"))
+		return 0;
+
+	ocotp_node = of_find_compatible_node(NULL, NULL, "fsl,vf610-ocotp");
+	if (!ocotp_node) {
+		pr_err("Unable to find OCOTP DT node\n");
+		return -ENODEV;
+	}
+
+	ocotp = cdev_by_device_node(ocotp_node);
+	if (!ocotp) {
+		pr_err("No OCOTP character device\n");
+		return -ENODEV;
+	}
+
+	ret = cdev_read(ocotp, &speed_grading, sizeof(speed_grading),
+		       OCOTP_SPEED_GRADING_OFFSET, 0);
+	if (ret != sizeof(speed_grading)) {
+		pr_err("Failed to read speed grading data\n");
+		return ret < 0 ? ret : -EIO;
+	}
+
+	speed_grading >>= OCOTP_SPEED_GRADING_SHIFT;
+	speed_grading &=  OCOTP_SPEED_GRADING_MASK;
+
+	switch (speed_grading) {
+	default:
+		pr_err("Unknown CPU speed grading %x\n", speed_grading);
+		return -EINVAL;
+
+	case VF610_SPEED_266:
+		return 0;
+
+	case VF610_SPEED_500:
+		ret = vf610_switch_cpu_clock_to_500mhz();
+		break;
+
+	case VF610_SPEED_400:
+		ret = vf610_switch_cpu_clock_to_400mhz();
+		break;
+	}
+
+	clock_notifier_call_chain();
+	return ret;
+}
+/*
+ * We can probably gain a bit of a boot speed if we switch CPU clock
+ * earlier, but if we do this we'd need to figure out a way how to
+ * re-adjust the baud rate settings of the UART for DEBUG_LL
+ * functionality, or, accept the fact that it will be unavailbe after
+ * this hook is executed. Both are far from ideal, so a bit slower
+ * boot it is.
+ */
+postconsole_initcall(vf610_switch_cpu_clock);
+
+#endif
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 07/16] i.MX: iomuxv3: Add low-level pad code to headers
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (5 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 08/16] i.MX: iomuxv3: Add helper type to deconstruct iomux_v3_cfg_t values Andrey Smirnov
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add a basic low-level pad configuration function that can be used to
implement early boot pin configuration code as well as shared with
various iomuxv3 and vf610 drivers.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/iomux-v3.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/iomux-v3.h b/arch/arm/mach-imx/include/mach/iomux-v3.h
index b8cc9af..3bf457f 100644
--- a/arch/arm/mach-imx/include/mach/iomux-v3.h
+++ b/arch/arm/mach-imx/include/mach/iomux-v3.h
@@ -16,6 +16,8 @@
 #ifndef __MACH_IOMUX_V3_H__
 #define __MACH_IOMUX_V3_H__
 
+#include <io.h>
+
 /*
  *	build IOMUX_PAD structure
  *
@@ -104,6 +106,32 @@ typedef u64 iomux_v3_cfg_t;
 
 #define IOMUX_CONFIG_SION		(0x1 << 4)
 
+#define SHARE_MUX_CONF_REG		0x1
+#define ZERO_OFFSET_VALID		0x2
+
+static inline void iomux_v3_setup_pad(void __iomem *iomux, unsigned int flags,
+				      u32 mux_reg, u32 conf_reg, u32 input_reg,
+				      u32 mux_val, u32 conf_val, u32 input_val)
+{
+	const bool mux_ok   = !!mux_reg || (flags & ZERO_OFFSET_VALID);
+	const bool conf_ok  = !!conf_reg;
+	const bool input_ok = !!input_reg;
+
+	if (flags & SHARE_MUX_CONF_REG) {
+		mux_val |= conf_val;
+	} else {
+		if (conf_ok)
+			writel(conf_val, iomux + conf_reg);
+	}
+
+	if (mux_ok)
+		writel(mux_val, iomux + mux_reg);
+
+	if (input_ok)
+		writel(input_val, iomux + input_reg);
+}
+
+
 /*
  * setups a single pad in the iomuxer
  */
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 08/16] i.MX: iomuxv3: Add helper type to deconstruct iomux_v3_cfg_t values
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (6 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 07/16] i.MX: iomuxv3: Add low-level pad code to headers Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 09/16] i.MX: iomuxv3: Add low-level pad configuration routine Andrey Smirnov
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/iomux-v3.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/iomux-v3.h b/arch/arm/mach-imx/include/mach/iomux-v3.h
index 3bf457f..470f774 100644
--- a/arch/arm/mach-imx/include/mach/iomux-v3.h
+++ b/arch/arm/mach-imx/include/mach/iomux-v3.h
@@ -78,6 +78,22 @@ typedef u64 iomux_v3_cfg_t;
 		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
 		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
 
+
+struct iomux_v3_pad_configuration {
+	u64 mux_ctrl_ofs  : 12;
+	u64 pad_ctrl_ofs  : 12;
+	u64 sel_input_ofs : 12;
+	u64 mux_mode      : 5;
+	u64 pad_ctrl      : 18;
+	u64 sel_inp       : 4;
+	u64 reserved      : 1;
+} __packed;
+
+union iomux_v3_pad {
+	iomux_v3_cfg_t raw;
+	struct iomux_v3_pad_configuration cfg;
+};
+
 #define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
 /*
  * Use to set PAD control
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 09/16] i.MX: iomuxv3: Add low-level pad configuration routine
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (7 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 08/16] i.MX: iomuxv3: Add helper type to deconstruct iomux_v3_cfg_t values Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 10/16] i.MX6: sabresd: Remove magic numbers in setup_uart Andrey Smirnov
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add low-level pad configuration routine that can be used by early boot
code as well as leveraged by pinmux driver.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/iomux-v3.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/iomux-v3.h b/arch/arm/mach-imx/include/mach/iomux-v3.h
index 470f774..0205ec7 100644
--- a/arch/arm/mach-imx/include/mach/iomux-v3.h
+++ b/arch/arm/mach-imx/include/mach/iomux-v3.h
@@ -147,6 +147,23 @@ static inline void iomux_v3_setup_pad(void __iomem *iomux, unsigned int flags,
 		writel(input_val, iomux + input_reg);
 }
 
+static inline void imx_setup_pad(void __iomem *iomux, iomux_v3_cfg_t __pad)
+{
+	union iomux_v3_pad pad = { .raw = __pad };
+	uint32_t pad_ctrl;
+
+	pad_ctrl = (pad.cfg.pad_ctrl & NO_PAD_CTRL) ? 0 : pad.cfg.pad_ctrl,
+
+	iomux_v3_setup_pad(iomux, 0,
+			   pad.cfg.mux_ctrl_ofs,
+			   pad.cfg.pad_ctrl_ofs,
+			   pad.cfg.sel_input_ofs,
+			   pad.cfg.mux_mode,
+			   pad_ctrl,
+			   pad.cfg.sel_inp);
+}
+
+
 
 /*
  * setups a single pad in the iomuxer
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 10/16] i.MX6: sabresd: Remove magic numbers in setup_uart
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (8 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 09/16] i.MX: iomuxv3: Add low-level pad configuration routine Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 11/16] i.MX: iomuxv3: Use helper functions in iomux-v3.h Andrey Smirnov
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Remove magic numbers in setup_uart and replace them with calls to
iomuxv3 helper functions.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/boards/freescale-mx6-sabresd/lowlevel.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c
index b329f46..5743dbc 100644
--- a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c
+++ b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c
@@ -2,6 +2,7 @@
 #include <common.h>
 #include <linux/sizes.h>
 #include <mach/generic.h>
+#include <mach/iomux-mx6.h>
 #include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
 
@@ -11,12 +12,8 @@ static inline void setup_uart(void)
 
 	imx6_ungate_all_peripherals();
 
-	writel(0x1b0b1, iomuxbase + 0x0650);
-	writel(3, iomuxbase + 0x0280);
-
-	writel(0x1b0b1, iomuxbase + 0x0654);
-	writel(3, iomuxbase + 0x0284);
-	writel(1, iomuxbase + 0x0920);
+	imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT10__UART1_TXD);
+	imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT11__UART1_RXD);
 
 	imx6_uart_setup_ll();
 
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 11/16] i.MX: iomuxv3: Use helper functions in iomux-v3.h
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (9 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 10/16] i.MX6: sabresd: Remove magic numbers in setup_uart Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 12/16] i.MX: vf610: Add low-level pin configuration helper Andrey Smirnov
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Avoid code duplication by using helper functions from iomux-v3.h

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/pinctrl/imx-iomux-v3.c | 38 ++++----------------------------------
 1 file changed, 4 insertions(+), 34 deletions(-)

diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c
index 4b3f033..bc93140 100644
--- a/drivers/pinctrl/imx-iomux-v3.c
+++ b/drivers/pinctrl/imx-iomux-v3.c
@@ -31,46 +31,17 @@ struct imx_iomux_v3 {
 };
 
 static void __iomem *iomuxv3_base;
-static struct device_d *iomuxv3_dev;
 
-static void imx_iomuxv3_setup_single(void __iomem *base, struct device_d *dev,
-		u32 mux_reg, u32 conf_reg, u32 input_reg,
-		u32 mux_val, u32 conf_val, u32 input_val)
-{
-	dev_dbg(dev,
-		"mux: 0x%08x -> 0x%04x, conf: 0x%08x -> 0x%04x input: 0x%08x -> 0x%04x\n",
-		mux_val, mux_reg, conf_val, conf_reg, input_val, input_reg);
-
-	if (mux_reg)
-		writel(mux_val, base + mux_reg);
-	if (conf_reg)
-		writel(conf_val, base + conf_reg);
-	if (input_reg)
-		writel(input_val, base + input_reg);
-}
 
 /*
  * configures a single pad in the iomuxer
  */
 int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
 {
-	u32 mux_reg = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
-	u32 mux_val = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
-	u32 input_reg = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
-	u32 input_val = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
-	u32 conf_reg = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
-	u32 conf_val = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
-
 	if (!iomuxv3_base)
 		return -EINVAL;
 
-	if (conf_val & NO_PAD_CTRL)
-		conf_reg = 0;
-
-	imx_iomuxv3_setup_single(iomuxv3_base, iomuxv3_dev,
-			mux_reg, conf_reg, input_reg,
-			mux_val, conf_val, input_val);
-
+	imx_setup_pad(iomuxv3_base, pad);
 	return 0;
 }
 EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
@@ -140,9 +111,9 @@ static int imx_iomux_v3_set_state(struct pinctrl_device *pdev, struct device_nod
 		if (conf_val & IMX_DT_NO_PAD_CTL)
 			conf_reg = 0;
 
-		imx_iomuxv3_setup_single(iomux->base, iomux->pinctrl.dev,
-				mux_reg, conf_reg, input_reg,
-				mux_val, conf_val, input_val);
+		iomux_v3_setup_pad(iomux->base, 0,
+				   mux_reg, conf_reg, input_reg,
+				   mux_val, conf_val, input_val);
 	}
 
 	return 0;
@@ -183,7 +154,6 @@ static int imx_iomux_v3_probe(struct device_d *dev)
 	if (IS_ERR(iores))
 		return PTR_ERR(iores);
 	iomuxv3_base = IOMEM(iores->start);
-	iomuxv3_dev = dev;
 
 	if (IS_ENABLED(CONFIG_PINCTRL) && dev->device_node)
 		ret = imx_pinctrl_dt(dev, iomuxv3_base);
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 12/16] i.MX: vf610: Add low-level pin configuration helper
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (10 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 11/16] i.MX: iomuxv3: Use helper functions in iomux-v3.h Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 13/16] i.MX: iomux-vf610: Add missing pad definitions Andrey Smirnov
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add low-level pin configuration helper for early boot code, and convert
pinctrl driver to use that code as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/iomux-vf610.h | 16 ++++++++++++++++
 drivers/pinctrl/pinctrl-vf610.c              | 11 ++++++-----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h
index 1535628..087d6f2 100644
--- a/arch/arm/mach-imx/include/mach/iomux-vf610.h
+++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h
@@ -223,4 +223,20 @@ enum {
 	VF610_PAD_DDR_ODT0__DDR_ODT_1	= IOMUX_PAD(0x02d8, 0x02d8, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
 };
 
+#define PINCTRL_VF610_MUX_SHIFT 20
+
+
+static inline void vf610_setup_pad(void __iomem *iomux, iomux_v3_cfg_t __pad)
+{
+	union iomux_v3_pad pad = { .raw = __pad };
+
+	iomux_v3_setup_pad(iomux, SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
+			   pad.cfg.mux_ctrl_ofs,
+			   pad.cfg.pad_ctrl_ofs,
+			   pad.cfg.sel_input_ofs,
+			   pad.cfg.mux_mode << PINCTRL_VF610_MUX_SHIFT,
+			   pad.cfg.pad_ctrl, pad.cfg.sel_inp);
+}
+
+
 #endif	/* __IOMUX_VF610_H__ */
diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
index b479bf2..4234263 100644
--- a/drivers/pinctrl/pinctrl-vf610.c
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -24,9 +24,10 @@
 #include <malloc.h>
 #include <gpio.h>
 
+#include <mach/iomux-vf610.h>
+
 enum {
 	PINCTRL_VF610_MUX_LINE_SIZE = 20,
-	PINCTRL_VF610_MUX_SHIFT = 20,
 
 	PINCTRL_VF610_IBE = 1 << 0,
 	PINCTRL_VF610_OBE = 1 << 1,
@@ -60,17 +61,17 @@ static int pinctrl_vf610_set_state(struct pinctrl_device *pdev,
 	npins = size / PINCTRL_VF610_MUX_LINE_SIZE;
 
 	for (i = 0; i < npins; i++) {
+		iomux_v3_cfg_t pad;
 		u32 mux_reg   = be32_to_cpu(*list++);
 		u32 input_reg = be32_to_cpu(*list++);
 		u32 mux_val   = be32_to_cpu(*list++);
 		u32 input_val = be32_to_cpu(*list++);
 		u32 conf_val  = be32_to_cpu(*list++);
 
-		writel(mux_val << PINCTRL_VF610_MUX_SHIFT | conf_val,
-		       iomux->base + mux_reg);
+		pad = IOMUX_PAD(mux_reg, mux_reg, mux_val,
+				input_reg, input_val, conf_val);
 
-		if (input_reg)
-			writel(input_val, iomux->base + input_reg);
+		vf610_setup_pad(iomux->base, pad);
 	}
 
 	return 0;
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 13/16] i.MX: iomux-vf610: Add missing pad definitions
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (11 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 12/16] i.MX: vf610: Add low-level pin configuration helper Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 14/16] i.MX: imx-usb-phy: Add VF610 OF compatiblity string Andrey Smirnov
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/include/mach/iomux-vf610.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h
index 087d6f2..b5c7f7f 100644
--- a/arch/arm/mach-imx/include/mach/iomux-vf610.h
+++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h
@@ -163,9 +163,13 @@ enum {
 	VF610_PAD_PTD22__NF_IO6		= IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD21__NF_IO5		= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD20__NF_IO4		= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD19__GPIO_75	= IOMUX_PAD(0x012C, 0x012C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD19__NF_IO3		= IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD18__GPIO_76	= IOMUX_PAD(0x0120, 0x0130, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD18__NF_IO2		= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD17__GPIO_77	= IOMUX_PAD(0x0134, 0x0134, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD17__NF_IO1		= IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD16__GPIO_78	= IOMUX_PAD(0x0138, 0x0138, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD16__NF_IO0		= IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTB24__NF_WE_B	= IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
 	VF610_PAD_PTB25__NF_CE0_B	= IOMUX_PAD(0x017c, 0x017c, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 14/16] i.MX: imx-usb-phy: Add VF610 OF compatiblity string
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (12 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 13/16] i.MX: iomux-vf610: Add missing pad definitions Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 15/16] i.MX: Default CONFI_USB_IMX_PHY to 'y' on Vybrid Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 16/16] i.MX: imx-usb-misc: Add Vybrid support Andrey Smirnov
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

From looking at analogous Linux driver code it seems that all of the
differences between code "imx23-usbphy" and "vf610-usbphy" pertain to
suspend/resume functionality, which shouldn't affetct Barebox. As a
result this commit just adds a compatiblity string and no other code.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/imx/imx-usb-phy.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 9f46f8d..274153b 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -168,6 +168,8 @@ static __maybe_unused struct of_device_id imx_usbphy_dt_ids[] = {
 	{
 		.compatible = "fsl,imx23-usbphy",
 	}, {
+		.compatible = "fsl,vf610-usbphy",
+	}, {
 		/* sentinel */
 	},
 };
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 15/16] i.MX: Default CONFI_USB_IMX_PHY to 'y' on Vybrid
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (13 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 14/16] i.MX: imx-usb-phy: Add VF610 OF compatiblity string Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  2016-12-05 14:54 ` [PATCH 16/16] i.MX: imx-usb-misc: Add Vybrid support Andrey Smirnov
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/imx/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig
index b0c6a41..8e6f315 100644
--- a/drivers/usb/imx/Kconfig
+++ b/drivers/usb/imx/Kconfig
@@ -16,4 +16,4 @@ config USB_IMX_CHIPIDEA
 
 config USB_IMX_PHY
 	bool
-	default y if ARCH_IMX6 && GENERIC_PHY
+	default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 16/16] i.MX: imx-usb-misc: Add Vybrid support
  2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
                   ` (14 preceding siblings ...)
  2016-12-05 14:54 ` [PATCH 15/16] i.MX: Default CONFI_USB_IMX_PHY to 'y' on Vybrid Andrey Smirnov
@ 2016-12-05 14:54 ` Andrey Smirnov
  15 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-05 14:54 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add code to do usbmisc initialization on VF610 family of SoCs. Based on
analogous code from Linux kernel.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/usb/imx/imx-usb-misc.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index 7c18ca2..9cae440 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -422,6 +422,28 @@ static __maybe_unused struct imx_usb_misc_data mx6_data = {
 	.post_init = mx6_post_init,
 };
 
+#define VF610_OVER_CUR_DIS		BIT(7)
+
+static __maybe_unused int vf610_initialize_usb_hw(void __iomem *base, int port,
+		unsigned int flags)
+{
+	u32 reg;
+
+	if (port >= 1)
+		return -EINVAL;
+
+	if (flags & MXC_EHCI_DISABLE_OVERCURRENT) {
+		reg = readl(base);
+		writel(reg | VF610_OVER_CUR_DIS, base);
+	}
+
+	return 0;
+}
+
+static __maybe_unused struct imx_usb_misc_data vf610_data = {
+	.init = vf610_initialize_usb_hw,
+};
+
 static struct platform_device_id imx_usbmisc_ids[] = {
 #ifdef CONFIG_ARCH_IMX25
 	{
@@ -519,6 +541,12 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = {
 		.data = &mx6_data,
 	},
 #endif
+#ifdef CONFIG_ARCH_VF610
+	{
+		.compatible = "fsl,vf610-usbmisc",
+		.data = &vf610_data,
+	},
+#endif
 	{
 		/* sentinel */
 	},
-- 
2.5.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-05 14:54 ` [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses Andrey Smirnov
@ 2016-12-05 15:14   ` Stefan Lengfeld
  2016-12-06 14:48     ` Andrey Smirnov
  0 siblings, 1 reply; 26+ messages in thread
From: Stefan Lengfeld @ 2016-12-05 15:14 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

Hi Andrey,

a similiar patch was posted some days ago to support two MAC addresses for the
i.MX6 UltraLite. See

    http://lists.infradead.org/pipermail/barebox/2016-November/028628.html

Your approach uses an extra device attribute  'mac_idx' to select the meaning
of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1. 

I find it less error prone and confusing to use two seperate device attributes
'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
value of 'mac_idx before reading or writing the MAC addresses.

Both approaches are backwards compatible since the name of 'mac_addr' for the
first MAC address is not changed.

Mit freundlichen Grüßen / Kind regards,
	Stefan Lengfeld

On Mon, Dec 05, 2016 at 06:54:30AM -0800, Andrey Smirnov wrote:
> i.MX SoC variants like Vybrid have more than one built-in Ethernet
> interface and as a consequence support storing more than one MAC address
> in OCOTP module. Add 'mac_idx' variable to allow to select which mac
> address is being referred to by 'mac_addr' variable and the code to
> handle it appropriately.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  arch/arm/mach-imx/ocotp.c | 50 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 46 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
> index 68ff0ce..9a07922 100644
> --- a/arch/arm/mach-imx/ocotp.c
> +++ b/arch/arm/mach-imx/ocotp.c
> @@ -69,12 +69,16 @@
>  /* Other definitions */
>  #define IMX6_OTP_DATA_ERROR_VAL		0xBADABADA
>  #define DEF_RELAX			20
> -#define MAC_OFFSET			(0x22 * 4)
> +#define MAC_OFFSET_0			(0x22 * 4)
> +#define MAC_OFFSET_1			(0x24 * 4)
> +#define MAX_MAC_OFFSETS			2
>  #define MAC_BYTES			8
>  
>  struct imx_ocotp_data {
>  	int num_regs;
>  	u32 (*addr_to_offset)(u32 addr);
> +	u8  mac_offsets[MAX_MAC_OFFSETS];
> +	u8  mac_offsets_num;
>  };
>  
>  struct ocotp_priv {
> @@ -87,6 +91,7 @@ struct ocotp_priv {
>  	char ethaddr[6];
>  	struct regmap_config map_config;
>  	const struct imx_ocotp_data *data;
> +	int  mac_offset_idx;
>  };
>  
>  static struct ocotp_priv *imx_ocotp;
> @@ -402,8 +407,10 @@ static int imx_ocotp_get_mac(struct param_d *param, void *priv)
>  	struct ocotp_priv *ocotp_priv = priv;
>  	char buf[8];
>  	int i, ret;
> +	u8  mac_offset;
>  
> -	ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
> +	mac_offset = ocotp_priv->data->mac_offsets[ocotp_priv->mac_offset_idx];
> +	ret = regmap_bulk_read(ocotp_priv->map, mac_offset, buf, MAC_BYTES);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -418,18 +425,43 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv)
>  	struct ocotp_priv *ocotp_priv = priv;
>  	char buf[8];
>  	int i, ret;
> +	u8 mac_offset;
> +
> +	mac_offset = ocotp_priv->data->mac_offsets[ocotp_priv->mac_offset_idx];
>  
>  	for (i = 0; i < 6; i++)
>  		buf[5 - i] = ocotp_priv->ethaddr[i];
>  	buf[6] = 0; buf[7] = 0;
>  
> -	ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
> +	ret = regmap_bulk_write(ocotp_priv->map, mac_offset, buf, MAC_BYTES);
>  	if (ret < 0)
>  		return ret;
>  
>  	return 0;
>  }
>  
> +static int imx_ocotp_set_mac_idx(struct param_d *param, void *priv)
> +{
> +	struct ocotp_priv *ocotp_priv = priv;
> +	const int min = 0;
> +	const int max = ocotp_priv->data->mac_offsets_num - 1;
> +	int old, new, ret = 0;
> +
> +	old = ocotp_priv->mac_offset_idx;
> +	new = clamp(old, min, max);
> +
> +	if (old != new) {
> +		dev_err(&ocotp_priv->dev,
> +			"%d is out of bounds for '%s', clamping to %d\n",
> +			old, param->name, new);
> +		ret = -EINVAL;
> +	}
> +
> +	ocotp_priv->mac_offset_idx = new;
> +
> +	return ret;
> +}
> +
>  static struct regmap_bus imx_ocotp_regmap_bus = {
>  	.reg_write = imx_ocotp_reg_write,
>  	.reg_read = imx_ocotp_reg_read,
> @@ -486,9 +518,13 @@ static int imx_ocotp_probe(struct device_d *dev)
>  				NULL, NULL, &priv->permanent_write_enable, NULL);
>  	}
>  
> -	if (IS_ENABLED(CONFIG_NET))
> +	if (IS_ENABLED(CONFIG_NET)) {
> +		dev_add_param_int(&priv->dev, "mac_idx",
> +				  imx_ocotp_set_mac_idx, NULL,
> +				  &priv->mac_offset_idx, "%d", priv);
>  		dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac,
>  				imx_ocotp_get_mac, priv->ethaddr, priv);
> +	}
>  
>  	dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv);
>  
> @@ -527,16 +563,22 @@ static u32 vf610_addr_to_offset(u32 addr)
>  static struct imx_ocotp_data imx6q_ocotp_data = {
>  	.num_regs = 512,
>  	.addr_to_offset = imx6q_addr_to_offset,
> +	.mac_offsets_num = 1,
> +	.mac_offsets = { MAC_OFFSET_0 },
>  };
>  
>  static struct imx_ocotp_data imx6sl_ocotp_data = {
>  	.num_regs = 256,
>  	.addr_to_offset = imx6sl_addr_to_offset,
> +	.mac_offsets_num = 1,
> +	.mac_offsets = { MAC_OFFSET_0 },
>  };
>  
>  static struct imx_ocotp_data vf610_ocotp_data = {
>  	.num_regs = 512,
>  	.addr_to_offset = vf610_addr_to_offset,
> +	.mac_offsets_num = 2,
> +	.mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 },
>  };
>  
>  static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
> -- 
> 2.5.5
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-05 15:14   ` Stefan Lengfeld
@ 2016-12-06 14:48     ` Andrey Smirnov
  2016-12-07  8:51       ` Stefan Lengfeld
  0 siblings, 1 reply; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-06 14:48 UTC (permalink / raw)
  To: Stefan Lengfeld; +Cc: barebox

Hi Stefan,

On Mon, Dec 5, 2016 at 7:14 AM, Stefan Lengfeld <s.lengfeld@phytec.de> wrote:
> Hi Andrey,
>
> a similiar patch was posted some days ago to support two MAC addresses for the
> i.MX6 UltraLite. See
>
>     http://lists.infradead.org/pipermail/barebox/2016-November/028628.html
>

I did see that patch go through, however since the title of it is
"arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
it any further.


> Your approach uses an extra device attribute  'mac_idx' to select the meaning
> of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
>
> I find it less error prone and confusing to use two seperate device attributes
> 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
> value of 'mac_idx before reading or writing the MAC addresses.

Can't say that I necessarily agree with you assessment. There's no
need to check 'mac_idx' if it is written every time as a part of MAC
address assignment operation. The reason I chose the approach that I
did was mainly because it allowed to both have backwards compatibility
with the old naming scheme and avoid having variable naming
inconsistency (as you see in your example where one variable has a
numerical suffix and the other doesn't) which I was concerned would be
make scripting it more clunky than necessary.

Anyway, I don't think I am impartial enough to make a good judge of
merits of both approaches, so I'll let Sascha decide which way he
wants to go.

Thanks,
Andrey Smirnov

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-06 14:48     ` Andrey Smirnov
@ 2016-12-07  8:51       ` Stefan Lengfeld
  2016-12-07 19:13         ` Sascha Hauer
  2016-12-07 19:32         ` Andrey Smirnov
  0 siblings, 2 replies; 26+ messages in thread
From: Stefan Lengfeld @ 2016-12-07  8:51 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

Hi Andrey,

> I did see that patch go through, however since the title of it is
> "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
> it any further.

In the light of the Vybrid also supports two MAC addresses your patch title

    i.MX: ocotp: Add provisions for storing multiple MAC addresses

is better, since it is more generic.

> > Your approach uses an extra device attribute  'mac_idx' to select the meaning
> > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
> >
> > I find it less error prone and confusing to use two seperate device attributes
> > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
> > value of 'mac_idx before reading or writing the MAC addresses.
> 
> Can't say that I necessarily agree with you assessment. There's no
> need to check 'mac_idx' if it is written every time as a part of MAC
> address assignment operation. The reason I chose the approach that I
> did was mainly because it allowed to both have backwards compatibility
> with the old naming scheme and avoid having variable naming
> inconsistency (as you see in your example where one variable has a
> numerical suffix and the other doesn't) which I was concerned would be
> make scripting it more clunky than necessary.

hmm, I find it more convenient use

    bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
    bootloader$ ocotp0.mac_addr1=22:33:44:AA:AA:AA

than 

    bootloader$ ocotp0.mac_idx=0
    bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
    bootloader$ ocotp0.mac_idx=1
    bootloader$ ocotp0.mac_addr=22:33:44:AA:AA:AA

The same goes for reading the MAC addresses. The first one is more obvious,
because the meaning of the variable "mac_addr" does not depend on another
variable "mac_idx".

Maybe we can settle on a different approach to avoid the inconsistent variable
names "mac_addr" and "mac_addr1":

	if (IS_ENABLED(CONFIG_NET)) { 
		if (!data->scnd_mac_addr) {
			/* one MAC */
		        dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac0,
			       imx_ocotp_get_mac0, priv->ethaddr[0], priv);

		} else {
			/* two MACs: Vybrid and UltraLite */
		        dev_add_param_mac(&(priv->dev), "mac_addr0", imx_ocotp_set_mac0,
			       imx_ocotp_get_mac0, priv->ethaddr[0], priv);
                        dev_add_param_mac(&(priv->dev), "mac_addr1", imx_ocotp_set_mac1,
				imx_ocotp_get_mac1, priv->ethaddr[1], priv);
		}
	}

All existing boards still uses "mac_addr" for there single MAC address and new
boards Vybrid and UltraLite use "mac_addr0" and "mac_addr1". In the wild there
will be two different sets of - for example - factory MAC burning scripts
anyway.  One to handle a single MAC address and another to handle two MAC
addresses.

What do you think?

Mit freundlichen Grüßen / Kind regards,
	Stefan Lengfeld

On Tue, Dec 06, 2016 at 06:48:16AM -0800, Andrey Smirnov wrote:
> Hi Stefan,
> 
> On Mon, Dec 5, 2016 at 7:14 AM, Stefan Lengfeld <s.lengfeld@phytec.de> wrote:
> > Hi Andrey,
> >
> > a similiar patch was posted some days ago to support two MAC addresses for the
> > i.MX6 UltraLite. See
> >
> >     http://lists.infradead.org/pipermail/barebox/2016-November/028628.html
> >
> 
> I did see that patch go through, however since the title of it is
> "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
> it any further.
> 
> 
> > Your approach uses an extra device attribute  'mac_idx' to select the meaning
> > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
> >
> > I find it less error prone and confusing to use two seperate device attributes
> > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
> > value of 'mac_idx before reading or writing the MAC addresses.
> 
> Can't say that I necessarily agree with you assessment. There's no
> need to check 'mac_idx' if it is written every time as a part of MAC
> address assignment operation. The reason I chose the approach that I
> did was mainly because it allowed to both have backwards compatibility
> with the old naming scheme and avoid having variable naming
> inconsistency (as you see in your example where one variable has a
> numerical suffix and the other doesn't) which I was concerned would be
> make scripting it more clunky than necessary.
> 
> Anyway, I don't think I am impartial enough to make a good judge of
> merits of both approaches, so I'll let Sascha decide which way he
> wants to go.
> 
> Thanks,
> Andrey Smirnov

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-07  8:51       ` Stefan Lengfeld
@ 2016-12-07 19:13         ` Sascha Hauer
  2016-12-07 19:36           ` Andrey Smirnov
  2016-12-07 19:32         ` Andrey Smirnov
  1 sibling, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2016-12-07 19:13 UTC (permalink / raw)
  To: Stefan Lengfeld; +Cc: Andrey Smirnov, barebox

On Wed, Dec 07, 2016 at 09:51:05AM +0100, Stefan Lengfeld wrote:
> Hi Andrey,
> 
> > I did see that patch go through, however since the title of it is
> > "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
> > it any further.
> 
> In the light of the Vybrid also supports two MAC addresses your patch title
> 
>     i.MX: ocotp: Add provisions for storing multiple MAC addresses
> 
> is better, since it is more generic.
> 
> > > Your approach uses an extra device attribute  'mac_idx' to select the meaning
> > > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
> > >
> > > I find it less error prone and confusing to use two seperate device attributes
> > > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
> > > value of 'mac_idx before reading or writing the MAC addresses.
> > 
> > Can't say that I necessarily agree with you assessment. There's no
> > need to check 'mac_idx' if it is written every time as a part of MAC
> > address assignment operation. The reason I chose the approach that I
> > did was mainly because it allowed to both have backwards compatibility
> > with the old naming scheme and avoid having variable naming
> > inconsistency (as you see in your example where one variable has a
> > numerical suffix and the other doesn't) which I was concerned would be
> > make scripting it more clunky than necessary.
> 
> hmm, I find it more convenient use
> 
>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>     bootloader$ ocotp0.mac_addr1=22:33:44:AA:AA:AA
> 
> than 
> 
>     bootloader$ ocotp0.mac_idx=0
>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>     bootloader$ ocotp0.mac_idx=1
>     bootloader$ ocotp0.mac_addr=22:33:44:AA:AA:AA
> 
> The same goes for reading the MAC addresses. The first one is more obvious,
> because the meaning of the variable "mac_addr" does not depend on another
> variable "mac_idx".

I agree here.

> 
> Maybe we can settle on a different approach to avoid the inconsistent variable
> names "mac_addr" and "mac_addr1":

How about always registering mac_addr0 with mac_addr as alias? Then we
have consistent variable naming and still the backward compatible
standard mac address.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency
  2016-12-05 14:54 ` [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency Andrey Smirnov
@ 2016-12-07 19:27   ` Sascha Hauer
  2016-12-12  5:24     ` Andrey Smirnov
  0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2016-12-07 19:27 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Mon, Dec 05, 2016 at 06:54:34AM -0800, Andrey Smirnov wrote:
> Mask ROM leaves the CPU running at 264Mhz, so configure the clock tree
> to such that CPU runs at maximum supported frequency, based on speed
> grading burned into OCOTP fusebox.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  arch/arm/mach-imx/Kconfig   |  13 +++
>  drivers/clk/imx/clk-vf610.c | 187 +++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 198 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index af533ea..1752335 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -750,6 +750,19 @@ config HABV3_IMG_CRT_DER
>  
>  endif
>  
> +config ADJUST_CPU_CLOCK
> +       bool "Adjust CPU clock based on its speed grading"
> +       select IMX_OCOTP
> +       depends on ARCH_VF610
> +       default y
> +       help
> +	  Some i.MX SoCs (e. g. Vybrid) are manufactured to have
> +	  several variants of the same chip different only in maxumum

s/maxumum/maximum/

> +	  CPU frequency supported. MaskROM on such chips plays it safe
> +	  and uses the lowest possible frequency. This option
> +	  configures Barebox to read chip's speed grade information
> +	  and increase CPU clock to it's highest possible value.

Why do we need this configurable?

> +
>  endmenu
>  
>  endif
> diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
> index 04cb02f..1cf2b65 100644
> --- a/drivers/clk/imx/clk-vf610.c
> +++ b/drivers/clk/imx/clk-vf610.c
> @@ -16,7 +16,9 @@
>  #include <of_address.h>
>  #include <linux/clkdev.h>
>  #include <linux/clk.h>
> +#include <notifier.h>
>  #include <dt-bindings/clock/vf610-clock.h>
> +#include <mach/vf610-regs.h>
>  
>  #include "clk.h"
>  
> @@ -76,6 +78,7 @@
>  #define PLL6_CTRL		(anatop_base + 0xa0)
>  #define PLL7_CTRL		(anatop_base + 0x20)
>  #define ANA_MISC1		(anatop_base + 0x160)
> +#define PLL_LOCK		(anatop_base + 0x2c0)
>  
>  static void __iomem *anatop_base;
>  static void __iomem *ccm_base;
> @@ -188,8 +191,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
>  	clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
>  	clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
>  
> -	clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
> -	clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
> +	clk[VF610_CLK_PLL1] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1, PLL_LOCK, BIT(6));
> +	clk[VF610_CLK_PLL2] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1, PLL_LOCK, BIT(5));
> +
>  	clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
>  	clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
>  	clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
> @@ -441,3 +445,182 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
>  	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
>  }
>  CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init);
> +
> +#ifdef CONFIG_ADJUST_CPU_CLOCK
> +
> +enum {
> +	OCOTP_SPEED_GRADING_OFFSET = (0x4 * sizeof(uint32_t)),
> +	OCOTP_SPEED_GRADING_SHIFT  = 18,
> +	OCOTP_SPEED_GRADING_MASK   = 0b1111,
> +
> +	VF610_SPEED_500 = 0b1110,
> +	VF610_SPEED_400 = 0b1001,
> +	VF610_SPEED_266 = 0b0001,
> +
> +	DDRMC_CR117 = 0x01d4,
> +	DDRMC_CR117_AXI0_FITYPEREG_SYNC = 0b01 << 16,
> +};
> +
> +static int vf610_switch_cpu_clock_to_500mhz(void)
> +{
> +	int ret;
> +
> +	/*
> +	 * When switching A5 CPU to 500Mhz we expect DDRC to be
> +	 * clocked by PLL2_PFD2 and the system to be configured in
> +	 * asynchronous mode.
> +	 *
> +	 * We also can't just use default PFD1 output of PLL1 due to
> +	 * Errata e6235, so we have to re-clock the PLL itself and use
> +	 * its output to clock the CPU directly.
> +	 */
> +
> +	if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
> +		pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_BUS]);
> +	if (ret < 0) {
> +		pr_crit("Unable to re-parent '%s'\n",
> +			clk[VF610_CLK_SYS_SEL]->name);
> +		return ret;
> +	}
> +
> +	ret = clk_set_rate(clk[VF610_CLK_PLL1], 500000000);
> +	if (ret < 0) {
> +		pr_crit("Unable to set %s to 500Mhz %d\n",
> +			clk[VF610_CLK_PLL1]->name, ret);
> +		return ret;
> +	}
> +
> +	ret = clk_set_parent(clk[VF610_CLK_PLL1_PFD_SEL], clk[VF610_CLK_PLL1_SYS]);
> +	if (ret < 0) {
> +		pr_crit("Unable to re-parent '%s'\n",
> +			clk[VF610_CLK_PLL1_PFD_SEL]->name);
> +		return ret;
> +	}
> +
> +	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL1_PFD_SEL]);
> +	if (ret < 0) {
> +		pr_crit("Unable to re-parent '%s'\n",
> +			clk[VF610_CLK_SYS_SEL]->name);
> +		return ret;
> +	}
> +
> +	/*
> +	 * imx_clk_divider has no error path in its set_rate hook
> +	 */
> +	clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
> +	clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
> +
> +	return ret;
> +}
> +
> +static int vf610_switch_cpu_clock_to_400mhz(void)
> +{
> +	int ret;
> +	uint32_t cr117;
> +	void * __iomem ddrmc = IOMEM(VF610_DDR_BASE_ADDR);
> +
> +	if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
> +		pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_parent(clk[VF610_CLK_PLL2_PFD_SEL], clk[VF610_CLK_PLL2_PFD2]);
> +	if (ret < 0) {
> +		pr_crit("Unable to re-parent '%s'\n",
> +			clk[VF610_CLK_PLL2_PFD_SEL]->name);
> +		return ret;
> +	}
> +
> +	ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_PFD_SEL]);
> +	if (ret < 0) {
> +		pr_crit("Unable to re-parent '%s'\n",
> +			clk[VF610_CLK_SYS_SEL]->name);
> +		return ret;
> +	}
> +
> +	/*
> +	 * imx_clk_divider has no error path in its set_rate hook
> +	 */
> +	clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
> +	clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
> +
> +	/*
> +	 * Now that we are running off of the same clock as DDRMC we
> +	 * shouldn't need to use clock domain corssing FIFO and

s/corssing/crossing/?

> +	 * asynchronous mode and instead can swithch to sychronous
> +	 * mode for AXI0 accesses
> +	 */
> +	cr117 =  readl(ddrmc + DDRMC_CR117);
> +	cr117 |= DDRMC_CR117_AXI0_FITYPEREG_SYNC;
> +	writel(cr117, ddrmc + DDRMC_CR117);
> +
> +	return 0;
> +}
> +
> +static int vf610_switch_cpu_clock(void)
> +{
> +	int ret;
> +	struct device_node *ocotp_node;
> +	struct cdev *ocotp;
> +	uint32_t speed_grading;
> +
> +	if (!of_machine_is_compatible("fsl,vf610"))
> +		return 0;
> +
> +	ocotp_node = of_find_compatible_node(NULL, NULL, "fsl,vf610-ocotp");
> +	if (!ocotp_node) {
> +		pr_err("Unable to find OCOTP DT node\n");
> +		return -ENODEV;
> +	}
> +
> +	ocotp = cdev_by_device_node(ocotp_node);
> +	if (!ocotp) {
> +		pr_err("No OCOTP character device\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = cdev_read(ocotp, &speed_grading, sizeof(speed_grading),
> +		       OCOTP_SPEED_GRADING_OFFSET, 0);
> +	if (ret != sizeof(speed_grading)) {
> +		pr_err("Failed to read speed grading data\n");
> +		return ret < 0 ? ret : -EIO;
> +	}

There's a better way to access ocotp registers. see
imx_ocotp_read_field().

> +
> +	speed_grading >>= OCOTP_SPEED_GRADING_SHIFT;
> +	speed_grading &=  OCOTP_SPEED_GRADING_MASK;
> +
> +	switch (speed_grading) {
> +	default:
> +		pr_err("Unknown CPU speed grading %x\n", speed_grading);
> +		return -EINVAL;
> +
> +	case VF610_SPEED_266:
> +		return 0;
> +
> +	case VF610_SPEED_500:
> +		ret = vf610_switch_cpu_clock_to_500mhz();
> +		break;
> +
> +	case VF610_SPEED_400:
> +		ret = vf610_switch_cpu_clock_to_400mhz();
> +		break;
> +	}
> +
> +	clock_notifier_call_chain();
> +	return ret;
> +}
> +/*
> + * We can probably gain a bit of a boot speed if we switch CPU clock
> + * earlier, but if we do this we'd need to figure out a way how to
> + * re-adjust the baud rate settings of the UART for DEBUG_LL
> + * functionality, or, accept the fact that it will be unavailbe after

s/unavailbe/unavailable/

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-07  8:51       ` Stefan Lengfeld
  2016-12-07 19:13         ` Sascha Hauer
@ 2016-12-07 19:32         ` Andrey Smirnov
  1 sibling, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-07 19:32 UTC (permalink / raw)
  To: Stefan Lengfeld; +Cc: barebox

On Wed, Dec 7, 2016 at 12:51 AM, Stefan Lengfeld <s.lengfeld@phytec.de> wrote:
> Hi Andrey,
>
>> I did see that patch go through, however since the title of it is
>> "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
>> it any further.
>
> In the light of the Vybrid also supports two MAC addresses your patch title
>
>     i.MX: ocotp: Add provisions for storing multiple MAC addresses
>
> is better, since it is more generic.
>
>> > Your approach uses an extra device attribute  'mac_idx' to select the meaning
>> > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
>> >
>> > I find it less error prone and confusing to use two seperate device attributes
>> > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
>> > value of 'mac_idx before reading or writing the MAC addresses.
>>
>> Can't say that I necessarily agree with you assessment. There's no
>> need to check 'mac_idx' if it is written every time as a part of MAC
>> address assignment operation. The reason I chose the approach that I
>> did was mainly because it allowed to both have backwards compatibility
>> with the old naming scheme and avoid having variable naming
>> inconsistency (as you see in your example where one variable has a
>> numerical suffix and the other doesn't) which I was concerned would be
>> make scripting it more clunky than necessary.
>
> hmm, I find it more convenient use
>
>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>     bootloader$ ocotp0.mac_addr1=22:33:44:AA:AA:AA
>
> than
>
>     bootloader$ ocotp0.mac_idx=0
>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>     bootloader$ ocotp0.mac_idx=1
>     bootloader$ ocotp0.mac_addr=22:33:44:AA:AA:AA
>
> The same goes for reading the MAC addresses. The first one is more obvious,
> because the meaning of the variable "mac_addr" does not depend on another
> variable "mac_idx".

Well you original point was about being error prone and confusing, not
convenience of use. ;-) My "scheme' involves way more typing, so it is
most certainly would be less convenient.

>
> Maybe we can settle on a different approach to avoid the inconsistent variable
> names "mac_addr" and "mac_addr1":
>
>         if (IS_ENABLED(CONFIG_NET)) {
>                 if (!data->scnd_mac_addr) {
>                         /* one MAC */
>                         dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac0,
>                                imx_ocotp_get_mac0, priv->ethaddr[0], priv);
>
>                 } else {
>                         /* two MACs: Vybrid and UltraLite */
>                         dev_add_param_mac(&(priv->dev), "mac_addr0", imx_ocotp_set_mac0,
>                                imx_ocotp_get_mac0, priv->ethaddr[0], priv);
>                         dev_add_param_mac(&(priv->dev), "mac_addr1", imx_ocotp_set_mac1,
>                                 imx_ocotp_get_mac1, priv->ethaddr[1], priv);
>                 }
>         }
>
> All existing boards still uses "mac_addr" for there single MAC address and new
> boards Vybrid and UltraLite use "mac_addr0" and "mac_addr1". In the wild there
> will be two different sets of - for example - factory MAC burning scripts
> anyway.  One to handle a single MAC address and another to handle two MAC
> addresses.
>
> What do you think?

Sounds reasonable. I didn't go this route originally because I wanted
to be backwards compatible, but thinking more on it I don't know if it
(backwards compatibility) matters too much.

Thanks,
Andrey

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-07 19:13         ` Sascha Hauer
@ 2016-12-07 19:36           ` Andrey Smirnov
  2016-12-07 20:57             ` Sascha Hauer
  0 siblings, 1 reply; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-07 19:36 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, Stefan Lengfeld

On Wed, Dec 7, 2016 at 11:13 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Dec 07, 2016 at 09:51:05AM +0100, Stefan Lengfeld wrote:
>> Hi Andrey,
>>
>> > I did see that patch go through, however since the title of it is
>> > "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
>> > it any further.
>>
>> In the light of the Vybrid also supports two MAC addresses your patch title
>>
>>     i.MX: ocotp: Add provisions for storing multiple MAC addresses
>>
>> is better, since it is more generic.
>>
>> > > Your approach uses an extra device attribute  'mac_idx' to select the meaning
>> > > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
>> > >
>> > > I find it less error prone and confusing to use two seperate device attributes
>> > > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
>> > > value of 'mac_idx before reading or writing the MAC addresses.
>> >
>> > Can't say that I necessarily agree with you assessment. There's no
>> > need to check 'mac_idx' if it is written every time as a part of MAC
>> > address assignment operation. The reason I chose the approach that I
>> > did was mainly because it allowed to both have backwards compatibility
>> > with the old naming scheme and avoid having variable naming
>> > inconsistency (as you see in your example where one variable has a
>> > numerical suffix and the other doesn't) which I was concerned would be
>> > make scripting it more clunky than necessary.
>>
>> hmm, I find it more convenient use
>>
>>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>>     bootloader$ ocotp0.mac_addr1=22:33:44:AA:AA:AA
>>
>> than
>>
>>     bootloader$ ocotp0.mac_idx=0
>>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
>>     bootloader$ ocotp0.mac_idx=1
>>     bootloader$ ocotp0.mac_addr=22:33:44:AA:AA:AA
>>
>> The same goes for reading the MAC addresses. The first one is more obvious,
>> because the meaning of the variable "mac_addr" does not depend on another
>> variable "mac_idx".
>
> I agree here.
>
>>
>> Maybe we can settle on a different approach to avoid the inconsistent variable
>> names "mac_addr" and "mac_addr1":
>
> How about always registering mac_addr0 with mac_addr as alias? Then we
> have consistent variable naming and still the backward compatible
> standard mac address.

That'd definetly would be even better way to go if we want to preserve
backwards compatibility. It might be a bit confusing UI wise to have
"ocotp0.mac_addr0", "ocotp0.mac_addr1" and "ocotp0.mac_addr" at the
same time, though.

I don't really have a any preference for either way.

Thanks,
Andrey

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses
  2016-12-07 19:36           ` Andrey Smirnov
@ 2016-12-07 20:57             ` Sascha Hauer
  0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2016-12-07 20:57 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox, Stefan Lengfeld

On Wed, Dec 07, 2016 at 11:36:21AM -0800, Andrey Smirnov wrote:
> On Wed, Dec 7, 2016 at 11:13 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > On Wed, Dec 07, 2016 at 09:51:05AM +0100, Stefan Lengfeld wrote:
> >> Hi Andrey,
> >>
> >> > I did see that patch go through, however since the title of it is
> >> > "arm: imx6: ocotp: Added support for the i.MX6UL" I didn't look into
> >> > it any further.
> >>
> >> In the light of the Vybrid also supports two MAC addresses your patch title
> >>
> >>     i.MX: ocotp: Add provisions for storing multiple MAC addresses
> >>
> >> is better, since it is more generic.
> >>
> >> > > Your approach uses an extra device attribute  'mac_idx' to select the meaning
> >> > > of the device attribute 'mac_addr': Whether it points to the MAC0 or MAC1.
> >> > >
> >> > > I find it less error prone and confusing to use two seperate device attributes
> >> > > 'mac_addr' and 'mac_addr1' for MAC0 and MAC1. So you don't have to check the
> >> > > value of 'mac_idx before reading or writing the MAC addresses.
> >> >
> >> > Can't say that I necessarily agree with you assessment. There's no
> >> > need to check 'mac_idx' if it is written every time as a part of MAC
> >> > address assignment operation. The reason I chose the approach that I
> >> > did was mainly because it allowed to both have backwards compatibility
> >> > with the old naming scheme and avoid having variable naming
> >> > inconsistency (as you see in your example where one variable has a
> >> > numerical suffix and the other doesn't) which I was concerned would be
> >> > make scripting it more clunky than necessary.
> >>
> >> hmm, I find it more convenient use
> >>
> >>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
> >>     bootloader$ ocotp0.mac_addr1=22:33:44:AA:AA:AA
> >>
> >> than
> >>
> >>     bootloader$ ocotp0.mac_idx=0
> >>     bootloader$ ocotp0.mac_addr=22:33:44:55:66:77
> >>     bootloader$ ocotp0.mac_idx=1
> >>     bootloader$ ocotp0.mac_addr=22:33:44:AA:AA:AA
> >>
> >> The same goes for reading the MAC addresses. The first one is more obvious,
> >> because the meaning of the variable "mac_addr" does not depend on another
> >> variable "mac_idx".
> >
> > I agree here.
> >
> >>
> >> Maybe we can settle on a different approach to avoid the inconsistent variable
> >> names "mac_addr" and "mac_addr1":
> >
> > How about always registering mac_addr0 with mac_addr as alias? Then we
> > have consistent variable naming and still the backward compatible
> > standard mac address.
> 
> That'd definetly would be even better way to go if we want to preserve
> backwards compatibility. It might be a bit confusing UI wise to have
> "ocotp0.mac_addr0", "ocotp0.mac_addr1" and "ocotp0.mac_addr" at the
> same time, though.

Yes, indeed, this might be confusing, but the fact that mac_addr and
mac_addr0 always have the same value should make that clear.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency
  2016-12-07 19:27   ` Sascha Hauer
@ 2016-12-12  5:24     ` Andrey Smirnov
  0 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2016-12-12  5:24 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On Wed, Dec 7, 2016 at 11:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Mon, Dec 05, 2016 at 06:54:34AM -0800, Andrey Smirnov wrote:
>> Mask ROM leaves the CPU running at 264Mhz, so configure the clock tree
>> to such that CPU runs at maximum supported frequency, based on speed
>> grading burned into OCOTP fusebox.
>>
>> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
>> ---
>>  arch/arm/mach-imx/Kconfig   |  13 +++
>>  drivers/clk/imx/clk-vf610.c | 187 +++++++++++++++++++++++++++++++++++++++++++-
>>  2 files changed, 198 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
>> index af533ea..1752335 100644
>> --- a/arch/arm/mach-imx/Kconfig
>> +++ b/arch/arm/mach-imx/Kconfig
>> @@ -750,6 +750,19 @@ config HABV3_IMG_CRT_DER
>>
>>  endif
>>
>> +config ADJUST_CPU_CLOCK
>> +       bool "Adjust CPU clock based on its speed grading"
>> +       select IMX_OCOTP
>> +       depends on ARCH_VF610
>> +       default y
>> +       help
>> +       Some i.MX SoCs (e. g. Vybrid) are manufactured to have
>> +       several variants of the same chip different only in maxumum
>
> s/maxumum/maximum/

Will fix in v3, thanks

>
>> +       CPU frequency supported. MaskROM on such chips plays it safe
>> +       and uses the lowest possible frequency. This option
>> +       configures Barebox to read chip's speed grade information
>> +       and increase CPU clock to it's highest possible value.
>
> Why do we need this configurable?

I don't really have a strong use-case for it to be. I'll drop this part in v3.

>
>> +
>>  endmenu
>>
>>  endif
>> diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
>> index 04cb02f..1cf2b65 100644
>> --- a/drivers/clk/imx/clk-vf610.c
>> +++ b/drivers/clk/imx/clk-vf610.c
>> @@ -16,7 +16,9 @@
>>  #include <of_address.h>
>>  #include <linux/clkdev.h>
>>  #include <linux/clk.h>
>> +#include <notifier.h>
>>  #include <dt-bindings/clock/vf610-clock.h>
>> +#include <mach/vf610-regs.h>
>>
>>  #include "clk.h"
>>
>> @@ -76,6 +78,7 @@
>>  #define PLL6_CTRL            (anatop_base + 0xa0)
>>  #define PLL7_CTRL            (anatop_base + 0x20)
>>  #define ANA_MISC1            (anatop_base + 0x160)
>> +#define PLL_LOCK             (anatop_base + 0x2c0)
>>
>>  static void __iomem *anatop_base;
>>  static void __iomem *ccm_base;
>> @@ -188,8 +191,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
>>       clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
>>       clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
>>
>> -     clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
>> -     clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
>> +     clk[VF610_CLK_PLL1] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1, PLL_LOCK, BIT(6));
>> +     clk[VF610_CLK_PLL2] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1, PLL_LOCK, BIT(5));
>> +
>>       clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
>>       clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
>>       clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
>> @@ -441,3 +445,182 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
>>       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
>>  }
>>  CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init);
>> +
>> +#ifdef CONFIG_ADJUST_CPU_CLOCK
>> +
>> +enum {
>> +     OCOTP_SPEED_GRADING_OFFSET = (0x4 * sizeof(uint32_t)),
>> +     OCOTP_SPEED_GRADING_SHIFT  = 18,
>> +     OCOTP_SPEED_GRADING_MASK   = 0b1111,
>> +
>> +     VF610_SPEED_500 = 0b1110,
>> +     VF610_SPEED_400 = 0b1001,
>> +     VF610_SPEED_266 = 0b0001,
>> +
>> +     DDRMC_CR117 = 0x01d4,
>> +     DDRMC_CR117_AXI0_FITYPEREG_SYNC = 0b01 << 16,
>> +};
>> +
>> +static int vf610_switch_cpu_clock_to_500mhz(void)
>> +{
>> +     int ret;
>> +
>> +     /*
>> +      * When switching A5 CPU to 500Mhz we expect DDRC to be
>> +      * clocked by PLL2_PFD2 and the system to be configured in
>> +      * asynchronous mode.
>> +      *
>> +      * We also can't just use default PFD1 output of PLL1 due to
>> +      * Errata e6235, so we have to re-clock the PLL itself and use
>> +      * its output to clock the CPU directly.
>> +      */
>> +
>> +     if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
>> +             pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
>> +             return -EINVAL;
>> +     }
>> +
>> +     ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_BUS]);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to re-parent '%s'\n",
>> +                     clk[VF610_CLK_SYS_SEL]->name);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_rate(clk[VF610_CLK_PLL1], 500000000);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to set %s to 500Mhz %d\n",
>> +                     clk[VF610_CLK_PLL1]->name, ret);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_parent(clk[VF610_CLK_PLL1_PFD_SEL], clk[VF610_CLK_PLL1_SYS]);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to re-parent '%s'\n",
>> +                     clk[VF610_CLK_PLL1_PFD_SEL]->name);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL1_PFD_SEL]);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to re-parent '%s'\n",
>> +                     clk[VF610_CLK_SYS_SEL]->name);
>> +             return ret;
>> +     }
>> +
>> +     /*
>> +      * imx_clk_divider has no error path in its set_rate hook
>> +      */
>> +     clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
>> +     clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
>> +
>> +     return ret;
>> +}
>> +
>> +static int vf610_switch_cpu_clock_to_400mhz(void)
>> +{
>> +     int ret;
>> +     uint32_t cr117;
>> +     void * __iomem ddrmc = IOMEM(VF610_DDR_BASE_ADDR);
>> +
>> +     if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) {
>> +             pr_warn("DDRC is clocked by PLL1, can't switch CPU clock");
>> +             return -EINVAL;
>> +     }
>> +
>> +     ret = clk_set_parent(clk[VF610_CLK_PLL2_PFD_SEL], clk[VF610_CLK_PLL2_PFD2]);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to re-parent '%s'\n",
>> +                     clk[VF610_CLK_PLL2_PFD_SEL]->name);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_PFD_SEL]);
>> +     if (ret < 0) {
>> +             pr_crit("Unable to re-parent '%s'\n",
>> +                     clk[VF610_CLK_SYS_SEL]->name);
>> +             return ret;
>> +     }
>> +
>> +     /*
>> +      * imx_clk_divider has no error path in its set_rate hook
>> +      */
>> +     clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL]));
>> +     clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3);
>> +
>> +     /*
>> +      * Now that we are running off of the same clock as DDRMC we
>> +      * shouldn't need to use clock domain corssing FIFO and
>
> s/corssing/crossing/?

Will fix in v3, thanks

>
>> +      * asynchronous mode and instead can swithch to sychronous
>> +      * mode for AXI0 accesses
>> +      */
>> +     cr117 =  readl(ddrmc + DDRMC_CR117);
>> +     cr117 |= DDRMC_CR117_AXI0_FITYPEREG_SYNC;
>> +     writel(cr117, ddrmc + DDRMC_CR117);
>> +
>> +     return 0;
>> +}
>> +
>> +static int vf610_switch_cpu_clock(void)
>> +{
>> +     int ret;
>> +     struct device_node *ocotp_node;
>> +     struct cdev *ocotp;
>> +     uint32_t speed_grading;
>> +
>> +     if (!of_machine_is_compatible("fsl,vf610"))
>> +             return 0;
>> +
>> +     ocotp_node = of_find_compatible_node(NULL, NULL, "fsl,vf610-ocotp");
>> +     if (!ocotp_node) {
>> +             pr_err("Unable to find OCOTP DT node\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     ocotp = cdev_by_device_node(ocotp_node);
>> +     if (!ocotp) {
>> +             pr_err("No OCOTP character device\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     ret = cdev_read(ocotp, &speed_grading, sizeof(speed_grading),
>> +                    OCOTP_SPEED_GRADING_OFFSET, 0);
>> +     if (ret != sizeof(speed_grading)) {
>> +             pr_err("Failed to read speed grading data\n");
>> +             return ret < 0 ? ret : -EIO;
>> +     }
>
> There's a better way to access ocotp registers. see
> imx_ocotp_read_field().
>

Good to know, I think I missed that patch going in. Will fix in v3.

>> +
>> +     speed_grading >>= OCOTP_SPEED_GRADING_SHIFT;
>> +     speed_grading &=  OCOTP_SPEED_GRADING_MASK;
>> +
>> +     switch (speed_grading) {
>> +     default:
>> +             pr_err("Unknown CPU speed grading %x\n", speed_grading);
>> +             return -EINVAL;
>> +
>> +     case VF610_SPEED_266:
>> +             return 0;
>> +
>> +     case VF610_SPEED_500:
>> +             ret = vf610_switch_cpu_clock_to_500mhz();
>> +             break;
>> +
>> +     case VF610_SPEED_400:
>> +             ret = vf610_switch_cpu_clock_to_400mhz();
>> +             break;
>> +     }
>> +
>> +     clock_notifier_call_chain();
>> +     return ret;
>> +}
>> +/*
>> + * We can probably gain a bit of a boot speed if we switch CPU clock
>> + * earlier, but if we do this we'd need to figure out a way how to
>> + * re-adjust the baud rate settings of the UART for DEBUG_LL
>> + * functionality, or, accept the fact that it will be unavailbe after
>
> s/unavailbe/unavailable/

Will fix in v3, thanks

Andrey

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2016-12-12  5:25 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-05 14:54 [PATCH 00/16] Vybrid related patches Andrey Smirnov
2016-12-05 14:54 ` [PATCH 01/16] i.MX: esdhc: Enable host->clk during initialization Andrey Smirnov
2016-12-05 14:54 ` [PATCH 02/16] i.MX: ocotp: Add provisions for storing multiple MAC addresses Andrey Smirnov
2016-12-05 15:14   ` Stefan Lengfeld
2016-12-06 14:48     ` Andrey Smirnov
2016-12-07  8:51       ` Stefan Lengfeld
2016-12-07 19:13         ` Sascha Hauer
2016-12-07 19:36           ` Andrey Smirnov
2016-12-07 20:57             ` Sascha Hauer
2016-12-07 19:32         ` Andrey Smirnov
2016-12-05 14:54 ` [PATCH 03/16] i.MX: ocotp: Initialize OCOTP as early as possible Andrey Smirnov
2016-12-05 14:54 ` [PATCH 04/16] i.MX: ocotp: Initialize 'sense_enable' to true on Vybrid Andrey Smirnov
2016-12-05 14:54 ` [PATCH 05/16] i.MX: clk: Add IMX_PLLV3_SYS_VF610 subtype Andrey Smirnov
2016-12-05 14:54 ` [PATCH 06/16] i.MX: vf610: Ramp CPU clock to maximum frequency Andrey Smirnov
2016-12-07 19:27   ` Sascha Hauer
2016-12-12  5:24     ` Andrey Smirnov
2016-12-05 14:54 ` [PATCH 07/16] i.MX: iomuxv3: Add low-level pad code to headers Andrey Smirnov
2016-12-05 14:54 ` [PATCH 08/16] i.MX: iomuxv3: Add helper type to deconstruct iomux_v3_cfg_t values Andrey Smirnov
2016-12-05 14:54 ` [PATCH 09/16] i.MX: iomuxv3: Add low-level pad configuration routine Andrey Smirnov
2016-12-05 14:54 ` [PATCH 10/16] i.MX6: sabresd: Remove magic numbers in setup_uart Andrey Smirnov
2016-12-05 14:54 ` [PATCH 11/16] i.MX: iomuxv3: Use helper functions in iomux-v3.h Andrey Smirnov
2016-12-05 14:54 ` [PATCH 12/16] i.MX: vf610: Add low-level pin configuration helper Andrey Smirnov
2016-12-05 14:54 ` [PATCH 13/16] i.MX: iomux-vf610: Add missing pad definitions Andrey Smirnov
2016-12-05 14:54 ` [PATCH 14/16] i.MX: imx-usb-phy: Add VF610 OF compatiblity string Andrey Smirnov
2016-12-05 14:54 ` [PATCH 15/16] i.MX: Default CONFI_USB_IMX_PHY to 'y' on Vybrid Andrey Smirnov
2016-12-05 14:54 ` [PATCH 16/16] i.MX: imx-usb-misc: Add Vybrid support Andrey Smirnov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox