Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v9 3/3] arm: pmu: Add CPI checking
From: Wei Huang @ 2016-11-19  4:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479528942-21866-1-git-send-email-wei@redhat.com>

From: Christopher Covington <cov@codeaurora.org>

Calculate the numbers of cycles per instruction (CPI) implied by ARM
PMU cycle counter values. The code includes a strict checking facility
intended for the -icount option in TCG mode in the configuration file.

Signed-off-by: Christopher Covington <cov@codeaurora.org>
Signed-off-by: Wei Huang <wei@redhat.com>
---
 arm/pmu.c         | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 arm/unittests.cfg |  14 +++++++
 2 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/arm/pmu.c b/arm/pmu.c
index fa87de4..b36c4fb 100644
--- a/arm/pmu.c
+++ b/arm/pmu.c
@@ -104,6 +104,25 @@ static inline uint32_t id_dfr0_read(void)
 	asm volatile("mrc p15, 0, %0, c0, c1, 2" : "=r" (val));
 	return val;
 }
+
+/*
+ * Extra instructions inserted by the compiler would be difficult to compensate
+ * for, so hand assemble everything between, and including, the PMCR accesses
+ * to start and stop counting.
+ */
+static inline void loop(int i, uint32_t pmcr)
+{
+	asm volatile(
+	"	mcr	p15, 0, %[pmcr], c9, c12, 0\n"
+	"	isb\n"
+	"1:	subs	%[i], %[i], #1\n"
+	"	bgt	1b\n"
+	"	mcr	p15, 0, %[z], c9, c12, 0\n"
+	"	isb\n"
+	: [i] "+r" (i)
+	: [pmcr] "r" (pmcr), [z] "r" (0)
+	: "cc");
+}
 #elif defined(__aarch64__)
 static inline uint32_t pmcr_read(void)
 {
@@ -150,6 +169,25 @@ static inline uint32_t id_dfr0_read(void)
 	asm volatile("mrs %0, id_dfr0_el1" : "=r" (id));
 	return id;
 }
+
+/*
+ * Extra instructions inserted by the compiler would be difficult to compensate
+ * for, so hand assemble everything between, and including, the PMCR accesses
+ * to start and stop counting.
+ */
+static inline void loop(int i, uint32_t pmcr)
+{
+	asm volatile(
+	"	msr	pmcr_el0, %[pmcr]\n"
+	"	isb\n"
+	"1:	subs	%[i], %[i], #1\n"
+	"	b.gt	1b\n"
+	"	msr	pmcr_el0, xzr\n"
+	"	isb\n"
+	: [i] "+r" (i)
+	: [pmcr] "r" (pmcr)
+	: "cc");
+}
 #endif
 
 /*
@@ -204,6 +242,71 @@ static bool check_cycles_increase(void)
 	return success;
 }
 
+/*
+ * Execute a known number of guest instructions. Only odd instruction counts
+ * greater than or equal to 3 are supported by the in-line assembly code. The
+ * control register (PMCR_EL0) is initialized with the provided value (allowing
+ * for example for the cycle counter or event counters to be reset). At the end
+ * of the exact instruction loop, zero is written to PMCR_EL0 to disable
+ * counting, allowing the cycle counter or event counters to be read at the
+ * leisure of the calling code.
+ */
+static void measure_instrs(int num, uint32_t pmcr)
+{
+	int i = (num - 1) / 2;
+
+	assert(num >= 3 && ((num - 1) % 2 == 0));
+	loop(i, pmcr);
+}
+
+/*
+ * Measure cycle counts for various known instruction counts. Ensure that the
+ * cycle counter progresses (similar to check_cycles_increase() but with more
+ * instructions and using reset and stop controls). If supplied a positive,
+ * nonzero CPI parameter, also strictly check that every measurement matches
+ * it. Strict CPI checking is used to test -icount mode.
+ */
+static bool check_cpi(int cpi)
+{
+	uint32_t pmcr = pmcr_read() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E;
+	
+	if (cpi > 0)
+		printf("Checking for CPI=%d.\n", cpi);
+	printf("instrs : cycles0 cycles1 ...\n");
+
+	for (unsigned int i = 3; i < 300; i += 32) {
+		uint64_t avg, sum = 0;
+
+		printf("%d :", i);
+		for (int j = 0; j < NR_SAMPLES; j++) {
+			uint64_t cycles;
+
+			pmccntr_write(0);
+			measure_instrs(i, pmcr);
+			cycles = pmccntr_read();
+			printf(" %"PRId64"", cycles);
+
+			/*
+			 * The cycles taken by the loop above should fit in
+			 * 32 bits easily. We check the upper 32 bits of the
+			 * cycle counter to make sure there is no supprise.
+			 */
+			if (!cycles || (cpi > 0 && cycles != i * cpi) ||
+			    (cycles & 0xffffffff00000000)) {
+				printf("\n");
+				return false;
+			}
+
+			sum += cycles;
+		}
+		avg = sum / NR_SAMPLES;
+		printf(" sum=%"PRId64" avg=%"PRId64" avg_ipc=%"PRId64" "
+		       "avg_cpi=%"PRId64"\n", sum, avg, i / avg, avg / i);
+	}
+
+	return true;
+}
+
 void pmu_init(void)
 {
 	uint32_t dfr0;
@@ -218,13 +321,19 @@ void pmu_init(void)
 	pmccfiltr_write(0); /* count cycles in EL0, EL1, but not EL2 */
 }
 
-int main(void)
+int main(int argc, char *argv[])
 {
+	int cpi = 0;
+
+	if (argc >= 1)
+		cpi = atol(argv[0]);
+
 	report_prefix_push("pmu");
 
 	pmu_init();
 	report("Control register", check_pmcr());
 	report("Monotonically increasing cycle count", check_cycles_increase());
+	report("Cycle/instruction ratio", check_cpi(cpi));
 
 	return report_summary();
 }
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index 7645180..2050dc8 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -59,3 +59,17 @@ groups = selftest
 [pmu]
 file = pmu.flat
 groups = pmu
+
+# Test PMU support (TCG) with -icount IPC=1
+[pmu-tcg-icount-1]
+file = pmu.flat
+extra_params = -icount 0 -append '1'
+groups = pmu
+accel = tcg
+
+# Test PMU support (TCG) with -icount IPC=256
+[pmu-tcg-icount-256]
+file = pmu.flat
+extra_params = -icount 8 -append '256'
+groups = pmu
+accel = tcg
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH V8 2/6] thermal: bcm2835: add thermal driver for bcm2835 soc
From: Eduardo Valentin @ 2016-11-19  4:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7957B3CC-0E18-4B27-82EB-EF88B7695E28@martin.sperl.org>

Hello Martin,

Thanks for your patience to take the time to explain to me how the
firmware/linux split is done in your platform. Still, one thing is not
clear to me.

On Fri, Nov 18, 2016 at 09:32:47AM +0100, kernel at martin.sperl.org wrote:
> 

> The way that firmware works on the RPI is quite different from most others I guess.
> in principle you got 2 different CPUs on the bcm2835:
> * ARM, which runs the linux instance
> * VideoCore 4, which runs the firmware (loading from SD initially) and
>   then booting the ARM.
> 
> So this Firmware on VC4 is the one that I am talking about.
> Without the working firmware linux can not boot on arm.

Given that "without the working firmware linux can not boot on arm",

(...)

> As far as I understand the conversion is continuous (as soon as the HW is
> configured). This case is there primarily to handle the situation where
> we initialize the HW ourselves (see line 226 and below), and we immediately

and around line 226 we have the comment:
+       /*
+        * right now the FW does set up the HW-block, so we are not
+        * touching the configuration registers.
+        * But if the HW is not enabled, then set it up
+        * using "sane" values used by the firmware right now.
+        */


> want to read the ADC value before the first conversion is finished.
> 

then, does the firmware initializes the device or not?

What are the cases you would load this driver but still get an
uninitialized device? That looks like some bug workaround hidden
somewhere. Do system integrators/engineers need to be aware of this w/a?
Would the driver work right aways when the subsystem is loaded during
boot? How about module insertion?


Who has the ownership of this device?

> The above mentioned ?configuration if not running? reflect the values that
> the FW is currently setting. We should not change those values as long as the
> Firmware is also reading the temperature on its own.

hmm.. that looks like racy to me. Again, How do you synchronize accesses to
this device? What if you configure the device and right after the
firmware updates the configs? How do you make sure the configs you are
writing here are the same used by the firmware? What if the firmware
version changes? What versions of the firmware does this driver support?

Would it make sense to simply always initialize the device? Do you have
a way to tell the firmware that it should not use the device?

Or, if you want to keep the device driver simply being a dummy reader,
would it make sense to simply avoid writing configurations to the
device, and simply retry to check if the firmware gets the device
initialized?

> 
> > 
> >> So do you need another version of the patchset that uses that new API?
> > 
> > I think the API usage is change that can be done together with
> > clarification for the above questions too: on hardware state,
> > firmware loading, maybe a master driver dependency, and the ADC
> > conversion sequence, which are not well clear to me on this driver. As long as
> > this is clarified and documented in the code (can be simple comments so
> > it is clear to whoever reads in the future), then I would be OK with
> > this driver. 
> 
> So how do you want this to get ?documented? in the driver?
> The setup and Firmware is a generic feature of the SOC, so if we would put
> some clarifications in this driver, then we would need to put it in every
> bcm283X driver (which seems unreasonable).
> 

I think a simple comment explaining the firmware dependency and the
expected pre-conditions to get this driver working in a sane state would
do it.

A better device initialization would also be appreciated. Based on my
limited understanding of this platform, and your explanations, this
device seams to have a serious race condition with firmware while
accessing this device.

> Thanks,
> 	Martin

^ permalink raw reply

* [PATCH] spi: davinci: Allow device tree devices to use DMA
From: David Lechner @ 2016-11-19  4:41 UTC (permalink / raw)
  To: linux-arm-kernel

This makes SPI devices specified in a device tree use DMA when the master
controller has DMA configured.

Since device tree is supposed to only describe the hardware, adding a
configuration option to device tree to enable DMA per-device would not be
acceptable. So, this is the best we can do for now to get SPI devices
working with DMA when using device tree.

Unfortunately, this excludes the possibility of using one SPI device with
DMA and one without on the same master.

I have tested this on LEGO MINDSTORMS EV3 using the NOR flash. Reading the
flash memory would fail with -EIO when DMA is not enabled for the device.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/spi/spi-davinci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index d36c11b..c6cf73a 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -388,6 +388,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
 static int davinci_spi_of_setup(struct spi_device *spi)
 {
 	struct davinci_spi_config *spicfg = spi->controller_data;
+	struct davinci_spi *dspi = spi_master_get_devdata(spi->master);
 	struct device_node *np = spi->dev.of_node;
 	u32 prop;
 
@@ -400,6 +401,9 @@ static int davinci_spi_of_setup(struct spi_device *spi)
 		if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
 			spicfg->wdelay = (u8)prop;
 		spi->controller_data = spicfg;
+		/* Use DMA for device if master supports it */
+		if (dspi->dma_rx)
+			spicfg->io_type = SPI_IO_TYPE_DMA;
 	}
 
 	return 0;
-- 
2.7.4

^ permalink raw reply related

* [GIT PULL v2] Qualcomm Device Tree Changes for v4.10
From: Andy Gross @ 2016-11-19  5:57 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:

  Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git tags/qcom-dts-for-4.10-1

for you to fetch changes up to 4c52ffc708c90b2985f941db5490145530e4df69:

  ARM: dts: add SMSC ethernet on the APQ8060 Dragonboard (2016-11-18 23:30:32 -0600)

----------------------------------------------------------------
Qualcomm Device Tree Changes for v4.10 - v2

* Add EBI2 support to MSM8660
* Add SMSC ethernet support to APQ8060
* Add support for display, pstore, iommu, and hdmi to APQ8064
* Add SDHCI node to MSM8974 Hammerhead
* Add WP8548 MangOH board support (MDM9615)

----------------------------------------------------------------
Archit Taneja (2):
      arm: dts: qcom: apq8064: Add display DT nodes
      arm: dts: qcom: apq8064-ifc6410: Add HDMI support

Bhushan Shah (1):
      ARM: dts: qcom: msm8974-hammerhead: Add sdhci1 node

John Stultz (3):
      arm: dts: qcom: apq8064: Add dsi, gpu and iommu nodes
      arm: dts: qcom: apq8064-nexus7: Add DSI and panel nodes
      arm: dts: qcom: apq8064-nexus7: Add pstore support to nexus7

Linus Walleij (2):
      ARM: dts: add EBI2 to the Qualcomm MSM8660 DTSI
      ARM: dts: add SMSC ethernet on the APQ8060 Dragonboard

Neil Armstrong (5):
      ARM: dts: Add MDM9615 dtsi
      dt-bindings: qcom: Add MDM9615 bindings
      ARM: dts: Add Sierra Wireless WP8548 dtsi
      ARM: dts: Add WP8548 based MangOH Green board DTS
      dt-bindings: arm: Add Sierra Wireless modules bindings

 Documentation/devicetree/bindings/arm/qcom.txt     |   1 +
 Documentation/devicetree/bindings/arm/swir.txt     |  12 +
 arch/arm/boot/dts/Makefile                         |   3 +-
 arch/arm/boot/dts/qcom-apq8060-dragonboard.dts     | 119 +++++
 arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts |  77 ++-
 arch/arm/boot/dts/qcom-apq8064-ifc6410.dts         |  74 +++
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 321 ++++++++++++
 .../boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts  | 281 +++++++++++
 arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi         | 170 +++++++
 arch/arm/boot/dts/qcom-mdm9615.dtsi                | 557 +++++++++++++++++++++
 arch/arm/boot/dts/qcom-msm8660.dtsi                |  17 +
 .../dts/qcom-msm8974-lge-nexus5-hammerhead.dts     |  29 ++
 12 files changed, 1658 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/swir.txt
 create mode 100644 arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts
 create mode 100644 arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi
 create mode 100644 arch/arm/boot/dts/qcom-mdm9615.dtsi

^ permalink raw reply

* [PATCH] ARM: dts: msm8916: Add and enable wcnss node
From: Bjorn Andersson @ 2016-11-19  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

Add the wcnss remoteproc node the SMD edge and the wcnss ctrl, bluetooth
and wifi nodes specified and enable this on db410c.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

This still require the last wcn36xx and scm-interrupted patches to land, but as
those won't affect the dts I'm posting this anyway.

 arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi  |  4 ++
 arch/arm64/boot/dts/qcom/msm8916-pins.dtsi | 13 ++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi      | 73 +++++++++++++++++++++++++++++-
 3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
index 08bd5ebafb4e..716d3ccbc309 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
@@ -306,6 +306,10 @@
                                 };
                         };
                 };
+
+		wcnss at a21b000 {
+			status = "okay";
+		};
 	};
 
 	usb2513 {
diff --git a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
index 10c83e11c272..4cb0b5834143 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
@@ -720,4 +720,17 @@
 			};
 		};
 	};
+
+	wcnss_pin_a: wcnss-active {
+		pinmux {
+			pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44";
+			function = "wcss_wlan";
+		};
+
+		pinconf {
+			pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44";
+			drive-strength = <6>;
+			bias-pull-up;
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 4221b7d2c0ce..2c692650ae43 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -14,6 +14,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/qcom,gcc-msm8916.h>
 #include <dt-bindings/reset/qcom,gcc-msm8916.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8916";
@@ -82,7 +83,7 @@
 			no-map;
 		};
 
-		wcnss at 89300000 {
+		wcnss_mem: wcnss at 89300000 {
 			reg = <0x0 0x89300000 0x0 0x600000>;
 			no-map;
 		};
@@ -853,6 +854,76 @@
 				memory-region = <&mpss_mem>;
 			};
 		};
+
+		pronto: wcnss at a21b000 {
+			compatible = "qcom,pronto-v2-pil", "qcom,pronto";
+			reg = <0x0a204000 0x2000>, <0x0a202000 0x1000>, <0x0a21b000 0x3000>;
+			reg-names = "ccu", "dxe", "pmu";
+
+			memory-region = <&wcnss_mem>;
+
+			interrupts-extended = <&intc 0 149 IRQ_TYPE_EDGE_RISING>,
+					      <&wcnss_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+					      <&wcnss_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+					      <&wcnss_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+					      <&wcnss_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "wdog", "fatal", "ready", "handover", "stop-ack";
+
+			vddmx-supply = <&pm8916_l3>;
+			vddpx-supply = <&pm8916_l7>;
+
+			qcom,state = <&wcnss_smp2p_out 0>;
+			qcom,state-names = "stop";
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&wcnss_pin_a>;
+
+			status = "disabled";
+
+			iris {
+				compatible = "qcom,wcn3620";
+
+				clocks = <&rpmcc RPM_SMD_RF_CLK2>;
+				clock-names = "xo";
+
+				vddxo-supply = <&pm8916_l7>;
+				vddrfa-supply = <&pm8916_s3>;
+				vddpa-supply = <&pm8916_l9>;
+				vdddig-supply = <&pm8916_l5>;
+			};
+
+			smd-edge {
+				interrupts = <0 142 1>;
+
+				qcom,ipc = <&apcs 8 17>;
+				qcom,smd-edge = <6>;
+				qcom,remote-pid = <4>;
+
+				label = "pronto";
+
+				wcnss {
+					compatible = "qcom,wcnss";
+					qcom,smd-channels = "WCNSS_CTRL";
+
+					qcom,mmio = <&pronto>;
+
+					bt {
+						compatible = "qcom,wcnss-bt";
+					};
+
+					wifi {
+						compatible = "qcom,wcnss-wlan";
+
+						interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>,
+							     <0 146 IRQ_TYPE_LEVEL_HIGH>;
+						interrupt-names = "tx", "rx";
+
+						qcom,smem-states = <&apps_smsm 10>, <&apps_smsm 9>;
+						qcom,smem-state-names = "tx-enable", "tx-rings-empty";
+					};
+				};
+			};
+		};
 	};
 
 	smd {
-- 
2.5.0

^ permalink raw reply related

* [PATCH] arm: spin one more cycle in timer-based delays
From: Afzal Mohammed @ 2016-11-19  7:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <582F0DD2.3030805@free.fr>

Hi Mason,

On Fri, Nov 18, 2016 at 03:18:58PM +0100, Mason wrote:
> On 18/11/2016 13:54, Russell King - ARM Linux wrote:

> > So, NAK on this change.  udelay is not super-accurate.
> 
> usleep_range() fixed this issue recently.
> 6c5e9059692567740a4ee51530dffe51a4b9584d
> https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?h=timers/core&id=6c5e9059692567740a4ee51530dffe51a4b9584d

But the above "timers: Fix usleep_range() in the context of
wake_up_process()" is to avoid wakeup causing premature return than
about being precise, no ?

With conflicting opinion on delay/sleep fn's from the players, the one
in gallery would get confused.

But Linus has mentioned udelay as not meant to be precise, okay ?

Regards
afzal

^ permalink raw reply

* [GIT PULL] ARM: mvebu: dt for v4.10 (#1)
From: Gregory CLEMENT @ 2016-11-19  8:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161119015838.GG2543@localhost>

Hi Olof,
 
 On sam., nov. 19 2016, Olof Johansson <olof@lixom.net> wrote:

> Hi,
>
> On Thu, Nov 17, 2016 at 10:50:33PM +0100, Gregory CLEMENT wrote:
>> Hi,
>> 
>> Here is the first pull request for dt for mvebu for v4.10.
>> 
>> I hope being able to send a second part very soon with the series
>> removing all the DT warning.
>> 
>> Gregory
>> 
>> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
>> 
>>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
>> 
>> are available in the git repository at:
>> 
>>   git://git.infradead.org/linux-mvebu.git tags/mvebu-dt-4.10-1
>> 
>> for you to fetch changes up to cf20c489de6fcef88405d4febef7a078d2053b9e:
>> 
>>   ARM: dt: orion5x: convert ls-chl to FDT (2016-11-07 17:23:34 +0100)
>> 
>> ----------------------------------------------------------------
>> mvebu fixes for 4.10 (part 1)
>> 
>> Most of the commit are pinmux and i2c fix for netgear NASes
>> Fix on a wrong comment about PLL frequency
>> Bigger commit: conversion of on otion5x based board to the device tree
>> 
>> ----------------------------------------------------------------
>> Ashley Hughes (1):
>>       ARM: dt: orion5x: convert ls-chl to FDT
>
> This is a great conversion, but I'd like to see the code handled a
> little differently.
>
> First of all, there's no longer a need to have a config option for 
> MACH_LINKSTATION_LSCHL, as long as ARCH_ORION5X_DT is enabled you'll
> be fine. So you can remove that Kconfig entry alltogether.
>
> Also, there's no need to make the DT addition and the legacy platform
> removal in one commit. It's common that we build up the DT support to the point
> that it's at parity, and then remove the legacy board. That way we also don't
> entangle DT commits with non-DT commits, which can sometimes be a bit of a pain
> (in particular for those who maintain a copy of the DT subdir in another git
> repo).
>
> So, mind respinning with this fixed? Thanks!

OK I am doing it.

Gregory

>
>
> -Olof
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [GIT PULL] ARM: mvebu: dt for v4.10 (#1)
From: Gregory CLEMENT @ 2016-11-19  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is the first pull request for dt for mvebu for v4.10. It repalces
the previous one sent 2 days ago as requested by Olof.

I take the opportunity to add new commits:
"ARM: dts: kirkwood: fix spelling mistake" which as applied recently but
which is harmless and trivial.

I also add all the non controversial patches removing the DTC
warning. They wre posted two weeks ago and was in linux-next since this
day. As there is still some discussions about MBUS_ID and ranges, I will
prepare a new series for them which I still hope mnage to be part of
4.10.

Gregory

The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:

  Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)

are available in the git repository at:

  git://git.infradead.org/linux-mvebu.git tags/mvebu-dt-4.10-1

for you to fetch changes up to 2f7132852038deb8e364bee155f51cb477c8d2f4:

  ARM: dts: armada-375: Fixup ethernet child DT warning (2016-11-19 09:16:52 +0100)

----------------------------------------------------------------
mvebu dt for 4.10 (part 1)

Add missing pinmux declaration for netgear NASes
Fix i2c compatible string for netgear NASes
Fix on a wrong comment about PLL frequency
Fix spelling mistake of the manufacturer's name of the Topkick
Add dt support for the orion5x ls-chl Linkstation device
First step of fixing DTC warning for Armada 370, 375 and XP

----------------------------------------------------------------
Ashley Hughes (1):
      ARM: dts: orion5x: convert ls-chl to FDT

Chris Packham (1):
      ARM: dts: mvebu: Update comment for main PLL frequency

Gregory CLEMENT (21):
      ARM: dts: armada-xp-matrix: Fix the location of the pcie-controller node
      ARM: dts: armada-370-xp: move the cpurst node in the common file
      ARM: dts: armada-370-xp: add node labels
      ARM: dts: armada-370-xp: Use the node labels
      ARM: dts: armada-370-xp: Fixup mdio DT warning
      ARM: dts: armada-xp: Fixup pcie DT warnings
      ARM: dts: armada-370: Fixup pcie DT warnings
      ARM: dts: armada-370-xp: Remove skeleton.dtsi
      ARM: dts: armada-370-xp: Fixup l2-cache DT warning
      ARM: dts: armada-370-xp: Fixup memory DT warning
      ARM: dts: armada-370-xp: Remove address from dsa unit name
      ARM: dts: armada-370-xp: Remove button address and fixup names
      ARM: dts: armada-370-xp: Fixup regulator DT warning
      ARM: dts: armada-375: Add node labels
      ARM: dts: armada-375: Use the node labels
      ARM: dts: armada-375: Fixup mdio DT warning
      ARM: dts: armada-375: Fixup pcie DT warnings
      ARM: dts: armada-375: Fixup pinctrl DT warnings
      ARM: dts: armada-375: Remove skeleton.dtsi
      ARM: dts: armada-375: Fixup memory DT warning
      ARM: dts: armada-375: Fixup ethernet child DT warning

Paul Wassi (1):
      ARM: dts: kirkwood: fix spelling mistake

Uwe Kleine-K?nig (6):
      ARM: dts: armada-370-rn104: add pinmuxing for i2c0
      ARM: dts: armada-370-rn104: drop specification of compatible for i2c0
      ARM: dts: armada-xp-rn2120: drop wrong compatible for i2c0
      ARM: dts: armada-xp-rn2120: add pinmuxing for ethernet
      ARM: dts: armada-370-rn102: drop specification of compatible for i2c0
      ARM: dts: armada-370-rn102: add pinmuxing for i2c0

 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/armada-370-db.dts                |  63 ++---
 arch/arm/boot/dts/armada-370-dlink-dns327l.dts     |  30 +--
 arch/arm/boot/dts/armada-370-mirabox.dts           |  57 ++---
 arch/arm/boot/dts/armada-370-netgear-rn102.dts     |  55 +++--
 arch/arm/boot/dts/armada-370-netgear-rn104.dts     |  63 ++---
 arch/arm/boot/dts/armada-370-rd.dts                |  57 ++---
 arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts  |  27 +-
 arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi |  45 ++--
 .../dts/armada-370-seagate-personal-cloud.dtsi     |  44 ++--
 arch/arm/boot/dts/armada-370-synology-ds213j.dts   |  18 +-
 arch/arm/boot/dts/armada-370-xp.dtsi               |  39 +--
 arch/arm/boot/dts/armada-370.dtsi                  | 136 +++++------
 arch/arm/boot/dts/armada-375-db.dts                | 271 +++++++++++----------
 arch/arm/boot/dts/armada-375.dtsi                  |  72 +++---
 arch/arm/boot/dts/armada-38x.dtsi                  |   2 +-
 arch/arm/boot/dts/armada-39x.dtsi                  |   2 +-
 arch/arm/boot/dts/armada-xp-axpwifiap.dts          |  68 +++---
 arch/arm/boot/dts/armada-xp-db.dts                 | 104 ++++----
 arch/arm/boot/dts/armada-xp-gp.dts                 |  80 +++---
 arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts    |  53 ++--
 arch/arm/boot/dts/armada-xp-linksys-mamba.dts      |  52 ++--
 arch/arm/boot/dts/armada-xp-matrix.dts             |  20 +-
 arch/arm/boot/dts/armada-xp-mv78230.dtsi           |  12 +-
 arch/arm/boot/dts/armada-xp-mv78260.dtsi           |  20 +-
 arch/arm/boot/dts/armada-xp-mv78460.dtsi           |  22 +-
 arch/arm/boot/dts/armada-xp-netgear-rn2120.dts     |  74 +++---
 arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts   |  58 ++---
 arch/arm/boot/dts/armada-xp-synology-ds414.dts     |  75 +++---
 arch/arm/boot/dts/armada-xp.dtsi                   |  94 +++----
 arch/arm/boot/dts/kirkwood-topkick.dts             |   2 +-
 arch/arm/boot/dts/orion5x-lschl.dts                | 171 +++++++++++++
 32 files changed, 1042 insertions(+), 845 deletions(-)
 create mode 100644 arch/arm/boot/dts/orion5x-lschl.dts

^ permalink raw reply

* [GIT PULL] ARM: mvebu: soc for v4.10 (#1)
From: Gregory CLEMENT @ 2016-11-19  8:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is the first pull request for soc for mvebu for v4.10.

On this PR there is only the removal part of the orion5x platform whcih
was initially part of the "ARM: dt: orion5x: convert ls-chl to FDT"
patch.

Gregory

The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:

  Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)

are available in the git repository at:

  git://git.infradead.org/linux-mvebu.git tags/mvebu-soc-4.10-1

for you to fetch changes up to ecfe69639157b6f70f53a7bc250efb4614c0eb31:

  ARM: orion5x: remove legacy support of ls-chl (2016-11-19 09:14:28 +0100)

----------------------------------------------------------------
mvebu soc for 4.10 (part 1)

remove legacy support of orion5x ls-chl

----------------------------------------------------------------
Ashley Hughes (1):
      ARM: orion5x: remove legacy support of ls-chl

 arch/arm/mach-orion5x/Kconfig        |   7 -
 arch/arm/mach-orion5x/Makefile       |   1 -
 arch/arm/mach-orion5x/ls-chl-setup.c | 331 -----------------------------------
 3 files changed, 339 deletions(-)
 delete mode 100644 arch/arm/mach-orion5x/ls-chl-setup.c

^ permalink raw reply

* [GIT PULL] ARM: mvebu: dt64 for v4.10 (#2)
From: Gregory CLEMENT @ 2016-11-19  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is the second pull request for dt64 for mvebu for v4.10.

This series was posted 2 weeks ago and actually should have been part
of the first PR.

Gregory

The following changes since commit e735aaf8fc4ac84dbdb3642a135da8dcdb84587b:

  arm64: dts: marvell: Add definition for the Globalscale Marvell ESPRESSOBin Board (2016-10-17 17:19:56 +0200)

are available in the git repository at:

  git://git.infradead.org/linux-mvebu.git tags/mvebu-dt64-4.10-2

for you to fetch changes up to 3684534548d4cbba7d3724b3d79152eff38dc82f:

  ARM64: dts: marvell: Fixup memory DT warning for Armada 37xx (2016-11-19 09:39:07 +0100)

----------------------------------------------------------------
mvebu dt64 for 4.10 (part 2)

Fix DTC warning on Armada 37xx and 7K/8K

----------------------------------------------------------------
Gregory CLEMENT (3):
      arm64: dts: marvell: Fixup internal-regs DT warning for Armada 37xx
      arm64: dts: marvell: Fixup config-space DT warning For Armada 7K/8K
      ARM64: dts: marvell: Fixup memory DT warning for Armada 37xx

 arch/arm64/boot/dts/marvell/armada-3720-db.dts          | 2 +-
 arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 2 +-
 arch/arm64/boot/dts/marvell/armada-37xx.dtsi            | 2 +-
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi           | 2 +-
 arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi    | 2 +-
 arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi     | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

^ permalink raw reply

* [GIT PULL v2] pxa-dt for v4.10
From: Robert Jarzmik @ 2016-11-19  9:51 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Arnd, Kevin, and Olof,

This is the second iteration of the pxa pull request for 4.10 device-tree, with
the patch subjects fixed.

Can you please consider pulling ?

The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:

  Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)

are available in the git repository at:

  https://github.com/rjarzmik/linux.git tags/pxa-dt-4.10

for you to fetch changes up to 74e382b870caf297f4e1a727010c9a26cce6b6af:

  ARM: dts: pxa: add pxa27x cpu operating points (2016-11-18 17:09:45 +0100)

----------------------------------------------------------------
This device-tree pxa update brings :
 - pxa25x support
 - cpu operating points in preparation for cpufreq-dt
 - small fixes

----------------------------------------------------------------
Robert Jarzmik (4):
      ARM: dts: pxa: add pxa25x .dtsi file
      ARM: dts: pxa: fix gpio0 and gpio1 interrupts
      ARM: dts: pxa: add pxa25x cpu operating points
      ARM: dts: pxa: add pxa27x cpu operating points

Vijay Kumar (1):
      ARM: dts: pxa: fix no. of gpio cells in the pxa gpio binding documentation

 .../devicetree/bindings/gpio/mrvl-gpio.txt         |   6 +-
 arch/arm/boot/dts/pxa25x.dtsi                      | 117 +++++++++++++++++++++
 arch/arm/boot/dts/pxa27x.dtsi                      |  40 +++++++
 arch/arm/boot/dts/pxa2xx.dtsi                      |   4 +-
 4 files changed, 163 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/boot/dts/pxa25x.dtsi

-- 
Robert

^ permalink raw reply

* [PATCH] ASoC: mioa701_wm9713: add missing white space in dev_err message
From: Robert Jarzmik @ 2016-11-19  9:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161112163025.4801-1-colin.king@canonical.com>

Colin King <colin.king@canonical.com> writes:

> From: Colin Ian King <colin.king@canonical.com>
>
> There is a missing whitespace in the dev_err message between
> "will" and "lead".  Add the whitespace.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>

Cheers.

-- 
Robert

^ permalink raw reply

* [PATCH] arm: spin one more cycle in timer-based delays
From: Russell King - ARM Linux @ 2016-11-19 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161119071702.GA25647@afzalpc>

Linus, please see the comment and patch at the bottom of this mail.
Thanks.

On Sat, Nov 19, 2016 at 12:47:02PM +0530, Afzal Mohammed wrote:
> Hi Mason,
> 
> On Fri, Nov 18, 2016 at 03:18:58PM +0100, Mason wrote:
> > On 18/11/2016 13:54, Russell King - ARM Linux wrote:
> 
> > > So, NAK on this change.  udelay is not super-accurate.
> > 
> > usleep_range() fixed this issue recently.
> > 6c5e9059692567740a4ee51530dffe51a4b9584d
> > https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?h=timers/core&id=6c5e9059692567740a4ee51530dffe51a4b9584d
> 
> But the above "timers: Fix usleep_range() in the context of
> wake_up_process()" is to avoid wakeup causing premature return than
> about being precise, no ?

usleep*() is different from udelay().  usleep*() is not based on looping
a certain number of times, and doesn't involve calibration of such a
loop.  usleep*() is based on the scheduler, which has tighter
requirements laid down in POSIX amongst other standards, such as "not
timing out before this specified time" (due to things like select(),
poll(), etc.)  udelay() is purely a kernel thing, unspecified by any
standard.

> With conflicting opinion on delay/sleep fn's from the players, the one
> in gallery would get confused.
> 
> But Linus has mentioned udelay as not meant to be precise, okay ?

Exactly - and the reason for that (as I've explained several times in
the past) the "standard" software delay loop calibrated against the
timer interrupt is _always_ going to be short.

I explain why this is in the message to which Linus replied:

  http://lists.openwall.net/linux-kernel/2011/01/09/56

A consequence of the formula that I give in (2) in that mail is that
the higher the HZ value, the more error in the resulting value of
loops_per_jiffy, and the shorter udelay(1) than 1us will be, since
"timer_interrupt_usec" is a constant but "usec_per_jiffy" reduces.

So folk need to put the idea that "udelay(1) will always be at least
1us" out of their minds - that's simply not guaranteed by the kernel.
Linus' reply also indicates that we don't care if it's out by 5%,
and probably more than that too.

If someone can show that our timer-based udelay() produces an error
more than 5%, then I'll apply the patch.  What I don't want to do is
to apply the patch because someone thinks that udelay() should not
return early.  Applying it in that case has the effect of re-inforcing
what is an incorrect assumption, leading to people writing buggy drivers
that have delays which are too finely "tuned" - which may work with a
timer-based udelay() but cause failures with a loop-based udelay().

This is all about ensuring that driver authors do the right thing.

Linus, how about we add something like this to linux/delay.h to document
this fact?

 include/linux/delay.h | 12 +++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/delay.h b/include/linux/delay.h
index a6ecb34cf547..2ecb3c46b20a 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -5,6 +5,18 @@
  * Copyright (C) 1993 Linus Torvalds
  *
  * Delay routines, using a pre-computed "loops_per_jiffy" value.
+ *
+ * Please note that ndelay(), udelay() and mdelay() may return early for
+ * several reasons:
+ *  1. computed loops_per_jiffy too low (due to the time taken to
+ *     execute the timer interrupt.)
+ *  2. cache behaviour affecting the time it takes to execute the
+ *     loop function.
+ *  3. CPU clock rate changes.
+ * As a result, delays should always be over-stated.
+ *
+ * Please see this thread:
+ *   http://lists.openwall.net/linux-kernel/2011/01/09/56
  */
 
 #include <linux/kernel.h>


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply related

* [PATCH next] arm64: remove "SMP: Total of %d processors activated." message
From: Russell King - ARM Linux @ 2016-11-19 11:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118101826.GC13470@arm.com>

On Fri, Nov 18, 2016 at 10:18:26AM +0000, Will Deacon wrote:
> On Fri, Nov 18, 2016 at 11:37:10AM +0800, Kefeng Wang wrote:
> > The message provides no further information than the generic code, so kill it.
> > Or show BogoMIPS like arm32?
> 
> Ha! No, I don't think printing the BogoMIPS is the right solution. I just
> think that, if you insist on removing the harmless print, then you should
> also consider doing the same thing for all the other architectures that
> print the same message.

Note that I'd removed the redundant message from ARM a long time ago,
until Linus reverted the patch due to the /proc/cpuinfo part.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* Low network throughput on i.MX28
From: Stefan Wahren @ 2016-11-19 11:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479512941.5577.1.camel@embedded.rocks>

Hi J?rg,

> J?rg Krause <joerg.krause@embedded.rocks> hat am 19. November 2016 um 00:49
> geschrieben:
> 
> 
> Hi all,
> 
> [snip]
> 
> I did some time measurements on the wifi, mmc and dma driver to compare
> the performance between the vendor and the mainline kernel. For this I
> toggled some GPIOs and measured the time difference with an osci. I
> started measuring the time before calling sdio_readsb() in the wifi
> driver [1] and stopped the time when the call returns. Note that the
> time was only measured for a packet length of 1536 bytes.
> 
> The vendor kernel took about 250 us to return whereas the mainline
> kernel took about 325 us. To investigate where this additional time
> comes from I divided the whole procedure into seperate parts and
> compared their time consumed.
> 
> I noticed that the mainline kernel does took much longer to return
> after the DMA request is done, signalled in this case by calling
> mxs_mmc_dma_irq_callback() [2] in the mxs-mmc driver. From here it
> takes about 150 us to get back to sdio_readsb().
> 
> An example for consuming much more time is the mainline mmc driver
> where it hangs in?mmc_wait_done() [2] about 50 us just calling
> complete(), whereas the vendor mmc driver almost immediately returns
> here.
> 
> I wonder why this call to complete consumes so much time? Any ideas?

i don't know why, but how about putting the SDIO clk signal parallel to the
GPIOs at your osci? So could get a better view of the runtime behavior.

Btw you should also verify the necessary time between to 2 packets.

Stefan

> 
> [1] http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/
> brcm80211/brcmfmac/bcmsdh.c#L488
> 
> [2] http://lxr.free-electrons.com/source/drivers/mmc/host/mxs-mmc.c#L17
> 9
> 
> [3] http://lxr.free-electrons.com/source/drivers/mmc/core/core.c#L386
> 
> Best regards,
> J?rg Krause

^ permalink raw reply

* [PATCH 8/9] mfd: wm97xx-core: core support for wm97xx Codec
From: Robert Jarzmik @ 2016-11-19 11:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118165040.GB19884@dell.home>

Lee Jones <lee.jones@linaro.org> writes:

> On Wed, 26 Oct 2016, Robert Jarzmik wrote:
>> +config MFD_WM97xx
>> +	tristate "Wolfson Microelectronics WM97xx"
>> +	select MFD_CORE
>> +	select REGMAP_AC97
>> +	select AC97_BUS_COMPAT if AC97_BUS_NEW
>> +	help
>> +
>
> Surplus '\n' here.
Right, for v2.

>> +	  The WM9705, WM9712 and WM9713 is a highly integrated hi-fi CODEC
>> +	  designed for smartphone applications.  As well as audio functionality
>> +	  it has on board GPIO and a touchscreen functionality which is
>> +	  supported via the relevant subsystems.  This driver provides core
>> +	  support for the WM97xx, in order to use the actual functionaltiy of
>
> Always spell check your work.
For v2.

>> + * Copyright (C) 2016 Robert Jarzmik
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * Features:
>> + *  - an AC97 audio codec
>> + *  - a touchscreen driver
>> + *  - a GPIO block
>
> Place this above the Copyright.
Right, for v2.

>> + */
>> +
>> +#include <linux/module.h>
>
> Why is this seperted?
No specific reason, I will remove the blank line, for v2.
>> +#include <linux/device.h>
>> +#include <linux/mfd/core.h>
>> +#include <linux/mfd/wm97xx.h>
>> +#include <linux/wm97xx.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +#include <sound/ac97/codec.h>
>> +#include <sound/ac97/compat.h>
>
> Alphabetical.
Ah yeah, the linux/wm97xx.h ... for v2.

>> +#define WM9705_VENDOR_ID 0x574d4c05
>> +#define WM9712_VENDOR_ID 0x574d4c12
>> +#define WM9713_VENDOR_ID 0x574d4c13
>> +#define WM97xx_VENDOR_ID_MASK 0xffffffff
>
> Use tabs, not spaces.
Right, for v2.

> These are probably better represented as enums.
These are ids, just as devicetree ids, or PCI ids, I don't think an enum will
fit.

>> +struct wm97xx_priv {
>> +	struct regmap *regmap;
>> +	struct snd_ac97 *ac97;
>> +	struct device *dev;
>> +};
>
> Replace _priv with _ddata.
Ok, will do, would you care to explain if this is something specific to your mfd
tree, or is it a kernel overall recommendation ?

> Also document using kerneldoc.
Right, for v2.
>
>> +static bool wm97xx_readable_reg(struct device *dev, unsigned int reg)
>> +{
>> +	switch (reg) {
>> +	case AC97_RESET ... AC97_PCM_SURR_DAC_RATE:
>> +	case AC97_PCM_LR_ADC_RATE:
>> +	case AC97_CENTER_LFE_MASTER:
>> +	case AC97_SPDIF ... AC97_LINE1_LEVEL:
>> +	case AC97_GPIO_CFG ... 0x5c:
>
> Please define.
>> +	case AC97_CODEC_CLASS_REV ... AC97_PCI_SID:
>> +	case 0x74 ... AC97_VENDOR_ID2:
>
> As above.
Right, for v2.

>> +static bool wm97xx_writeable_reg(struct device *dev, unsigned int reg)
>> +{
>> +	switch (reg) {
>> +	case AC97_VENDOR_ID1:
>> +	case AC97_VENDOR_ID2:
>> +		return false;
>> +	default:
>> +		return wm97xx_readable_reg(dev, reg);
>> +	}
>> +}
>> +
>> +static const struct reg_default wm97xx_reg_defaults[] = {
>> +};
>
> What's the point in this?
Ah, that's a reminder I have still more work on this patch ... Either I remove
support for wm9705 and wm9712 in the first version, or I complete it and add the
tables :
 - wm9705_reg_defaults
 - wm9712_reg_defaults

>> +static int wm9705_register(struct wm97xx_priv *wm97xx)
>> +{
>> +	return 0;
>> +}
>> +
>> +static int wm9712_register(struct wm97xx_priv *wm97xx)
>> +{
>> +	return 0;
>> +}
>
> I don't get it?
>
> Either populate or don't provide.
Same story as above, either I complete wm9705 and wm9712 support or I remove it.

>> +static int wm9713_register(struct wm97xx_priv *wm97xx,
>> +			   struct wm97xx_pdata *pdata)
>> +{
>
> What are you lining this up with?
Emacs ... I don't see your point though, seeing it not aligned in the diff chunk
doesn't mean it's not properly aligned.

>> +	struct wm97xx_platform_data codec_pdata;
>> +	const struct mfd_cell cells[] = {
>> +		{
>> +			.name = "wm9713-codec",
>> +			.platform_data = &codec_pdata,
>> +			.pdata_size = sizeof(codec_pdata),
>> +		},
>> +		{
>> +			.name = "wm97xx-ts",
>> +			.platform_data = &codec_pdata,
>> +			.pdata_size = sizeof(codec_pdata),
>> +		},
>> +	};
>> +
>> +	codec_pdata.ac97 = wm97xx->ac97;
>> +	codec_pdata.regmap = devm_regmap_init_ac97(wm97xx->ac97,
>> +						   &wm9713_regmap_config);
>> +	codec_pdata.batt_pdata = pdata->batt_pdata;
>> +	if (IS_ERR(codec_pdata.regmap))
>> +		return PTR_ERR(codec_pdata.regmap);
>
> This doesn't look like pdata.  You can get rid of all of this hoop
> jumping if you add it to ddata and set it as such.
You mean I should pass ddata to mfd sub-cells, right ?

>> +	return devm_mfd_add_devices(wm97xx->dev, -1, cells,
>
> Use the defines.
Ok.

>
>> +				    ARRAY_SIZE(cells), NULL, 0, NULL);
>> +}
>> +
>> +static int wm97xx_ac97_probe(struct ac97_codec_device *adev)
>
> This looks sound specific.
>
> Why isn't this a plane platform driver?
That's the whole purpose of the patch serie.

This serie transforms the wm97xx drivers from a platform driver model to an ac97
model, where the ac97 devices are automatically discovered. The long explanation
is in patch 0/9, on how it started and what is the global purpose.

The short story is : switch to the new AC97 bus driver model.

As for the "sound specific part", it's because AC97 bus is mainly used in sound
oriented drivers, but still the codec IPs provide more than just sound, as the
Wolfson codecs for instance.

>> +{
>> +	struct wm97xx_priv *wm97xx;
>> +	int ret;
>> +	void *pdata = snd_ac97_codec_get_platdata(adev);
>> +
>> +	wm97xx = devm_kzalloc(ac97_codec_dev2dev(adev),
>> +			      sizeof(*wm97xx), GFP_KERNEL);
>> +	if (!wm97xx)
>> +		return -ENOMEM;
>> +
>> +	wm97xx->dev = ac97_codec_dev2dev(adev);
>> +	wm97xx->ac97 = snd_ac97_compat_alloc(adev);
>> +	if (IS_ERR(wm97xx->ac97))
>> +		return PTR_ERR(wm97xx->ac97);
>> +
>> +
>> +	ac97_set_drvdata(adev, wm97xx);
>> +	dev_info(wm97xx->dev, "wm97xx core found, id=0x%x\n",
>> +		 adev->vendor_id);
>
> All of this ac97/sound stuff should be done in the ac97/sound driver.

Nope, it's not sound adherence you're seeing here, it's ac97 bus and driver
model adherence you're seeing. Would the bus be in drivers/ac97 instead of
sound/ac97, the code would remain the same, would be bus be i2c you would see
the same kind of calls but with i2c_xxx and not ac97_xxx.

The wm97xx needs an ac97 bus to interact with the hardware, to provide sound,
gpio, adc, etc ... functions. That's what is expressed here, and the fact that
this ac97 access has to shared amongst the mfd sub-cells, and that these cells
require :
 - wm97xx->ac97 : this one is for drivers/input/touchscreen/wm97xx-core.c

So the requirement in this case is not for ac97/sound but input/touchscreen.

>> diff --git a/include/linux/mfd/wm97xx.h b/include/linux/mfd/wm97xx.h
>> new file mode 100644
>> index 000000000000..627322f14d48
>> --- /dev/null
>> +++ b/include/linux/mfd/wm97xx.h
>> @@ -0,0 +1,31 @@
>> +/*
>> + * wm97xx client interface
>> + *
>> + * Copyright (C) 2016 Robert Jarzmik
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#ifndef __LINUX_MFD_WM97XX_H
>> +#define __LINUX_MFD_WM97XX_H
>> +
>> +struct regmap;
>> +struct wm97xx_batt_pdata;
>> +struct snd_ac97;
>
> Why can't you just add the include files?
I could, but I don't need to, do I ?
Moreover, if a mfd sub-cell doesn't use regmap for example, I won't include a
useless define.

Thanks for the review, Lee. This will iterate, I'll split out mfd patch(es) to
follow up the review with you and Mark to lessen the burden on your mailbox.

Cheers.

-- 
Robert

^ permalink raw reply

* [PATCH v3 1/6] Documentation: dt-bindings: Document STM32 ADC DT bindings
From: Jonathan Cameron @ 2016-11-19 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161116151549.m6phclc6cqy4lj2y@rob-hp-laptop>

On 16/11/16 15:15, Rob Herring wrote:
> On Tue, Nov 15, 2016 at 04:30:56PM +0100, Fabrice Gasnier wrote:
>> This patch adds documentation of device tree bindings for the STM32 ADC.
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>>  .../devicetree/bindings/iio/adc/st,stm32-adc.txt   | 83 ++++++++++++++++++++++
>>  1 file changed, 83 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
> 
> Acked-by: Rob Herring <robh@kernel.org>
Applied to the togreg branch of iio.git.

Thanks,

Jonathan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [RFC 2/6] drm/etnaviv: allow building etnaviv on omap devices
From: Joshua Clayton @ 2016-11-19 11:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118163342.5t2tbsw54k2gmqe3@rob-hp-laptop>

On Friday, November 18, 2016 10:33:42 AM Rob Herring wrote:
> On Thu, Nov 17, 2016 at 08:44:32PM -0600, Robert Nelson wrote:
> > Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
> > CC: Christian Gmeiner <christian.gmeiner@gmail.com>
> > CC: Russell King <rmk+kernel@arm.linux.org.uk>
> > CC: Lucas Stach <l.stach@pengutronix.de>
> > ---
> >  drivers/gpu/drm/etnaviv/Kconfig | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
> > index 2cde7a5..b776f41 100644
> > --- a/drivers/gpu/drm/etnaviv/Kconfig
> > +++ b/drivers/gpu/drm/etnaviv/Kconfig
> > @@ -2,7 +2,7 @@
> >  config DRM_ETNAVIV
> >  	tristate "ETNAVIV (DRM support for Vivante GPU IP cores)"
> >  	depends on DRM
> > -	depends on ARCH_MXC || ARCH_DOVE
> > +	depends on ARCH_MXC || ARCH_DOVE || ARCH_OMAP2PLUS
> 
> Why not just drop this line. Then it will get better build testing, too.
> 
> >  	select SHMEM
> >  	select TMPFS
> >  	select IOMMU_API
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
...building with ARCH=x86_64
            ^
drivers/gpu/drm/etnaviv/etnaviv_gpu.c: In function ?etnaviv_gpu_init?:
drivers/gpu/drm/etnaviv/etnaviv_gpu.c:633:18: error: ?PHYS_OFFSET? undeclared (first use in this function)
   if (dma_mask < PHYS_OFFSET + SZ_2G)
                  ^
drivers/gpu/drm/etnaviv/etnaviv_gpu.c:633:18: note: each undeclared identifier is reported only once for each function it appears in
make[4]: *** [scripts/Makefile.build:290: drivers/gpu/drm/etnaviv/etnaviv_gpu.o] Error 1
make[3]: *** [scripts/Makefile.build:440: drivers/gpu/drm/etnaviv] Error 2
make[2]: *** [scripts/Makefile.build:440: drivers/gpu/drm] Error 2
make[1]: *** [scripts/Makefile.build:440: drivers/gpu] Error 2
make: *** [Makefile:968: drivers] Error 2


...looks like this snippit is the only (compile time) problem:
 
 622         /*
 623          * Set the GPU linear window to be@the end of the DMA window, where
 624          * the CMA area is likely to reside. This ensures that we are able to
 625          * map the command buffers while having the linear window overlap as
 626          * much RAM as possible, so we can optimize mappings for other buffers.
 627          *
 628          * For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads
 629          * to different views of the memory on the individual engines.
 630          */
 631         if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
 632             (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
 633                 u32 dma_mask = (u32)dma_get_required_mask(gpu->dev);
 634                 if (dma_mask < PHYS_OFFSET + SZ_2G)
 635                         gpu->memory_base = PHYS_OFFSET;
 636                 else
 637                         gpu->memory_base = dma_mask - SZ_2G + 1;
 638         }

Joshua

^ permalink raw reply

* [PATCH v3 2/6] iio: adc: Add support for STM32 ADC core
From: Jonathan Cameron @ 2016-11-19 12:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-3-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> Add core driver for STMicroelectronics STM32 ADC (Analog to Digital
> Converter). STM32 ADC can be composed of up to 3 ADCs with shared
> resources like clock prescaler, common interrupt line and analog
> reference voltage.
> This core driver basically manages shared resources.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>

There is nothing in here that demands selecting a fixed regulator.
I've also switched the select regulator over to depends on inline with
other drivers in IIO that have a hard dependency on regulators.
Other than that which showed up during build tests, looks good to me.
Shout if I've broken anything with this change.

Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.

Thanks,

Jonathan
> ---
>  drivers/iio/adc/Kconfig          |  13 ++
>  drivers/iio/adc/Makefile         |   1 +
>  drivers/iio/adc/stm32-adc-core.c | 303 +++++++++++++++++++++++++++++++++++++++
>  drivers/iio/adc/stm32-adc-core.h |  52 +++++++
>  4 files changed, 369 insertions(+)
>  create mode 100644 drivers/iio/adc/stm32-adc-core.c
>  create mode 100644 drivers/iio/adc/stm32-adc-core.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 7edcf32..ff30239 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -419,6 +419,19 @@ config ROCKCHIP_SARADC
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called rockchip_saradc.
>  
> +config STM32_ADC_CORE
> +	tristate "STMicroelectronics STM32 adc core"
> +	depends on ARCH_STM32 || COMPILE_TEST
> +	depends on OF
> +	select REGULATOR
> +	select REGULATOR_FIXED_VOLTAGE
> +	help
> +	  Select this option to enable the core driver for STMicroelectronics
> +	  STM32 analog-to-digital converter (ADC).
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called stm32-adc-core.
> +
>  config STX104
>  	tristate "Apex Embedded Systems STX104 driver"
>  	depends on X86 && ISA_BUS_API
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 7a40c04..a1e8f44 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
>  obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
>  obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
>  obj-$(CONFIG_STX104) += stx104.o
> +obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
>  obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>  obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
>  obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> new file mode 100644
> index 0000000..4214b0c
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -0,0 +1,303 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * Inspired from: fsl-imx25-tsadc
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * 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/interrupt.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdesc.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +
> +#include "stm32-adc-core.h"
> +
> +/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
> +#define STM32F4_ADC_CSR			(STM32_ADCX_COMN_OFFSET + 0x00)
> +#define STM32F4_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x04)
> +
> +/* STM32F4_ADC_CSR - bit fields */
> +#define STM32F4_EOC3			BIT(17)
> +#define STM32F4_EOC2			BIT(9)
> +#define STM32F4_EOC1			BIT(1)
> +
> +/* STM32F4_ADC_CCR - bit fields */
> +#define STM32F4_ADC_ADCPRE_SHIFT	16
> +#define STM32F4_ADC_ADCPRE_MASK		GENMASK(17, 16)
> +
> +/* STM32 F4 maximum analog clock rate (from datasheet) */
> +#define STM32F4_ADC_MAX_CLK_RATE	36000000
> +
> +/**
> + * struct stm32_adc_priv - stm32 ADC core private data
> + * @irq:		irq for ADC block
> + * @domain:		irq domain reference
> + * @aclk:		clock reference for the analog circuitry
> + * @vref:		regulator reference
> + * @common:		common data for all ADC instances
> + */
> +struct stm32_adc_priv {
> +	int				irq;
> +	struct irq_domain		*domain;
> +	struct clk			*aclk;
> +	struct regulator		*vref;
> +	struct stm32_adc_common		common;
> +};
> +
> +static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
> +{
> +	return container_of(com, struct stm32_adc_priv, common);
> +}
> +
> +/* STM32F4 ADC internal common clock prescaler division ratios */
> +static int stm32f4_pclk_div[] = {2, 4, 6, 8};
> +
> +/**
> + * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
> + * @priv: stm32 ADC core private data
> + * Select clock prescaler used for analog conversions, before using ADC.
> + */
> +static int stm32f4_adc_clk_sel(struct platform_device *pdev,
> +			       struct stm32_adc_priv *priv)
> +{
> +	unsigned long rate;
> +	u32 val;
> +	int i;
> +
> +	rate = clk_get_rate(priv->aclk);
> +	for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
> +		if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
> +			break;
> +	}
> +	if (i >= ARRAY_SIZE(stm32f4_pclk_div))
> +		return -EINVAL;
> +
> +	val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
> +	val &= ~STM32F4_ADC_ADCPRE_MASK;
> +	val |= i << STM32F4_ADC_ADCPRE_SHIFT;
> +	writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR);
> +
> +	dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n",
> +		rate / (stm32f4_pclk_div[i] * 1000));
> +
> +	return 0;
> +}
> +
> +/* ADC common interrupt for all instances */
> +static void stm32_adc_irq_handler(struct irq_desc *desc)
> +{
> +	struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	u32 status;
> +
> +	chained_irq_enter(chip, desc);
> +	status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
> +
> +	if (status & STM32F4_EOC1)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 0));
> +
> +	if (status & STM32F4_EOC2)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 1));
> +
> +	if (status & STM32F4_EOC3)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 2));
> +
> +	chained_irq_exit(chip, desc);
> +};
> +
> +static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
> +				irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_data(irq, d->host_data);
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
> +{
> +	irq_set_chip_and_handler(irq, NULL, NULL);
> +	irq_set_chip_data(irq, NULL);
> +}
> +
> +static const struct irq_domain_ops stm32_adc_domain_ops = {
> +	.map = stm32_adc_domain_map,
> +	.unmap  = stm32_adc_domain_unmap,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int stm32_adc_irq_probe(struct platform_device *pdev,
> +			       struct stm32_adc_priv *priv)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	priv->irq = platform_get_irq(pdev, 0);
> +	if (priv->irq < 0) {
> +		dev_err(&pdev->dev, "failed to get irq\n");
> +		return priv->irq;
> +	}
> +
> +	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
> +					     &stm32_adc_domain_ops,
> +					     priv);
> +	if (!priv->domain) {
> +		dev_err(&pdev->dev, "Failed to add irq domain\n");
> +		return -ENOMEM;
> +	}
> +
> +	irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
> +	irq_set_handler_data(priv->irq, priv);
> +
> +	return 0;
> +}
> +
> +static void stm32_adc_irq_remove(struct platform_device *pdev,
> +				 struct stm32_adc_priv *priv)
> +{
> +	int hwirq;
> +
> +	for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
> +		irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
> +	irq_domain_remove(priv->domain);
> +	irq_set_chained_handler(priv->irq, NULL);
> +}
> +
> +static int stm32_adc_probe(struct platform_device *pdev)
> +{
> +	struct stm32_adc_priv *priv;
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	priv->common.base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(priv->common.base))
> +		return PTR_ERR(priv->common.base);
> +
> +	priv->vref = devm_regulator_get(&pdev->dev, "vref");
> +	if (IS_ERR(priv->vref)) {
> +		ret = PTR_ERR(priv->vref);
> +		dev_err(&pdev->dev, "vref get failed, %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = regulator_enable(priv->vref);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "vref enable failed\n");
> +		return ret;
> +	}
> +
> +	ret = regulator_get_voltage(priv->vref);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
> +		goto err_regulator_disable;
> +	}
> +	priv->common.vref_mv = ret / 1000;
> +	dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
> +
> +	priv->aclk = devm_clk_get(&pdev->dev, "adc");
> +	if (IS_ERR(priv->aclk)) {
> +		ret = PTR_ERR(priv->aclk);
> +		dev_err(&pdev->dev, "Can't get 'adc' clock\n");
> +		goto err_regulator_disable;
> +	}
> +
> +	ret = clk_prepare_enable(priv->aclk);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "adc clk enable failed\n");
> +		goto err_regulator_disable;
> +	}
> +
> +	ret = stm32f4_adc_clk_sel(pdev, priv);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "adc clk selection failed\n");
> +		goto err_clk_disable;
> +	}
> +
> +	ret = stm32_adc_irq_probe(pdev, priv);
> +	if (ret < 0)
> +		goto err_clk_disable;
> +
> +	platform_set_drvdata(pdev, &priv->common);
> +
> +	ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to populate DT children\n");
> +		goto err_irq_remove;
> +	}
> +
> +	return 0;
> +
> +err_irq_remove:
> +	stm32_adc_irq_remove(pdev, priv);
> +
> +err_clk_disable:
> +	clk_disable_unprepare(priv->aclk);
> +
> +err_regulator_disable:
> +	regulator_disable(priv->vref);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_remove(struct platform_device *pdev)
> +{
> +	struct stm32_adc_common *common = platform_get_drvdata(pdev);
> +	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
> +
> +	of_platform_depopulate(&pdev->dev);
> +	stm32_adc_irq_remove(pdev, priv);
> +	clk_disable_unprepare(priv->aclk);
> +	regulator_disable(priv->vref);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id stm32_adc_of_match[] = {
> +	{ .compatible = "st,stm32f4-adc-core" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> +
> +static struct platform_driver stm32_adc_driver = {
> +	.probe = stm32_adc_probe,
> +	.remove = stm32_adc_remove,
> +	.driver = {
> +		.name = "stm32-adc-core",
> +		.of_match_table = stm32_adc_of_match,
> +	},
> +};
> +module_platform_driver(stm32_adc_driver);
> +
> +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC core driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:stm32-adc-core");
> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
> new file mode 100644
> index 0000000..081fa5f
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc-core.h
> @@ -0,0 +1,52 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __STM32_ADC_H
> +#define __STM32_ADC_H
> +
> +/*
> + * STM32 - ADC global register map
> + * ________________________________________________________
> + * | Offset |                 Register                    |
> + * --------------------------------------------------------
> + * | 0x000  |                Master ADC1                  |
> + * --------------------------------------------------------
> + * | 0x100  |                Slave ADC2                   |
> + * --------------------------------------------------------
> + * | 0x200  |                Slave ADC3                   |
> + * --------------------------------------------------------
> + * | 0x300  |         Master & Slave common regs          |
> + * --------------------------------------------------------
> + */
> +#define STM32_ADC_MAX_ADCS		3
> +#define STM32_ADCX_COMN_OFFSET		0x300
> +
> +/**
> + * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
> + * @base:		control registers base cpu addr
> + * @vref_mv:		vref voltage (mv)
> + */
> +struct stm32_adc_common {
> +	void __iomem			*base;
> +	int				vref_mv;
> +};
> +
> +#endif
> 

^ permalink raw reply

* [PATCH v3 3/6] iio: adc: Add support for STM32 ADC
From: Jonathan Cameron @ 2016-11-19 12:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-4-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> This patch adds support for STMicroelectronics STM32 MCU's analog to
> digital converter.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.

Very nice driver!

Thanks,

Jonathan
> ---
>  drivers/iio/adc/Kconfig     |  10 +
>  drivers/iio/adc/Makefile    |   1 +
>  drivers/iio/adc/stm32-adc.c | 518 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 529 insertions(+)
>  create mode 100644 drivers/iio/adc/stm32-adc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index ff30239..f93b990 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -432,6 +432,16 @@ config STM32_ADC_CORE
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called stm32-adc-core.
>  
> +config STM32_ADC
> +	tristate "STMicroelectronics STM32 adc"
> +	depends on STM32_ADC_CORE
> +	help
> +	  Say yes here to build support for STMicroelectronics stm32 Analog
> +	  to Digital Converter (ADC).
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called stm32-adc.
> +
>  config STX104
>  	tristate "Apex Embedded Systems STX104 driver"
>  	depends on X86 && ISA_BUS_API
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index a1e8f44..8e02a94 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
>  obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
>  obj-$(CONFIG_STX104) += stx104.o
>  obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
> +obj-$(CONFIG_STM32_ADC) += stm32-adc.o
>  obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>  obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
>  obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> new file mode 100644
> index 0000000..5715e79
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -0,0 +1,518 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * 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/iio/iio.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +
> +#include "stm32-adc-core.h"
> +
> +/* STM32F4 - Registers for each ADC instance */
> +#define STM32F4_ADC_SR			0x00
> +#define STM32F4_ADC_CR1			0x04
> +#define STM32F4_ADC_CR2			0x08
> +#define STM32F4_ADC_SMPR1		0x0C
> +#define STM32F4_ADC_SMPR2		0x10
> +#define STM32F4_ADC_HTR			0x24
> +#define STM32F4_ADC_LTR			0x28
> +#define STM32F4_ADC_SQR1		0x2C
> +#define STM32F4_ADC_SQR2		0x30
> +#define STM32F4_ADC_SQR3		0x34
> +#define STM32F4_ADC_JSQR		0x38
> +#define STM32F4_ADC_JDR1		0x3C
> +#define STM32F4_ADC_JDR2		0x40
> +#define STM32F4_ADC_JDR3		0x44
> +#define STM32F4_ADC_JDR4		0x48
> +#define STM32F4_ADC_DR			0x4C
> +
> +/* STM32F4_ADC_SR - bit fields */
> +#define STM32F4_STRT			BIT(4)
> +#define STM32F4_EOC			BIT(1)
> +
> +/* STM32F4_ADC_CR1 - bit fields */
> +#define STM32F4_SCAN			BIT(8)
> +#define STM32F4_EOCIE			BIT(5)
> +
> +/* STM32F4_ADC_CR2 - bit fields */
> +#define STM32F4_SWSTART			BIT(30)
> +#define STM32F4_EXTEN_MASK		GENMASK(29, 28)
> +#define STM32F4_EOCS			BIT(10)
> +#define STM32F4_ADON			BIT(0)
> +
> +/* STM32F4_ADC_SQR1 - bit fields */
> +#define STM32F4_L_SHIFT			20
> +#define STM32F4_L_MASK			GENMASK(23, 20)
> +
> +/* STM32F4_ADC_SQR3 - bit fields */
> +#define STM32F4_SQ1_SHIFT		0
> +#define STM32F4_SQ1_MASK		GENMASK(4, 0)
> +
> +#define STM32_ADC_TIMEOUT_US		100000
> +#define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
> +
> +/**
> + * struct stm32_adc - private data of each ADC IIO instance
> + * @common:		reference to ADC block common data
> + * @offset:		ADC instance register offset in ADC block
> + * @completion:		end of single conversion completion
> + * @buffer:		data buffer
> + * @clk:		clock for this adc instance
> + * @irq:		interrupt for this adc instance
> + * @lock:		spinlock
> + */
> +struct stm32_adc {
> +	struct stm32_adc_common	*common;
> +	u32			offset;
> +	struct completion	completion;
> +	u16			*buffer;
> +	struct clk		*clk;
> +	int			irq;
> +	spinlock_t		lock;		/* interrupt lock */
> +};
> +
> +/**
> + * struct stm32_adc_chan_spec - specification of stm32 adc channel
> + * @type:	IIO channel type
> + * @channel:	channel number (single ended)
> + * @name:	channel name (single ended)
> + */
> +struct stm32_adc_chan_spec {
> +	enum iio_chan_type	type;
> +	int			channel;
> +	const char		*name;
> +};
> +
> +/* Input definitions common for all STM32F4 instances */
> +static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
> +	{ IIO_VOLTAGE, 0, "in0" },
> +	{ IIO_VOLTAGE, 1, "in1" },
> +	{ IIO_VOLTAGE, 2, "in2" },
> +	{ IIO_VOLTAGE, 3, "in3" },
> +	{ IIO_VOLTAGE, 4, "in4" },
> +	{ IIO_VOLTAGE, 5, "in5" },
> +	{ IIO_VOLTAGE, 6, "in6" },
> +	{ IIO_VOLTAGE, 7, "in7" },
> +	{ IIO_VOLTAGE, 8, "in8" },
> +	{ IIO_VOLTAGE, 9, "in9" },
> +	{ IIO_VOLTAGE, 10, "in10" },
> +	{ IIO_VOLTAGE, 11, "in11" },
> +	{ IIO_VOLTAGE, 12, "in12" },
> +	{ IIO_VOLTAGE, 13, "in13" },
> +	{ IIO_VOLTAGE, 14, "in14" },
> +	{ IIO_VOLTAGE, 15, "in15" },
> +};
> +
> +/**
> + * STM32 ADC registers access routines
> + * @adc: stm32 adc instance
> + * @reg: reg offset in adc instance
> + *
> + * Note: All instances share same base, with 0x0, 0x100 or 0x200 offset resp.
> + * for adc1, adc2 and adc3.
> + */
> +static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
> +{
> +	return readl_relaxed(adc->common->base + adc->offset + reg);
> +}
> +
> +static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
> +{
> +	return readw_relaxed(adc->common->base + adc->offset + reg);
> +}
> +
> +static void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
> +{
> +	writel_relaxed(val, adc->common->base + adc->offset + reg);
> +}
> +
> +static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +/**
> + * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
> +{
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
> +};
> +
> +/**
> + * stm32_adc_conv_irq_disable() - Disable end of conversion interrupt
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
> +{
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
> +}
> +
> +/**
> + * stm32_adc_start_conv() - Start conversions for regular channels.
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_start_conv(struct stm32_adc *adc)
> +{
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
> +
> +	/* Wait for Power-up time (tSTAB from datasheet) */
> +	usleep_range(2, 3);
> +
> +	/* Software start ? (e.g. trigger detection disabled ?) */
> +	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
> +		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
> +}
> +
> +static void stm32_adc_stop_conv(struct stm32_adc *adc)
> +{
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
> +
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_ADON);
> +}
> +
> +/**
> + * stm32_adc_single_conv() - Performs a single conversion
> + * @indio_dev: IIO device
> + * @chan: IIO channel
> + * @res: conversion result
> + *
> + * The function performs a single conversion on a given channel:
> + * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
> + * - Use SW trigger
> + * - Start conversion, then wait for interrupt completion.
> + */
> +static int stm32_adc_single_conv(struct iio_dev *indio_dev,
> +				 const struct iio_chan_spec *chan,
> +				 int *res)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +	long timeout;
> +	u32 val;
> +	u16 result;
> +	int ret;
> +
> +	reinit_completion(&adc->completion);
> +
> +	adc->buffer = &result;
> +
> +	/* Program chan number in regular sequence */
> +	val = stm32_adc_readl(adc, STM32F4_ADC_SQR3);
> +	val &= ~STM32F4_SQ1_MASK;
> +	val |= chan->channel << STM32F4_SQ1_SHIFT;
> +	stm32_adc_writel(adc, STM32F4_ADC_SQR3, val);
> +
> +	/* Set regular sequence len (0 for 1 conversion) */
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_SQR1, STM32F4_L_MASK);
> +
> +	/* Trigger detection disabled (conversion can be launched in SW) */
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
> +
> +	stm32_adc_conv_irq_enable(adc);
> +
> +	stm32_adc_start_conv(adc);
> +
> +	timeout = wait_for_completion_interruptible_timeout(
> +					&adc->completion, STM32_ADC_TIMEOUT);
> +	if (timeout == 0) {
> +		ret = -ETIMEDOUT;
> +	} else if (timeout < 0) {
> +		ret = timeout;
> +	} else {
> +		*res = result;
> +		ret = IIO_VAL_INT;
> +	}
> +
> +	stm32_adc_stop_conv(adc);
> +
> +	stm32_adc_conv_irq_disable(adc);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_read_raw(struct iio_dev *indio_dev,
> +			      struct iio_chan_spec const *chan,
> +			      int *val, int *val2, long mask)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = iio_device_claim_direct_mode(indio_dev);
> +		if (ret)
> +			return ret;
> +		if (chan->type == IIO_VOLTAGE)
> +			ret = stm32_adc_single_conv(indio_dev, chan, val);
> +		else
> +			ret = -EINVAL;
> +		iio_device_release_direct_mode(indio_dev);
> +		return ret;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = adc->common->vref_mv;
> +		*val2 = chan->scan_type.realbits;
> +		return IIO_VAL_FRACTIONAL_LOG2;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static irqreturn_t stm32_adc_isr(int irq, void *data)
> +{
> +	struct stm32_adc *adc = data;
> +	u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR);
> +
> +	if (status & STM32F4_EOC) {
> +		*adc->buffer = stm32_adc_readw(adc, STM32F4_ADC_DR);
> +		complete(&adc->completion);
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
> +			      const struct of_phandle_args *iiospec)
> +{
> +	int i;
> +
> +	for (i = 0; i < indio_dev->num_channels; i++)
> +		if (indio_dev->channels[i].channel == iiospec->args[0])
> +			return i;
> +
> +	return -EINVAL;
> +}
> +
> +/**
> + * stm32_adc_debugfs_reg_access - read or write register value
> + *
> + * To read a value from an ADC register:
> + *   echo [ADC reg offset] > direct_reg_access
> + *   cat direct_reg_access
> + *
> + * To write a value in a ADC register:
> + *   echo [ADC_reg_offset] [value] > direct_reg_access
> + */
> +static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
> +					unsigned reg, unsigned writeval,
> +					unsigned *readval)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +
> +	if (!readval)
> +		stm32_adc_writel(adc, reg, writeval);
> +	else
> +		*readval = stm32_adc_readl(adc, reg);
> +
> +	return 0;
> +}
> +
> +static const struct iio_info stm32_adc_iio_info = {
> +	.read_raw = stm32_adc_read_raw,
> +	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
> +	.of_xlate = stm32_adc_of_xlate,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
> +				    struct iio_chan_spec *chan,
> +				    const struct stm32_adc_chan_spec *channel,
> +				    int scan_index)
> +{
> +	chan->type = channel->type;
> +	chan->channel = channel->channel;
> +	chan->datasheet_name = channel->name;
> +	chan->scan_index = scan_index;
> +	chan->indexed = 1;
> +	chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
> +	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
> +	chan->scan_type.sign = 'u';
> +	chan->scan_type.realbits = 12;
> +	chan->scan_type.storagebits = 16;
> +}
> +
> +static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
> +{
> +	struct device_node *node = indio_dev->dev.of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	struct iio_chan_spec *channels;
> +	int scan_index = 0, num_channels;
> +	u32 val;
> +
> +	num_channels = of_property_count_u32_elems(node, "st,adc-channels");
> +	if (num_channels < 0 ||
> +	    num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) {
> +		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
> +		return num_channels < 0 ? num_channels : -EINVAL;
> +	}
> +
> +	channels = devm_kcalloc(&indio_dev->dev, num_channels,
> +				sizeof(struct iio_chan_spec), GFP_KERNEL);
> +	if (!channels)
> +		return -ENOMEM;
> +
> +	of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
> +		if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) {
> +			dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
> +			return -EINVAL;
> +		}
> +		stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
> +					&stm32f4_adc123_channels[val],
> +					scan_index);
> +		scan_index++;
> +	}
> +
> +	indio_dev->num_channels = scan_index;
> +	indio_dev->channels = channels;
> +
> +	return 0;
> +}
> +
> +static int stm32_adc_probe(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev;
> +	struct stm32_adc *adc;
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	adc = iio_priv(indio_dev);
> +	adc->common = dev_get_drvdata(pdev->dev.parent);
> +	spin_lock_init(&adc->lock);
> +	init_completion(&adc->completion);
> +
> +	indio_dev->name = dev_name(&pdev->dev);
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->dev.of_node = pdev->dev.of_node;
> +	indio_dev->info = &stm32_adc_iio_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	platform_set_drvdata(pdev, adc);
> +
> +	ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
> +	if (ret != 0) {
> +		dev_err(&pdev->dev, "missing reg property\n");
> +		return -EINVAL;
> +	}
> +
> +	adc->irq = platform_get_irq(pdev, 0);
> +	if (adc->irq < 0) {
> +		dev_err(&pdev->dev, "failed to get irq\n");
> +		return adc->irq;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr,
> +			       0, pdev->name, adc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request IRQ\n");
> +		return ret;
> +	}
> +
> +	adc->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(adc->clk)) {
> +		dev_err(&pdev->dev, "Can't get clock\n");
> +		return PTR_ERR(adc->clk);
> +	}
> +
> +	ret = clk_prepare_enable(adc->clk);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "clk enable failed\n");
> +		return ret;
> +	}
> +
> +	ret = stm32_adc_chan_of_init(indio_dev);
> +	if (ret < 0)
> +		goto err_clk_disable;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "iio dev register failed\n");
> +		goto err_clk_disable;
> +	}
> +
> +	return 0;
> +
> +err_clk_disable:
> +	clk_disable_unprepare(adc->clk);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_remove(struct platform_device *pdev)
> +{
> +	struct stm32_adc *adc = platform_get_drvdata(pdev);
> +	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> +
> +	iio_device_unregister(indio_dev);
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id stm32_adc_of_match[] = {
> +	{ .compatible = "st,stm32f4-adc" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> +
> +static struct platform_driver stm32_adc_driver = {
> +	.probe = stm32_adc_probe,
> +	.remove = stm32_adc_remove,
> +	.driver = {
> +		.name = "stm32-adc",
> +		.of_match_table = stm32_adc_of_match,
> +	},
> +};
> +module_platform_driver(stm32_adc_driver);
> +
> +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:stm32-adc");
> 

^ permalink raw reply

* [PATCH v3 4/6] ARM: configs: stm32: enable ADC driver
From: Jonathan Cameron @ 2016-11-19 12:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-5-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
The driver is now on it's way in.  I'm assuming this and the two device tree patches
will go via the relevant route to arm-soc.

Thanks,

Jonathan
> ---
>  arch/arm/configs/stm32_defconfig | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
> index 1e5ec2a..5d241e0 100644
> --- a/arch/arm/configs/stm32_defconfig
> +++ b/arch/arm/configs/stm32_defconfig
> @@ -57,6 +57,9 @@ CONFIG_LEDS_TRIGGERS=y
>  CONFIG_LEDS_TRIGGER_HEARTBEAT=y
>  CONFIG_DMADEVICES=y
>  CONFIG_STM32_DMA=y
> +CONFIG_IIO=y
> +CONFIG_STM32_ADC_CORE=y
> +CONFIG_STM32_ADC=y
>  # CONFIG_FILE_LOCKING is not set
>  # CONFIG_DNOTIFY is not set
>  # CONFIG_INOTIFY_USER is not set
> 

^ permalink raw reply

* [PATCH 0/6] ASoC: samsung: Minor cleanup for old machines
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Few patches removing dead code (machines not supported).

The third patch ([RFT 3/6] ASoC: samsung: smdk_wm8580: Remove machine
specific quirks) requires testing. I hope I understood the code
correctly.

The last ARM patch is independent. I will take it through samsung-soc
tree. I put it here for reference.

Best regards,
Krzysztof

Krzysztof Kozlowski (6):
  ASoC: samsung: Remove non-existing MACH dependencies
  ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types
    usage
  ASoC: samsung: smdk_wm8580: Remove machine specific quirks
  ASoC: samsung: Enable COMPILE_TEST for SmartQ and WM8580
  ASoC: samsung: Enable COMPILE_TEST for entire Samsung ASoc
  ARM: s5pv210_defconfig: Remove old MACHs

 arch/arm/configs/s5pv210_defconfig |  4 ----
 sound/soc/samsung/Kconfig          |  8 +++++---
 sound/soc/samsung/smdk_wm8580.c    | 17 ++---------------
 3 files changed, 7 insertions(+), 22 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/6] ASoC: samsung: Remove non-existing MACH dependencies
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

MACH_SMDKC100 was removed in commit b8529ec1c1b0 ("ARM: S5PC100: no more
support S5PC100 SoC"). MACH_SMDKV210 and MACH_SMDKC110 in commit
28c8331d386 ("ARM: S5PV210: Remove support for board files").

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 79ae6a7c93ff..ea0fa9971a0c 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -49,7 +49,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
 	tristate "SoC I2S Audio support for WM8580 on SMDK"
-	depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110
+	depends on MACH_SMDK6410
 	depends on I2C
 	select SND_SOC_WM8580
 	select SND_SAMSUNG_I2S
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

MACH_SMDKC100, MACH_SMDKV210 and MACH_SMDKC110 are no longer supported
so drop the dead code.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/smdk_wm8580.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 548bfd993788..59fd3b8fd414 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -14,8 +14,6 @@
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
-#include <asm/mach-types.h>
-
 #include "../codecs/wm8580.h"
 #include "i2s.h"
 
@@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
 	int ret;
 	char *str;
 
-	if (machine_is_smdkc100()
-			|| machine_is_smdkv210() || machine_is_smdkc110()) {
-		smdk.num_links = 3;
-	} else if (machine_is_smdk6410()) {
-		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
-		str[strlen(str) - 1] = '2';
-		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
-		str[strlen(str) - 1] = '2';
-	}
+	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
+	str[strlen(str) - 1] = '2';
+	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
+	str[strlen(str) - 1] = '2';
 
 	smdk_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!smdk_snd_device)
-- 
2.7.4

^ permalink raw reply related

* [RFT 3/6] ASoC: samsung: smdk_wm8580: Remove machine specific quirks
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

The driver no longer differentiates between machines (S3C24xx machines
are not supported by it) so there is no need to override I2S device id
in cpu_dai_name.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

---

Not tested. The driver did not override .platform_name which looks
suspicious to me. However I did not want to add changes which could have
some visible impact on output code.
---
 sound/soc/samsung/smdk_wm8580.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 59fd3b8fd414..3bf33387dfeb 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -155,7 +155,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 	[PRI_PLAYBACK] = { /* Primary Playback i/f */
 		.name = "WM8580 PAIF RX",
 		.stream_name = "Playback",
-		.cpu_dai_name = "samsung-i2s.0",
+		.cpu_dai_name = "samsung-i2s.2",
 		.codec_dai_name = "wm8580-hifi-playback",
 		.platform_name = "samsung-i2s.0",
 		.codec_name = "wm8580.0-001b",
@@ -165,7 +165,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 	[PRI_CAPTURE] = { /* Primary Capture i/f */
 		.name = "WM8580 PAIF TX",
 		.stream_name = "Capture",
-		.cpu_dai_name = "samsung-i2s.0",
+		.cpu_dai_name = "samsung-i2s.2",
 		.codec_dai_name = "wm8580-hifi-capture",
 		.platform_name = "samsung-i2s.0",
 		.codec_name = "wm8580.0-001b",
@@ -202,12 +202,6 @@ static struct platform_device *smdk_snd_device;
 static int __init smdk_audio_init(void)
 {
 	int ret;
-	char *str;
-
-	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
-	str[strlen(str) - 1] = '2';
-	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
-	str[strlen(str) - 1] = '2';
 
 	smdk_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!smdk_snd_device)
-- 
2.7.4

^ 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