Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ARM: davinci: Remove DMA resources for MMC/SPI
From: Sekhar Nori @ 2016-10-01 17:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160928103530.15291-1-peter.ujfalusi@ti.com>

On Wednesday 28 September 2016 04:05 PM, Peter Ujfalusi wrote:
> Hi,
> 
> The drivers for davinci MMC and SPI have been converted to the new DMAengine API
> and no longer rely on the IORESOURCE_DMA.
> This is the case for at least one release cycle so now we can remove the
> IORESOURCE_DMA for these devices.

Hi Peter, applied to v4.10/cleanup branch of my tree. Thanks!

~Sekhar

^ permalink raw reply

* [RFC] arm64: Enforce observed order for spinlock and data
From: bdegraaf at codeaurora.org @ 2016-10-01 16:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930193231.GA2521@remoulade>

On 2016-09-30 15:32, Mark Rutland wrote:
> On Fri, Sep 30, 2016 at 01:40:57PM -0400, Brent DeGraaf wrote:
>> Prior spinlock code solely used load-acquire and store-release
>> semantics to ensure ordering of the spinlock lock and the area it
>> protects. However, store-release semantics and ordinary stores do
>> not protect against accesses to the protected area being observed
>> prior to the access that locks the lock itself.
>> 
>> While the load-acquire and store-release ordering is sufficient
>> when the spinlock routines themselves are strictly used, other
>> kernel code that references the lock values directly (e.g. lockrefs)
>> could observe changes to the area protected by the spinlock prior
>> to observance of the lock itself being in a locked state, despite
>> the fact that the spinlock logic itself is correct.
> 
> If the spinlock logic is correct, why are we changing that, and not the 
> lockref
> code that you say has a problem?
> 
> What exactly goes wrong in the lockref code? Can you give a concrete 
> example?
> 
> Why does the lockref code accesses lock-protected fields without taking 
> the
> lock first? Wouldn't concurrent modification be a problem regardless?
> 
>> +	/*
>> +	 * Yes: The store done on this cpu was the one that locked the lock.
>> +	 * Store-release one-way barrier on LL/SC means that accesses coming
>> +	 * after this could be reordered into the critical section of the
> 
> I assume you meant s/store-release/load-acquire/ here. This does not 
> make sense
> to me otherwise.
> 
>> +	 * load-acquire/store-release, where we did not own the lock. On 
>> LSE,
>> +	 * even the one-way barrier of the store-release semantics is 
>> missing,
> 
> Likewise (for the LSE case description).
> 
>> +	 * so LSE needs an explicit barrier here as well.  Without this, the
>> +	 * changed contents of the area protected by the spinlock could be
>> +	 * observed prior to the lock.
>> +	 */
> 
> By whom? We generally expect that if data is protected by a lock, you 
> take the
> lock before accessing it. If you expect concurrent lockless readers, 
> then
> there's a requirement on the writer side to explicitly provide the 
> ordering it
> requires -- spinlocks are not expected to provide that.
More details are in my response to Robin, but there is an API arm64 
supports
in spinlock.h which is used by lockref to determine whether a lock is 
free or not.
For that code to work properly without adding these barriers, that API 
needs to
take the lock.  I tested that configuration, and it cost us heavily in 
terms of
lockref performance in the form of a 30 to 50 percent performance loss.  
On the
other hand, I have not seen any performance degradation due to the 
introduction
of these barriers.

> 
> So, why aren't those observers taking the lock?

lockref doesn't take the lock specifically because it is slower.

> 
> What pattern of accesses are made by readers and writers such that 
> there is a
> problem?

I added the barriers to the readers/writers because I do not know these 
are not
similarly abused.  There is a lot of driver code out there, and ensuring 
order is
the safest way to be sure we don't get burned by something similar to 
the lockref
access.

> 
> What does this result in?
> 
No measureable negative performance impact.  However, the lockref 
performance actually
improved slightly (between 1 and 2 percent on my 24-core test system) 
due to the change.

>> +"	dmb	ish\n"
>> +"	b	3f\n"
>> +"4:\n"
>>  	/*
>>  	 * No: spin on the owner. Send a local event to avoid missing an
>>  	 * unlock before the exclusive load.
>> @@ -116,7 +129,15 @@ static inline void arch_spin_lock(arch_spinlock_t 
>> *lock)
>>  "	ldaxrh	%w2, %4\n"
>>  "	eor	%w1, %w2, %w0, lsr #16\n"
>>  "	cbnz	%w1, 2b\n"
>> -	/* We got the lock. Critical section starts here. */
>> +	/*
>> +	 * We got the lock and have observed the prior owner's 
>> store-release.
>> +	 * In this case, the one-way barrier of the prior owner that we
>> +	 * observed combined with the one-way barrier of our load-acquire is
>> +	 * enough to ensure accesses to the protected area coming after this
>> +	 * are not accessed until we own the lock.  In this case, other
>> +	 * observers will not see our changes prior to observing the lock
>> +	 * itself.  Critical locked section starts here.
>> +	 */
> 
> Each of these comments ends up covers, and their repeated presence 
> makes the
> code harder to read. If there's a common problem, note it once at the 
> top of
> the file.

I added these comments to make it crystal clear that the absence of a 
barrier at this
point was deliberate, and that I did consider each code path.

> 
> Thanks,
> Mark.

^ permalink raw reply

* [RFC] arm64: Enforce observed order for spinlock and data
From: bdegraaf at codeaurora.org @ 2016-10-01 15:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930190535.GB3142@twins.programming.kicks-ass.net>

On 2016-09-30 15:05, Peter Zijlstra wrote:
> On Fri, Sep 30, 2016 at 01:40:57PM -0400, Brent DeGraaf wrote:
>> Prior spinlock code solely used load-acquire and store-release
>> semantics to ensure ordering of the spinlock lock and the area it
>> protects. However, store-release semantics and ordinary stores do
>> not protect against accesses to the protected area being observed
>> prior to the access that locks the lock itself.
>> 
>> While the load-acquire and store-release ordering is sufficient
>> when the spinlock routines themselves are strictly used, other
>> kernel code that references the lock values directly (e.g. lockrefs)
> 
> Isn't the problem with lockref the fact that arch_spin_value_unlocked()
> isn't a load-acquire, and therefore the CPU in question doesn't need to
> observe the contents of the critical section etc..?
> 
> That is, wouldn't fixing arch_spin_value_unlocked() by making that an
> smp_load_acquire() fix things much better?
> 
>> could observe changes to the area protected by the spinlock prior
>> to observance of the lock itself being in a locked state, despite
>> the fact that the spinlock logic itself is correct.

Thanks for your comments.

The load-acquire would not be enough for lockref, as it can still 
observe
the changed data out of order. To ensure order, lockref has to take the
lock, which comes at a high performance cost.  Turning off the config
option CONFIG_ARCH_USE_CMPXCHG_LOCKREF, which forces arch_spin_lock 
calls
reduced my multicore performance between 30 and 50 percent using Linus'
"stat" test that was part of the grounds for introducing lockref.

On the other hand, I did not see any negative impact to performance by
the new barriers, in large part probably because they only tend to come
into play when locks are not heavily contended in the case of ticket
locks.

I have not yet found any other spinlock "abuses" in the kernel besides
lockref, but locks are referenced in a large number of places that
includes drivers, which are dynamic.  It is arguable that I could remove
the barriers to the read/write locks, as lockref doesn't use those, but
it seemed to me to be safer and more "normal" to ensure that the locked
write to the lock itself is visible prior to the changed contents of the
protected area.

Brent

^ permalink raw reply

* [RFC] arm64: Enforce observed order for spinlock and data
From: bdegraaf at codeaurora.org @ 2016-10-01 15:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <61567858-7224-c7af-5207-3872671b58ad@arm.com>

On 2016-09-30 14:43, Robin Murphy wrote:
>> +	 * so LSE needs an explicit barrier here as well.  Without this, the
>> +	 * changed contents of the area protected by the spinlock could be
>> +	 * observed prior to the lock.
> 
> What is that last sentence supposed to mean? If the lock is free, then
> surely any previous writes to the data it's protecting would have
> already been observed by the release semantics of the previous unlock?
> If the lock is currently held, what do we care about the state of the
> data while we're still spinning on the lock itself? And if someone's
> touching the data without having acquired *or* released the lock, why 
> is
> there a lock in the first place?
> 
> This seems like a very expensive way of papering over broken callers :/
> 
> Robin.
> 

Thanks for your question.

First off, I saw no negative impact to performance as a result of 
introducing
these barriers running a wide variety of use cases, both for mobile and
server-class devices ranging from 4 to 24 cpus.

Yes, it does protect lockref, which observes the spinlocks in a 
non-conventional
way.  In fact, with this code in place, the performance of Linus' test 
which runs
stat like crazy actually improved in the range of 1-2% (I suspect this 
is due to
fewer failures due to contention on the protected count lockref uses).

The lockref code can be made compliant, but not by a single 
load-acquire--it has
to take the lock.  Turning off CONFIG_ARCH_USE_CMPXCHG_LOCKREF is the 
most
obvious solution as it forces lockref.c to take the lock.  That, 
however, comes
at a very high performance cost: 30-50% on Linus' stat test on a 24-core 
system.
For larger systems, this performance gap will get even worse.

With the above in mind, it seems that supporting lockref's unorthodox 
method of
dealing with the lock is the better alternative, as it helps, rather 
than hurts,
arm64 performance.

Brent

^ permalink raw reply

* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
From: Sinan Kaya @ 2016-10-01 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001061906.GG2467@localhost>

On 10/1/2016 2:19 AM, Vinod Koul wrote:
>> Making it atomic so that it can be updated from multiple contexts.
> How is it multiple contexts? It's either existing context of MSI, not both!
> 

I was trying to mean multiple processor contexts here. The driver allocates 11
MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then, 
we have a race condition for common variables as they share the same interrupt
handler with a different cause bit. 

I will put the above description into the commit text.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
From: Sinan Kaya @ 2016-10-01 15:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001061710.GF2467@localhost>

On 10/1/2016 2:17 AM, Vinod Koul wrote:
> On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
>> Configure the DMA bindings for the device tree based firmware.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> ---
>>  drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
>> index 82f36e4..e8f6b84 100644
>> --- a/drivers/dma/qcom/hidma_mgmt.c
>> +++ b/drivers/dma/qcom/hidma_mgmt.c
>> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
>>  			ret = PTR_ERR(new_pdev);
>>  			goto out;
>>  		}
>> +		of_node_get(child);
>> +		new_pdev->dev.of_node = child;
>>  		of_dma_configure(&new_pdev->dev, child);
>> -
>> +		of_msi_configure(&new_pdev->dev, child);
>> +		of_node_put(child);
> 
> should this be done unconditionally? Dont we needto call this only for
> platforms with msi?

I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
side effects on my testing either.


> 
>>  		kfree(res);
>>  		res = NULL;
>>  	}
>> -- 
>> 1.9.1
>>
> 


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH] ARM: dts: rockchip: Reserve unusable memory region on rk3066
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2016-10-01 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

For some reason accessing memory region above 0xfe000000 freezes
system on rk3066. There is similiar bug on later rockchip soc (rk3288)
solved same way.

Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
---
 arch/arm/boot/dts/rk3066a.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 0d0dae3..44c8956 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -93,6 +93,19 @@
 		};
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		/*
+		 * The rk3066 cannot use the memory area above 0x9F000000
+		 * for some unknown reason.
+		 */
+		unusable at 9F000000 {
+			reg = <0x9F000000 0x1000000>;
+		};
+	};
+
 	i2s0: i2s at 10118000 {
 		compatible = "rockchip,rk3066-i2s";
 		reg = <0x10118000 0x2000>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 5/6] ARM: davinci: enable the LCDC DRM driver in defconfig
From: Sekhar Nori @ 2016-10-01 12:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475166715-7857-6-git-send-email-bgolaszewski@baylibre.com>

On Thursday 29 September 2016 10:01 PM, Bartosz Golaszewski wrote:
> With the device tree changes for tilcdc in place, we can now enable
> the driver by default in the davinci_all defconfig file.
> 
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Applied to v4.10/defconfig branch of my tree. Adjusted the subject line
to be consistent with how patches for defconfig are usually headlines.

ARM: davinci_all_defconfig: enable LCDC DRM driver

defconfig updates are last in the pull request I will send up, so the
description will make sense when finally merged.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v3 3/3] phy: meson: add USB2 PHY support for Meson8b and GXBB
From: Martin Blumenstingl @ 2016-10-01 12:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001121900.1168-1-martin.blumenstingl@googlemail.com>

This is a new driver for the USB PHY found in Meson8b and GXBB SoCs.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
---
 drivers/phy/Kconfig            |  13 ++
 drivers/phy/Makefile           |   1 +
 drivers/phy/phy-meson8b-usb2.c | 284 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 298 insertions(+)
 create mode 100644 drivers/phy/phy-meson8b-usb2.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19bff3a..b0c8135 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -453,4 +453,17 @@ config PHY_NS2_PCIE
 	help
 	  Enable this to support the Broadcom Northstar2 PCIe PHY.
 	  If unsure, say N.
+
+config PHY_MESON8B_USB2
+	tristate "Meson8b and GXBB USB2 PHY driver"
+	default ARCH_MESON
+	depends on OF && (ARCH_MESON || COMPILE_TEST)
+	depends on USB_SUPPORT
+	select USB_COMMON
+	select GENERIC_PHY
+	help
+	  Enable this to support the Meson USB2 PHYs found in Meson8b
+	  and GXBB SoCs.
+	  If unsure, say N.
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 90ae198..5649473 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -56,3 +56,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
 obj-$(CONFIG_ARCH_TEGRA) += tegra/
 obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
+obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/phy-meson8b-usb2.c
new file mode 100644
index 0000000..73bf632
--- /dev/null
+++ b/drivers/phy/phy-meson8b-usb2.c
@@ -0,0 +1,284 @@
+/*
+ * Meson8b and GXBB USB2 PHY driver
+ *
+ * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb/of.h>
+
+#define REG_CONFIG					0x00
+	#define REG_CONFIG_CLK_EN			BIT(0)
+	#define REG_CONFIG_CLK_SEL_MASK			GENMASK(3, 1)
+	#define REG_CONFIG_CLK_DIV_MASK			GENMASK(10, 4)
+	#define REG_CONFIG_CLK_32k_ALTSEL		BIT(15)
+	#define REG_CONFIG_TEST_TRIG			BIT(31)
+
+#define REG_CTRL					0x04
+	#define REG_CTRL_SOFT_PRST			BIT(0)
+	#define REG_CTRL_SOFT_HRESET			BIT(1)
+	#define REG_CTRL_SS_SCALEDOWN_MODE_MASK		GENMASK(3, 2)
+	#define REG_CTRL_CLK_DET_RST			BIT(4)
+	#define REG_CTRL_INTR_SEL			BIT(5)
+	#define REG_CTRL_CLK_DETECTED			BIT(8)
+	#define REG_CTRL_SOF_SENT_RCVD_TGL		BIT(9)
+	#define REG_CTRL_SOF_TOGGLE_OUT			BIT(10)
+	#define REG_CTRL_POWER_ON_RESET			BIT(15)
+	#define REG_CTRL_SLEEPM				BIT(16)
+	#define REG_CTRL_TX_BITSTUFF_ENN_H		BIT(17)
+	#define REG_CTRL_TX_BITSTUFF_ENN		BIT(18)
+	#define REG_CTRL_COMMON_ON			BIT(19)
+	#define REG_CTRL_REF_CLK_SEL_MASK		GENMASK(21, 20)
+	#define REG_CTRL_REF_CLK_SEL_SHIFT		20
+	#define REG_CTRL_FSEL_MASK			GENMASK(24, 22)
+	#define REG_CTRL_FSEL_SHIFT			22
+	#define REG_CTRL_PORT_RESET			BIT(25)
+	#define REG_CTRL_THREAD_ID_MASK			GENMASK(31, 26)
+
+#define REG_ENDP_INTR					0x08
+
+/* bits [31:26], [24:21] and [15:3] seem to be read-only */
+#define REG_ADP_BC					0x0c
+	#define REG_ADP_BC_VBUS_VLD_EXT_SEL		BIT(0)
+	#define REG_ADP_BC_VBUS_VLD_EXT			BIT(1)
+	#define REG_ADP_BC_OTG_DISABLE			BIT(2)
+	#define REG_ADP_BC_ID_PULLUP			BIT(3)
+	#define REG_ADP_BC_DRV_VBUS			BIT(4)
+	#define REG_ADP_BC_ADP_PRB_EN			BIT(5)
+	#define REG_ADP_BC_ADP_DISCHARGE		BIT(6)
+	#define REG_ADP_BC_ADP_CHARGE			BIT(7)
+	#define REG_ADP_BC_SESS_END			BIT(8)
+	#define REG_ADP_BC_DEVICE_SESS_VLD		BIT(9)
+	#define REG_ADP_BC_B_VALID			BIT(10)
+	#define REG_ADP_BC_A_VALID			BIT(11)
+	#define REG_ADP_BC_ID_DIG			BIT(12)
+	#define REG_ADP_BC_VBUS_VALID			BIT(13)
+	#define REG_ADP_BC_ADP_PROBE			BIT(14)
+	#define REG_ADP_BC_ADP_SENSE			BIT(15)
+	#define REG_ADP_BC_ACA_ENABLE			BIT(16)
+	#define REG_ADP_BC_DCD_ENABLE			BIT(17)
+	#define REG_ADP_BC_VDAT_DET_EN_B		BIT(18)
+	#define REG_ADP_BC_VDAT_SRC_EN_B		BIT(19)
+	#define REG_ADP_BC_CHARGE_SEL			BIT(20)
+	#define REG_ADP_BC_CHARGE_DETECT		BIT(21)
+	#define REG_ADP_BC_ACA_PIN_RANGE_C		BIT(22)
+	#define REG_ADP_BC_ACA_PIN_RANGE_B		BIT(23)
+	#define REG_ADP_BC_ACA_PIN_RANGE_A		BIT(24)
+	#define REG_ADP_BC_ACA_PIN_GND			BIT(25)
+	#define REG_ADP_BC_ACA_PIN_FLOAT		BIT(26)
+
+#define REG_DBG_UART					0x14
+
+#define REG_TEST					0x18
+	#define REG_TEST_DATA_IN_MASK			GENMASK(3, 0)
+	#define REG_TEST_EN_MASK			GENMASK(7, 4)
+	#define REG_TEST_ADDR_MASK			GENMASK(11, 8)
+	#define REG_TEST_DATA_OUT_SEL			BIT(12)
+	#define REG_TEST_CLK				BIT(13)
+	#define REG_TEST_VA_TEST_EN_B_MASK		GENMASK(15, 14)
+	#define REG_TEST_DATA_OUT_MASK			GENMASK(19, 16)
+	#define REG_TEST_DISABLE_ID_PULLUP		BIT(20)
+
+#define REG_TUNE					0x1c
+	#define REG_TUNE_TX_RES_TUNE_MASK		GENMASK(1, 0)
+	#define REG_TUNE_TX_HSXV_TUNE_MASK		GENMASK(3, 2)
+	#define REG_TUNE_TX_VREF_TUNE_MASK		GENMASK(7, 4)
+	#define REG_TUNE_TX_RISE_TUNE_MASK		GENMASK(9, 8)
+	#define REG_TUNE_TX_PREEMP_PULSE_TUNE		BIT(10)
+	#define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK	GENMASK(12, 11)
+	#define REG_TUNE_TX_FSLS_TUNE_MASK		GENMASK(16, 13)
+	#define REG_TUNE_SQRX_TUNE_MASK			GENMASK(19, 17)
+	#define REG_TUNE_OTG_TUNE			GENMASK(22, 20)
+	#define REG_TUNE_COMP_DIS_TUNE			GENMASK(25, 23)
+	#define REG_TUNE_HOST_DM_PULLDOWN		BIT(26)
+	#define REG_TUNE_HOST_DP_PULLDOWN		BIT(27)
+
+#define RESET_COMPLETE_TIME				500
+#define ACA_ENABLE_COMPLETE_TIME			50
+
+struct phy_meson8b_usb2_priv {
+	void __iomem		*regs;
+	enum usb_dr_mode	dr_mode;
+	struct clk		*clk_usb_general;
+	struct clk		*clk_usb;
+	struct reset_control	*reset;
+};
+
+static u32 phy_meson8b_usb2_read(struct phy_meson8b_usb2_priv *phy_priv,
+				 u32 reg)
+{
+	return readl(phy_priv->regs + reg);
+}
+
+static void phy_meson8b_usb2_mask_bits(struct phy_meson8b_usb2_priv *phy_priv,
+				       u32 reg, u32 mask, u32 value)
+{
+	u32 data;
+
+	data = phy_meson8b_usb2_read(phy_priv, reg);
+	data &= ~mask;
+	data |= (value & mask);
+
+	writel(data, phy_priv->regs + reg);
+}
+
+static int phy_meson8b_usb2_power_on(struct phy *phy)
+{
+	struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	if (!IS_ERR_OR_NULL(priv->reset)) {
+		ret = reset_control_reset(priv->reset);
+		if (ret) {
+			dev_err(&phy->dev, "Failed to trigger USB reset\n");
+			return ret;
+		}
+	}
+
+	ret = clk_prepare_enable(priv->clk_usb_general);
+	if (ret) {
+		dev_err(&phy->dev, "Failed to enable USB general clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(priv->clk_usb);
+	if (ret) {
+		dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
+		return ret;
+	}
+
+	phy_meson8b_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
+				   REG_CONFIG_CLK_32k_ALTSEL);
+
+	phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
+				   0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
+
+	phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK,
+				   0x5 << REG_CTRL_FSEL_SHIFT);
+
+	/* reset the PHY */
+	phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET,
+				   REG_CTRL_POWER_ON_RESET);
+	udelay(RESET_COMPLETE_TIME);
+	phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
+	udelay(RESET_COMPLETE_TIME);
+
+	phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
+				   REG_CTRL_SOF_TOGGLE_OUT);
+
+	if (priv->dr_mode == USB_DR_MODE_HOST) {
+		phy_meson8b_usb2_mask_bits(priv, REG_ADP_BC,
+					   REG_ADP_BC_ACA_ENABLE,
+					   REG_ADP_BC_ACA_ENABLE);
+
+		udelay(ACA_ENABLE_COMPLETE_TIME);
+
+		if (phy_meson8b_usb2_read(priv, REG_ADP_BC) &
+			REG_ADP_BC_ACA_PIN_FLOAT) {
+			dev_warn(&phy->dev, "USB ID detect failed!\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int phy_meson8b_usb2_power_off(struct phy *phy)
+{
+	struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
+
+	clk_disable_unprepare(priv->clk_usb);
+	clk_disable_unprepare(priv->clk_usb_general);
+
+	return 0;
+}
+
+static const struct phy_ops phy_meson8b_usb2_ops = {
+	.power_on	= phy_meson8b_usb2_power_on,
+	.power_off	= phy_meson8b_usb2_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int phy_meson8b_usb2_probe(struct platform_device *pdev)
+{
+	struct phy_meson8b_usb2_priv *priv;
+	struct resource *res;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
+	if (IS_ERR(priv->clk_usb_general))
+		return PTR_ERR(priv->clk_usb_general);
+
+	priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
+	if (IS_ERR(priv->clk_usb))
+		return PTR_ERR(priv->clk_usb);
+
+	priv->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
+								NULL);
+	if (PTR_ERR(priv->reset) == -EPROBE_DEFER)
+		return PTR_ERR(priv->reset);
+
+	priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
+	if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+		dev_err(&pdev->dev,
+			"missing dual role configuration of the controller\n");
+		return -EINVAL;
+	}
+
+	phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
+	if (IS_ERR(phy)) {
+		dev_err(&pdev->dev, "failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	phy_set_drvdata(phy, priv);
+
+	phy_provider =
+		devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson8b_usb2_of_match[] = {
+	{ .compatible = "amlogic,meson8b-usb2-phy", },
+	{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
+
+static struct platform_driver phy_meson8b_usb2_driver = {
+	.probe	= phy_meson8b_usb2_probe,
+	.driver	= {
+		.name		= "phy-meson-usb2",
+		.of_match_table	= phy_meson8b_usb2_of_match,
+	},
+};
+module_platform_driver(phy_meson8b_usb2_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
+MODULE_LICENSE("GPL");
-- 
2.10.0

^ permalink raw reply related

* [PATCH v3 2/3] Documentation: dt-bindings: rename meson-usb2-phy to meson8b-usb2-phy
From: Martin Blumenstingl @ 2016-10-01 12:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001121900.1168-1-martin.blumenstingl@googlemail.com>

The corresponding driver only supports the USB PHY on Meson8b and GXBB
SoCs. Newer SoC versions are using a different USB PHY implementation,
which will mean that a new driver is required. Thus make sure that our
naming is specific enough so it does not conflict with upcoming drivers.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 .../bindings/phy/{meson-usb2-phy.txt => meson8b-usb2-phy.txt}           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename Documentation/devicetree/bindings/phy/{meson-usb2-phy.txt => meson8b-usb2-phy.txt} (95%)

diff --git a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt b/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt
similarity index 95%
rename from Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
rename to Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt
index bc616c1..5fa73b9 100644
--- a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
+++ b/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt
@@ -1,4 +1,4 @@
-* Amlogic USB2 PHY
+* Amlogic Meson8b and GXBB USB2 PHY
 
 Required properties:
 - compatible:	Depending on the platform this should be one of:
-- 
2.10.0

^ permalink raw reply related

* [PATCH v3 1/3] Documentation: dt-bindings: update the meson-usb2-phy example
From: Martin Blumenstingl @ 2016-10-01 12:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001121900.1168-1-martin.blumenstingl@googlemail.com>

Update the example so the node name uses a dash (instead of an
underscore) as per convention.
Additionally it updates the example register offset to a real example
(the old value was taken from a draft where there was an additional PHY
bus).

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 Documentation/devicetree/bindings/phy/meson-usb2-phy.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt b/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
index 9da5ea2..bc616c1 100644
--- a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
+++ b/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
@@ -16,10 +16,10 @@ Optional properties:
 
 Example:
 
-usb0_phy: usb_phy at 0 {
+usb0_phy: usb-phy at c0000000 {
 	compatible = "amlogic,meson-gxbb-usb2-phy";
 	#phy-cells = <0>;
-	reg = <0x0 0x0 0x0 0x20>;
+	reg = <0x0 0xc0000000 0x0 0x20>;
 	resets = <&reset RESET_USB_OTG>;
 	clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
 	clock-names = "usb_general", "usb";
-- 
2.10.0

^ permalink raw reply related

* [PATCH v3 0/3] usb/phy: Add Amlogic Meson8b and GXBB USB support
From: Martin Blumenstingl @ 2016-10-01 12:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160904213152.25837-1-martin.blumenstingl@googlemail.com>

This series adds initial support for the DWC2 USB controllers and Meson
specific USB PHYs found in Meson8b and GXBB SoCs, which means:
- new DWC2 bindings and platform specific core configuration
- a PHY driver supporting the USB2 PHY on Meson8b and GXBB SoCs

The first DWC2 controller is usually configured in OTG mode, whereas
the second DWC2 controller is usually configured in host(-only) mode.

Unfortunately no (public) datasheet is available and the reference PHY
driver does not contain comments or speaking register name definitions.
The nice people from BayLibre have already requested the datasheets
(currently we can for example only guess that there is a mux clock
inside the PHY, but we don't know it's parents).

With this series both DWC2 controllers are configure in host mode,
because the reference driver polls some of the PHY registers in OTG
mode and then re-configures the dwc2 driver instance accordingly (if
anyone is interested, this is the relevant piece of code: [0]). This
seems good enough for the beginning though.


Changes since v2:
- integrated a patch from Axel Lin to add the USB_SUPPORT dependency
- renamed driver (Kconfig, source and docs) to phy-meson8b-usb2 as the
  driver is only compatible with the USB2 PHY found on Meson8b and GXBB
  (newer SoC versions are using a different USB PHY and I could not
  find anything that the Meson8b / GXBB and GXL / GXM USB PHYs have in
  common)
- switch from device_reset_optional to reset_control_reset and move
  this call to phy_meson8b_usb2_power_on. This will allow us to simply
  switch to devm_reset_control_get_optional_shared in the future, once
  the reset control supports reset pulses for shared reset lines
- updated documentation example (use dash instead of unserscore in node
  name and use a better reg example)
- dropped the following patches as they were accepted upstream (the
  only patch which remains from the original series is the actual PHY
  driver):
  - "usb: dwc2: add support for Meson8b and GXBB SoCs" (f94310ac076e in
    arm-soc.git/next/late)
  - "Documentation: dt-bindings: Add documentation for the Meson USB2
    PHYs" (c940d7658de0 in arm-soc.git/next/late)
  - "ARM64: meson-gxbb: add USB Nodes" (566603e5e6b6 in
    arm-soc.git/next/late)
  - "ARM64: meson-gxbb-p20x: Enable USB Nodes" (8735053d7968 in
    arm-soc.git/next/late)
  - "ARM64: meson-gxbb-vega-s95: Enable USB Nodes" (c763eb82a01d in
    arm-soc.git/next/late)

Changes since v1:
- the patch "clk: gxbb: expose USB clocks" was not sent again as it was
  already applied by Kevin Hilman (thanks!)
- dropped (unnecessary) USB PHY bus from .dts
- remove underscores from PHY node names in .dts
- rename the dwc2 nodes in the .dts to usb (as per convention)
- remove unused struct reset_control from phy_meson_usb2_priv
- removed refcounting "reset" workaround and only specify the reset for
  the first PHY in the .dts (Jerome has reported that his boards don't
  need the explicit reset, while my board needs it). In addition (to
  make this work) the driver now treats the reset as optional
- use the RESET_USB_OTG definition (from
  <dt-bindings/reset/amlogic,meson-gxbb-reset.h>) instead of a magic
  number in the .dts


[0] https://github.com/150balbes/Amlogic_s905-kernel/blob/master/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c#L642

Martin Blumenstingl (3):
  Documentation: dt-bindings: update the meson-usb2-phy example
  Documentation: dt-bindings: rename meson-usb2-phy to meson8b-usb2-phy
  phy: meson: add USB2 PHY support for Meson8b and GXBB

 .../{meson-usb2-phy.txt => meson8b-usb2-phy.txt}   |   6 +-
 drivers/phy/Kconfig                                |  13 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-meson8b-usb2.c                     | 284 +++++++++++++++++++++
 4 files changed, 301 insertions(+), 3 deletions(-)
 rename Documentation/devicetree/bindings/phy/{meson-usb2-phy.txt => meson8b-usb2-phy.txt} (87%)
 create mode 100644 drivers/phy/phy-meson8b-usb2.c

-- 
2.10.0

^ permalink raw reply

* [PATCH RFC v2 0/12] Add R8A7743/SK-RZG1M board support
From: Geert Uytterhoeven @ 2016-10-01 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1987532.PE2ex6PrJ5@wasted.cogentembedded.com>

Hi Sergei,

On Fri, Sep 30, 2016 at 12:14 AM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
>    Here's the set of 12 patches against Simon Horman's 'renesas.git' repo,
> 'renesas-devel-20160926-v4.8-rc8' tag. I'm adding the device tree support for
> the R8A7743-based SK-RZG1M board. The SoC is close to R8A7791 and the board
> seems  identical to the R8A7791/Porter board. This version includes the Ether,
> so the board should boot with NFS root now. I tried to address all the comments
> to the version 1 (except the need to use the new CPG/MSSR drivers -- this one
> will be addressed RSN). The DMAC/SCIF/IRQC bindings patches posted recently are

There's an (old) version of an r8a7791 CPG/MSSR driver at
https://git.kernel.org/cgit/linux/kernel/git/geert/renesas-drivers.git/log/?h=topic/cpg-mssr-v4

To handle it cleanly, this is going to need "[PATCH/RFC v3 00/22] soc:
renesas: Add R-Car RST driver for obtaining mode pin state"...

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH v2 6/6] arm: dts: imx7-colibri: Use enable-gpios for BL_ON
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

Use pwm-backlight driver 'enable-gpios' property for backlight on/off control.

Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
---
 arch/arm/boot/dts/imx7-colibri.dtsi | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index 2af5e3e..ce5edb5 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -43,7 +43,10 @@
 / {
 	bl: backlight {
 		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_bl_on>;
 		pwms = <&pwm1 0 5000000 0>;
+		enable-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	reg_module_3v3: regulator-module-3v3 {
@@ -356,7 +359,6 @@
 		fsl,pins = <
 			MX7D_PAD_ECSPI2_SS0__GPIO4_IO23		0x14 /* SODIMM 65 */
 			MX7D_PAD_SD1_CD_B__GPIO5_IO0		0x14 /* SODIMM 69 */
-			MX7D_PAD_SD1_WP__GPIO5_IO1		0x14 /* SODIMM 71 */
 			MX7D_PAD_I2C4_SDA__GPIO4_IO15		0x14 /* SODIMM 75 */
 			MX7D_PAD_ECSPI1_MISO__GPIO4_IO18	0x14 /* SODIMM 79 */
 			MX7D_PAD_I2C3_SCL__GPIO4_IO12		0x14 /* SODIMM 81 */
@@ -388,6 +390,12 @@
 		>;
 	};
 
+		pinctrl_gpio_bl_on: gpio-bl-on {
+			fsl,pins = <
+				MX7D_PAD_SD1_WP__GPIO5_IO1		0x14
+			>;
+		};
+
 	pinctrl_i2c1_int: i2c1-int-grp { /* PMIC / TOUCH */
 		fsl,pins = <
 			MX7D_PAD_GPIO1_IO13__GPIO1_IO13	0x79
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 5/6] arm: dts: imx7-colibri: Use pwm polarity control
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

Configure PWM polarity control.

Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
---
 arch/arm/boot/dts/imx7-colibri.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index a9cc657..2af5e3e 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -43,7 +43,7 @@
 / {
 	bl: backlight {
 		compatible = "pwm-backlight";
-		pwms = <&pwm1 0 5000000>;
+		pwms = <&pwm1 0 5000000 0>;
 	};
 
 	reg_module_3v3: regulator-module-3v3 {
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 4/6] arm: dts: imx7: Update #pwm-cells for PWM polarity control
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

Update #pwm-cells to 3 in order to support PWM signal polarity control.

Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 arch/arm/boot/dts/imx7s.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 0d7d5ac..8d1d471 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -601,7 +601,7 @@
 				clocks = <&clks IMX7D_PWM1_ROOT_CLK>,
 					 <&clks IMX7D_PWM1_ROOT_CLK>;
 				clock-names = "ipg", "per";
-				#pwm-cells = <2>;
+				#pwm-cells = <3>;
 				status = "disabled";
 			};
 
@@ -612,7 +612,7 @@
 				clocks = <&clks IMX7D_PWM2_ROOT_CLK>,
 					 <&clks IMX7D_PWM2_ROOT_CLK>;
 				clock-names = "ipg", "per";
-				#pwm-cells = <2>;
+				#pwm-cells = <3>;
 				status = "disabled";
 			};
 
@@ -623,7 +623,7 @@
 				clocks = <&clks IMX7D_PWM3_ROOT_CLK>,
 					 <&clks IMX7D_PWM3_ROOT_CLK>;
 				clock-names = "ipg", "per";
-				#pwm-cells = <2>;
+				#pwm-cells = <3>;
 				status = "disabled";
 			};
 
@@ -634,7 +634,7 @@
 				clocks = <&clks IMX7D_PWM4_ROOT_CLK>,
 					 <&clks IMX7D_PWM4_ROOT_CLK>;
 				clock-names = "ipg", "per";
-				#pwm-cells = <2>;
+				#pwm-cells = <3>;
 				status = "disabled";
 			};
 
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 3/6] pwm: imx: support output polarity inversion
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

From: Lothar Wassmann <LW@KARO-electronics.de>

The i.MX pwm unit on i.MX27 and newer SoCs provides a configurable output
polarity. This patch adds support to utilize this feature where available.

Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 Documentation/devicetree/bindings/pwm/imx-pwm.txt |  6 +--
 drivers/pwm/pwm-imx.c                             | 51 +++++++++++++++++++++--
 2 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
index e00c2e9..c61bdf8 100644
--- a/Documentation/devicetree/bindings/pwm/imx-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
@@ -6,8 +6,8 @@ Required properties:
   - "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
   - "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
 - reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
-  the cells format.
+- #pwm-cells: 2 for i.MX1 and 3 for i.MX27 and newer SoCs. See pwm.txt
+  in this directory for a description of the cells format.
 - clocks : Clock specifiers for both ipg and per clocks.
 - clock-names : Clock names should include both "ipg" and "per"
 See the clock consumer binding,
@@ -17,7 +17,7 @@ See the clock consumer binding,
 Example:
 
 pwm1: pwm at 53fb4000 {
-	#pwm-cells = <2>;
+	#pwm-cells = <3>;
 	compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
 	reg = <0x53fb4000 0x4000>;
 	clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index d600fd5..c37d223 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -38,6 +38,7 @@
 #define MX3_PWMCR_DOZEEN		(1 << 24)
 #define MX3_PWMCR_WAITEN		(1 << 23)
 #define MX3_PWMCR_DBGEN			(1 << 22)
+#define MX3_PWMCR_POUTC			(1 << 18)
 #define MX3_PWMCR_CLKSRC_IPG_HIGH	(2 << 16)
 #define MX3_PWMCR_CLKSRC_IPG		(1 << 16)
 #define MX3_PWMCR_SWR			(1 << 3)
@@ -180,6 +181,9 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
 	if (enable)
 		cr |= MX3_PWMCR_EN;
 
+	if (pwm->args.polarity == PWM_POLARITY_INVERSED)
+		cr |= MX3_PWMCR_POUTC;
+
 	writel(cr, imx->mmio_base + MX3_PWMCR);
 
 	return 0;
@@ -240,27 +244,62 @@ static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	clk_disable_unprepare(imx->clk_per);
 }
 
-static struct pwm_ops imx_pwm_ops = {
+static int imx_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+				enum pwm_polarity polarity)
+{
+	struct imx_chip *imx = to_imx_chip(chip);
+	u32 val;
+
+	if (polarity == pwm->args.polarity)
+		return 0;
+
+	val = readl(imx->mmio_base + MX3_PWMCR);
+
+	if (polarity == PWM_POLARITY_INVERSED)
+		val |= MX3_PWMCR_POUTC;
+	else
+		val &= ~MX3_PWMCR_POUTC;
+
+	writel(val, imx->mmio_base + MX3_PWMCR);
+
+	dev_dbg(imx->chip.dev, "%s: polarity set to %s\n", __func__,
+		polarity == PWM_POLARITY_INVERSED ? "inverted" : "normal");
+
+	return 0;
+}
+
+static struct pwm_ops imx_pwm_ops_v1 = {
 	.enable = imx_pwm_enable,
 	.disable = imx_pwm_disable,
 	.config = imx_pwm_config,
 	.owner = THIS_MODULE,
 };
 
+static struct pwm_ops imx_pwm_ops_v2 = {
+	.enable = imx_pwm_enable,
+	.disable = imx_pwm_disable,
+	.set_polarity = imx_pwm_set_polarity,
+	.config = imx_pwm_config,
+	.owner = THIS_MODULE,
+};
+
 struct imx_pwm_data {
 	int (*config)(struct pwm_chip *chip,
 		struct pwm_device *pwm, int duty_ns, int period_ns);
 	void (*set_enable)(struct pwm_chip *chip, bool enable);
+	struct pwm_ops *pwm_ops;
 };
 
 static struct imx_pwm_data imx_pwm_data_v1 = {
 	.config = imx_pwm_config_v1,
 	.set_enable = imx_pwm_set_enable_v1,
+	.pwm_ops = &imx_pwm_ops_v1,
 };
 
 static struct imx_pwm_data imx_pwm_data_v2 = {
 	.config = imx_pwm_config_v2,
 	.set_enable = imx_pwm_set_enable_v2,
+	.pwm_ops = &imx_pwm_ops_v2,
 };
 
 static const struct of_device_id imx_pwm_dt_ids[] = {
@@ -282,6 +321,8 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	if (!of_id)
 		return -ENODEV;
 
+	data = of_id->data;
+
 	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
 	if (imx == NULL)
 		return -ENOMEM;
@@ -300,18 +341,22 @@ static int imx_pwm_probe(struct platform_device *pdev)
 		return PTR_ERR(imx->clk_ipg);
 	}
 
-	imx->chip.ops = &imx_pwm_ops;
+	imx->chip.ops = data->pwm_ops;
 	imx->chip.dev = &pdev->dev;
 	imx->chip.base = -1;
 	imx->chip.npwm = 1;
 	imx->chip.can_sleep = true;
+	if (data->pwm_ops->set_polarity) {
+		dev_dbg(&pdev->dev, "PWM supports output inversion\n");
+		imx->chip.of_xlate = of_pwm_xlate_with_flags;
+		imx->chip.of_pwm_n_cells = 3;
+	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(imx->mmio_base))
 		return PTR_ERR(imx->mmio_base);
 
-	data = of_id->data;
 	imx->config = data->config;
 	imx->set_enable = data->set_enable;
 
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 2/6] pwm: core: make the PWM_POLARITY flag in DTB optional
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

From: Lothar Wassmann <LW@KARO-electronics.de>

Change the pwm chip driver registration, so that a chip driver that supports
polarity inversion can still be used with DTBs that don't provide the
'PWM_POLARITY' flag.

This is done to provide polarity inversion support for the pwm-imx driver
without having to modify all existing DTS files.

Signed-off-by: Lothar Wassmann <LW@KARO-electronics.de>
Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
Suggested-by: Thierry Reding <thierry.reding@gmail.com>
---
 drivers/pwm/core.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 195373e..aae8db3 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -137,9 +137,14 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
 	struct pwm_device *pwm;
 
+	/* check, whether the driver supports a third cell for flags */
 	if (pc->of_pwm_n_cells < 3)
 		return ERR_PTR(-EINVAL);
 
+	/* flags in the third cell are optional */
+	if (args->args_count < 2)
+		return ERR_PTR(-EINVAL);
+
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
@@ -149,10 +154,12 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 
 	pwm->args.period = args->args[1];
 
-	if (args->args[2] & PWM_POLARITY_INVERTED)
-		pwm->args.polarity = PWM_POLARITY_INVERSED;
-	else
-		pwm->args.polarity = PWM_POLARITY_NORMAL;
+	if (args->args_count > 2) {
+		if (args->args[2] & PWM_POLARITY_INVERTED)
+			pwm_set_polarity(pwm, PWM_POLARITY_INVERSED);
+		else
+			pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);
+	}
 
 	return pwm;
 }
@@ -163,9 +170,14 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
 	struct pwm_device *pwm;
 
+	/* sanity check driver support */
 	if (pc->of_pwm_n_cells < 2)
 		return ERR_PTR(-EINVAL);
 
+	/* all cells are required */
+	if (args->args_count != pc->of_pwm_n_cells)
+		return ERR_PTR(-EINVAL);
+
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
@@ -672,13 +684,6 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id)
 		goto put;
 	}
 
-	if (args.args_count != pc->of_pwm_n_cells) {
-		pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name,
-			 args.np->full_name);
-		pwm = ERR_PTR(-EINVAL);
-		goto put;
-	}
-
 	pwm = pc->of_xlate(pc, &args);
 	if (IS_ERR(pwm))
 		goto put;
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 1/6] pwm: print error messages with pr_err() instead of pr_debug()
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-1-bhuvanchandra.dv@toradex.com>

From: Lothar Wassmann <LW@KARO-electronics.de>

Make the messages that are printed in case of fatal errors actually visible to
the user without having to recompile the driver with debugging enabled.

Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
---
 drivers/pwm/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 0dbd29e..195373e 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -661,13 +661,13 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id)
 	err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index,
 					 &args);
 	if (err) {
-		pr_debug("%s(): can't parse \"pwms\" property\n", __func__);
+		pr_err("%s(): can't parse \"pwms\" property\n", __func__);
 		return ERR_PTR(err);
 	}
 
 	pc = of_node_to_pwmchip(args.np);
 	if (IS_ERR(pc)) {
-		pr_debug("%s(): PWM chip not found\n", __func__);
+		pr_err("%s(): PWM chip not found\n", __func__);
 		pwm = ERR_CAST(pc);
 		goto put;
 	}
-- 
2.9.2

^ permalink raw reply related

* [PATCH v2 0/6] Support PWM polarity control
From: Bhuvanchandra DV @ 2016-10-01 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Changes since v2:

- Picked the stalled patchset[1] from Lothar Wassmann which adds the basic
  support for polarity control on imx-pwm driver and adds backward compatibility
  support for devices which does not have polarity control feature.

Changes since Lothars v6:

- Squash Lukasz patch[2].

[1] http://thread.gmane.org/gmane.linux.pwm/1621
[2] https://www.spinics.net/lists/arm-kernel/msg530818.html

Bhuvanchandra DV (3):
  arm: dts: imx7: Update #pwm-cells for PWM polarity control
  arm: dts: imx7-colibri: Use pwm polarity control
  arm: dts: imx7-colibri: Use enable-gpios for BL_ON

Lothar Wassmann (3):
  pwm: print error messages with pr_err() instead of pr_debug()
  pwm: core: make the PWM_POLARITY flag in DTB optional
  pwm: imx: support output polarity inversion

 Documentation/devicetree/bindings/pwm/imx-pwm.txt |  6 +--
 arch/arm/boot/dts/imx7-colibri.dtsi               | 12 +++++-
 arch/arm/boot/dts/imx7s.dtsi                      |  8 ++--
 drivers/pwm/core.c                                | 31 ++++++++------
 drivers/pwm/pwm-imx.c                             | 51 +++++++++++++++++++++--
 5 files changed, 83 insertions(+), 25 deletions(-)

-- 
2.9.2

^ permalink raw reply

* [PATCH 4/6] ARM: dts: da850-lcdk: add support for 1024x768 resolution
From: Sekhar Nori @ 2016-10-01  9:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMpxmJX25Yx0Rget4bOUf+t2qn01bpbNGBwwVFfomK1h_2Oydg@mail.gmail.com>

On Friday 30 September 2016 07:18 PM, Bartosz Golaszewski wrote:
> 2016-09-30 14:49 GMT+02:00 Karl Beldan <karl.beldan@gmail.com>:
>> On Fri, Sep 30, 2016 at 11:37:57AM +0200, Bartosz Golaszewski wrote:
>>> 2016-09-29 20:58 GMT+02:00 Karl Beldan <karl.beldan@gmail.com>:
>>>> Hi,
>>>>
>>>> On Thu, Sep 29, 2016 at 06:31:53PM +0200, Bartosz Golaszewski wrote:
>>>>> Add svga timings for 1024x768 resolution to the da850-lcdk
>>>>> device tree.
>>>>>
>>>>
>>>
>>> [snip]
>>>
>>>>
>>>> Why do you also call 1024x768 svga ?
>>>>
>>>
>>> Thanks, should have been xga. will fix in v2.
>>>
>>>> I don't think the LCDK can cope with this resolution at this frequency
>>>> (in terms of mem bandwidth), at least that's what I observed back in
>>>> August. If confirmed I think it is worth mentioning in the log at least,
>>>> but then I doubt adding this config would be useful.
>>>>
>>>
>>> Thanks for the heads up. How would that manifest itself? This seems to
>>> work fine for me - I'm not getting any warnings on a simple system -
>>> maybe if I added some additional memory load it would complain.
>>>
>>
>> A mere dmesg > /dev/tty0 (or repeatedly cat-ting a file to /dev/tty0)
>> should suffice to make the issue visible and trigger FIFO underflows.
>>
> 
> Thanks, this is correct unfortunately.

The OMAP-L138 datasheet documents 37.5 MHz as the maximum pixel clock
possible on the device. Looks like you need 72MHz pixel clock for
1024x768 which is definitely out of spec.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v2] drm: tilcdc: add a da850-specific compatible string
From: Sekhar Nori @ 2016-10-01  9:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475243564-15765-1-git-send-email-bgolaszewski@baylibre.com>

On Friday 30 September 2016 07:22 PM, Bartosz Golaszewski wrote:
> Due to some potential tweaks for the da850 LCDC (for example: the
> required memory bandwith settings) we need a separate compatible
> for the IP present on the da850 boards.
> 
> Suggested-by: Sekhar Nori <nsekhar@ti.com>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> v1 -> v2:
> - added the new compatible to the bindings documentation
> 
>  Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt | 4 ++--
>  drivers/gpu/drm/tilcdc/tilcdc_drv.c                         | 1 +
>  2 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
> index a83abd7..33b6e8a 100644
> --- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
> +++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
> @@ -1,7 +1,7 @@
>  Device-Tree bindings for tilcdc DRM driver
>  
>  Required properties:
> - - compatible: value should be "ti,am33xx-tilcdc".
> + - compatible: value should be "ti,am33xx-tilcdc" or "ti,da850-tilcdc".

This documentation does not help much :( It should be on the lines of:

compatible: value should be "ti,am33xx-tilcdc" for AM335x based boards
	    value should be "ti,da850-tilcdc" for DA850/AM18x/OMAP-L138
	    based boards

There are many existing examples of the way compatible strings are
documented. You can take a look at them too. Also, since you are
introducing a new device-tree compatible, please keep the devicetree
list and maintainers in CC too. I don't think it shows up in
get_maintainer.pl, so you will have to remember to do it.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH] mtd: mtk: avoid warning in mtk_ecc_encode
From: Boris Brezillon @ 2016-10-01  9:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201609301925.17577.arnd@arndb.de>

On Fri, 30 Sep 2016 19:25:17 +0200
Arnd Bergmann <arnd@arndb.de> wrote:

> On Friday 30 September 2016, Boris Brezillon wrote:
> > > +     /* copy into possibly unaligned OOB region with actual length */
> > > +     memcpy(data + bytes, eccdata, len);  
> > 
> > Is it better than
> > 
> >         for (i = 0; i < len; i += 4) {
> >                 u32 val = __raw_readl(ecc->regs + ECC_ENCPAR(i / 4));
> > 
> >                 memcpy(data + bytes + i, &val, min(len, 4));
> >         }
> > 
> > I'm probably missing something, but what's the point of creating a
> > temporary buffer of 112 bytes on the stack since you'll have to copy
> > this data to the oob buffer at some point?  
> 
> 
> I tried something like that first, but wasn't too happy with it for
> a number of small reasons:
> 
> - __raw_readl in a driver is not usually the right API, __memcpy32_from_io
>   uses it internally, but it's better for a driver not to rely on that,
>   in case we need some barriers (which we may in factt need for other drivers).

I agree, even though calling something prefixed with __ (in this case,
__ioread32_copy()) sounds like a bad thing too :).

> 
> - the min(len,4) expression is incorrect, fixing that makes it more complicated
>   again

Sorry, it's min(len - i, 4), which is not that complicated :P.

> 
> - I didn't like to call memcpy() multiple times, as that might get turned
>   into an external function call (the compiler is free to optimize small
>   memcpy calls or not).

Okay.

> 
> I agree that he 112 byte buffer isn't ideal either, it just seemed to
> be the lesser annoyance.

How about we keep your approach, but put the buffer in the mtk_ecc
struct?

^ permalink raw reply

* [PATCH 6/6] ARM: da850: adjust memory settings for tilcdc
From: Sekhar Nori @ 2016-10-01  9:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <91db8934-bfd6-8fc4-74e3-4844ef3bd3e7@ti.com>

On Saturday 01 October 2016 12:49 AM, Peter Ujfalusi wrote:
> On 09/30/2016 06:06 PM, Bartosz Golaszewski wrote:
>> 2016-09-30 14:59 GMT+02:00 Peter Ujfalusi <peter.ujfalusi@ti.com>:
>>> On 09/29/16 19:31, Bartosz Golaszewski wrote:
>>>> Default memory settings of da850 do not meet the throughput/latency
>>>> requirements of tilcdc. This results in the image displayed being
>>>> incorrect and the following warning being displayed by the LCDC
>>>> drm driver:
>>>>
>>>>   tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow
>>>>
>>>> Reconfigure the LCDC priority to the highest. This is a workaround
>>>> for the da850-lcdk board which has the LCD controller enabled in
>>>> the device tree, but a long-term, system-wide fix is needed for
>>>> all davinci boards.
>>>>
>>>> This patch has been modified for mainline linux. It comes from a
>>>> downstream TI release for da850[1].
>>>>
>>>> Original author: Vishwanathrao Badarkhe, Manish <manishv.b@ti.com>
>>>>
>>
>> [snip]
>>
>>>
>>> Is this safe to do for all da850 boards (to change PR_OLD_COUNT from 0xff to
>>> 0x20)? Most probably it is, but this setting has nothing to do with LCDC.
>>>
>>> The whole priority configuration has nothing to do with the LCDC, it is a
>>> system level priority.
>>>
>>> Now you have lowered the eDMA3_0-TPTC0/1 priority. Audio is serviced by
>>> eDMA3_0-TPTC1. So are we going to see issues in audio if LCDC is taking the
>>> highest priority?
>>>
>>
>> Just ran a quick test with speaker-test -c2 -twav. Besides the fact
>> that the left and right channels are inverted (I'm looking into that),
>> I didn't notice any problems. Even at 1024x768 resolution, playing
>> audio at the same time seems to work fine.
> 
> That's good to hear, but I think the priorities should be set:
> LCDC and EDMA30TC1 to highest priority
> EDMA30TC0 to priority 2
> 
> The 0TC0 is used by MMC and if you want to play a video you might need the
> servicing TC to be higher priority then other masters.
> 
> If audio playback would trigger sync losts in lcdc then we might need to move
> 0TC1 to priority 1.
> 
> I agree that LCDC priority needs to be higher, but I do wonder why the default
> (5) is not working and if it is not working why it is 5...
> 
> My guess is that the change in the PBBPR register is the one actually helping
> here.

Good point, Peter. If you are booting off NFS and not playing any audio,
then there is pretty much no EDMA generated traffic on the interconnect.

I would guess too that its the PBBPR setting that is making a
difference. The EDMA vs LCDC priority adjustment might be needed in
particular situations too, but specific experiments should be done to
narrow down on that being the cause.

In any case, to configure the PBBR, you will have to introduce a driver
for it in drivers/memory. Then you can set it up per board using a DT
parameter.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
From: Vinod Koul @ 2016-10-01  6:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475115167-5898-6-git-send-email-okaya@codeaurora.org>

On Wed, Sep 28, 2016 at 10:12:42PM -0400, Sinan Kaya wrote:
> Getting ready for the MSI interrupts. The pending_tre_count is used
> in the interrupt handler to make sure all outstanding requests are
> serviced.
> 
> Making it atomic so that it can be updated from multiple contexts.

How is it multiple contexts? It's either existing context of MSI, not both!

> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/dma/qcom/hidma.h     |  2 +-
>  drivers/dma/qcom/hidma_dbg.c |  3 ++-
>  drivers/dma/qcom/hidma_ll.c  | 13 ++++++-------
>  3 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
> index e52e207..3f2ddd4 100644
> --- a/drivers/dma/qcom/hidma.h
> +++ b/drivers/dma/qcom/hidma.h
> @@ -58,7 +58,7 @@ struct hidma_lldev {
>  	void __iomem *evca;		/* Event Channel address          */
>  	struct hidma_tre
>  		**pending_tre_list;	/* Pointers to pending TREs	  */
> -	s32 pending_tre_count;		/* Number of TREs pending	  */
> +	atomic_t pending_tre_count;	/* Number of TREs pending	  */
>  
>  	void *tre_ring;			/* TRE ring			  */
>  	dma_addr_t tre_dma;		/* TRE ring to be shared with HW  */
> diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
> index fa827e5..87db285 100644
> --- a/drivers/dma/qcom/hidma_dbg.c
> +++ b/drivers/dma/qcom/hidma_dbg.c
> @@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
>  	seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
>  	seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
>  	seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
> -	seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
> +	seq_printf(s, "pending_tre_count=%d\n",
> +			atomic_read(&lldev->pending_tre_count));
>  	seq_printf(s, "evca=%p\n", lldev->evca);
>  	seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
>  	seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
> diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
> index 3224f24..29fef4f 100644
> --- a/drivers/dma/qcom/hidma_ll.c
> +++ b/drivers/dma/qcom/hidma_ll.c
> @@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
>  	 * Keep track of pending TREs that SW is expecting to receive
>  	 * from HW. We got one now. Decrement our counter.
>  	 */
> -	lldev->pending_tre_count--;
> -	if (lldev->pending_tre_count < 0) {
> +	if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
>  		dev_warn(lldev->dev, "tre count mismatch on completion");
> -		lldev->pending_tre_count = 0;
> +		atomic_set(&lldev->pending_tre_count, 0);
>  	}
>  
>  	spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
>  	u32 tre_read_off;
>  
>  	tre_iterator = lldev->tre_processed_off;
> -	while (lldev->pending_tre_count) {
> +	while (atomic_read(&lldev->pending_tre_count)) {
>  		if (hidma_post_completed(lldev, tre_iterator, err_info,
>  					 err_code))
>  			break;
> @@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
>  	tre->err_code = 0;
>  	tre->err_info = 0;
>  	tre->queued = 1;
> -	lldev->pending_tre_count++;
> +	atomic_inc(&lldev->pending_tre_count);
>  	lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
>  					% lldev->tre_ring_size;
>  	spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
>  	u32 val;
>  	u32 nr_tres = lldev->nr_tres;
>  
> -	lldev->pending_tre_count = 0;
> +	atomic_set(&lldev->pending_tre_count, 0);
>  	lldev->tre_processed_off = 0;
>  	lldev->evre_processed_off = 0;
>  	lldev->tre_write_offset = 0;
> @@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
>  	tasklet_kill(&lldev->task);
>  	memset(lldev->trepool, 0, required_bytes);
>  	lldev->trepool = NULL;
> -	lldev->pending_tre_count = 0;
> +	atomic_set(&lldev->pending_tre_count, 0);
>  	lldev->tre_write_offset = 0;
>  
>  	rc = hidma_ll_reset(lldev);
> -- 
> 1.9.1
> 

-- 
~Vinod

^ permalink raw reply


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