Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/4] clk: ti: add support for default-rate property from DT
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

default-rate property can now be used to define default rates for clocks,
which get configured during boot.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/prm_common.c |    2 ++
 drivers/clk/ti/clk.c             |    1 +
 2 files changed, 3 insertions(+)

diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index b4c4ab9..4703545 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -528,5 +528,7 @@ int __init of_prcm_init(void)
 
 	ti_dt_clockdomains_setup();
 
+	of_clk_set_init_rates();
+
 	return 0;
 }
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f71..23998b7 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -156,6 +156,7 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
 		clk_init_cb = (of_clk_init_cb_t)match->data;
 		pr_debug("%s: initializing: %s\n", __func__, np->name);
 		clk_init_cb(np);
+		of_clk_parse_init_rate(np, NULL);
 	}
 
 	list_for_each_entry_safe(retry, tmp, &retry_list, link) {
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 4/4] clk: ti: omap4: set default-parents and default-rates using DT
From: Tero Kristo @ 2014-02-13  9:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com>

Setup dpll_usb_ck and dpll_abe_ck using DT properties instead of hardcoding
the parents and rates in kernel.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/boot/dts/omap4.dtsi |   12 ++++++++++++
 drivers/clk/ti/clk-44xx.c    |   42 ------------------------------------------
 2 files changed, 12 insertions(+), 42 deletions(-)

diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index d3f8a6e..282ce66 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -761,3 +761,15 @@
 };
 
 /include/ "omap44xx-clocks.dtsi"
+
+&dpll_usb_ck {
+	default-rate = <960000000>;
+};
+
+&dpll_abe_ck {
+	default-rate = <98304000>;
+};
+
+&abe_dpll_refclk_mux_ck {
+	ti,default-parent = <&sys_32k_ck>;
+};
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index ae00218..bc14a49 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -16,21 +16,6 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
-/*
- * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
- * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
- * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
- * half of this value.
- */
-#define OMAP4_DPLL_ABE_DEFFREQ				98304000
-
-/*
- * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
- * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
- * locked frequency for the USB DPLL is 960MHz.
- */
-#define OMAP4_DPLL_USB_DEFFREQ				960000000
-
 static struct ti_dt_clk omap44xx_clks[] = {
 	DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
 	DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
@@ -281,36 +266,9 @@ static struct ti_dt_clk omap44xx_clks[] = {
 
 int __init omap4xxx_dt_clk_init(void)
 {
-	int rc;
-	struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
-
 	ti_dt_clocks_register(omap44xx_clks);
 
 	omap2_clk_disable_autoidle_all();
 
-	/*
-	 * Lock USB DPLL on OMAP4 devices so that the L3INIT power
-	 * domain can transition to retention state when not in use.
-	 */
-	usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
-	rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
-	if (rc)
-		pr_err("%s: failed to configure USB DPLL!\n", __func__);
-
-	/*
-	 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
-	 * state when turning the ABE clock domain. Workaround this by
-	 * locking the ABE DPLL on boot.
-	 * Lock the ABE DPLL in any case to avoid issues with audio.
-	 */
-	abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
-	sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
-	rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
-	abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
-	if (!rc)
-		rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
-	if (rc)
-		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-
 	return 0;
 }
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Tomasz Figa @ 2014-02-13  9:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPDyKFo9Xpxe0XzevPEeaofLeCNivnf3R_RttToP2h3aFyB4Yw@mail.gmail.com>



On 13.02.2014 09:56, Ulf Hansson wrote:
> On 28 January 2014 11:48, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Tuesday 28 January 2014, Ulf Hansson wrote:
>>> On 28 January 2014 01:59, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>>>> On 27.01.2014 11:19, Ulf Hansson wrote:
>>>>> There is already a host capability that I think we could use to handle
>>>>> this. MMC_CAP_NONREMOVABLE, the corresponding DT binding string is
>>>>> "non-removable", and it may be set per host device.
>>>>>
>>>>> Using this cap means the mmc_rescan process that runs to detect new
>>>>> cards, will only be executed once and during boot. So, we need to make
>>>>> sure all resources and powers are provided to the card at this point.
>>>>> Otherwise the card will not be detected.
>>>>
>>>> I don't quite like this requirement, especially if you consider
>>>> multi-platform kernels where a lot of drivers is going to be provided as
>>>> modules. WLAN drivers are especially good candidates. This means that even
>>>> if the card is powered off at boot-up, if user (or init system) loads
>>>> appropriate module, which powers the chip on, MMC core must be able to
>>>> notice this.
>>>
>>> To be able to detect the card, the WLAN driver doesn't have to be
>>> probed, only the "power controller" driver. I suppose this is were it
>>> becomes a bit tricky.
>>>
>>> Somehow the mmc core needs to be involved in the probe process of the
>>> power controller driver. Could perhaps the power controller bus be
>>> located in the mmc core and thus the power controller driver needs to
>>> register itself by using a new API from the mmc core? Similar how SDIO
>>> func driver's register themselves.
>>
>> I think there is another option, which does have its own pros and cons:
>> We could move all the power handling back into the sdio function driver
>> if we allow a secondary detection path using DT rather than the probing
>> of the SDIO bus. Essentially you'd have to list the class/vendor/device
>> ID for each function that cannot be autodetected in DT, and have the
>> SDIO core pretend that it found the device just by looking at the
>> device nodes, and register the struct sdio_func so it can be bound to
>> the driver. The driver then does all the power handling in a device
>> specific way. At some point the hardware gets registered at the
>> mmc host, and the sdio core connects the bus state to the already present
>> sdio_func, possibly notifying the function driver that it has become
>> usable.
>
> It seems like an option we could try.
>
> There are some tricky parts that needs to be taken care of by the
> mmc/sdio core, regarding the probe/removal and the suspend/resume
> sequence, but I suppose it should be possible.
>
> A minor concern is how do we handle devices that are fully powered at
> boot? Unless the sdio func driver will be loaded we can't power off
> them, right? Do we need to cover this case, do you think?
>
>>
>> Obviously, this can only work for CAP_NONREMOVABLE devices, but those
>> are exactly the ones we are worried about here. The advantage is that
>> the power sequencing for a particular device can then be in device
>> specific code and can have an arbitrarily complex in the driver without
>> needing the mmc code to handle all possible corner cases.
>
> Agree!
>
> I think a removable SDIO card won't l need this additional power
> controller mechanism.

Yes, sounds good to me too. It will be more tricky to implement than the 
solution I initially proposed, but should end up being much cleaner and 
possibly cover more cases.

Best regards,
Tomasz

^ permalink raw reply

* [PATCH] i2c: mv64xxx: Fix locked bus when offload is selected but not used on a message
From: Wolfram Sang @ 2014-02-13  9:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391770588-1344-1-git-send-email-gregory.clement@free-electrons.com>

> --- a/drivers/i2c/busses/i2c-mv64xxx.c
> +++ b/drivers/i2c/busses/i2c-mv64xxx.c
> @@ -461,8 +461,15 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
>  	case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
>  		if (!mv64xxx_i2c_offload_msg(drv_data))
>  			break;
> -		else
> +		else {

Here you break the coding style...

>  			drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
> +			/*
> +			 * Switch to the standard path, so we finally need to
> +			 * prepare the io that have not been done in
> +			 * mv64xxx_i2c_execute_msg
> +			 */
> +			mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
> +		}

... but more importantly, NACK. The code is already hard to follow which
is the cause for this bug. This snipplet makes the code even harder to
read, so it needs some simplification IMO. I'll fire up a counterpatch
in a minute to explain what I mean.

>  		/* FALLTHRU */
>  	case MV64XXX_I2C_ACTION_SEND_START:
>  		writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
> -- 
> 1.8.1.2
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140213/cee40674/attachment.sig>

^ permalink raw reply

* [PATCH] dt: platform driver: Fill the resources before probe and defer if needed
From: Jean-Jacques Hiblot @ 2014-02-13  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

The goal of this patch is to allow drivers to be probed even if at the time of
the DT parsing some of their ressources are not available yet.

In the current situation, the resource of a platform device are filled from the
DT at the time the device is created (of_device_alloc()). The drawbackof this
is that a device sitting close to the top of the DT (ahb for example) but
depending on ressources that are initialized later (IRQ domain dynamically
created for example)  will fail to probe because the ressources don't exist
at this time.

This patch fills the resource structure only before the device is probed and
will defer the probe if the resource are not available yet.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 drivers/base/platform.c     |  6 ++++
 drivers/of/platform.c       | 71 +++++++++++++++++++++++++++++----------------
 include/linux/of_platform.h | 10 +++++++
 3 files changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index bc78848..8e37d8b 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -481,6 +481,12 @@ static int platform_drv_probe(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
+	if (_dev->of_node) {
+		ret = of_platform_device_populate_resources(dev);
+		if (ret < 0)
+			return drv->prevent_deferred_probe ? ret : -EPROBE_DEFER;
+	}
+
 	if (ACPI_HANDLE(_dev))
 		acpi_dev_pm_attach(_dev, true);
 
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..64a8eb8 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -141,36 +141,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
 				  struct device *parent)
 {
 	struct platform_device *dev;
-	int rc, i, num_reg = 0, num_irq;
-	struct resource *res, temp_res;
 
 	dev = platform_device_alloc("", -1);
 	if (!dev)
 		return NULL;
 
-	/* count the io and irq resources */
-	if (of_can_translate_address(np))
-		while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-			num_reg++;
-	num_irq = of_irq_count(np);
-
-	/* Populate the resource table */
-	if (num_irq || num_reg) {
-		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
-		if (!res) {
-			platform_device_put(dev);
-			return NULL;
-		}
-
-		dev->num_resources = num_reg + num_irq;
-		dev->resource = res;
-		for (i = 0; i < num_reg; i++, res++) {
-			rc = of_address_to_resource(np, i, res);
-			WARN_ON(rc);
-		}
-		WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
-	}
-
 	dev->dev.of_node = of_node_get(np);
 #if defined(CONFIG_MICROBLAZE)
 	dev->dev.dma_mask = &dev->archdata.dma_mask;
@@ -233,6 +208,52 @@ static struct platform_device *of_platform_device_create_pdata(
 	return dev;
 }
 
+int of_platform_device_populate_resources(struct platform_device *dev)
+{
+	struct device_node *np;
+	int rc = 0, i, nreg = 0, nirq;
+
+	np = dev->dev.of_node;
+
+	/* count the io and irq resources */
+	if (of_can_translate_address(np)) {
+		struct resource temp_res;
+		while (of_address_to_resource(np, nreg, &temp_res) == 0)
+			nreg++;
+	}
+	nirq = of_irq_count(np);
+
+	/* Populate the resource table */
+	if (nirq || nreg) {
+		struct resource *res;
+
+		res = krealloc(dev->resource, sizeof(*res) * (nirq + nreg),
+			       GFP_KERNEL);
+		if (!res) {
+			kfree(dev->resource);
+			dev->resource = NULL;
+			return -ENOMEM;
+		}
+		memset(res, 0, sizeof(*res) * (nirq + nreg));
+		dev->resource = res;
+		dev->num_resources = nreg + nirq;
+
+		for (i = 0; i < nreg; i++, res++) {
+			rc = of_address_to_resource(np, i, res);
+			WARN_ON(rc);
+			if (rc)
+				break;
+		}
+
+		if (!rc && of_irq_to_resource_table(np, res, nirq) != nirq) {
+			rc = -ENOENT;
+			WARN_ON(rc);
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL(of_platform_device_populate_resources);
+
 /**
  * of_platform_device_create - Alloc, initialize and register an of_device
  * @np: pointer to node to create device for
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 05cb4a9..315e1e3 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -53,6 +53,16 @@ struct of_dev_auxdata {
 
 extern const struct of_device_id of_default_bus_match_table[];
 
+/* Populate the resource for a platform device */
+#ifdef CONFIG_OF
+int of_platform_device_populate_resources(struct platform_device *dev);
+#else
+static inline int of_platform_device_populate_resources(
+	struct platform_device *)
+{
+	return -ENOSYS;
+}
+#endif
 /* Platform drivers register/unregister */
 extern struct platform_device *of_device_alloc(struct device_node *np,
 					 const char *bus_id,
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH 0/8] OMAP: OMAP3 DSS related clock patches
From: Tomi Valkeinen @ 2014-02-13 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

I've been debugging OMAP3 related issues with DSS clocks, and I hopefully have
them all fixed with this series. This fixes the problems for both non-DT boot,
but also for DT boot with DSS DT support (which is not merged yet).

The non-DT boot related fixes should be merged for 3.14, but I'd like the DT
boot related fixes to be merged for 3.14 also, as that'll make handling the DSS
DT support easier.

This is based on v3.14-rc2.

 Tomi

Tomi Valkeinen (8):
  clk: divider: fix rate calculation for fractional rates
  clk: ti/divider: fix rate calculation for fractional rates
  ARM: OMAP2+: clock: fix clkoutx2 with CLK_SET_RATE_PARENT
  ARM: dts: fix omap3 dss clock handle names
  ARM: dts: fix DPLL4 x2 clkouts on 3630
  ARM: dts: use ti,fixed-factor-clock for dpll4_m4x2_mul_ck
  ARM: dts: set 'ti,set-rate-parent' for dpll4_m4 path
  OMAPDSS: fix rounding when calculating fclk rate

 arch/arm/boot/dts/omap3430es1-clocks.dtsi          |  6 +--
 .../omap36xx-am35xx-omap3430es2plus-clocks.dtsi    |  6 +--
 arch/arm/boot/dts/omap36xx-clocks.dtsi             | 20 +++++++
 arch/arm/boot/dts/omap36xx.dtsi                    |  2 +-
 arch/arm/boot/dts/omap3xxx-clocks.dtsi             |  8 +--
 arch/arm/mach-omap2/cclock3xxx_data.c              |  2 +
 arch/arm/mach-omap2/dpll3xxx.c                     | 62 ++++++++++++++++++++++
 drivers/clk/clk-divider.c                          | 10 ++--
 drivers/clk/ti/divider.c                           |  8 +--
 drivers/video/omap2/dss/dss.c                      |  4 +-
 include/linux/clk/ti.h                             |  4 ++
 11 files changed, 111 insertions(+), 21 deletions(-)

-- 
1.8.3.2

^ permalink raw reply

* [PATCH 1/8] clk: divider: fix rate calculation for fractional rates
From: Tomi Valkeinen @ 2014-02-13 10:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

clk-divider.c does not calculate the rates consistently at the moment.

As an example, on OMAP3 we have a clock divider with a source clock of
864000000 Hz. With dividers 6, 7 and 8 the theoretical rates are:

6: 144000000
7: 123428571.428571...
8: 108000000

Calling clk_round_rate() with the rate in the first column will give the
rate in the second column:

144000000 -> 144000000
143999999 -> 123428571
123428572 -> 123428571
123428571 -> 108000000

Note how clk_round_rate() returns 123428571 for rates from 123428572 to
143999999, which is mathematically correct, but when clk_round_rate() is
called with 123428571, the returned value is surprisingly 108000000.

This means that the following code works a bit oddly:

rate = clk_round_rate(clk, 123428572);
clk_set_rate(clk, rate);

As clk_set_rate() also does clock rate rounding, the result is that the
clock is set to the rate of 108000000, not 123428571 returned by the
clk_round_rate.

This patch changes the clk-divider.c to use DIV_ROUND_UP when
calculating the rate. This gives the following behavior which fixes the
inconsistency:

144000000 -> 144000000
143999999 -> 123428572
123428572 -> 123428572
123428571 -> 108000000

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Mike Turquette <mturquette@linaro.org>
---
 drivers/clk/clk-divider.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 5543b7df8e16..ec22112e569f 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -24,7 +24,7 @@
  * Traits of this clock:
  * prepare - clk_prepare only ensures that parents are prepared
  * enable - clk_enable only ensures that parents are enabled
- * rate - rate is adjustable.  clk->rate = parent->rate / divisor
+ * rate - rate is adjustable.  clk->rate = DIV_ROUND_UP(parent->rate / divisor)
  * parent - fixed parent.  No clk_set_parent support
  */
 
@@ -115,7 +115,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 		return parent_rate;
 	}
 
-	return parent_rate / div;
+	return DIV_ROUND_UP(parent_rate, div);
 }
 
 /*
@@ -185,7 +185,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 		}
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
 				MULT_ROUND_UP(rate, i));
-		now = parent_rate / i;
+		now = DIV_ROUND_UP(parent_rate, i);
 		if (now <= rate && now > best) {
 			bestdiv = i;
 			best = now;
@@ -207,7 +207,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 	int div;
 	div = clk_divider_bestdiv(hw, rate, prate);
 
-	return *prate / div;
+	return DIV_ROUND_UP(*prate, div);
 }
 
 static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -218,7 +218,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags = 0;
 	u32 val;
 
-	div = parent_rate / rate;
+	div = DIV_ROUND_UP(parent_rate, rate);
 	value = _get_val(divider, div);
 
 	if (value > div_mask(divider))
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 2/8] clk: ti/divider: fix rate calculation for fractional rates
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

ti/clk-divider.c does not calculate the rates consistently at the moment.

As an example, on OMAP3 we have a clock divider with a source clock of
864000000 Hz. With dividers 6, 7 and 8 the theoretical rates are:

6: 144000000
7: 123428571.428571...
8: 108000000

Calling clk_round_rate() with the rate in the first column will give the
rate in the second column:

144000000 -> 144000000
143999999 -> 123428571
123428572 -> 123428571
123428571 -> 108000000

Note how clk_round_rate() returns 123428571 for rates from 123428572 to
143999999, which is mathematically correct, but when clk_round_rate() is
called with 123428571, the returned value is surprisingly 108000000.

This means that the following code works a bit oddly:

rate = clk_round_rate(clk, 123428572);
clk_set_rate(clk, rate);

As clk_set_rate() also does clock rate rounding, the result is that the
clock is set to the rate of 108000000, not 123428571 returned by the
clk_round_rate.

This patch changes the ti/clk-divider.c to use DIV_ROUND_UP when
calculating the rate. This gives the following behavior which fixes the
inconsistency:

144000000 -> 144000000
143999999 -> 123428572
123428572 -> 123428572
123428571 -> 108000000

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/clk/ti/divider.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index a15e445570b2..e6aa10db7bba 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -112,7 +112,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
 		return parent_rate;
 	}
 
-	return parent_rate / div;
+	return DIV_ROUND_UP(parent_rate, div);
 }
 
 /*
@@ -182,7 +182,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 		}
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
 				MULT_ROUND_UP(rate, i));
-		now = parent_rate / i;
+		now = DIV_ROUND_UP(parent_rate, i);
 		if (now <= rate && now > best) {
 			bestdiv = i;
 			best = now;
@@ -205,7 +205,7 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 	int div;
 	div = ti_clk_divider_bestdiv(hw, rate, prate);
 
-	return *prate / div;
+	return DIV_ROUND_UP(*prate, div);
 }
 
 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -216,7 +216,7 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long flags = 0;
 	u32 val;
 
-	div = parent_rate / rate;
+	div = DIV_ROUND_UP(parent_rate, rate);
 	value = _get_val(divider, div);
 
 	if (value > div_mask(divider))
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 3/8] ARM: OMAP2+: clock: fix clkoutx2 with CLK_SET_RATE_PARENT
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

If CLK_SET_RATE_PARENT is set for a clkoutx2 clock, calling
clk_set_rate() on the clock "skips" the x2 multiplier as there are no
set_rate and round_rate functions defined for the clkoutx2.

This results in getting double the requested clock rates, breaking the
display on omap3430 based devices.

This patch implements set_rate and round_rate for clkoutx2.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/cclock3xxx_data.c |  2 ++
 arch/arm/mach-omap2/dpll3xxx.c        | 62 +++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h                |  4 +++
 3 files changed, 68 insertions(+)

diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 3b05aea56d1f..11ed9152e665 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -433,7 +433,9 @@ static const struct clk_ops dpll4_m5x2_ck_ops = {
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.set_rate	= &omap3_clkoutx2_set_rate,
 	.recalc_rate	= &omap3_clkoutx2_recalc,
+	.round_rate	= &omap3_clkoutx2_round_rate,
 };
 
 static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 3185ced807c9..4ba7e90e127b 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -672,6 +672,68 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	return rate;
 }
 
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	return 0;
+}
+
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	const struct dpll_data *dd;
+	u32 v;
+	struct clk_hw_omap *pclk = NULL;
+	struct clk *parent;
+
+	if (!*prate)
+		return 0;
+
+	/* Walk up the parents of clk, looking for a DPLL */
+	do {
+		do {
+			parent = __clk_get_parent(hw->clk);
+			hw = __clk_get_hw(parent);
+		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+		if (!hw)
+			break;
+		pclk = to_clk_hw_omap(hw);
+	} while (pclk && !pclk->dpll_data);
+
+	/* clk does not have a DPLL as a parent?  error in the clock data */
+	if (!pclk) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	dd = pclk->dpll_data;
+
+	/* TYPE J does not have a clkoutx2 */
+	if (dd->flags & DPLL_J_TYPE) {
+		*prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
+		return *prate;
+	}
+
+	WARN_ON(!dd->enable_mask);
+
+	v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+	v >>= __ffs(dd->enable_mask);
+
+	/* If in bypass, the rate is fixed to the bypass rate*/
+	if (v != OMAP3XXX_EN_DPLL_LOCKED)
+		return *prate;
+
+	if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent;
+
+		best_parent = (rate / 2);
+		*prate = __clk_round_rate(__clk_get_parent(hw->clk),
+				best_parent);
+	}
+
+	return *prate * 2;
+}
+
 /* OMAP3/4 non-CORE DPLL clkops */
 const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
 	.allow_idle	= omap3_dpll_allow_idle,
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 092b64168d7f..4a21a872dbbd 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -245,6 +245,10 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate);
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 4/8] ARM: dts: fix omap3 dss clock handle names
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

The DSS fclk and iclk handles are named differently on OMAP3430 ES1 than
on later OMAP revisions. The ES1 has handles 'dss1_alwon_fck_3430es1'
and 'dss_ick_3430es1', whereas later revisions have similar names but
ending with 'es2'.

This means we don't have one clock handle to which we could refer to
when defining the DSS clocks.

However, as the namespaces are separate for ES1 and ES2+ OMAPs, we can
just rename the handles to 'dss1_alwon_fck' and 'dss_ick' for both ES1
and ES2+, removing the issue.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/boot/dts/omap3430es1-clocks.dtsi                     | 6 +++---
 arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/omap3430es1-clocks.dtsi b/arch/arm/boot/dts/omap3430es1-clocks.dtsi
index 02f6c7fabbec..f9202656168f 100644
--- a/arch/arm/boot/dts/omap3430es1-clocks.dtsi
+++ b/arch/arm/boot/dts/omap3430es1-clocks.dtsi
@@ -152,7 +152,7 @@
 		clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
 	};
 
-	dss1_alwon_fck_3430es1: dss1_alwon_fck_3430es1 {
+	dss1_alwon_fck: dss1_alwon_fck_3430es1 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m4x2_ck>;
@@ -161,7 +161,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_ick_3430es1: dss_ick_3430es1 {
+	dss_ick: dss_ick_3430es1 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&l4_ick>;
@@ -184,7 +184,7 @@
 	dss_clkdm: dss_clkdm {
 		compatible = "ti,clockdomain";
 		clocks = <&dss_tv_fck>, <&dss_96m_fck>, <&dss2_alwon_fck>,
-			 <&dss1_alwon_fck_3430es1>, <&dss_ick_3430es1>;
+			 <&dss1_alwon_fck>, <&dss_ick>;
 	};
 
 	d2d_clkdm: d2d_clkdm {
diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
index af9ae5346bf2..080fb3f4e429 100644
--- a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
+++ b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
@@ -160,7 +160,7 @@
 		ti,bit-shift = <30>;
 	};
 
-	dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2 {
+	dss1_alwon_fck: dss1_alwon_fck_3430es2 {
 		#clock-cells = <0>;
 		compatible = "ti,dss-gate-clock";
 		clocks = <&dpll4_m4x2_ck>;
@@ -169,7 +169,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_ick_3430es2: dss_ick_3430es2 {
+	dss_ick: dss_ick_3430es2 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dss-interface-clock";
 		clocks = <&l4_ick>;
@@ -216,7 +216,7 @@
 	dss_clkdm: dss_clkdm {
 		compatible = "ti,clockdomain";
 		clocks = <&dss_tv_fck>, <&dss_96m_fck>, <&dss2_alwon_fck>,
-			 <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
+			 <&dss1_alwon_fck>, <&dss_ick>;
 	};
 
 	core_l4_clkdm: core_l4_clkdm {
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 5/8] ARM: dts: fix DPLL4 x2 clkouts on 3630
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

OMAP3630 DPLL4 is different than on OMAP3430, in that it doesn't have
the x2 multiplier for its outputs. This is not currently reflected in
the clock DT data.

Fix the issue by setting the clock multiplier to 1 (instead of 2) for the
DPLL4 output clocks.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/boot/dts/omap36xx-clocks.dtsi | 20 ++++++++++++++++++++
 arch/arm/boot/dts/omap36xx.dtsi        |  2 +-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap36xx-clocks.dtsi
index 2fcf253b677c..0b2df76b9d38 100644
--- a/arch/arm/boot/dts/omap36xx-clocks.dtsi
+++ b/arch/arm/boot/dts/omap36xx-clocks.dtsi
@@ -70,6 +70,26 @@
 	};
 };
 
+&dpll4_m2x2_mul_ck {
+	clock-mult = <1>;
+};
+
+&dpll4_m3x2_mul_ck {
+	clock-mult = <1>;
+};
+
+&dpll4_m4x2_mul_ck {
+	clock-mult = <1>;
+};
+
+&dpll4_m5x2_mul_ck {
+	clock-mult = <1>;
+};
+
+&dpll4_m6x2_mul_ck {
+	clock-mult = <1>;
+};
+
 &cm_clockdomains {
 	dpll4_clkdm: dpll4_clkdm {
 		compatible = "ti,clockdomain";
diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
index 7e8dee9175d6..5e1bcd06a996 100644
--- a/arch/arm/boot/dts/omap36xx.dtsi
+++ b/arch/arm/boot/dts/omap36xx.dtsi
@@ -52,7 +52,7 @@
 	};
 };
 
-/include/ "omap36xx-clocks.dtsi"
 /include/ "omap34xx-omap36xx-clocks.dtsi"
 /include/ "omap36xx-omap3430es2plus-clocks.dtsi"
 /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
+/include/ "omap36xx-clocks.dtsi"
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 6/8] ARM: dts: use ti, fixed-factor-clock for dpll4_m4x2_mul_ck
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

We need to use set-rate-parent for dpll4_m4 clock path, so use the
ti,fixed-factor-clock version which supports set-rate-parent property.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/boot/dts/omap36xx-clocks.dtsi | 2 +-
 arch/arm/boot/dts/omap3xxx-clocks.dtsi | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap36xx-clocks.dtsi
index 0b2df76b9d38..6b5280d04a0e 100644
--- a/arch/arm/boot/dts/omap36xx-clocks.dtsi
+++ b/arch/arm/boot/dts/omap36xx-clocks.dtsi
@@ -79,7 +79,7 @@
 };
 
 &dpll4_m4x2_mul_ck {
-	clock-mult = <1>;
+	ti,clock-mult = <1>;
 };
 
 &dpll4_m5x2_mul_ck {
diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
index cb04d4b37e7f..df3c699a1893 100644
--- a/arch/arm/boot/dts/omap3xxx-clocks.dtsi
+++ b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
@@ -425,10 +425,10 @@
 
 	dpll4_m4x2_mul_ck: dpll4_m4x2_mul_ck {
 		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
+		compatible = "ti,fixed-factor-clock";
 		clocks = <&dpll4_m4_ck>;
-		clock-mult = <2>;
-		clock-div = <1>;
+		ti,clock-mult = <2>;
+		ti,clock-div = <1>;
 	};
 
 	dpll4_m4x2_ck: dpll4_m4x2_ck {
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 7/8] ARM: dts: set 'ti,set-rate-parent' for dpll4_m4 path
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

Set 'ti,set-rate-parent' property for clocks in the dpll4_m4 clock
path, which is used for DSS functional clock. This fixes DSS driver's
clock rate configuration, which needs the rate to be propagated properly
to the divider node (dpll4_m4_ck).

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/boot/dts/omap3xxx-clocks.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
index df3c699a1893..12be2b35dae9 100644
--- a/arch/arm/boot/dts/omap3xxx-clocks.dtsi
+++ b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
@@ -429,6 +429,7 @@
 		clocks = <&dpll4_m4_ck>;
 		ti,clock-mult = <2>;
 		ti,clock-div = <1>;
+		ti,set-rate-parent;
 	};
 
 	dpll4_m4x2_ck: dpll4_m4x2_ck {
@@ -438,6 +439,7 @@
 		ti,bit-shift = <0x1d>;
 		reg = <0x0d00>;
 		ti,set-bit-to-disable;
+		ti,set-rate-parent;
 	};
 
 	dpll4_m5_ck: dpll4_m5_ck {
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 8/8] OMAPDSS: fix rounding when calculating fclk rate
From: Tomi Valkeinen @ 2014-02-13 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-1-git-send-email-tomi.valkeinen@ti.com>

"clk: divider: fix rate calculation for fractional rates" patch (and
similar for TI specific divider) fixes the clk-divider's rounding. This
patch updates the DSS driver to round the rates accordingly.

This fixes the DSS's warnings about clock rate mismatch, and also fixes
the wrong fclk rate being set.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 9a145da35ad3..efe7c308341d 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -471,7 +471,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
 	fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
 
 	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
-		fck = prate / fckd * m;
+		fck = DIV_ROUND_UP(prate, fckd) * m;
 
 		if (func(fck, data))
 			return true;
@@ -520,7 +520,7 @@ static int dss_setup_default_clock(void)
 
 		fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
 				max_dss_fck);
-		fck = prate / fck_div * dss.feat->dss_fck_multiplier;
+		fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
 	}
 
 	r = dss_set_fck_rate(fck);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH] dt: platform driver: Fill the resources before probe and defer if needed
From: Jean-Jacques Hiblot @ 2014-02-13 10:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285429-9325-1-git-send-email-jjhiblot@traphandler.com>

Hi all,

I forgot to add the link to the discussion that lead to this patch:
https://lkml.org/lkml/2014/2/12/306.

Jean-Jacques

2014-02-13 10:57 GMT+01:00 Jean-Jacques Hiblot <jjhiblot@traphandler.com>:
> The goal of this patch is to allow drivers to be probed even if at the time of
> the DT parsing some of their ressources are not available yet.
>
> In the current situation, the resource of a platform device are filled from the
> DT at the time the device is created (of_device_alloc()). The drawbackof this
> is that a device sitting close to the top of the DT (ahb for example) but
> depending on ressources that are initialized later (IRQ domain dynamically
> created for example)  will fail to probe because the ressources don't exist
> at this time.
>
> This patch fills the resource structure only before the device is probed and
> will defer the probe if the resource are not available yet.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
>  drivers/base/platform.c     |  6 ++++
>  drivers/of/platform.c       | 71 +++++++++++++++++++++++++++++----------------
>  include/linux/of_platform.h | 10 +++++++
>  3 files changed, 62 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index bc78848..8e37d8b 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -481,6 +481,12 @@ static int platform_drv_probe(struct device *_dev)
>         struct platform_device *dev = to_platform_device(_dev);
>         int ret;
>
> +       if (_dev->of_node) {
> +               ret = of_platform_device_populate_resources(dev);
> +               if (ret < 0)
> +                       return drv->prevent_deferred_probe ? ret : -EPROBE_DEFER;
> +       }
> +
>         if (ACPI_HANDLE(_dev))
>                 acpi_dev_pm_attach(_dev, true);
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 404d1da..64a8eb8 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -141,36 +141,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
>                                   struct device *parent)
>  {
>         struct platform_device *dev;
> -       int rc, i, num_reg = 0, num_irq;
> -       struct resource *res, temp_res;
>
>         dev = platform_device_alloc("", -1);
>         if (!dev)
>                 return NULL;
>
> -       /* count the io and irq resources */
> -       if (of_can_translate_address(np))
> -               while (of_address_to_resource(np, num_reg, &temp_res) == 0)
> -                       num_reg++;
> -       num_irq = of_irq_count(np);
> -
> -       /* Populate the resource table */
> -       if (num_irq || num_reg) {
> -               res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
> -               if (!res) {
> -                       platform_device_put(dev);
> -                       return NULL;
> -               }
> -
> -               dev->num_resources = num_reg + num_irq;
> -               dev->resource = res;
> -               for (i = 0; i < num_reg; i++, res++) {
> -                       rc = of_address_to_resource(np, i, res);
> -                       WARN_ON(rc);
> -               }
> -               WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
> -       }
> -
>         dev->dev.of_node = of_node_get(np);
>  #if defined(CONFIG_MICROBLAZE)
>         dev->dev.dma_mask = &dev->archdata.dma_mask;
> @@ -233,6 +208,52 @@ static struct platform_device *of_platform_device_create_pdata(
>         return dev;
>  }
>
> +int of_platform_device_populate_resources(struct platform_device *dev)
> +{
> +       struct device_node *np;
> +       int rc = 0, i, nreg = 0, nirq;
> +
> +       np = dev->dev.of_node;
> +
> +       /* count the io and irq resources */
> +       if (of_can_translate_address(np)) {
> +               struct resource temp_res;
> +               while (of_address_to_resource(np, nreg, &temp_res) == 0)
> +                       nreg++;
> +       }
> +       nirq = of_irq_count(np);
> +
> +       /* Populate the resource table */
> +       if (nirq || nreg) {
> +               struct resource *res;
> +
> +               res = krealloc(dev->resource, sizeof(*res) * (nirq + nreg),
> +                              GFP_KERNEL);
> +               if (!res) {
> +                       kfree(dev->resource);
> +                       dev->resource = NULL;
> +                       return -ENOMEM;
> +               }
> +               memset(res, 0, sizeof(*res) * (nirq + nreg));
> +               dev->resource = res;
> +               dev->num_resources = nreg + nirq;
> +
> +               for (i = 0; i < nreg; i++, res++) {
> +                       rc = of_address_to_resource(np, i, res);
> +                       WARN_ON(rc);
> +                       if (rc)
> +                               break;
> +               }
> +
> +               if (!rc && of_irq_to_resource_table(np, res, nirq) != nirq) {
> +                       rc = -ENOENT;
> +                       WARN_ON(rc);
> +               }
> +       }
> +       return rc;
> +}
> +EXPORT_SYMBOL(of_platform_device_populate_resources);
> +
>  /**
>   * of_platform_device_create - Alloc, initialize and register an of_device
>   * @np: pointer to node to create device for
> diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
> index 05cb4a9..315e1e3 100644
> --- a/include/linux/of_platform.h
> +++ b/include/linux/of_platform.h
> @@ -53,6 +53,16 @@ struct of_dev_auxdata {
>
>  extern const struct of_device_id of_default_bus_match_table[];
>
> +/* Populate the resource for a platform device */
> +#ifdef CONFIG_OF
> +int of_platform_device_populate_resources(struct platform_device *dev);
> +#else
> +static inline int of_platform_device_populate_resources(
> +       struct platform_device *)
> +{
> +       return -ENOSYS;
> +}
> +#endif
>  /* Platform drivers register/unregister */
>  extern struct platform_device *of_device_alloc(struct device_node *np,
>                                          const char *bus_id,
> --
> 1.8.5.3
>

^ permalink raw reply

* [PATCH v2 2/3] ARM: bios32: use pci_enable_resource to enable PCI resources
From: Will Deacon @ 2014-02-13 10:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140212222825.GC17248@obsidianresearch.com>

On Wed, Feb 12, 2014 at 10:28:25PM +0000, Jason Gunthorpe wrote:
> On Wed, Feb 12, 2014 at 08:16:10PM +0000, Will Deacon wrote:
> > This patch moves bios32 over to using the generic code for enabling PCI
> > resources. Since the core code takes care of bridge resources too, we
> > can also drop the explicit IO and MEMORY enabling for them in the arch
> > code.
> 
> Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> (on Kirkwood)
> 
> PCI: bus1: Fast back to back transfers disabled
> pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
> pci 0000:00:01.0: BAR 8: assigned [mem 0xe0000000-0xe00fffff]
> pci 0000:01:00.0: BAR 0: assigned [mem 0xe0000000-0xe001ffff]
> pci 0000:00:01.0: PCI bridge to [bus 01]
> pci 0000:00:01.0:   bridge window [mem 0xe0000000-0xe00fffff]
> pci 0000:00:01.0: enabling device (0140 -> 0142)

That's really helpful. Thanks for testing, Jason!

Will

^ permalink raw reply

* [PATCH v2 0/4] ARM: dts: Fixes for Overo/Tobi against 3.14-rc2
From: Florian Vaussard @ 2014-02-13 10:25 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP36xx-based Overo (Storm and alike) are now failing to boot with 3.14-rc2 [1].
This series fixes this, by moving model-agnostic DT into a common dtsi file,
and creating model-specific DT files:

- omap3-overo-tobi.dts -> older OMAP35xx Overo
- omap3-overo-storm-tobi.dts -> newer OMAP36xx/AM37xx/DM37xx Overo

People will have to use the right Overo / expansion board combination.

(Patch 2 in an unrelated fix that was waiting in my queue.)

omap3-overo-tobi.dts tested with Overo Sand (OMAP3503) and omap3-overo-storm-tobi.dts
tested with Overo EarthStorm (AM3703). Both boot. With the Overo Sand, I cannot
mount the ext3 rootfs, but this seems unrelated to the current topic, maybe
a missing errata.

Regards,
Florian

Changes since v1:
- Add "ti,omap3430" as a compatible string for OMAP35xx-based Overo
- Update the DT documentation to silence out checkpatch warnings (patch 4)

[1] http://thread.gmane.org/gmane.linux.ports.arm.omap/110006

Florian Vaussard (4):
  ARM: dts: omap3-tobi: Fix boot with OMAP36xx-based Overo
  ARM: dts: omap3-tobi: Use the correct vendor prefix
  ARM: dts: Add support for both OMAP35xx and OMAP36xx Overo/Tobi
  Documentation: dt: OMAP: Update Overo/Tobi

 .../devicetree/bindings/arm/omap/omap.txt          |  2 +-
 arch/arm/boot/dts/Makefile                         |  3 ++-
 arch/arm/boot/dts/omap3-overo-storm-tobi.dts       | 22 ++++++++++++++++++++++
 ...omap3-tobi.dts => omap3-overo-tobi-common.dtsi} |  3 ---
 arch/arm/boot/dts/omap3-overo-tobi.dts             | 22 ++++++++++++++++++++++
 arch/arm/boot/dts/omap3-overo.dtsi                 |  3 ---
 6 files changed, 47 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/boot/dts/omap3-overo-storm-tobi.dts
 rename arch/arm/boot/dts/{omap3-tobi.dts => omap3-overo-tobi-common.dtsi} (94%)
 create mode 100644 arch/arm/boot/dts/omap3-overo-tobi.dts

-- 
1.8.1.2

^ permalink raw reply

* [PATCH v2 1/4] ARM: dts: omap3-tobi: Fix boot with OMAP36xx-based Overo
From: Florian Vaussard @ 2014-02-13 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392287116-4548-1-git-send-email-florian.vaussard@epfl.ch>

Tobi expansion board can be used with both OMAP35xx-based Overo,
and OMAP36xx-based Overo. Currently the boot is broken with newer
OMAP36xx-based Overo (Storm and alike). Fix include file and
compatible string to be able to boot newer models.

This will break older models. This will be addressed later.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
Tested-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/boot/dts/omap3-overo.dtsi | 3 ---
 arch/arm/boot/dts/omap3-tobi.dts   | 5 ++++-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
index a461d2f..5970999 100644
--- a/arch/arm/boot/dts/omap3-overo.dtsi
+++ b/arch/arm/boot/dts/omap3-overo.dtsi
@@ -9,9 +9,6 @@
 /*
  * The Gumstix Overo must be combined with an expansion board.
  */
-/dts-v1/;
-
-#include "omap34xx.dtsi"
 
 / {
 	pwmleds {
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts
index 7e4ad2a..0e3b8bf 100644
--- a/arch/arm/boot/dts/omap3-tobi.dts
+++ b/arch/arm/boot/dts/omap3-tobi.dts
@@ -10,11 +10,14 @@
  * Tobi expansion board is manufactured by Gumstix Inc.
  */
 
+/dts-v1/;
+
+#include "omap36xx.dtsi"
 #include "omap3-overo.dtsi"
 
 / {
 	model = "TI OMAP3 Gumstix Overo on Tobi";
-	compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3";
+	compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3";
 
 	leds {
 		compatible = "gpio-leds";
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2 2/4] ARM: dts: omap3-tobi: Use the correct vendor prefix
From: Florian Vaussard @ 2014-02-13 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392287116-4548-1-git-send-email-florian.vaussard@epfl.ch>

Gumstix is the correct vendor for all Overo related products.

Reported-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
---
 arch/arm/boot/dts/omap3-tobi.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts
index 0e3b8bf..c742afa 100644
--- a/arch/arm/boot/dts/omap3-tobi.dts
+++ b/arch/arm/boot/dts/omap3-tobi.dts
@@ -17,7 +17,7 @@
 
 / {
 	model = "TI OMAP3 Gumstix Overo on Tobi";
-	compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3";
+	compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
 
 	leds {
 		compatible = "gpio-leds";
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2 3/4] ARM: dts: Add support for both OMAP35xx and OMAP36xx Overo/Tobi
From: Florian Vaussard @ 2014-02-13 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392287116-4548-1-git-send-email-florian.vaussard@epfl.ch>

Unfortunatly the device tree for older OMAP35xx Overo cannot be used
with newer OMAP36xx and vice-versa. To address this issue, move most of
the Tobi DTS to a common include file, and create model-specific Tobi
DTS.

Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
Tested-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/boot/dts/Makefile                         |  3 ++-
 arch/arm/boot/dts/omap3-overo-storm-tobi.dts       | 22 ++++++++++++++++++++++
 ...omap3-tobi.dts => omap3-overo-tobi-common.dtsi} |  6 ------
 arch/arm/boot/dts/omap3-overo-tobi.dts             | 22 ++++++++++++++++++++++
 4 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/boot/dts/omap3-overo-storm-tobi.dts
 rename arch/arm/boot/dts/{omap3-tobi.dts => omap3-overo-tobi-common.dtsi} (91%)
 create mode 100644 arch/arm/boot/dts/omap3-overo-tobi.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b9d6a8b..e8355f4 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -208,7 +208,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	omap3-n900.dtb \
 	omap3-n9.dtb \
 	omap3-n950.dtb \
-	omap3-tobi.dtb \
+	omap3-overo-tobi.dtb \
+	omap3-overo-storm-tobi.dtb \
 	omap3-gta04.dtb \
 	omap3-igep0020.dtb \
 	omap3-igep0030.dtb \
diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
new file mode 100644
index 0000000..966b5c9
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+	model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi";
+	compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
+};
+
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
similarity index 91%
rename from arch/arm/boot/dts/omap3-tobi.dts
rename to arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
index c742afa..4edc013 100644
--- a/arch/arm/boot/dts/omap3-tobi.dts
+++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
@@ -10,15 +10,9 @@
  * Tobi expansion board is manufactured by Gumstix Inc.
  */
 
-/dts-v1/;
-
-#include "omap36xx.dtsi"
 #include "omap3-overo.dtsi"
 
 / {
-	model = "TI OMAP3 Gumstix Overo on Tobi";
-	compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
-
 	leds {
 		compatible = "gpio-leds";
 		heartbeat {
diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts
new file mode 100644
index 0000000..de5653e
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-overo-tobi.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+	model = "OMAP35xx Gumstix Overo on Tobi";
+	compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3";
+};
+
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v2 4/4] Documentation: dt: OMAP: Update Overo/Tobi
From: Florian Vaussard @ 2014-02-13 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392287116-4548-1-git-send-email-florian.vaussard@epfl.ch>

Update the compatible string for Overo/Tobi to reflect the latest
changes.

Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
---
 Documentation/devicetree/bindings/arm/omap/omap.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index 34dc40c..af9b4a0 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -91,7 +91,7 @@ Boards:
   compatible = "ti,omap3-beagle", "ti,omap3"
 
 - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
-  compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
+  compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
 
 - OMAP4 SDP : Software Development Board
   compatible = "ti,omap4-sdp", "ti,omap4430"
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 4/4] phy: miphy365x: Provide support for the MiPHY356x Generic PHY
From: Lee Jones @ 2014-02-13 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52FC6BF5.9030900@ti.com>

> > The MiPHY365x is a Generic PHY which can serve various SATA or PCIe
> > devices. It has 2 ports which it can use for either; both SATA, both
> 
> various SATA or PCIe devices in STMicroelectronics STiH41x SoC series?

To tell you the truth, I'm not sure if it is limited to ST's h/w, but
I think it can only be found there, so I'm happy to fixup.

<snip>

> > +config PHY_MIPHY365X
> > +	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
> > +	depends on ARCH_STI
> > +	depends on GENERIC_PHY
> depends on CONFIG_OF and HAS_IOMEM?

Sure, I'll fix.

<snip>

> > + * Copyright (C) 2014 STMicroelectronics
> > + *
> > + * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
> > + *
> > + * Author: Alexandre Torgue <alexandre.torgue@st.com>
> 
> The author of this patch is not Alexandre Torgue?

The history of this driver is long and the authors are many. Alex
did the last internal over-haul and converted it to use Generic PHY. I
took Alex's driver and made significant changes in order to upstream.

<snip>

> > +#define HFC_TIMEOUT		50
> > +
> > +#define SYSCFG_2521		0x824
> > +#define SYSCFG_2522		0x828
> > +#define SYSCFG_PCIE_SATA_MASK	BIT(1)
> > +#define SYSCFG_PCIE_SATA_POS	1
> > +
> > +/* MiPHY365x register definitiona */
> > +#define RESET_REG		0x00
> > +#define RST_PLL			BIT(1)
> 
> There are quite a few alignment problems with these macros. It needs
> to be fixed.

This is just Git playing up.

In reality everything is perfectly aligned and all using tabs.

<snip>

> > +/*
> > + * This function selects the system configuration,
> > + * either two SATA, one SATA and one PCIe, or two PCIe lanes.
> > + */
> > +static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
> > +			      struct miphy365x_dev *miphy_dev)
> > +{
> > +	u8 config = miphy_phy->type | miphy_phy->port;
> > +	u32 mask  = SYSCFG_PCIE_SATA_MASK;
> > +	u32 reg;
> > +	bool sata;
> > +
> > +	switch (config) {
> > +	case MIPHY_SATA_PORT0:
> > +		reg = SYSCFG_2521;
> > +		sata = true;
> 
> How do we configure PORT1 for SATA here? Do we really support all the system
> configuration?

Good spot eagle-eye!

Actually in the current version there is a h/w bug which only allows
the SATA_PORT0 and PCIE_PORT1 configuration. When a new version fixing
this is released I will add version detection to the driver and we can
support full intended configuration options. 

<snip>

> > +static inline int miphy365x_phy_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
> > +					    struct miphy365x_dev *miphy_dev)
> > +{
> > +	int timeout = HFC_TIMEOUT;
> > +	u8 mask = IDLL_RDY | PLL_RDY;
> > +	u8 regval;
> > +
> > +	do {
> > +		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
> > +		usleep_range(2000, 2500);
> 
> Any comment on how this delay value is obtained?

I don't have any specific comments, I believe the 2000us it taken from
the datasheet and the 2500 is us playing nice with the scheduler.

<snip>

> > +static inline int miphy365x_phy_rdy(struct miphy365x_phy *miphy_phy,
> > +				    struct miphy365x_dev *miphy_dev)
> > +{
> > +	int timeout = HFC_TIMEOUT;
> > +	u8 mask = mask = IDLL_RDY | PLL_RDY;
> 
> just u8 mask = IDLL_RDY | PLL_RDY; would suffice.

Hmm... not sure how this slipped through - will fix.

> > +	u8 regval;
> > +
> > +	do {
> > +		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
> > +		usleep_range(2000, 2500);
> 
> same here.

As above.

<snip>

> > +	mask = DES_BIT_LOCK | DES_SYMBOL_LOCK;
> > +	while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask)	!= mask)
> > +		cpu_relax();
> 
> Don't we need to break from here at some point if the LOCK's are never set?

I'm sure sure that's possible, but I will invesigate and fixup if req'd.

<snip>

> > +static int miphy365x_phy_power_on(struct phy *phy)
> > +{
> > +	return 0;
> > +}
> > +
> > +static int miphy365x_phy_power_off(struct phy *phy)
> > +{
> > +	return 0;
> > +}
> 
> Both these empty functions can be removed.

You're right, I see the NULL checks, thanks.

<snip>

> > +static int miphy365x_phy_get_base_addr(struct platform_device *pdev,
> > +				       struct miphy365x_phy *phy, u8 port)
> > +{
> > +	struct resource *res;
> > +	char sata[16];
> > +	char pcie[16];
> 
> It can be done with a single variable ;-)

Right. :)

<snip>

> Phy provider register should be the last step in registering the PHY.

Okay, will fix, thanks.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH 0/3] RFC/RFT: Powering on MMC Wifi/BT modules in MMC core
From: Russell King - ARM Linux @ 2014-02-13 10:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140201161420.GA26684@n2100.arm.linux.org.uk>

Any comments on this?

On Sat, Feb 01, 2014 at 04:14:20PM +0000, Russell King - ARM Linux wrote:
> On Thu, Jan 30, 2014 at 09:49:17PM +0000, Russell King - ARM Linux wrote:
> > On Sun, Jan 19, 2014 at 07:56:52PM -0800, Olof Johansson wrote:
> > > This is a small series enhancing the MMC core code to power on modules
> > > before the host in cases where needed, and the corresponding DT bindings
> > > changes.
> > > 
> > > I've got some other issues to debug on the Chromebook, i.e. the interface
> > > doens't actually work. So far it seems unrelated to this patch set so
> > > it's worth posting this and get things going since others need the same
> > > functionality (i.e Cubox-i).
> > > 
> > > As mentioned in the patch in the series, I haven't implemented power-down
> > > yet, I wanted to make sure that the power-on side will be adequate for
> > > those who are looking to use it right away.
> > > 
> > > Comments/test reports/etc welcome.
> > 
> > So, I thought I'd give this a go on the Cubox-i4, and... it doesn't work
> > there.  It's not your patches, it's down to sdhci-esdhc-imx.c not using
> > mmc_of_parse() at all, so those new properties have no way to be used
> > there.
> > 
> > It doesn't look like it could in its current form use mmc_of_parse(),
> > as the imx code manually parses some of the generic properties to hand
> > them into the sdhci layer.  This looks icky, and it looks like something
> > that should be fixed - why should drivers be parsing the core attributes
> > themselves?
> 
> Here's an illustration of why it's icky.
> 
> If we call mmc_of_parse() in the sdhci-esdhc-imx driver (which we'd need to
> do in order to get information on how to configure the card detection etc)
> then this fills in mmc->f_max.
> 
> However, the subsequent call to sdhci_add_host() computes the maximum clock
> from the sdhci capabilities, and then does this:
> 
>         host->max_clk *= 1000000;
>         if (host->max_clk == 0 || host->quirks &
>                         SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
>                 if (!host->ops->get_max_clock) {
>                         pr_err("%s: Hardware doesn't specify base clock "
>                                "frequency.\n", mmc_hostname(mmc));
>                         return -ENODEV;
>                 }
>                 host->max_clk = host->ops->get_max_clock(host);
>         }
> ...
>         /*
>          * Set host parameters.
>          */
>         mmc->ops = &sdhci_ops;
>         mmc->f_max = host->max_clk;
> 
> which would have the effect of overwriting a previously set f_max from
> the OF data.
> 
> There's also the whole "cd-gpios" thing which would need sorting out -
> the imx sdhci driver already parses this property itself, and sets its
> own internal data (so it knows whether it has to use the controller
> based card detect or the gpio card detect) and simply adding a call to
> mmc_of_parse() would result in the gpio slot stuff being setup twice.
> 
> The obvious solution here is to rewrite the sdhci initialisation such
> that it uses the generic infrastructure, but I don't have the motivation
> to do that (I've already plenty of patches to deal with that I don't
> need any more at the moment.)
> 
> A simpler solution would be to split mmc_of_parse() so that the new bits
> are a separate function, which the generic MMC core always calls for
> every host - taking the decision over whether this is supported completely
> away from hosts.  I think that makes a lot of sense, especially as this
> has nothing to do with the facilities found on any particular host.
> 
> There's another issue here about resets.  Let's take the case where the
> external card is powered off, but has active high resets.  At the moment,
> the sequence is this:
> 
> power: _____/~~~~~~~~~~~~
> reset: __/~~~~\__________
> 
> That's not particularly nice, as the reset signal will tend do drive power
> into the device before it's powered up via the clamping diodes in the case.
> Generally, devices are not designed to be powered in this way.  However,
> this is a relatively minor issue though compared to this one, which is what
> happens if the card uses active low reset:
> 
> power: _____/~~~~~~~~~~~~
> reset: ~~\_____/~~~~~~~~~
> 
> This is definitely not good, because it means that the reset is higher for
> longer, which may result in unacceptable dissapation in the package from
> those clamping diodes.  What we need instead is for active low reset is:
> 
> power: _____/~~~~~~~~~~~~
> reset: ________/~~~~~~~~~
> 
> So, we need the GPIO layer to tell us whether the output is active high or
> active low and adjust the initial setting accordingly.  Basically, whenever
> the attached device is powered down, GPIOs to it should be held at low level
> or high impedance (with a pull-down to reduce the risks of ESD damage.)
> 
> I've seen designs get this wrong in the past - Intel Assabet is a good one
> where the UDA1341 audio codec ends up illuminating a LED by being powered
> not via it's supply pin, but by a CPLD output driving one of the I2S pins
> high.  The result is that the CPLD output sources quite a bit of current
> into the UDA1341, which then holds other pins on the SA1110 around mid-rail,
> which is the /worst/ thing you can do with CMOS.  Powering chips via their
> inputs is basically a big no-no.
> 
> So, I think something like the below is needed on top of your patches.
> Note that I added -EPROBE_DEFER handling too (which fixes a bug, because
> regulator_get() returns pointer-errors):
> 
>  drivers/mmc/core/host.c            | 90 +++++++++++++++++++++++++++-----------
>  1 files changed, 65 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index e6b850b3241f..64942eb495b6 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -316,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)
>  	u32 bus_width;
>  	bool explicit_inv_wp, gpio_inv_wp = false;
>  	enum of_gpio_flags flags;
> -	int i, len, ret, gpio;
> +	int len, ret, gpio;
>  
>  	if (!host->parent || !host->parent->of_node)
>  		return 0;
> @@ -419,30 +419,6 @@ int mmc_of_parse(struct mmc_host *host)
>  	if (explicit_inv_wp ^ gpio_inv_wp)
>  		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
>  
> -	/* Parse card power/reset/clock control */
> -	if (of_find_property(np, "card-reset-gpios", NULL)) {
> -		struct gpio_desc *gpd;
> -		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
> -			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
> -			if (IS_ERR(gpd))
> -				break;
> -			gpiod_direction_output(gpd, 0);
> -			host->card_reset_gpios[i] = gpd;
> -		}
> -
> -		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
> -		if (!IS_ERR(gpd)) {
> -			dev_warn(host->parent, "More reset gpios than we can handle");
> -			gpiod_put(gpd);
> -		}
> -	}
> -
> -	host->card_clk = of_clk_get_by_name(np, "card_ext_clock");
> -	if (IS_ERR(host->card_clk))
> -		host->card_clk = NULL;
> -
> -	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
> -
>  	if (of_find_property(np, "cap-sd-highspeed", &len))
>  		host->caps |= MMC_CAP_SD_HIGHSPEED;
>  	if (of_find_property(np, "cap-mmc-highspeed", &len))
> @@ -467,6 +443,66 @@ int mmc_of_parse(struct mmc_host *host)
>  
>  EXPORT_SYMBOL(mmc_of_parse);
>  
> +static int mmc_of_parse_child(struct mmc_host *host)
> +{
> +	struct device_node *np;
> +	struct clk *clk;
> +	int i;
> +
> +	if (!host->parent || !host->parent->of_node)
> +		return 0;
> +
> +	np = host->parent->of_node;
> +
> +	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
> +	if (IS_ERR(host->card_regulator)) {
> +		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
> +			return PTR_ERR(host->card_regulator);
> +		host->card_regulator = NULL;
> +	}
> +
> +	/* Parse card power/reset/clock control */
> +	if (of_find_property(np, "card-reset-gpios", NULL)) {
> +		struct gpio_desc *gpd;
> +		int level = 0;
> +
> +		/*
> +		 * If the regulator is enabled, then we can hold the
> +		 * card in reset with an active high resets.  Otherwise,
> +		 * hold the resets low.
> +		 */
> +		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
> +			level = 1;
> +
> +		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
> +			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
> +			if (IS_ERR(gpd)) {
> +				if (PTR_ERR(gpd) == -EPROBE_DEFER)
> +					return PTR_ERR(gpd);
> +				break;
> +			}
> +			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
> +			host->card_reset_gpios[i] = gpd;
> +		}
> +
> +		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
> +		if (!IS_ERR(gpd)) {
> +			dev_warn(host->parent, "More reset gpios than we can handle");
> +			gpiod_put(gpd);
> +		}
> +	}
> +
> +	clk = of_clk_get_by_name(np, "card_ext_clock");
> +	if (IS_ERR(clk)) {
> +		if (PTR_ERR(clk) == -EPROBE_DEFER)
> +			return PTR_ERR(clk);
> +		clk = NULL;
> +	}
> +	host->card_clk = clk;
> +
> +	return 0;
> +}
> +
>  /**
>   *	mmc_alloc_host - initialise the per-host structure.
>   *	@extra: sizeof private data structure
> @@ -546,6 +582,10 @@ int mmc_add_host(struct mmc_host *host)
>  {
>  	int err;
>  
> +	err = mmc_of_parse_child(host);
> +	if (err)
> +		return err;
> +
>  	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
>  		!host->ops->enable_sdio_irq);
>  
> 
> -- 
> FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
> in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
> Estimate before purchase was "up to 13.2Mbit".
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Russell King - ARM Linux @ 2014-02-13 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401281148.10670.arnd@arndb.de>

On Tue, Jan 28, 2014 at 11:48:10AM +0100, Arnd Bergmann wrote:
> I think there is another option, which does have its own pros and cons:
> We could move all the power handling back into the sdio function driver
> if we allow a secondary detection path using DT rather than the probing
> of the SDIO bus.

No thanks.

What if we have a platform where things subtly change, like for instance,
the wiring on the SD slot to fix a problem with UHS-1 cards, which means
you don't have UHS-1 support for some platforms but do for others.

What if you have a platform which uses a brcm4329 chip for Wifi, but then
later in the production run switch to using a different Wifi chipset?

With this information encoded into DT, the number of DT files quickly
increases, and then this presents its own problem - how do users get to
know which DT file should be used for their platform when all they see
externally is "a product of type A"?

Let's say that the board folk were kind enough to set some kind of
identifing feature for the first but not the second (why would they,
it's probe-able, damn it).

The "we can do it in DT" approach just makes things unnecessarily more
difficult from the _user_ and _hardware_ point of view.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH 3/8] ARM: OMAP2+: clock: fix clkoutx2 with CLK_SET_RATE_PARENT
From: Tomi Valkeinen @ 2014-02-13 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392285846-13199-4-git-send-email-tomi.valkeinen@ti.com>

On 13/02/14 12:04, Tomi Valkeinen wrote:
> If CLK_SET_RATE_PARENT is set for a clkoutx2 clock, calling
> clk_set_rate() on the clock "skips" the x2 multiplier as there are no
> set_rate and round_rate functions defined for the clkoutx2.
> 
> This results in getting double the requested clock rates, breaking the
> display on omap3430 based devices.
> 
> This patch implements set_rate and round_rate for clkoutx2.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>  arch/arm/mach-omap2/cclock3xxx_data.c |  2 ++
>  arch/arm/mach-omap2/dpll3xxx.c        | 62 +++++++++++++++++++++++++++++++++++
>  include/linux/clk/ti.h                |  4 +++
>  3 files changed, 68 insertions(+)

Argh. This patch 3/8 was an old version, and not valid. It does not work for
omap3430. I had earlier posted a proper version, but somehow I managed to get
an old version for this series.

The correct version can be found from

http://mid.gmane.org/1391080640-23370-1-git-send-email-tomi.valkeinen at ti.com

and I'll also include it below.

 Tomi

>From 0d46054a8b33bc1f7a37bc9b17dd1631b1a06047 Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
Date: Thu, 30 Jan 2014 13:17:20 +0200
Subject: [PATCH] ARM: OMAP2+: clock: fix clkoutx2 with CLK_SET_RATE_PARENT

If CLK_SET_RATE_PARENT is set for a clkoutx2 clock, calling
clk_set_rate() on the clock "skips" the x2 multiplier as there are no
set_rate and round_rate functions defined for the clkoutx2.

This results in getting double the requested clock rates, breaking the
display on omap3430 based devices. This got broken when
d0f58bd3bba3877fb1af4664c4e33273d36f00e4 and related patches were merged
for v3.14, as omapdss driver now relies more on the clk-framework and
CLK_SET_RATE_PARENT.

This patch implements set_rate and round_rate for clkoutx2.

Tested on OMAP3430, OMAP3630, OMAP4460.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/cclock3xxx_data.c |  2 +
 arch/arm/mach-omap2/dpll3xxx.c        | 92 +++++++++++++++++++++++++++++------
 include/linux/clk/ti.h                |  4 ++
 3 files changed, 83 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 3b05aea56d1f..11ed9152e665 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -433,7 +433,9 @@ static const struct clk_ops dpll4_m5x2_ck_ops = {
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.set_rate	= &omap3_clkoutx2_set_rate,
 	.recalc_rate	= &omap3_clkoutx2_recalc,
+	.round_rate	= &omap3_clkoutx2_round_rate,
 };
 
 static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 3185ced807c9..3c418ea54bbe 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -623,6 +623,32 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 
 /* Clock control for DPLL outputs */
 
+/* Find the parent DPLL for the given clkoutx2 clock */
+static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
+{
+	struct clk_hw_omap *pclk = NULL;
+	struct clk *parent;
+
+	/* Walk up the parents of clk, looking for a DPLL */
+	do {
+		do {
+			parent = __clk_get_parent(hw->clk);
+			hw = __clk_get_hw(parent);
+		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+		if (!hw)
+			break;
+		pclk = to_clk_hw_omap(hw);
+	} while (pclk && !pclk->dpll_data);
+
+	/* clk does not have a DPLL as a parent?  error in the clock data */
+	if (!pclk) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	return pclk;
+}
+
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
@@ -637,27 +663,14 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	unsigned long rate;
 	u32 v;
 	struct clk_hw_omap *pclk = NULL;
-	struct clk *parent;
 
 	if (!parent_rate)
 		return 0;
 
-	/* Walk up the parents of clk, looking for a DPLL */
-	do {
-		do {
-			parent = __clk_get_parent(hw->clk);
-			hw = __clk_get_hw(parent);
-		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
-		if (!hw)
-			break;
-		pclk = to_clk_hw_omap(hw);
-	} while (pclk && !pclk->dpll_data);
+	pclk = omap3_find_clkoutx2_dpll(hw);
 
-	/* clk does not have a DPLL as a parent?  error in the clock data */
-	if (!pclk) {
-		WARN_ON(1);
+	if (!pclk)
 		return 0;
-	}
 
 	dd = pclk->dpll_data;
 
@@ -672,6 +685,55 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 	return rate;
 }
 
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	return 0;
+}
+
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	const struct dpll_data *dd;
+	u32 v;
+	struct clk_hw_omap *pclk = NULL;
+
+	if (!*prate)
+		return 0;
+
+	pclk = omap3_find_clkoutx2_dpll(hw);
+
+	if (!pclk)
+		return 0;
+
+	dd = pclk->dpll_data;
+
+	/* TYPE J does not have a clkoutx2 */
+	if (dd->flags & DPLL_J_TYPE) {
+		*prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
+		return *prate;
+	}
+
+	WARN_ON(!dd->enable_mask);
+
+	v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+	v >>= __ffs(dd->enable_mask);
+
+	/* If in bypass, the rate is fixed to the bypass rate*/
+	if (v != OMAP3XXX_EN_DPLL_LOCKED)
+		return *prate;
+
+	if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent;
+
+		best_parent = (rate / 2);
+		*prate = __clk_round_rate(__clk_get_parent(hw->clk),
+				best_parent);
+	}
+
+	return *prate * 2;
+}
+
 /* OMAP3/4 non-CORE DPLL clkops */
 const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
 	.allow_idle	= omap3_dpll_allow_idle,
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 092b64168d7f..4a21a872dbbd 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -245,6 +245,10 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate);
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
-- 
1.8.3.2



-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140213/1f45fc18/attachment.sig>

^ permalink raw reply related


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