* [PATCH 2/3][v3] arm64: freescale: ls2080a: Split devicetree for code resuability
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini, Priyanka Jain, Ashish Kumar
In-Reply-To: <1483938896-2221-1-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
LS2088A and LS2080A are similar SoCs with a few differences like
ARM cores etc.
Reorganize the LS2080A device tree to move the common nodes to:
- fsl-ls208xa.dtsi
- fsl-ls208xa-rdb.dtsi
- fsl-ls208xa-qds.dtsi
Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
---
Changes for v3:
- rename dts/dtsi files
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 154 +----
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts | 106 +---
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 715 +---------------------
3 files changed, 26 insertions(+), 949 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
index 8bc1f8f..3cf4a5c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
@@ -1,8 +1,9 @@
/*
* Device Tree file for Freescale LS2080a QDS Board.
*
- * Copyright (C) 2015, Freescale Semiconductor
+ * Copyright (C) 2015-17, Freescale Semiconductor
*
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
* Bhupesh Sharma <bhupesh.sharma-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
*
* This file is dual-licensed: you can use it either under the terms
@@ -62,153 +63,4 @@
};
};
-&esdhc {
- status = "okay";
-};
-
-&ifc {
- status = "okay";
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x5 0x80000000 0x08000000
- 0x2 0x0 0x5 0x30000000 0x00010000
- 0x3 0x0 0x5 0x20000000 0x00010000>;
-
- nor@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x0 0x0 0x8000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand@2,0 {
- compatible = "fsl,ifc-nand";
- reg = <0x2 0x0 0x10000>;
- };
-
- cpld@3,0 {
- reg = <0x3 0x0 0x10000>;
- compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
- };
-};
-
-&i2c0 {
- status = "okay";
- pca9547@77 {
- compatible = "nxp,pca9547";
- reg = <0x77>;
- #address-cells = <1>;
- #size-cells = <0>;
- i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x00>;
- rtc@68 {
- compatible = "dallas,ds3232";
- reg = <0x68>;
- };
- };
-
- i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x02>;
-
- ina220@40 {
- compatible = "ti,ina220";
- reg = <0x40>;
- shunt-resistor = <500>;
- };
-
- ina220@41 {
- compatible = "ti,ina220";
- reg = <0x41>;
- shunt-resistor = <1000>;
- };
- };
-
- i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x3>;
-
- adt7481@4c {
- compatible = "adi,adt7461";
- reg = <0x4c>;
- };
- };
- };
-};
-
-&i2c1 {
- status = "disabled";
-};
-
-&i2c2 {
- status = "disabled";
-};
-
-&i2c3 {
- status = "disabled";
-};
-
-&dspi {
- status = "okay";
- dflash0: n25q128a {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <0>;
- };
- dflash1: sst25wf040b {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <1>;
- };
- dflash2: en25s64 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <2>;
- };
-};
-
-&qspi {
- status = "okay";
- flash0: s25fl256s1@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <20000000>;
- reg = <0>;
- };
- flash2: s25fl256s1@2 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <20000000>;
- reg = <0>;
- };
-};
-
-&sata0 {
- status = "okay";
-};
-
-&sata1 {
- status = "okay";
-};
-
-&usb0 {
- status = "okay";
-};
-
-&usb1 {
- status = "okay";
-};
+#include "fsl-ls208xa-qds.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
index 2ff46ca..d5224fb 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
@@ -62,108 +62,4 @@
};
};
-&esdhc {
- status = "okay";
-};
-
-&ifc {
- status = "okay";
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x5 0x80000000 0x08000000
- 0x2 0x0 0x5 0x30000000 0x00010000
- 0x3 0x0 0x5 0x20000000 0x00010000>;
-
- nor@0,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x0 0x0 0x8000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand@2,0 {
- compatible = "fsl,ifc-nand";
- reg = <0x2 0x0 0x10000>;
- };
-
- cpld@3,0 {
- reg = <0x3 0x0 0x10000>;
- compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
- };
-
-};
-
-&i2c0 {
- status = "okay";
- pca9547@75 {
- compatible = "nxp,pca9547";
- reg = <0x75>;
- #address-cells = <1>;
- #size-cells = <0>;
- i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x01>;
- rtc@68 {
- compatible = "dallas,ds3232";
- reg = <0x68>;
- };
- };
-
- i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x3>;
-
- adt7481@4c {
- compatible = "adi,adt7461";
- reg = <0x4c>;
- };
- };
- };
-};
-
-&i2c1 {
- status = "disabled";
-};
-
-&i2c2 {
- status = "disabled";
-};
-
-&i2c3 {
- status = "disabled";
-};
-
-&dspi {
- status = "okay";
- dflash0: n25q512a {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "st,m25p80";
- spi-max-frequency = <3000000>;
- reg = <0>;
- };
-};
-
-&qspi {
- status = "disabled";
-};
-
-&sata0 {
- status = "okay";
-};
-
-&sata1 {
- status = "okay";
-};
-
-&usb0 {
- status = "okay";
-};
-
-&usb1 {
- status = "okay";
-};
+#include "fsl-ls208xa-rdb.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index e5935f2..35801f3 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -1,8 +1,9 @@
/*
* Device Tree Include file for Freescale Layerscape-2080A family SoC.
*
- * Copyright (C) 2014-2015, Freescale Semiconductor
+ * Copyright (C) 2014-2017, Freescale Semiconductor
*
+ * Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
* Bhupesh Sharma <bhupesh.sharma-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
*
* This file is dual-licensed: you can use it either under the terms
@@ -149,697 +150,25 @@
};
};
- memory@80000000 {
- device_type = "memory";
- reg = <0x00000000 0x80000000 0 0x80000000>;
- /* DRAM space - 1, size : 2 GB DRAM */
- };
-
- sysclk: sysclk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <100000000>;
- clock-output-names = "sysclk";
- };
-
- gic: interrupt-controller@6000000 {
- compatible = "arm,gic-v3";
- reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
- <0x0 0x06100000 0 0x100000>, /* GICR (RD_base + SGI_base) */
- <0x0 0x0c0c0000 0 0x2000>, /* GICC */
- <0x0 0x0c0d0000 0 0x1000>, /* GICH */
- <0x0 0x0c0e0000 0 0x20000>; /* GICV */
- #interrupt-cells = <3>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- interrupt-controller;
- interrupts = <1 9 0x4>;
-
- its: gic-its@6020000 {
- compatible = "arm,gic-v3-its";
- msi-controller;
- reg = <0x0 0x6020000 0 0x20000>;
- };
- };
-
- rstcr: syscon@1e60000 {
- compatible = "fsl,ls2080a-rstcr", "syscon";
- reg = <0x0 0x1e60000 0x0 0x4>;
- };
-
- reboot {
- compatible ="syscon-reboot";
- regmap = <&rstcr>;
- offset = <0x0>;
- mask = <0x2>;
- };
-
- timer {
- compatible = "arm,armv8-timer";
- interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
- <1 14 4>, /* Physical Non-Secure PPI, active-low */
- <1 11 4>, /* Virtual PPI, active-low */
- <1 10 4>; /* Hypervisor PPI, active-low */
- fsl,erratum-a008585;
- };
-
- pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
- };
-
- soc {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- clockgen: clocking@1300000 {
- compatible = "fsl,ls2080a-clockgen";
- reg = <0 0x1300000 0 0xa0000>;
- #clock-cells = <2>;
- clocks = <&sysclk>;
- };
-
- dcfg: dcfg@1e00000 {
- compatible = "fsl,ls2080a-dcfg", "syscon";
- reg = <0x0 0x1e00000 0x0 0x10000>;
- little-endian;
- };
-
- tmu: tmu@1f80000 {
- compatible = "fsl,qoriq-tmu";
- reg = <0x0 0x1f80000 0x0 0x10000>;
- interrupts = <0 23 0x4>;
- fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
- fsl,tmu-calibration = <0x00000000 0x00000026
- 0x00000001 0x0000002d
- 0x00000002 0x00000032
- 0x00000003 0x00000039
- 0x00000004 0x0000003f
- 0x00000005 0x00000046
- 0x00000006 0x0000004d
- 0x00000007 0x00000054
- 0x00000008 0x0000005a
- 0x00000009 0x00000061
- 0x0000000a 0x0000006a
- 0x0000000b 0x00000071
-
- 0x00010000 0x00000025
- 0x00010001 0x0000002c
- 0x00010002 0x00000035
- 0x00010003 0x0000003d
- 0x00010004 0x00000045
- 0x00010005 0x0000004e
- 0x00010006 0x00000057
- 0x00010007 0x00000061
- 0x00010008 0x0000006b
- 0x00010009 0x00000076
-
- 0x00020000 0x00000029
- 0x00020001 0x00000033
- 0x00020002 0x0000003d
- 0x00020003 0x00000049
- 0x00020004 0x00000056
- 0x00020005 0x00000061
- 0x00020006 0x0000006d
-
- 0x00030000 0x00000021
- 0x00030001 0x0000002a
- 0x00030002 0x0000003c
- 0x00030003 0x0000004e>;
- little-endian;
- #thermal-sensor-cells = <1>;
- };
-
- thermal-zones {
- cpu_thermal: cpu-thermal {
- polling-delay-passive = <1000>;
- polling-delay = <5000>;
-
- thermal-sensors = <&tmu 4>;
-
- trips {
- cpu_alert: cpu-alert {
- temperature = <75000>;
- hysteresis = <2000>;
- type = "passive";
- };
- cpu_crit: cpu-crit {
- temperature = <85000>;
- hysteresis = <2000>;
- type = "critical";
- };
- };
-
- cooling-maps {
- map0 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu0 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map1 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu2 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map2 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu4 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- map3 {
- trip = <&cpu_alert>;
- cooling-device =
- <&cpu6 THERMAL_NO_LIMIT
- THERMAL_NO_LIMIT>;
- };
- };
- };
- };
-
- serial0: serial@21c0500 {
- compatible = "fsl,ns16550", "ns16550a";
- reg = <0x0 0x21c0500 0x0 0x100>;
- clocks = <&clockgen 4 3>;
- interrupts = <0 32 0x4>; /* Level high type */
- };
-
- serial1: serial@21c0600 {
- compatible = "fsl,ns16550", "ns16550a";
- reg = <0x0 0x21c0600 0x0 0x100>;
- clocks = <&clockgen 4 3>;
- interrupts = <0 32 0x4>; /* Level high type */
- };
-
- cluster1_core0_watchdog: wdt@c000000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc000000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster1_core1_watchdog: wdt@c010000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc010000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster2_core0_watchdog: wdt@c100000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc100000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster2_core1_watchdog: wdt@c110000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc110000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster3_core0_watchdog: wdt@c200000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc200000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster3_core1_watchdog: wdt@c210000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc210000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster4_core0_watchdog: wdt@c300000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc300000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- cluster4_core1_watchdog: wdt@c310000 {
- compatible = "arm,sp805-wdt", "arm,primecell";
- reg = <0x0 0xc310000 0x0 0x1000>;
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "apb_pclk", "wdog_clk";
- };
-
- fsl_mc: fsl-mc@80c000000 {
- compatible = "fsl,qoriq-mc";
- reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */
- <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
- msi-parent = <&its>;
- #address-cells = <3>;
- #size-cells = <1>;
-
- /*
- * Region type 0x0 - MC portals
- * Region type 0x1 - QBMAN portals
- */
- ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
- 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
-
- /*
- * Define the maximum number of MACs present on the SoC.
- */
- dpmacs {
- #address-cells = <1>;
- #size-cells = <0>;
-
- dpmac1: dpmac@1 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x1>;
- };
-
- dpmac2: dpmac@2 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x2>;
- };
-
- dpmac3: dpmac@3 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x3>;
- };
-
- dpmac4: dpmac@4 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x4>;
- };
-
- dpmac5: dpmac@5 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x5>;
- };
-
- dpmac6: dpmac@6 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x6>;
- };
-
- dpmac7: dpmac@7 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x7>;
- };
-
- dpmac8: dpmac@8 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x8>;
- };
-
- dpmac9: dpmac@9 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x9>;
- };
-
- dpmac10: dpmac@a {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xa>;
- };
-
- dpmac11: dpmac@b {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xb>;
- };
-
- dpmac12: dpmac@c {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xc>;
- };
-
- dpmac13: dpmac@d {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xd>;
- };
-
- dpmac14: dpmac@e {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xe>;
- };
-
- dpmac15: dpmac@f {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0xf>;
- };
-
- dpmac16: dpmac@10 {
- compatible = "fsl,qoriq-mc-dpmac";
- reg = <0x10>;
- };
- };
- };
-
- smmu: iommu@5000000 {
- compatible = "arm,mmu-500";
- reg = <0 0x5000000 0 0x800000>;
- #global-interrupts = <12>;
- interrupts = <0 13 4>, /* global secure fault */
- <0 14 4>, /* combined secure interrupt */
- <0 15 4>, /* global non-secure fault */
- <0 16 4>, /* combined non-secure interrupt */
- /* performance counter interrupts 0-7 */
- <0 211 4>, <0 212 4>,
- <0 213 4>, <0 214 4>,
- <0 215 4>, <0 216 4>,
- <0 217 4>, <0 218 4>,
- /* per context interrupt, 64 interrupts */
- <0 146 4>, <0 147 4>,
- <0 148 4>, <0 149 4>,
- <0 150 4>, <0 151 4>,
- <0 152 4>, <0 153 4>,
- <0 154 4>, <0 155 4>,
- <0 156 4>, <0 157 4>,
- <0 158 4>, <0 159 4>,
- <0 160 4>, <0 161 4>,
- <0 162 4>, <0 163 4>,
- <0 164 4>, <0 165 4>,
- <0 166 4>, <0 167 4>,
- <0 168 4>, <0 169 4>,
- <0 170 4>, <0 171 4>,
- <0 172 4>, <0 173 4>,
- <0 174 4>, <0 175 4>,
- <0 176 4>, <0 177 4>,
- <0 178 4>, <0 179 4>,
- <0 180 4>, <0 181 4>,
- <0 182 4>, <0 183 4>,
- <0 184 4>, <0 185 4>,
- <0 186 4>, <0 187 4>,
- <0 188 4>, <0 189 4>,
- <0 190 4>, <0 191 4>,
- <0 192 4>, <0 193 4>,
- <0 194 4>, <0 195 4>,
- <0 196 4>, <0 197 4>,
- <0 198 4>, <0 199 4>,
- <0 200 4>, <0 201 4>,
- <0 202 4>, <0 203 4>,
- <0 204 4>, <0 205 4>,
- <0 206 4>, <0 207 4>,
- <0 208 4>, <0 209 4>;
- mmu-masters = <&fsl_mc 0x300 0>;
- };
-
- dspi: dspi@2100000 {
- status = "disabled";
- compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2100000 0x0 0x10000>;
- interrupts = <0 26 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- clock-names = "dspi";
- spi-num-chipselects = <5>;
- bus-num = <0>;
- };
-
- esdhc: esdhc@2140000 {
- status = "disabled";
- compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
- reg = <0x0 0x2140000 0x0 0x10000>;
- interrupts = <0 28 0x4>; /* Level high type */
- clock-frequency = <0>; /* Updated by bootloader */
- voltage-ranges = <1800 1800 3300 3300>;
- sdhci,auto-cmd12;
- little-endian;
- bus-width = <4>;
- };
-
- gpio0: gpio@2300000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2300000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio1: gpio@2310000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2310000 0x0 0x10000>;
- interrupts = <0 36 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio2: gpio@2320000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2320000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- gpio3: gpio@2330000 {
- compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
- reg = <0x0 0x2330000 0x0 0x10000>;
- interrupts = <0 37 0x4>; /* Level high type */
- gpio-controller;
- little-endian;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
-
- i2c0: i2c@2000000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2000000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c1: i2c@2010000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2010000 0x0 0x10000>;
- interrupts = <0 34 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c2: i2c@2020000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2020000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- i2c3: i2c@2030000 {
- status = "disabled";
- compatible = "fsl,vf610-i2c";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x2030000 0x0 0x10000>;
- interrupts = <0 35 0x4>; /* Level high type */
- clock-names = "i2c";
- clocks = <&clockgen 4 3>;
- };
-
- ifc: ifc@2240000 {
- compatible = "fsl,ifc", "simple-bus";
- reg = <0x0 0x2240000 0x0 0x20000>;
- interrupts = <0 21 0x4>; /* Level high type */
- little-endian;
- #address-cells = <2>;
- #size-cells = <1>;
-
- ranges = <0 0 0x5 0x80000000 0x08000000
- 2 0 0x5 0x30000000 0x00010000
- 3 0 0x5 0x20000000 0x00010000>;
- };
-
- qspi: quadspi@20c0000 {
- status = "disabled";
- compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x0 0x20c0000 0x0 0x10000>,
- <0x0 0x20000000 0x0 0x10000000>;
- reg-names = "QuadSPI", "QuadSPI-memory";
- interrupts = <0 25 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>, <&clockgen 4 3>;
- clock-names = "qspi_en", "qspi";
- };
-
- pcie@3400000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
- 0x10 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 108 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>,
- <0000 0 0 2 &gic 0 0 0 110 4>,
- <0000 0 0 3 &gic 0 0 0 111 4>,
- <0000 0 0 4 &gic 0 0 0 112 4>;
- };
-
- pcie@3500000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
- 0x12 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 113 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>,
- <0000 0 0 2 &gic 0 0 0 115 4>,
- <0000 0 0 3 &gic 0 0 0 116 4>,
- <0000 0 0 4 &gic 0 0 0 117 4>;
- };
-
- pcie@3600000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */
- 0x14 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 118 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <8>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>,
- <0000 0 0 2 &gic 0 0 0 120 4>,
- <0000 0 0 3 &gic 0 0 0 121 4>,
- <0000 0 0 4 &gic 0 0 0 122 4>;
- };
-
- pcie@3700000 {
- compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
- "snps,dw-pcie";
- reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */
- 0x16 0x00000000 0x0 0x00002000>; /* configuration space */
- reg-names = "regs", "config";
- interrupts = <0 123 0x4>; /* Level high type */
- interrupt-names = "intr";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- dma-coherent;
- num-lanes = <4>;
- bus-range = <0x0 0xff>;
- ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000 /* downstream I/O */
- 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
- msi-parent = <&its>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>,
- <0000 0 0 2 &gic 0 0 0 125 4>,
- <0000 0 0 3 &gic 0 0 0 126 4>,
- <0000 0 0 4 &gic 0 0 0 127 4>;
- };
-
- sata0: sata@3200000 {
- status = "disabled";
- compatible = "fsl,ls2080a-ahci";
- reg = <0x0 0x3200000 0x0 0x10000>;
- interrupts = <0 133 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- dma-coherent;
- };
-
- sata1: sata@3210000 {
- status = "disabled";
- compatible = "fsl,ls2080a-ahci";
- reg = <0x0 0x3210000 0x0 0x10000>;
- interrupts = <0 136 0x4>; /* Level high type */
- clocks = <&clockgen 4 3>;
- dma-coherent;
- };
-
- usb0: usb3@3100000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3100000 0x0 0x10000>;
- interrupts = <0 80 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- };
-
- usb1: usb3@3110000 {
- status = "disabled";
- compatible = "snps,dwc3";
- reg = <0x0 0x3110000 0x0 0x10000>;
- interrupts = <0 81 0x4>; /* Level high type */
- dr_mode = "host";
- snps,quirk-frame-length-adjustment = <0x20>;
- snps,dis_rxdet_inp3_quirk;
- };
-
- ccn@4000000 {
- compatible = "arm,ccn-504";
- reg = <0x0 0x04000000 0x0 0x01000000>;
- interrupts = <0 12 4>;
- };
- };
-
- ddr1: memory-controller@1080000 {
- compatible = "fsl,qoriq-memory-controller";
- reg = <0x0 0x1080000 0x0 0x1000>;
- interrupts = <0 17 0x4>;
- little-endian;
- };
+ #include "fsl-ls208xa.dtsi"
+};
- ddr2: memory-controller@1090000 {
- compatible = "fsl,qoriq-memory-controller";
- reg = <0x0 0x1090000 0x0 0x1000>;
- interrupts = <0 18 0x4>;
- little-endian;
- };
+&pcie1 {
+ ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
+
+&pcie2 {
+ ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
+
+&pcie3 {
+ ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
};
+
+&pcie4 {
+ ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000 /* downstream I/O */
+ 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ };
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/3][v3] dt-bindings: Add compatible for LS2088A QDS and RDB board
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini, Priyanka Jain, Ashish Kumar
In-Reply-To: <1483938896-2221-1-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes for v2:
- reorganize LS2088A device tree to use common
nodes from LS2080A device trees.
- Both LS2080A and LS2088A have same hardware
controllers, so separate dt-binding patches for
pcie, gpio, dspi, qspi are not required.
Documentation/devicetree/bindings/arm/fsl.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index d6ee9c6..75ad8c5 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -179,3 +179,14 @@ LS2080A ARMv8 based RDB Board
Required root node properties:
- compatible = "fsl,ls2080a-rdb", "fsl,ls2080a";
+LS2088A SoC
+Required root node properties:
+ - compatible = "fsl,ls2088a";
+
+LS2088A ARMv8 based QDS Board
+Required root node properties:
+ - compatible = "fsl,ls2088a-qds", "fsl,ls2088a";
+
+LS2088A ARMv8 based RDB Board
+Required root node properties:
+ - compatible = "fsl,ls2088a-rdb", "fsl,ls2088a";
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/3][v3] Add QorIQ LS2088A platform support
From: Abhimanyu Saini @ 2017-01-09 5:14 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: scott.wood-3arQi8VN3Tc, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Abhimanyu Saini
This patchset adds support for the QorIQ LS2088A SoC.
LS2088A SoC is similar to LS2080A SoC with a few differences like it has A72 cores.
This patchset
- reorganize LS2088A DTS/DTSI for code reuseability
- adds LS2088A device dtsi and dts files.
Abhimanyu Saini (3):
dt-bindings: Add compatible for LS2088A QDS and RDB boards
arm64: freescale: ls2080a: Split devicetree for code resuability
arm64: Add DTS support for FSL's LS2088A SoC
Changes for v3:
- rename dts/dtsi files
Changes for v2:
- reorganize LS2088A device tree to use common
nodes from LS2080A device trees.
- Both LS2080A and LS2088A have same hardware
controllers, so separate dt-binding patches for
pcie, gpio, dspi, qspi are not required.
Abhimanyu Saini (3):
dt-bindings: Add compatible for LS2088A QDS and RDB board
arm64: freescale: ls2080a: Split devicetree for code resuability
arm64: freescale: ls2088a: Add DTS support for FSL's LS2088A SoC
Documentation/devicetree/bindings/arm/fsl.txt | 11 +
arch/arm64/boot/dts/freescale/Makefile | 2 +
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 154 +----
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts | 106 +---
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 715 +---------------------
arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts | 65 ++
arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts | 65 ++
arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi | 162 +++++
8 files changed, 331 insertions(+), 949 deletions(-)
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 4/4] mmc: pwrseq-simple: add disable-post-power-on option
From: Matt Ranostay @ 2017-01-09 4:53 UTC (permalink / raw)
To: Linus Walleij
Cc: Ulf Hansson, Rob Herring, devicetree@vger.kernel.org,
linux-mmc@vger.kernel.org, Tony Lindgren, Liam Breck
In-Reply-To: <CACRpkdad7JXzxYfuB_XYdo2vuZmEt5iWgq79Va5cWwTaJc6Y5Q@mail.gmail.com>
On Fri, Dec 30, 2016 at 12:05 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> On Mon, Dec 19, 2016 at 1:01 AM, Matt Ranostay <matt@ranostay.consulting> wrote:
>
>> * SD8787 has a "powerdown" line, and CW1200 has a "powerup" line.. I
>> know this is a simple logic inversion.
>
> If this is a GPIO line, the GPIO subsystem can flag a line for
> inverted logic. GPIO_ACTIVE_LOW from device tree for example.
Slight ping on Ulf on this thread :).
I do understand the inverted logic flag but that doesn't help if there
are different logic states between various chipsets.
>
> Yours,
> Linus Walleij
^ permalink raw reply
* gpio_key.c device tree question
From: noman pouigt @ 2017-01-09 3:42 UTC (permalink / raw)
To: dmitry.torokhov, linux-input; +Cc: devicetree, linux-kernel
Hello,
I am trying to see how to disable the sub device nodes in
gpio_keys device node.
I have this in my base dtsi file:
#include "vendor_file.dtsi"
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
pinctrl-names = "gpio_key_active","gpio_key_suspend";
pinctrl-0 = <&key_active>;
pinctrl-1 = <&key_suspend>;
camera_snapshot {
label = "camera_snapshot";
//snip
};
};
I have this in vendor_file.dtsi:
gpio_keys {
source_key_1 {
label = "source_key_1";
//snip
};
};
In my current consolidated dtb file all nodes are getting
added i.e. camera_snapshot and source_key_1. How
can i remove camera_snapshot node from the
gpio_keys device node or disable it?
Thanks,
^ permalink raw reply
* Re: [PATCH v4 1/2] power: reset: add linkstation-reset driver
From: Roger Shimizu @ 2017-01-09 3:31 UTC (permalink / raw)
To: Ryan Tandy
Cc: Andrew Lunn, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel, Florian Fainelli, linux-pm, devicetree,
linux-arm-kernel
In-Reply-To: <20170108170209.GD573@kiwi.nardis.ca>
Dear Ryan,
Thanks for your comments!
On Mon, Jan 9, 2017 at 2:02 AM, Ryan Tandy <ryan@nardis.ca> wrote:
> On Sun, Jan 08, 2017 at 12:04:50AM +0900, Roger Shimizu wrote:
>>
>> +config POWER_RESET_LINKSTATION
>> + bool "Buffalo Linkstation and its variants reset driver"
>> + depends on OF_GPIO && PLAT_ORION
>> + help
>> + This driver supports power off Buffalo Linkstation / KuroBox Pro
>> + NAS and their variants by sending commands to the
>> micro-controller
>> + which controls the main power.
>
> Would it make sense to mention something about these being the ARM9/orion5x
> Linkstations? If I understand correctly, the older PPC Linkstations have a
> single-byte poweroff command. (Maybe they could even be supported by
> qnap-poweroff.)
>
> See arch/powerpc/platforms/embedded6xx/linkstation.c around line 123, and
> arch/powerpc/platforms/embedded6xx/ls_uart.c.
This driver, linkstation-reset, can also handle PPC Linkstation after
it's converted to DT.
I already considered this and mentioned in previous reply [0].
[0] http://marc.info/?l=linux-pm&m=148216908031283
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply
* Re: [PATCH 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: Sean Wang @ 2017-01-09 3:13 UTC (permalink / raw)
To: Sean Young
Cc: mchehab-JPH+aEBZ4P+UEJcrhfAQsw, hdegoede-H+wXaHxf7aLQT0dZR+AlfA,
hkallweit1-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
andi.shyti-Sze3O3UU22JBDgjK7y7TUQ,
hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
ivo.g.dimitrov.75-Re5JQEeQqe8AvxtiuMwx3w,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
keyhaede-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <20170108211624.GB7866-3XSxi2G4b3iXFJAUJl40Xg@public.gmane.org>
On Sun, 2017-01-08 at 21:16 +0000, Sean Young wrote:
> Hi Sean,
>
> On Fri, Jan 06, 2017 at 03:31:25PM +0800, Sean Wang wrote:
> > On Thu, 2017-01-05 at 17:12 +0000, Sean Young wrote:
> > > On Fri, Jan 06, 2017 at 12:06:24AM +0800, sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> > > > + /* Handle pulse and space until end of message */
> > > > + for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
> > > > + val = mtk_r32(ir, MTK_CHKDATA_REG(i));
> > > > + dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
> > > > +
> > > > + for (j = 0 ; j < 4 ; j++) {
> > > > + wid = (val & (0xff << j * 8)) >> j * 8;
> > > > + rawir.pulse = !rawir.pulse;
> > > > + rawir.duration = wid * (MTK_IR_SAMPLE + 1);
> > > > + ir_raw_event_store_with_filter(ir->rc, &rawir);
> > > > +
> > > > + if (MTK_IR_END(wid))
> > > > + goto end_msg;
> > > > + }
> > > > + }
> > >
> > > If I read this correctly, there is a maximum of 17 * 4 = 68 edges per
> > > IR message. The rc6 mce key 0 (scancode 0x800f0400) is 69 edges, so that
> > > won't work.
> > >
> > Uh, this is related to hardware limitation. Maximum number hardware
> > holds indeed is only 68 edges as you said :(
> >
> > For the case, I will try change the logic into that the whole message
> > is dropped if no end of message is seen within 68 counts to avoid
> > wasting CPU for decoding.
>
> I'm not sure it is worthwhile dropping the IR in that case. The processing
> is minimal and it might be possible that we have just enough IR to decode
> a scancode even if the trailing end of message is missing. Note that
> the call to ir_raw_event_set_idle() will generate an timeout IR event, so
> there will always be an end of message marker.
1)
I agree with you :) The original logic I made already as you pointed out
is sent incomplete IR message to let ir-raw try to decode as possible.
2)
I had another question. I found multiple and same IR messages being
received when using SONY remote controller. Should driver needs to
report each message or only one of these to the upper layer ?
> All I wanted to do was point out a limitation in case there is a
> workaround; if there is not then we might as well make do with the IR
> we do have.
I also will leave some words about limitation we had in the comments.
> Thanks
> Sean
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v1 3/3] thermal: zx2967: add thermal driver for ZTE's zx2967 family
From: Jun Nie @ 2017-01-09 3:00 UTC (permalink / raw)
To: Baoyou Xie, rui.zhang, edubezval, robh+dt, mark.rutland, gregkh,
davem, geert+renesas, akpm, mchehab, linux
Cc: linux-pm, devicetree, linux-kernel, linux-arm-kernel, shawnguo,
xie.baoyou, chen.chaokai, wang.qiang01
In-Reply-To: <1483767488-19778-3-git-send-email-baoyou.xie@linaro.org>
On 2017年01月07日 13:38, Baoyou Xie wrote:
> This patch adds thermal driver for ZTE's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/thermal/Kconfig | 6 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/zx2967_thermal.c | 241 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 248 insertions(+)
> create mode 100644 drivers/thermal/zx2967_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 18f2de6..0dd597e 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -445,3 +445,9 @@ config BCM2835_THERMAL
> Support for thermal sensors on Broadcom bcm2835 SoCs.
>
> endif
> +
> +config ZX2967_THERMAL
> + tristate "Thermal sensors on zx2967 SoC"
> + depends on ARCH_ZX
> + help
> + Support for thermal sensors on ZTE zx2967 SoCs.
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 677c6d9..c00c05e 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -57,3 +57,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
> +obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
> diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c
> new file mode 100644
> index 0000000..1aef070
> --- /dev/null
> +++ b/drivers/thermal/zx2967_thermal.c
> @@ -0,0 +1,241 @@
> +/*
> + * ZTE's zx2967 family thermal sensor driver
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
Please follow alphabet sequence.
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +/* DCF Control Register */
> +#define ZX2967_THERMAL_DCF 0x4
> +
> +/* Selection Register */
> +#define ZX2967_THERMAL_SEL 0x8
> +
> +/* Control Register */
> +#define ZX2967_THERMAL_CTRL 0x10
> +
> +#define ZX2967_THERMAL_ID_MASK (0x18)
> +
> +struct zx2967_thermal_sensor {
> + struct zx2967_thermal_priv *priv;
> + struct thermal_zone_device *tzd;
> + int id;
> +};
> +
> +#define NUM_SENSORS 1
> +
> +struct zx2967_thermal_priv {
> + struct zx2967_thermal_sensor sensors[NUM_SENSORS];
> + struct mutex lock;
> + struct clk *clk_gate;
> + struct clk *pclk;
> + void __iomem *regs;
> + struct pinctrl *pinmux_dvi0_d3;
> + struct pinctrl *pinmux_dvi0_d4;
> + struct pinctrl *pinmux_dvi0_d5;
I do not see usage of pinmux_div0_d*, please remove it.
> +};
> +
> +static int zx2967_thermal_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> +
> + if (priv && priv->pclk)
> + clk_disable_unprepare(priv->pclk);
> +
> + if (priv && priv->clk_gate)
> + clk_disable_unprepare(priv->clk_gate);
> + dev_info(dev, "suspended\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int error;
> +
> + error = clk_prepare_enable(priv->clk_gate);
> + if (error)
Use IS_ERR(ret) to check error.
> + return error;
> +
> + error = clk_prepare_enable(priv->pclk);
> + if (error)
Ditto.
> + return error;
> +
> + dev_info(dev, "resumed\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_get_temp(void *data, int *temp)
> +{
> + void __iomem *regs;
> + struct zx2967_thermal_sensor *sensor = data;
> + struct zx2967_thermal_priv *priv = sensor->priv;
> + unsigned long timeout = jiffies + msecs_to_jiffies(100);
> + u32 val, sel_id;
> +
> + regs = priv->regs;
> + mutex_lock(&priv->lock);
> +
> + writel_relaxed(0, regs);
> + writel_relaxed(2, regs + ZX2967_THERMAL_DCF);
> +
> + val = readl_relaxed(regs + ZX2967_THERMAL_SEL);
> + val &= ~ZX2967_THERMAL_ID_MASK;
> + sel_id = sensor->id ? 8 : 0x10;
You can define a macro for 8 and 0x10. BTW: NUM_SENSORS is 1 currently,
you can change it to 2 if hardware support it. Or you can add TODO mark
for later work.
> + val |= sel_id;
> + writel_relaxed(val, regs + ZX2967_THERMAL_SEL);
> +
> + usleep_range(100, 300);
> + while (!(readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0x1000)) {
> + if (time_after(jiffies, timeout)) {
> + pr_err("*** Thermal sensor %d data timeout\n",
> + sensor->id);
> + mutex_unlock(&priv->lock);
> + return -EIO;
> + }
> + }
> +
> + writel_relaxed(3, regs + ZX2967_THERMAL_DCF);
> + val = readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0xfff;
Define 0xfff as a macro.
> + writel_relaxed(1, regs);
> +
> + /** Calculate temperature */
> + *temp = DIV_ROUND_CLOSEST((val - 922) * 1000, 1951);
> +
> + mutex_unlock(&priv->lock);
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = {
> + .get_temp = zx2967_thermal_get_temp,
> +};
> +
> +static int zx2967_thermal_probe(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv;
> + struct resource *res;
> + int ret, i;
> +
> + 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_gate = devm_clk_get(&pdev->dev, "tempsensor_gate");
> + if (IS_ERR(priv->clk_gate)) {
> + ret = PTR_ERR(priv->clk_gate);
> + dev_err(&pdev->dev, "failed to get clock gate: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->clk_gate);
> + if (ret) {
Use IS_ERR(ret) to check error.
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + priv->pclk = devm_clk_get(&pdev->dev, "tempsensor_pclk");
> + if (IS_ERR(priv->pclk)) {
> + ret = PTR_ERR(priv->pclk);
> + dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->pclk);
> + if (ret) {
Ditto.
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + mutex_init(&priv->lock);
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + sensor->priv = priv;
> + sensor->id = i;
> + sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev,
> + i,
> + sensor,
No need to create new line.
> + &zx2967_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
> + i, ret);
> + goto remove_ts;
> + }
> + }
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +remove_ts:
> + for (i--; i >= 0; i--)
> + thermal_zone_of_sensor_unregister(&pdev->dev,
> + priv->sensors[i].tzd);
> +
> + return ret;
> +}
> +
> +static int zx2967_thermal_exit(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
> + }
> + clk_disable_unprepare(priv->pclk);
> + clk_disable_unprepare(priv->clk_gate);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id zx2967_thermal_id_table[] = {
> + { .compatible = "zte,zx2967-thermal" },
> + { .compatible = "zte,zx296718-thermal" },
Does the sensors that maps to the two compatibles have any difference?
If yes, we can add the difference with data member. If not, we can use
the same compatible string.
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops,
> + zx2967_thermal_suspend, zx2967_thermal_resume);
> +
> +static struct platform_driver zx2967_thermal_driver = {
> + .probe = zx2967_thermal_probe,
> + .remove = zx2967_thermal_exit,
> + .driver = {
> + .name = "zx2967_thermal",
> + .of_match_table = zx2967_thermal_id_table,
> + .pm = &zx2967_thermal_pm_ops,
> + },
> +};
> +module_platform_driver(zx2967_thermal_driver);
> +
> +MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
> +MODULE_DESCRIPTION("ZTE zx2967 thermal driver");
> +MODULE_LICENSE("GPL");
>
^ permalink raw reply
* Re: [PATCH v1 3/3] thermal: zx2967: add thermal driver for ZTE's zx2967 family
From: Shawn Guo @ 2017-01-09 3:00 UTC (permalink / raw)
To: Baoyou Xie
Cc: rui.zhang, edubezval, robh+dt, mark.rutland, jun.nie, gregkh,
davem, geert+renesas, akpm, mchehab, linux, linux-pm, devicetree,
linux-kernel, linux-arm-kernel, xie.baoyou, chen.chaokai,
wang.qiang01
In-Reply-To: <1483767488-19778-3-git-send-email-baoyou.xie@linaro.org>
On Sat, Jan 07, 2017 at 01:38:08PM +0800, Baoyou Xie wrote:
> This patch adds thermal driver for ZTE's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/thermal/Kconfig | 6 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/zx2967_thermal.c | 241 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 248 insertions(+)
> create mode 100644 drivers/thermal/zx2967_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 18f2de6..0dd597e 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -445,3 +445,9 @@ config BCM2835_THERMAL
> Support for thermal sensors on Broadcom bcm2835 SoCs.
>
> endif
> +
> +config ZX2967_THERMAL
> + tristate "Thermal sensors on zx2967 SoC"
> + depends on ARCH_ZX
> + help
> + Support for thermal sensors on ZTE zx2967 SoCs.
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 677c6d9..c00c05e 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -57,3 +57,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
> +obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
> diff --git a/drivers/thermal/zx2967_thermal.c b/drivers/thermal/zx2967_thermal.c
> new file mode 100644
> index 0000000..1aef070
> --- /dev/null
> +++ b/drivers/thermal/zx2967_thermal.c
> @@ -0,0 +1,241 @@
> +/*
> + * ZTE's zx2967 family thermal sensor driver
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +/* DCF Control Register */
> +#define ZX2967_THERMAL_DCF 0x4
> +
> +/* Selection Register */
> +#define ZX2967_THERMAL_SEL 0x8
> +
> +/* Control Register */
> +#define ZX2967_THERMAL_CTRL 0x10
> +
> +#define ZX2967_THERMAL_ID_MASK (0x18)
> +
> +struct zx2967_thermal_sensor {
> + struct zx2967_thermal_priv *priv;
> + struct thermal_zone_device *tzd;
> + int id;
> +};
> +
> +#define NUM_SENSORS 1
> +
> +struct zx2967_thermal_priv {
> + struct zx2967_thermal_sensor sensors[NUM_SENSORS];
What's the point of defining an array with only one element?
> + struct mutex lock;
> + struct clk *clk_gate;
> + struct clk *pclk;
> + void __iomem *regs;
> + struct pinctrl *pinmux_dvi0_d3;
> + struct pinctrl *pinmux_dvi0_d4;
> + struct pinctrl *pinmux_dvi0_d5;
These three pointers are not used.
> +};
> +
> +static int zx2967_thermal_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> +
> + if (priv && priv->pclk)
> + clk_disable_unprepare(priv->pclk);
> +
> + if (priv && priv->clk_gate)
> + clk_disable_unprepare(priv->clk_gate);
> + dev_info(dev, "suspended\n");
Noisy message.
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int error;
> +
> + error = clk_prepare_enable(priv->clk_gate);
> + if (error)
> + return error;
> +
> + error = clk_prepare_enable(priv->pclk);
> + if (error)
> + return error;
clk_disable_unprepare() should be called for priv->clk_gate before
returning here.
> +
> + dev_info(dev, "resumed\n");
> +
> + return 0;
> +}
> +
> +static int zx2967_thermal_get_temp(void *data, int *temp)
> +{
> + void __iomem *regs;
> + struct zx2967_thermal_sensor *sensor = data;
> + struct zx2967_thermal_priv *priv = sensor->priv;
> + unsigned long timeout = jiffies + msecs_to_jiffies(100);
> + u32 val, sel_id;
> +
> + regs = priv->regs;
> + mutex_lock(&priv->lock);
> +
> + writel_relaxed(0, regs);
I suggest we have a macro for register at offset 0 as well to improve
the readability.
> + writel_relaxed(2, regs + ZX2967_THERMAL_DCF);
> +
> + val = readl_relaxed(regs + ZX2967_THERMAL_SEL);
> + val &= ~ZX2967_THERMAL_ID_MASK;
> + sel_id = sensor->id ? 8 : 0x10;
> + val |= sel_id;
> + writel_relaxed(val, regs + ZX2967_THERMAL_SEL);
> +
> + usleep_range(100, 300);
> + while (!(readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0x1000)) {
> + if (time_after(jiffies, timeout)) {
> + pr_err("*** Thermal sensor %d data timeout\n",
> + sensor->id);
dev_err? And drop "*** ".
> + mutex_unlock(&priv->lock);
> + return -EIO;
-ETIMEDOUT?
> + }
> + }
> +
> + writel_relaxed(3, regs + ZX2967_THERMAL_DCF);
> + val = readl_relaxed(regs + ZX2967_THERMAL_CTRL) & 0xfff;
> + writel_relaxed(1, regs);
> +
> + /** Calculate temperature */
> + *temp = DIV_ROUND_CLOSEST((val - 922) * 1000, 1951);
> +
> + mutex_unlock(&priv->lock);
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops zx2967_of_thermal_ops = {
> + .get_temp = zx2967_thermal_get_temp,
> +};
> +
> +static int zx2967_thermal_probe(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv;
> + struct resource *res;
> + int ret, i;
> +
> + 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_gate = devm_clk_get(&pdev->dev, "tempsensor_gate");
> + if (IS_ERR(priv->clk_gate)) {
> + ret = PTR_ERR(priv->clk_gate);
> + dev_err(&pdev->dev, "failed to get clock gate: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->clk_gate);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
> + }
> +
> + priv->pclk = devm_clk_get(&pdev->dev, "tempsensor_pclk");
> + if (IS_ERR(priv->pclk)) {
> + ret = PTR_ERR(priv->pclk);
> + dev_err(&pdev->dev, "failed to get apb clock: %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(priv->pclk);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
> + ret);
> + return ret;
The use count of enable and prepare on priv->clk_gate will be
unbalanced.
> + }
> +
> + mutex_init(&priv->lock);
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + sensor->priv = priv;
> + sensor->id = i;
> + sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev,
> + i,
> + sensor,
> + &zx2967_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
> + i, ret);
> + goto remove_ts;
> + }
> + }
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +remove_ts:
> + for (i--; i >= 0; i--)
> + thermal_zone_of_sensor_unregister(&pdev->dev,
> + priv->sensors[i].tzd);
> +
> + return ret;
Unbalanced clk_prepare_enable(priv->pclk).
Shawn
> +}
> +
> +static int zx2967_thermal_exit(struct platform_device *pdev)
> +{
> + struct zx2967_thermal_priv *priv = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < NUM_SENSORS; i++) {
> + struct zx2967_thermal_sensor *sensor = &priv->sensors[i];
> +
> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
> + }
> + clk_disable_unprepare(priv->pclk);
> + clk_disable_unprepare(priv->clk_gate);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id zx2967_thermal_id_table[] = {
> + { .compatible = "zte,zx2967-thermal" },
> + { .compatible = "zte,zx296718-thermal" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, zx2967_thermal_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(zx2967_thermal_pm_ops,
> + zx2967_thermal_suspend, zx2967_thermal_resume);
> +
> +static struct platform_driver zx2967_thermal_driver = {
> + .probe = zx2967_thermal_probe,
> + .remove = zx2967_thermal_exit,
> + .driver = {
> + .name = "zx2967_thermal",
> + .of_match_table = zx2967_thermal_id_table,
> + .pm = &zx2967_thermal_pm_ops,
> + },
> +};
> +module_platform_driver(zx2967_thermal_driver);
> +
> +MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
> +MODULE_DESCRIPTION("ZTE zx2967 thermal driver");
> +MODULE_LICENSE("GPL");
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH v7 2/2] mtd: nand: Add support for Arasan NAND Flash Controller
From: Punnaiah Choudary Kalluri @ 2017-01-09 2:58 UTC (permalink / raw)
To: dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, michals-gjFFaj9aHVfQT0dZR+AlfA,
kalluripunnaiahchoudary-Re5JQEeQqe8AvxtiuMwx3w,
kpc528-Re5JQEeQqe8AvxtiuMwx3w, Punnaiah Choudary Kalluri
In-Reply-To: <1483930734-10309-1-git-send-email-punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
Added the basic driver for Arasan NAND Flash Controller used in
Zynq UltraScale+ MPSoC. It supports only Hw ECC and upto 24bit
correction.
Signed-off-by: Punnaiah Choudary Kalluri <punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---
Changes in v7:
- Implemented Marek suggestions and comments
- Corrected the acronyms those should be in caps
- Modified kconfig/Make file to keep arasan entry in sorted order
- Added is_vmlloc_addr check
- Used ioread/write32_rep variants to avoid compilation error for intel
platforms
- separated PIO and DMA mode read/write functions
- Minor cleanup
Chnages in v6:
- Addressed most of the Brian and Boris comments
- Separated the nandchip from the nand controller
- Removed the ecc lookup table from driver
- Now use framework nand waitfunction and readoob
- Fixed the compiler warning
- Adapted the new frameowrk changes related to ecc and ooblayout
- Disabled the clocks after the nand_reelase
- Now using only one completion object
- Boris suggessions like adapting cmd_ctrl and rework on read/write byte
are not implemented and i will patch them later
- Also check_erased_ecc_chunk for erase and check for is_vmalloc_addr will
implement later once the basic driver is mainlined.
Changes in v5:
- Renamed the driver filei as arasan_nand.c
- Fixed all comments relaqted coding style
- Fixed comments related to propagating the errors
- Modified the anfc_write_page_hwecc as per the write_page
prototype
Changes in v4:
- Added support for onfi timing mode configuration
- Added clock supppport
- Added support for multiple chipselects
Changes in v3:
- Removed unused variables
- Avoided busy loop and used jifies based implementation
- Fixed compiler warnings "right shift count >= width of type"
- Removed unneeded codei and improved error reporting
- Added onfi version check to ensure reading the valid address cycles
Changes in v2:
- Added missing of.h to avoid kbuild system report erro
---
drivers/mtd/nand/Kconfig | 8 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/arasan_nand.c | 932 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 941 insertions(+)
create mode 100644 drivers/mtd/nand/arasan_nand.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7b7a887..c4cfca2 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -41,6 +41,14 @@ config MTD_SM_COMMON
tristate
default n
+config MTD_NAND_ARASAN
+ tristate "Support for Arasan Nand Flash controller"
+ depends on HAS_IOMEM
+ depends on HAS_DMA
+ help
+ Enables the driver for the Arasan NAND Flash controller on
+ Zynq UltraScale+ MPSoC.
+
config MTD_NAND_DENALI
tristate
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index cafde6f..7754170 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o
+obj-$(CONFIG_MTD_NAND_ARASAN) += arasan_nand.o
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
diff --git a/drivers/mtd/nand/arasan_nand.c b/drivers/mtd/nand/arasan_nand.c
new file mode 100644
index 0000000..2103134
--- /dev/null
+++ b/drivers/mtd/nand/arasan_nand.c
@@ -0,0 +1,932 @@
+/*
+ * Arasan NAND Flash Controller Driver
+ *
+ * Copyright (C) 2014 - 2017 Xilinx, Inc.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define DRIVER_NAME "arasan_nand"
+#define EVNT_TIMEOUT_MSEC 1000
+
+#define PKT_OFST 0x00
+#define MEM_ADDR1_OFST 0x04
+#define MEM_ADDR2_OFST 0x08
+#define CMD_OFST 0x0C
+#define PROG_OFST 0x10
+#define INTR_STS_EN_OFST 0x14
+#define INTR_SIG_EN_OFST 0x18
+#define INTR_STS_OFST 0x1C
+#define READY_STS_OFST 0x20
+#define DMA_ADDR1_OFST 0x24
+#define FLASH_STS_OFST 0x28
+#define DATA_PORT_OFST 0x30
+#define ECC_OFST 0x34
+#define ECC_ERR_CNT_OFST 0x38
+#define ECC_SPR_CMD_OFST 0x3C
+#define ECC_ERR_CNT_1BIT_OFST 0x40
+#define ECC_ERR_CNT_2BIT_OFST 0x44
+#define DMA_ADDR0_OFST 0x50
+#define DATA_INTERFACE_OFST 0x6C
+
+#define PKT_CNT_SHIFT 12
+
+#define ECC_ENABLE BIT(31)
+#define DMA_EN_MASK GENMASK(27, 26)
+#define DMA_ENABLE 0x2
+#define DMA_EN_SHIFT 26
+#define REG_PAGE_SIZE_SHIFT 23
+#define REG_PAGE_SIZE_512 0
+#define REG_PAGE_SIZE_1K 5
+#define REG_PAGE_SIZE_2K 1
+#define REG_PAGE_SIZE_4K 2
+#define REG_PAGE_SIZE_8K 3
+#define REG_PAGE_SIZE_16K 4
+#define CMD2_SHIFT 8
+#define ADDR_CYCLES_SHIFT 28
+
+#define XFER_COMPLETE BIT(2)
+#define READ_READY BIT(1)
+#define WRITE_READY BIT(0)
+#define MBIT_ERROR BIT(3)
+
+#define PROG_PGRD BIT(0)
+#define PROG_ERASE BIT(2)
+#define PROG_STATUS BIT(3)
+#define PROG_PGPROG BIT(4)
+#define PROG_RDID BIT(6)
+#define PROG_RDPARAM BIT(7)
+#define PROG_RST BIT(8)
+#define PROG_GET_FEATURE BIT(9)
+#define PROG_SET_FEATURE BIT(10)
+
+#define PG_ADDR_SHIFT 16
+#define BCH_MODE_SHIFT 25
+#define BCH_EN_SHIFT 27
+#define ECC_SIZE_SHIFT 16
+
+#define MEM_ADDR_MASK GENMASK(7, 0)
+#define BCH_MODE_MASK GENMASK(27, 25)
+
+#define CS_MASK GENMASK(31, 30)
+#define CS_SHIFT 30
+
+#define PAGE_ERR_CNT_MASK GENMASK(16, 8)
+#define PKT_ERR_CNT_MASK GENMASK(7, 0)
+
+#define NVDDR_MODE BIT(9)
+#define NVDDR_TIMING_MODE_SHIFT 3
+
+#define ONFI_ID_LEN 8
+#define TEMP_BUF_SIZE 1024
+#define NVDDR_MODE_PACKET_SIZE 8
+#define SDR_MODE_PACKET_SIZE 4
+
+#define ONFI_DATA_INTERFACE_NVDDR BIT(4)
+#define EVENT_MASK (XFER_COMPLETE | READ_READY | WRITE_READY | MBIT_ERROR)
+
+/**
+ * struct anfc_nand_chip - Defines the nand chip related information
+ * @node: used to store NAND chips into a list.
+ * @chip: NAND chip information structure.
+ * @bch: Bch / Hamming mode enable/disable.
+ * @bchmode: Bch mode.
+ * @eccval: Ecc config value.
+ * @raddr_cycles: Row address cycle information.
+ * @caddr_cycles: Column address cycle information.
+ * @pktsize: Packet size for read / write operation.
+ * @csnum: chipselect number to be used.
+ * @spktsize: Packet size in ddr mode for status operation.
+ * @inftimeval Data interface and timing mode information
+ */
+struct anfc_nand_chip {
+ struct list_head node;
+ struct nand_chip chip;
+ bool bch;
+ u32 bchmode;
+ u32 eccval;
+ u16 raddr_cycles;
+ u16 caddr_cycles;
+ u32 pktsize;
+ int csnum;
+ u32 spktsize;
+ u32 inftimeval;
+};
+
+/**
+ * struct anfc - Defines the Arasan NAND flash driver instance
+ * @controller: base controller structure.
+ * @chips: list of all nand chips attached to the ctrler.
+ * @dev: Pointer to the device structure.
+ * @base: Virtual address of the NAND flash device.
+ * @curr_cmd: Current command issued.
+ * @clk_sys: Pointer to the system clock.
+ * @clk_flash: Pointer to the flash clock.
+ * @dma: Dma enable/disable.
+ * @iswriteoob: Identifies if oob write operation is required.
+ * @buf: Buffer used for read/write byte operations.
+ * @irq: irq number
+ * @bufshift: Variable used for indexing buffer operation
+ * @csnum: Chip select number currently inuse.
+ * @event: Completion event for nand status events.
+ */
+struct anfc {
+ struct nand_hw_control controller;
+ struct list_head chips;
+ struct device *dev;
+ void __iomem *base;
+ int curr_cmd;
+ struct clk *clk_sys;
+ struct clk *clk_flash;
+ bool dma;
+ bool iswriteoob;
+ u8 buf[TEMP_BUF_SIZE];
+ int irq;
+ u32 bufshift;
+ int csnum;
+ struct completion event;
+};
+
+static int anfc_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->length = nand->ecc.total;
+ oobregion->offset = mtd->oobsize - oobregion->length;
+
+ return 0;
+}
+
+static int anfc_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+
+ if (section)
+ return -ERANGE;
+
+ oobregion->offset = 2;
+ oobregion->length = mtd->oobsize - nand->ecc.total - 2;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops anfc_ooblayout_ops = {
+ .ecc = anfc_ooblayout_ecc,
+ .free = anfc_ooblayout_free,
+};
+
+static inline struct anfc_nand_chip *to_anfc_nand(struct nand_chip *nand)
+{
+ return container_of(nand, struct anfc_nand_chip, chip);
+}
+
+static inline struct anfc *to_anfc(struct nand_hw_control *ctrl)
+{
+ return container_of(ctrl, struct anfc, controller);
+}
+
+static u8 anfc_page(u32 pagesize)
+{
+ switch (pagesize) {
+ case 512:
+ return REG_PAGE_SIZE_512;
+ case 1024:
+ return REG_PAGE_SIZE_1K;
+ case 2048:
+ return REG_PAGE_SIZE_2K;
+ case 4096:
+ return REG_PAGE_SIZE_4K;
+ case 8192:
+ return REG_PAGE_SIZE_8K;
+ case 16384:
+ return REG_PAGE_SIZE_16K;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline void anfc_enable_intrs(struct anfc *nfc, u32 val)
+{
+ writel(val, nfc->base + INTR_STS_EN_OFST);
+ writel(val, nfc->base + INTR_SIG_EN_OFST);
+}
+
+static inline void anfc_config_ecc(struct anfc *nfc, int on)
+{
+ u32 val;
+
+ val = readl(nfc->base + CMD_OFST);
+ if (on)
+ val |= ECC_ENABLE;
+ else
+ val &= ~ECC_ENABLE;
+ writel(val, nfc->base + CMD_OFST);
+}
+
+static inline void anfc_config_dma(struct anfc *nfc, int on)
+{
+ u32 val;
+
+ val = readl(nfc->base + CMD_OFST);
+ val &= ~DMA_EN_MASK;
+ if (on)
+ val |= DMA_ENABLE << DMA_EN_SHIFT;
+ writel(val, nfc->base + CMD_OFST);
+}
+
+static inline int anfc_wait_for_event(struct anfc *nfc)
+{
+ return wait_for_completion_timeout(&nfc->event,
+ msecs_to_jiffies(EVNT_TIMEOUT_MSEC));
+}
+
+static inline void anfc_setpktszcnt(struct anfc *nfc, u32 pktsize,
+ u32 pktcount)
+{
+ writel(pktsize | (pktcount << PKT_CNT_SHIFT), nfc->base + PKT_OFST);
+}
+
+static inline void anfc_set_eccsparecmd(struct anfc *nfc,
+ struct anfc_nand_chip *achip, u8 cmd1, u8 cmd2)
+{
+ writel(cmd1 | (cmd2 << CMD2_SHIFT) |
+ (achip->caddr_cycles << ADDR_CYCLES_SHIFT),
+ nfc->base + ECC_SPR_CMD_OFST);
+}
+
+static void anfc_setpagecoladdr(struct anfc *nfc, u32 page, u16 col)
+{
+ u32 val;
+
+ writel(col | (page << PG_ADDR_SHIFT), nfc->base + MEM_ADDR1_OFST);
+
+ val = readl(nfc->base + MEM_ADDR2_OFST);
+ val = (val & ~MEM_ADDR_MASK) |
+ ((page >> PG_ADDR_SHIFT) & MEM_ADDR_MASK);
+ writel(val, nfc->base + MEM_ADDR2_OFST);
+}
+
+static void anfc_prepare_cmd(struct anfc *nfc, u8 cmd1, u8 cmd2, u8 dmamode,
+ u32 pagesize, u8 addrcycles)
+{
+ u32 regval;
+
+ regval = cmd1 | (cmd2 << CMD2_SHIFT);
+ if (dmamode && nfc->dma)
+ regval |= DMA_ENABLE << DMA_EN_SHIFT;
+ regval |= addrcycles << ADDR_CYCLES_SHIFT;
+ regval |= anfc_page(pagesize) << REG_PAGE_SIZE_SHIFT;
+ writel(regval, nfc->base + CMD_OFST);
+}
+
+static int anfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ nfc->iswriteoob = true;
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+ nfc->iswriteoob = false;
+
+ return 0;
+}
+
+static void anfc_rw_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len,
+ int operation, u32 prog)
+{
+ dma_addr_t paddr;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ u32 eccintr = 0, dir;
+ u32 pktsize = len, pktcount = 1;
+
+ if ((nfc->curr_cmd == NAND_CMD_READ0) ||
+ ((nfc->curr_cmd == NAND_CMD_SEQIN) && !nfc->iswriteoob)) {
+ pktsize = achip->pktsize;
+ pktcount = DIV_ROUND_UP(mtd->writesize, pktsize);
+ }
+ anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+ if (!achip->bch && (nfc->curr_cmd == NAND_CMD_READ0))
+ eccintr = MBIT_ERROR;
+
+ if (operation)
+ dir = DMA_FROM_DEVICE;
+ else
+ dir = DMA_TO_DEVICE;
+
+ paddr = dma_map_single(nfc->dev, buf, len, dir);
+ if (dma_mapping_error(nfc->dev, paddr)) {
+ dev_err(nfc->dev, "Read buffer mapping error");
+ return;
+ }
+ lo_hi_writeq(paddr, nfc->base + DMA_ADDR0_OFST);
+ anfc_enable_intrs(nfc, (XFER_COMPLETE | eccintr));
+ writel(prog, nfc->base + PROG_OFST);
+ anfc_wait_for_event(nfc);
+ dma_unmap_single(nfc->dev, paddr, len, dir);
+}
+
+static void anfc_rw_buf_pio(struct mtd_info *mtd, uint8_t *buf, int len,
+ int operation, int prog)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ u32 *bufptr = (u32 *)buf;
+ u32 cnt = 0, intr = 0;
+ u32 pktsize = len, pktcount = 1;
+
+ anfc_config_dma(nfc, 0);
+
+ if ((nfc->curr_cmd == NAND_CMD_READ0) ||
+ ((nfc->curr_cmd == NAND_CMD_SEQIN) && !nfc->iswriteoob)) {
+ pktsize = achip->pktsize;
+ pktcount = DIV_ROUND_UP(mtd->writesize, pktsize);
+ }
+ anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+ if (!achip->bch && (nfc->curr_cmd == NAND_CMD_READ0))
+ intr = MBIT_ERROR;
+
+ if (operation)
+ intr |= READ_READY;
+ else
+ intr |= WRITE_READY;
+
+ anfc_enable_intrs(nfc, intr);
+ writel(prog, nfc->base + PROG_OFST);
+
+ while (cnt < pktcount) {
+ anfc_wait_for_event(nfc);
+ cnt++;
+ if (cnt == pktcount)
+ anfc_enable_intrs(nfc, XFER_COMPLETE);
+ if (operation)
+ ioread32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+ pktsize/4);
+ else
+ iowrite32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+ pktsize/4);
+ bufptr += (pktsize / 4);
+ if (cnt < pktcount)
+ anfc_enable_intrs(nfc, intr);
+ }
+
+ anfc_wait_for_event(nfc);
+}
+
+static void anfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (nfc->dma && !is_vmalloc_addr(buf))
+ anfc_rw_buf_dma(mtd, buf, len, 1, PROG_PGRD);
+ else
+ anfc_rw_buf_pio(mtd, buf, len, 1, PROG_PGRD);
+}
+
+static void anfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (nfc->dma && !is_vmalloc_addr(buf))
+ anfc_rw_buf_dma(mtd, (char *)buf, len, 0, PROG_PGPROG);
+ else
+ anfc_rw_buf_pio(mtd, (char *)buf, len, 0, PROG_PGPROG);
+}
+
+static int anfc_read_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
+{
+ u32 val;
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+ anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART);
+ anfc_config_ecc(nfc, 1);
+
+ val = readl(nfc->base + CMD_OFST);
+ val = val | ECC_ENABLE;
+ writel(val, nfc->base + CMD_OFST);
+
+ chip->read_buf(mtd, buf, mtd->writesize);
+
+ val = readl(nfc->base + ECC_ERR_CNT_OFST);
+ if (achip->bch) {
+ mtd->ecc_stats.corrected += val & PAGE_ERR_CNT_MASK;
+ } else {
+ val = readl(nfc->base + ECC_ERR_CNT_1BIT_OFST);
+ mtd->ecc_stats.corrected += val;
+ val = readl(nfc->base + ECC_ERR_CNT_2BIT_OFST);
+ mtd->ecc_stats.failed += val;
+ /* Clear ecc error count register 1Bit, 2Bit */
+ writel(0x0, nfc->base + ECC_ERR_CNT_1BIT_OFST);
+ writel(0x0, nfc->base + ECC_ERR_CNT_2BIT_OFST);
+ }
+
+ if (oob_required)
+ chip->ecc.read_oob(mtd, chip, page);
+
+ return 0;
+}
+
+static int anfc_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page)
+{
+ int ret;
+ struct anfc *nfc = to_anfc(chip->controller);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+
+ anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDIN, 0);
+ anfc_config_ecc(nfc, 1);
+
+ chip->write_buf(mtd, buf, mtd->writesize);
+
+ if (oob_required) {
+ chip->waitfunc(mtd, chip);
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, ecc_calc, mtd->oobsize);
+ ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi,
+ 0, chip->ecc.total);
+ if (ret)
+ return ret;
+ chip->ecc.write_oob(mtd, chip, page);
+ }
+
+ return 0;
+}
+
+static u8 anfc_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ return nfc->buf[nfc->bufshift++];
+}
+
+static int anfc_ecc_init(struct mtd_info *mtd,
+ struct nand_ecc_ctrl *ecc)
+{
+ u32 ecc_addr;
+ unsigned int bchmode, steps;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+ ecc->mode = NAND_ECC_HW;
+ ecc->read_page = anfc_read_page_hwecc;
+ ecc->write_page = anfc_write_page_hwecc;
+ ecc->write_oob = anfc_write_oob;
+ mtd_set_ooblayout(mtd, &anfc_ooblayout_ops);
+
+ steps = mtd->writesize / chip->ecc_step_ds;
+
+ switch (chip->ecc_strength_ds) {
+ case 12:
+ bchmode = 0x1;
+ break;
+ case 8:
+ bchmode = 0x2;
+ break;
+ case 4:
+ bchmode = 0x3;
+ break;
+ case 24:
+ bchmode = 0x4;
+ break;
+ default:
+ bchmode = 0x0;
+ }
+
+ if (!bchmode)
+ ecc->total = 3 * steps;
+ else
+ ecc->total =
+ DIV_ROUND_UP(fls(8 * chip->ecc_step_ds) *
+ chip->ecc_strength_ds * steps, 8);
+
+ ecc->strength = chip->ecc_strength_ds;
+ ecc->size = chip->ecc_step_ds;
+ ecc->bytes = ecc->total / steps;
+ ecc->steps = steps;
+ achip->bchmode = bchmode;
+ achip->bch = achip->bchmode;
+ ecc_addr = mtd->writesize + (mtd->oobsize - ecc->total);
+
+ achip->eccval = ecc_addr | (ecc->total << ECC_SIZE_SHIFT) |
+ (achip->bch << BCH_EN_SHIFT);
+
+ if (chip->ecc_step_ds >= 1024)
+ achip->pktsize = 1024;
+ else
+ achip->pktsize = 512;
+
+ return 0;
+}
+
+static void anfc_cmd_function(struct mtd_info *mtd,
+ unsigned int cmd, int column, int page_addr)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ struct anfc *nfc = to_anfc(chip->controller);
+ bool wait = false, read = false;
+ u32 addrcycles, prog;
+ u32 *bufptr = (u32 *)nfc->buf;
+
+ nfc->bufshift = 0;
+ nfc->curr_cmd = cmd;
+
+ if (page_addr == -1)
+ page_addr = 0;
+ if (column == -1)
+ column = 0;
+
+ switch (cmd) {
+ case NAND_CMD_RESET:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 0);
+ prog = PROG_RST;
+ wait = true;
+ break;
+ case NAND_CMD_SEQIN:
+ addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_PAGEPROG, 1,
+ mtd->writesize, addrcycles);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_READOOB:
+ column += mtd->writesize;
+ case NAND_CMD_READ0:
+ case NAND_CMD_READ1:
+ addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+ anfc_prepare_cmd(nfc, NAND_CMD_READ0, NAND_CMD_READSTART, 1,
+ mtd->writesize, addrcycles);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_RNDOUT:
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_RNDOUTSTART, 1,
+ mtd->writesize, 2);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ case NAND_CMD_PARAM:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf,
+ (4 * sizeof(struct nand_onfi_params)),
+ 1, PROG_RDPARAM);
+ break;
+ case NAND_CMD_READID:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf, ONFI_ID_LEN, 1, PROG_RDID);
+ break;
+ case NAND_CMD_ERASE1:
+ addrcycles = achip->raddr_cycles;
+ prog = PROG_ERASE;
+ anfc_prepare_cmd(nfc, cmd, NAND_CMD_ERASE2, 0, 0, addrcycles);
+ column = page_addr & 0xffff;
+ page_addr = (page_addr >> PG_ADDR_SHIFT) & 0xffff;
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ wait = true;
+ break;
+ case NAND_CMD_STATUS:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 0);
+ anfc_setpktszcnt(nfc, achip->spktsize/4, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ prog = PROG_STATUS;
+ wait = read = true;
+ break;
+ case NAND_CMD_GET_FEATURES:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ anfc_rw_buf_pio(mtd, nfc->buf, achip->spktsize, 1,
+ PROG_GET_FEATURE);
+ break;
+ case NAND_CMD_SET_FEATURES:
+ anfc_prepare_cmd(nfc, cmd, 0, 0, 0, 1);
+ anfc_setpagecoladdr(nfc, page_addr, column);
+ break;
+ default:
+ return;
+ }
+
+ if (wait) {
+ anfc_enable_intrs(nfc, XFER_COMPLETE);
+ writel(prog, nfc->base + PROG_OFST);
+ anfc_wait_for_event(nfc);
+ }
+
+ if (read)
+ bufptr[0] = readl(nfc->base + FLASH_STS_OFST);
+}
+
+static void anfc_select_chip(struct mtd_info *mtd, int num)
+{
+ u32 val;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ struct anfc *nfc = to_anfc(chip->controller);
+
+ if (num == -1)
+ return;
+
+ val = readl(nfc->base + MEM_ADDR2_OFST);
+ val &= (val & ~(CS_MASK | BCH_MODE_MASK));
+ val |= (achip->csnum << CS_SHIFT) | (achip->bchmode << BCH_MODE_SHIFT);
+ writel(val, nfc->base + MEM_ADDR2_OFST);
+ nfc->csnum = achip->csnum;
+ writel(achip->eccval, nfc->base + ECC_OFST);
+ writel(achip->inftimeval, nfc->base + DATA_INTERFACE_OFST);
+}
+
+static irqreturn_t anfc_irq_handler(int irq, void *ptr)
+{
+ struct anfc *nfc = ptr;
+ u32 status;
+
+ status = readl(nfc->base + INTR_STS_OFST);
+ if (status & EVENT_MASK) {
+ complete(&nfc->event);
+ writel((status & EVENT_MASK), nfc->base + INTR_STS_OFST);
+ writel(0, nfc->base + INTR_STS_EN_OFST);
+ writel(0, nfc->base + INTR_SIG_EN_OFST);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int anfc_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
+ int addr, uint8_t *subfeature_param)
+{
+ struct anfc_nand_chip *achip = to_anfc_nand(chip);
+ int status;
+
+ if (!chip->onfi_version)
+ return -EINVAL;
+
+ if (!(le16_to_cpu(chip->onfi_params.opt_cmd) &
+ ONFI_OPT_CMD_SET_GET_FEATURES))
+ return -EINVAL;
+
+ chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
+ anfc_rw_buf_pio(mtd, subfeature_param, achip->spktsize,
+ 0, PROG_SET_FEATURE);
+ status = chip->waitfunc(mtd, chip);
+ if (status & NAND_STATUS_FAIL)
+ return -EIO;
+
+ return 0;
+}
+
+static int anfc_init_timing_mode(struct anfc *nfc,
+ struct anfc_nand_chip *achip)
+{
+ int mode, err;
+ unsigned int feature[2];
+ u32 inftimeval;
+ struct nand_chip *chip = &achip->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+
+ memset(feature, 0, NVDDR_MODE_PACKET_SIZE);
+ /* Get nvddr timing modes */
+ mode = onfi_get_sync_timing_mode(chip) & 0xff;
+ if (!mode) {
+ mode = fls(onfi_get_async_timing_mode(chip)) - 1;
+ inftimeval = mode;
+ } else {
+ mode = fls(mode) - 1;
+ inftimeval = NVDDR_MODE | (mode << NVDDR_TIMING_MODE_SHIFT);
+ mode |= ONFI_DATA_INTERFACE_NVDDR;
+ }
+
+ feature[0] = mode;
+ chip->select_chip(mtd, achip->csnum);
+ err = chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_TIMING_MODE,
+ (uint8_t *)feature);
+ chip->select_chip(mtd, -1);
+ if (err)
+ return err;
+
+ achip->inftimeval = inftimeval;
+
+ if (mode & ONFI_DATA_INTERFACE_NVDDR)
+ achip->spktsize = NVDDR_MODE_PACKET_SIZE;
+
+ return 0;
+}
+
+static int anfc_nand_chip_init(struct anfc *nfc,
+ struct anfc_nand_chip *anand_chip,
+ struct device_node *np)
+{
+ struct nand_chip *chip = &anand_chip->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", &anand_chip->csnum);
+ if (ret) {
+ dev_err(nfc->dev, "can't get chip-select\n");
+ return -ENXIO;
+ }
+
+ mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, "arasan_nand.%d",
+ anand_chip->csnum);
+ mtd->dev.parent = nfc->dev;
+
+ chip->cmdfunc = anfc_cmd_function;
+ chip->chip_delay = 30;
+ chip->controller = &nfc->controller;
+ chip->read_buf = anfc_read_buf;
+ chip->write_buf = anfc_write_buf;
+ chip->read_byte = anfc_read_byte;
+ chip->options = NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE;
+ chip->bbt_options = NAND_BBT_USE_FLASH;
+ chip->select_chip = anfc_select_chip;
+ chip->onfi_set_features = anfc_onfi_set_features;
+ nand_set_flash_node(chip, np);
+
+ anand_chip->spktsize = SDR_MODE_PACKET_SIZE;
+ ret = nand_scan_ident(mtd, 1, NULL);
+ if (ret) {
+ dev_err(nfc->dev, "nand_scan_ident for NAND failed\n");
+ return ret;
+ }
+ if (chip->onfi_version) {
+ anand_chip->raddr_cycles = chip->onfi_params.addr_cycles & 0xf;
+ anand_chip->caddr_cycles =
+ (chip->onfi_params.addr_cycles >> 4) & 0xf;
+ } else {
+ /* For non-ONFI devices, configuring the address cyles as 5 */
+ anand_chip->raddr_cycles = 3;
+ anand_chip->caddr_cycles = 2;
+ }
+
+ ret = anfc_init_timing_mode(nfc, anand_chip);
+ if (ret) {
+ dev_err(nfc->dev, "timing mode init failed\n");
+ return ret;
+ }
+
+ ret = anfc_ecc_init(mtd, &chip->ecc);
+ if (ret)
+ return ret;
+
+ ret = nand_scan_tail(mtd);
+ if (ret) {
+ dev_err(nfc->dev, "nand_scan_tail for NAND failed\n");
+ return ret;
+ }
+
+ return mtd_device_register(mtd, NULL, 0);
+}
+
+static int anfc_probe(struct platform_device *pdev)
+{
+ struct anfc *nfc;
+ struct anfc_nand_chip *anand_chip;
+ struct device_node *np = pdev->dev.of_node, *child;
+ struct resource *res;
+ int err;
+
+ nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc)
+ return -ENOMEM;
+
+ init_waitqueue_head(&nfc->controller.wq);
+ INIT_LIST_HEAD(&nfc->chips);
+ init_completion(&nfc->event);
+ nfc->dev = &pdev->dev;
+ platform_set_drvdata(pdev, nfc);
+ nfc->csnum = -1;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nfc->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(nfc->base))
+ return PTR_ERR(nfc->base);
+ nfc->dma = of_property_read_bool(pdev->dev.of_node,
+ "arasan,has-mdma");
+ nfc->irq = platform_get_irq(pdev, 0);
+ if (nfc->irq < 0) {
+ dev_err(&pdev->dev, "platform_get_irq failed\n");
+ return -ENXIO;
+ }
+ err = devm_request_irq(&pdev->dev, nfc->irq, anfc_irq_handler,
+ 0, "arasannfc", nfc);
+ if (err)
+ return err;
+ nfc->clk_sys = devm_clk_get(&pdev->dev, "clk_sys");
+ if (IS_ERR(nfc->clk_sys)) {
+ dev_err(&pdev->dev, "sys clock not found.\n");
+ return PTR_ERR(nfc->clk_sys);
+ }
+
+ nfc->clk_flash = devm_clk_get(&pdev->dev, "clk_flash");
+ if (IS_ERR(nfc->clk_flash)) {
+ dev_err(&pdev->dev, "flash clock not found.\n");
+ return PTR_ERR(nfc->clk_flash);
+ }
+
+ err = clk_prepare_enable(nfc->clk_sys);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to enable sys clock.\n");
+ return err;
+ }
+
+ err = clk_prepare_enable(nfc->clk_flash);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to enable flash clock.\n");
+ goto clk_dis_sys;
+ }
+
+ for_each_available_child_of_node(np, child) {
+ anand_chip = devm_kzalloc(&pdev->dev, sizeof(*anand_chip),
+ GFP_KERNEL);
+ if (!anand_chip) {
+ of_node_put(child);
+ err = -ENOMEM;
+ goto nandchip_clean_up;
+ }
+
+ err = anfc_nand_chip_init(nfc, anand_chip, child);
+ if (err) {
+ devm_kfree(&pdev->dev, anand_chip);
+ continue;
+ }
+
+ list_add_tail(&anand_chip->node, &nfc->chips);
+ }
+
+ return 0;
+
+nandchip_clean_up:
+ list_for_each_entry(anand_chip, &nfc->chips, node)
+ nand_release(nand_to_mtd(&anand_chip->chip));
+ clk_disable_unprepare(nfc->clk_flash);
+clk_dis_sys:
+ clk_disable_unprepare(nfc->clk_sys);
+
+ return err;
+}
+
+static int anfc_remove(struct platform_device *pdev)
+{
+ struct anfc *nfc = platform_get_drvdata(pdev);
+ struct anfc_nand_chip *anand_chip;
+
+ list_for_each_entry(anand_chip, &nfc->chips, node)
+ nand_release(nand_to_mtd(&anand_chip->chip));
+
+ clk_disable_unprepare(nfc->clk_sys);
+ clk_disable_unprepare(nfc->clk_flash);
+
+ return 0;
+}
+
+static const struct of_device_id anfc_ids[] = {
+ { .compatible = "arasan,nfc-v3p10" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, anfc_ids);
+
+static struct platform_driver anfc_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = anfc_ids,
+ },
+ .probe = anfc_probe,
+ .remove = anfc_remove,
+};
+module_platform_driver(anfc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("Arasan NAND Flash Controller Driver");
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 1/2] mtd: arasan: Add device tree binding documentation
From: Punnaiah Choudary Kalluri @ 2017-01-09 2:58 UTC (permalink / raw)
To: dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, michals-gjFFaj9aHVfQT0dZR+AlfA,
kalluripunnaiahchoudary-Re5JQEeQqe8AvxtiuMwx3w,
kpc528-Re5JQEeQqe8AvxtiuMwx3w, Punnaiah Choudary Kalluri
This patch adds the dts binding document for arasan nand flash
controller.
Signed-off-by: Punnaiah Choudary Kalluri <punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---
Changes in v7:
- Corrected the acronyms those should be in caps
changes in v6:
- Removed num-cs property
- Separated nandchip from nand controller
changes in v5:
- None
Changes in v4:
- Added num-cs property
- Added clock support
Changes in v3:
- None
Changes in v2:
- None
---
.../devicetree/bindings/mtd/arasan_nfc.txt | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/arasan_nfc.txt
diff --git a/Documentation/devicetree/bindings/mtd/arasan_nfc.txt b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
new file mode 100644
index 0000000..f20adfc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
@@ -0,0 +1,38 @@
+Arasan NAND Flash Controller with ONFI 3.1 support
+
+Required properties:
+- compatible: Should be "arasan,nfc-v3p10"
+- reg: Memory map for module access
+- interrupt-parent: Interrupt controller the interrupt is routed through
+- interrupts: Should contain the interrupt for the device
+- clock-name: List of input clocks - "clk_sys", "clk_flash"
+ (See clock bindings for details)
+- clocks: Clock phandles (see clock bindings for details)
+
+Optional properties:
+- arasan,has-mdma: Enables DMA support
+
+For NAND partition information please refer the below file
+Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+ nand0: nand@ff100000 {
+ compatible = "arasan,nfc-v3p10"
+ reg = <0x0 0xff100000 0x1000>;
+ clock-name = "clk_sys", "clk_flash"
+ clocks = <&misc_clk &misc_clk>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 14 4>;
+ arasan,has-mdma;
+ #address-cells = <1>;
+ #size-cells = <0>
+
+ nand@0 {
+ reg = <0>
+ partition@0 {
+ label = "filesystem";
+ reg = <0x0 0x0 0x1000000>;
+ };
+ (...)
+ };
+ };
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v4] iio:temperature: Add support for TI TMP007 sensor
From: Manivannan Sadhasivam @ 2017-01-09 2:55 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A, pmeerw-jW+XmwGofnusTnJN9+BGXg
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
This patch adds support for TI TMP007 - 16 bit IR thermopile sensor with integrated Math engine.
Sensor takes care of calculating the object temperature with the help of calibrated constants stored in non-volatile memory,
thereby reducing the calculation overhead.
Signed-off-by: Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
Changes since v3:
1. Removed caching of status register
2. Modified comments for data validity
3. Added possible address combinations in dTree bindings file
.../devicetree/bindings/iio/temperature/tmp007.txt | 27 ++
drivers/iio/temperature/Kconfig | 10 +
drivers/iio/temperature/Makefile | 1 +
drivers/iio/temperature/tmp007.c | 345 +++++++++++++++++++++
4 files changed, 383 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/temperature/tmp007.txt
create mode 100644 drivers/iio/temperature/tmp007.c
diff --git a/Documentation/devicetree/bindings/iio/temperature/tmp007.txt b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
new file mode 100644
index 0000000..3b8f41f
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
@@ -0,0 +1,27 @@
+* TI TMP007 - IR thermopile sensor with integrated math engine
+
+Link to datasheet: http://www.ti.com/lit/ds/symlink/tmp007.pdf
+
+Required properties:
+
+ - compatible: should be "ti,tmp007"
+ - reg: the I2C address of the sensor (changeable via ADR pins)
+ ------------------------------
+ |ADR1 | ADR0 | Device Address|
+ ------------------------------
+ 0 0 0x40
+ 0 1 0x41
+ 0 SDA 0x42
+ 0 SCL 0x43
+ 1 0 0x44
+ 1 1 0x45
+ 1 SDA 0x46
+ 1 SCL 0x47
+
+Example:
+
+tmp007@40 {
+ compatible = "ti,tmp007";
+ reg = <0x40>;
+};
+
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index c4664e5..538ce9e 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -23,6 +23,16 @@ config TMP006
This driver can also be built as a module. If so, the module will
be called tmp006.
+config TMP007
+ tristate "TMP007 infrared thermopile sensor with Integrated Math Engine"
+ depends on I2C
+ help
+ If you say yes here you get support for the Texas Instruments
+ TMP007 infrared thermopile sensor with Integrated Math Engine.
+
+ This driver can also be built as a module. If so, the module will
+ be called tmp007.
+
config TSYS01
tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
depends on I2C
diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
index 02bc79d..f0cf5c5 100644
--- a/drivers/iio/temperature/Makefile
+++ b/drivers/iio/temperature/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_MLX90614) += mlx90614.o
obj-$(CONFIG_TMP006) += tmp006.o
+obj-$(CONFIG_TMP007) += tmp007.o
obj-$(CONFIG_TSYS01) += tsys01.o
obj-$(CONFIG_TSYS02D) += tsys02d.o
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
new file mode 100644
index 0000000..24c6c16
--- /dev/null
+++ b/drivers/iio/temperature/tmp007.c
@@ -0,0 +1,345 @@
+/*
+ * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
+ *
+ * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
+ *
+ * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
+ *
+ * Note: This driver assumes that the sensor has been calibrated beforehand
+ *
+ * TODO: ALERT irq, limit threshold events
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define TMP007_TDIE 0x01
+#define TMP007_CONFIG 0x02
+#define TMP007_TOBJECT 0x03
+#define TMP007_STATUS 0x04
+#define TMP007_STATUS_MASK 0x05
+#define TMP007_MANUFACTURER_ID 0x1e
+#define TMP007_DEVICE_ID 0x1f
+
+#define TMP007_CONFIG_CONV_EN BIT(12)
+#define TMP007_CONFIG_COMP_EN BIT(5)
+#define TMP007_CONFIG_TC_EN BIT(6)
+#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
+#define TMP007_CONFIG_CR_SHIFT 9
+
+#define TMP007_STATUS_CONV_READY BIT(14)
+#define TMP007_STATUS_DATA_VALID BIT(9)
+
+#define TMP007_MANUFACTURER_MAGIC 0x5449
+#define TMP007_DEVICE_MAGIC 0x0078
+
+#define TMP007_TEMP_SHIFT 2
+
+struct tmp007_data {
+ struct i2c_client *client;
+ u16 config;
+};
+
+static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
+ {0, 500000}, {0, 250000} };
+
+static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
+{
+ s32 ret;
+ int tries = 50;
+
+ while (tries-- > 0) {
+ ret = i2c_smbus_read_word_swapped(data->client,
+ TMP007_STATUS);
+ if (ret < 0)
+ return ret;
+ if ((ret & TMP007_STATUS_CONV_READY) &&
+ !(ret & TMP007_STATUS_DATA_VALID))
+ break;
+ msleep(100);
+ }
+
+ if (tries < 0)
+ return -EIO;
+
+ return i2c_smbus_read_word_swapped(data->client, reg);
+}
+
+static int tmp007_powerdown(struct tmp007_data *data)
+{
+ return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config & ~TMP007_CONFIG_CONV_EN);
+}
+
+static int tmp007_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int *val,
+ int *val2, long mask)
+{
+ struct tmp007_data *data = iio_priv(indio_dev);
+ s32 ret;
+ int conv_rate;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (channel->channel2) {
+ case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
+ if (ret < 0)
+ return ret;
+ break;
+ case IIO_MOD_TEMP_OBJECT:
+ ret = tmp007_read_temperature(data, TMP007_TOBJECT);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 31;
+ *val2 = 250000;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
+ >> TMP007_CONFIG_CR_SHIFT;
+ *val = tmp007_avgs[conv_rate][0];
+ *val2 = tmp007_avgs[conv_rate][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int tmp007_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int val,
+ int val2, long mask)
+{
+ struct tmp007_data *data = iio_priv(indio_dev);
+ int i;
+ u16 tmp;
+
+ if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
+ for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
+ if ((val == tmp007_avgs[i][0]) &&
+ (val2 == tmp007_avgs[i][1])) {
+ tmp = data->config & ~TMP007_CONFIG_CR_MASK;
+ tmp |= (i << TMP007_CONFIG_CR_SHIFT);
+
+ return i2c_smbus_write_word_swapped(data->client,
+ TMP007_CONFIG,
+ data->config = tmp);
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
+
+static struct attribute *tmp007_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group tmp007_attribute_group = {
+ .attrs = tmp007_attributes,
+};
+
+static const struct iio_chan_spec tmp007_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .modified = 1,
+ .channel2 = IIO_MOD_TEMP_AMBIENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_TEMP,
+ .modified = 1,
+ .channel2 = IIO_MOD_TEMP_OBJECT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ }
+};
+
+static const struct iio_info tmp007_info = {
+ .read_raw = tmp007_read_raw,
+ .write_raw = tmp007_write_raw,
+ .attrs = &tmp007_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static bool tmp007_identify(struct i2c_client *client)
+{
+ int manf_id, dev_id;
+
+ manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
+ if (manf_id < 0)
+ return false;
+
+ dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
+ if (dev_id < 0)
+ return false;
+
+ return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
+}
+
+static int tmp007_probe(struct i2c_client *client,
+ const struct i2c_device_id *tmp007_id)
+{
+ struct tmp007_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+ u16 status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -EOPNOTSUPP;
+
+ if (!tmp007_identify(client)) {
+ dev_err(&client->dev, "TMP007 not found\n");
+ return -ENODEV;
+ }
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = dev_name(&client->dev);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &tmp007_info;
+
+ indio_dev->channels = tmp007_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
+
+ /*
+ * Set Configuration register:
+ * 1. Conversion ON
+ * 2. Comparator mode
+ * 3. Transient correction enable
+ */
+
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
+ if (ret < 0)
+ return ret;
+
+ data->config = ret;
+ data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
+
+ ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Set Status Mask register:
+ * 1. Conversion ready enable
+ * 2. Data valid enable
+ */
+
+ ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
+ if (ret < 0)
+ goto error_powerdown;
+
+ status = ret;
+ status |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
+
+ ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, status);
+ if (ret < 0)
+ goto error_powerdown;
+
+ return iio_device_register(indio_dev);
+
+error_powerdown:
+ tmp007_powerdown(data);
+
+ return ret;
+}
+
+static int tmp007_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct tmp007_data *data = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ tmp007_powerdown(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tmp007_suspend(struct device *dev)
+{
+ struct tmp007_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+
+ return tmp007_powerdown(data);
+}
+
+static int tmp007_resume(struct device *dev)
+{
+ struct tmp007_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+
+ return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
+ data->config | TMP007_CONFIG_CONV_EN);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
+
+static const struct of_device_id tmp007_of_match[] = {
+ { .compatible = "ti,tmp007", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tmp007_of_match);
+
+static const struct i2c_device_id tmp007_id[] = {
+ { "tmp007", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tmp007_id);
+
+static struct i2c_driver tmp007_driver = {
+ .driver = {
+ .name = "tmp007",
+ .of_match_table = of_match_ptr(tmp007_of_match),
+ .pm = &tmp007_pm_ops,
+ },
+ .probe = tmp007_probe,
+ .remove = tmp007_remove,
+ .id_table = tmp007_id,
+};
+module_i2c_driver(tmp007_driver);
+
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
+MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
+MODULE_LICENSE("GPL");
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v1 1/3] dt: bindings: add thermal device driver for zx2967
From: Shawn Guo @ 2017-01-09 2:41 UTC (permalink / raw)
To: Baoyou Xie
Cc: rui.zhang, edubezval, robh+dt, mark.rutland, jun.nie, gregkh,
davem, geert+renesas, akpm, mchehab, linux, linux-pm, devicetree,
linux-kernel, linux-arm-kernel, xie.baoyou, chen.chaokai,
wang.qiang01
In-Reply-To: <1483767488-19778-1-git-send-email-baoyou.xie@linaro.org>
On Sat, Jan 07, 2017 at 01:38:06PM +0800, Baoyou Xie wrote:
> This patch adds dt-binding documentation for zx2967 family thermal sensor.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
The patch subject is inappropriate. The patch adds a bindings not
device driver.
> ---
> .../devicetree/bindings/thermal/zx2967-thermal.txt | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
> new file mode 100644
> index 0000000..2633964
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/zx2967-thermal.txt
> @@ -0,0 +1,22 @@
> +* ZTE zx2967 family Thermal
> +
> +Required Properties:
> +- compatible: should be one of the following.
> + * zte,zx2967-thermal
> + * zte,zx296718-thermal
We usually use specific SoC name in compatible string to specify the
programming model for the hardware. That said, I do not think we need
"zte,zx2967-thermal".
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +- clocks : Pairs of phandle and specifier referencing the controller's clocks.
> +- clock-names: "tempsensor_gate" for the topcrm clock.
> + "tempsensor_pclk" for the apb clock.
In the context of tempsensor device, the "tempsensor_" in the clock
names are not really necessary.
> +- #thermal-sensor-cells: must be 0.
> +
> +Example:
> +
> + tempsensor: tempsensor@148a000 {
> + compatible = "zte,zx2967-thermal";
"zte,zx296718-thermal"
Shawn
> + reg = <0x0148a000 0x20>;
> + clocks = <&topcrm TEMPSENSOR_GATE>, <&audiocrm AUDIO_TS_PCLK>;
> + clock-names = "tempsensor_gate", "tempsensor_pclk";
> + #thermal-sensor-cells = <0>;
> + };
> --
> 2.7.4
>
^ permalink raw reply
* RE: [PATCH v2 05/12] Document: dt: binding: imx: update pinctrl doc for imx6sll
From: Jacky Bai @ 2017-01-09 2:32 UTC (permalink / raw)
To: Linus Walleij
Cc: Shawn Guo, Michael Turquette, Stephen Boyd, Rob Herring,
Mark Rutland, Sascha Hauer, Fabio Estevam, Daniel Lezcano,
Thomas Gleixner, Philipp Zabel, linux-clk,
devicetree@vger.kernel.org, linux-gpio@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, jacky.baip@gmail.com
In-Reply-To: <CACRpkdYUME8K+JusA0ORRKqxyBuhDdyei8eg7UZbHidKw9=bQw@mail.gmail.com>
> Subject: Re: [PATCH v2 05/12] Document: dt: binding: imx: update pinctrl doc
> for imx6sll
>
> On Tue, Dec 27, 2016 at 10:47 AM, Bai Ping <ping.bai@nxp.com> wrote:
>
> > Add pinctrl binding doc update for imx6sll.
> >
> > Signed-off-by: Bai Ping <ping.bai@nxp.com>
>
> I have to push back on this a bit.
>
> > +Please refer to fsl,imx-pinctrl.txt in this directory for common
> > +binding part and usage.
>
> I understand that it is building on top of the old i.MX bindings and that it has
> some kind of "tradition" coming with it.
>
> At the same time, the i.MX bindings came about before we had the generic pin
> control bindings defined.
>
> > +CONFIG bits definition:
> > +PAD_CTL_LVE (1 << 22)
> > +PAD_CTL_HYS (1 << 16)
> > +PAD_CTL_PUS_100K_DOWN (0 << 14)
> > +PAD_CTL_PUS_47K_UP (1 << 14)
> > +PAD_CTL_PUS_100K_UP (2 << 14)
> > +PAD_CTL_PUS_22K_UP (3 << 14)
> > +PAD_CTL_PUE (1 << 13)
> > +PAD_CTL_PKE (1 << 12)
> > +PAD_CTL_ODE (1 << 11)
> > +PAD_CTL_SPEED_LOW (0 << 6)
> > +PAD_CTL_SPEED_MED (1 << 6)
> > +PAD_CTL_SPEED_HIGH (3 << 6)
> > +PAD_CTL_DSE_DISABLE (0 << 3)
> > +PAD_CTL_DSE_260ohm (1 << 3)
> > +PAD_CTL_DSE_130ohm (2 << 3)
> > +PAD_CTL_DSE_87ohm (3 << 3)
> > +PAD_CTL_DSE_65ohm (4 << 3)
> > +PAD_CTL_DSE_52ohm (5 << 3)
> > +PAD_CTL_DSE_43ohm (6 << 3)
> > +PAD_CTL_DSE_37ohm (7 << 3)
> > +PAD_CTL_SRE_FAST (1 << 0)
> > +PAD_CTL_SRE_SLOW (0 << 0)
>
> A whole slew of these if not all correspond to the generic bindings.
>
> I would consider augmenting the code in the driver to handle the generic
> bindings *in addition* to the old legacy bindings, and use those over these
> random custom bits.
>
> Read drivers using CONFIG_GENERIC_PINCONF as an inspiration.
>
> For example see commit
> cefbf1a1b29531a970bc2908a50a75d6474fcc38
> "pinctrl: sunxi: Support generic binding"
> from Maxime Ripard, where he does a similar thing for sunxi.
I have look into the above commit on using generic binding. But I think the generic pinconf
is not very easy to add in imx pinctrl Driver. imx pinctrl use a different way to parse the pin configure.
Each fsl,pin entry looks like <PIN_FUNC_ID CONFIG> in dts, the CONFIG is the pad setting value like
pull-up, open-drain, drive strength etc. The above config bit definition is specific to each SOC in the PAD CTL register.
If we want set the pin config to enable hysteresis, 47KOhm Pull Up, 50Mhz speed, 80Ohm driver strength
and Fast Slew Rate, then the CONFIG value should be 0x17059( ORs corresponding bit definition). This value will be set in
PAD CTL register to config the corresponding pin.
BR
Jacky Bai
>
> Yours,
> Linus Walleij
^ permalink raw reply
* Re: [PATCH v7 5/5] soc: zte: pm_domains: Add support for zx296718
From: Shawn Guo @ 2017-01-09 2:16 UTC (permalink / raw)
To: Baoyou Xie
Cc: jun.nie, robh+dt, mark.rutland, gregkh, davem, geert+renesas,
akpm, mchehab, krzk, arnd, claudiu.manoil, amitdanielk,
pankaj.dubey, yangbo.lu, scott.branden, simon.horman, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <1483694164-7668-5-git-send-email-baoyou.xie@linaro.org>
On Fri, Jan 06, 2017 at 05:16:04PM +0800, Baoyou Xie wrote:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's zx2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> Reviewed-by: Jun Nie <jun.nie@linaro.org>
Except the need of PCU_DM_xxx enum (I'm not strong on that,so would
leave it to author's decision), the patch series looks good to me.
I'm going to queue it up for 4.11 after getting Rob's ACK on bindings.
Let me know if anyone has any objections.
Shawn
^ permalink raw reply
* Re: [PATCH v7 1/5] dt-bindings: zte: add bindings document for zx2967 power domain controller
From: Shawn Guo @ 2017-01-09 2:09 UTC (permalink / raw)
To: Baoyou Xie, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: jun.nie-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
davem-fT/PcQaiUtIeIZ0/mPfg9Q,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, krzk-DgEjT+Ai2ygdnm+yROfE0A,
arnd-r2nGTMty4D4, claudiu.manoil-3arQi8VN3Tc,
amitdanielk-Re5JQEeQqe8AvxtiuMwx3w,
pankaj.dubey-Sze3O3UU22JBDgjK7y7TUQ, yangbo.lu-3arQi8VN3Tc,
scott.branden-dY08KVG/lbpWk0Htik3J/w,
simon.horman-wFxRvT7yatFl57MIdRCFDg,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1483694164-7668-1-git-send-email-baoyou.xie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Fri, Jan 06, 2017 at 05:16:00PM +0800, Baoyou Xie wrote:
> This patch adds device tree bindings document for ZTE zx2967
> family power domain controller.
>
> Signed-off-by: Baoyou Xie <baoyou.xie-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Rob,
Are you happy with the bindings? I plan to merge the series through
arm-soc tree with your ACK on this patch.
Shawn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3] iio:temperature: Add support for TI TMP007 sensor
From: Mani Sadhasivam @ 2017-01-09 2:06 UTC (permalink / raw)
To: Jonathan Cameron
Cc: pmeerw-jW+XmwGofnusTnJN9+BGXg, linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <9efdb51f-1b15-d8b7-8c3d-777cae4c382b-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On Sun, Jan 08, 2017 at 10:56:14AM +0000, Jonathan Cameron wrote:
> On 06/01/17 02:50, Mani Sadhasivam wrote:
> > This patch adds support for TI TMP007 - 16 bit IR thermopile sensor with integrated Math engine.
> > Sensor takes care of calculating the object temperature with the help of calibrated constants stored in non-volatile memory,
> > thereby reducing the calculation overhead.
> >
> > Signed-off-by: Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Pretty good. A few minor comments inline. It 'might' be worth using
> regmap for this part to avoid hand rolling masked partial register writes
> and caching of register values. Perhaps it's not worth it for such a
> simple interface however.
>
> Jonathan
Thanks Jonathan for your review.
> > ---
> >
> > Changes in v3 (based on suggestions from Peter):
> >
> > 1. Added data validity check for TObj
> > 2. Modified the comment style
> > 3. Added powerdown function
> > 4. Some code cleanups
> >
> > .../devicetree/bindings/iio/temperature/tmp007.txt | 16 +
> > drivers/iio/temperature/Kconfig | 10 +
> > drivers/iio/temperature/Makefile | 1 +
> > drivers/iio/temperature/tmp007.c | 345 +++++++++++++++++++++
> > 4 files changed, 372 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > create mode 100644 drivers/iio/temperature/tmp007.c
> >
> > diff --git a/Documentation/devicetree/bindings/iio/temperature/tmp007.txt b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > new file mode 100644
> > index 0000000..9ae0519
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/iio/temperature/tmp007.txt
> > @@ -0,0 +1,16 @@
> > +* TI TMP007 - IR thermopile sensor with integrated math engine
> > +
> > +Link to datasheet: http://www.ti.com/lit/ds/symlink/tmp007.pdf
> > +
> > +Required properties:
> > +
> > + - compatible: should be "ti,tmp007"
> > + - reg: the I2C address of the sensor (changeable via ADR pins)
> Perhaps list the options that are possible?
ACK.
> > +
> > +Example:
> > +
> > +tmp007@40 {
> > + compatible = "ti,tmp007";
> > + reg = <0x40>;
> > +};
> > +
> > diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
> > index c4664e5..538ce9e 100644
> > --- a/drivers/iio/temperature/Kconfig
> > +++ b/drivers/iio/temperature/Kconfig
> > @@ -23,6 +23,16 @@ config TMP006
> > This driver can also be built as a module. If so, the module will
> > be called tmp006.
> >
> > +config TMP007
> > + tristate "TMP007 infrared thermopile sensor with Integrated Math Engine"
> > + depends on I2C
> > + help
> > + If you say yes here you get support for the Texas Instruments
> > + TMP007 infrared thermopile sensor with Integrated Math Engine.
> > +
> > + This driver can also be built as a module. If so, the module will
> > + be called tmp007.
> > +
> > config TSYS01
> > tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection"
> > depends on I2C
> > diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile
> > index 02bc79d..f0cf5c5 100644
> > --- a/drivers/iio/temperature/Makefile
> > +++ b/drivers/iio/temperature/Makefile
> > @@ -4,5 +4,6 @@
> >
> > obj-$(CONFIG_MLX90614) += mlx90614.o
> > obj-$(CONFIG_TMP006) += tmp006.o
> > +obj-$(CONFIG_TMP007) += tmp007.o
> > obj-$(CONFIG_TSYS01) += tsys01.o
> > obj-$(CONFIG_TSYS02D) += tsys02d.o
> > diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
> > new file mode 100644
> > index 0000000..a385ef5
> > --- /dev/null
> > +++ b/drivers/iio/temperature/tmp007.c
> > @@ -0,0 +1,345 @@
> > +/*
> > + * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
> > + *
> > + * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > + *
> > + * This file is subject to the terms and conditions of version 2 of
> > + * the GNU General Public License. See the file COPYING in the main
> > + * directory of this archive for more details.
> > + *
> > + * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
> > + *
> > + * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
> > + *
> > + * Note: This driver assumes that the sensor has been calibrated beforehand
> > + *
> > + * TODO: ALERT irq, limit threshold events
> > + *
> > + */
> > +
> > +#include <linux/err.h>
> > +#include <linux/i2c.h>
> > +#include <linux/delay.h>
> > +#include <linux/module.h>
> > +#include <linux/pm.h>
> > +#include <linux/bitops.h>
> > +#include <linux/of.h>
> > +
> > +#include <linux/iio/iio.h>
> > +#include <linux/iio/sysfs.h>
> > +
> > +#define TMP007_TDIE 0x01
> > +#define TMP007_CONFIG 0x02
> > +#define TMP007_TOBJECT 0x03
> > +#define TMP007_STATUS 0x04
> > +#define TMP007_STATUS_MASK 0x05
> > +#define TMP007_MANUFACTURER_ID 0x1e
> > +#define TMP007_DEVICE_ID 0x1f
> > +
> > +#define TMP007_CONFIG_CONV_EN BIT(12)
> > +#define TMP007_CONFIG_COMP_EN BIT(5)
> > +#define TMP007_CONFIG_TC_EN BIT(6)
> > +#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
> > +#define TMP007_CONFIG_CR_SHIFT 9
> > +
> > +#define TMP007_STATUS_CONV_READY BIT(14)
> > +#define TMP007_STATUS_DATA_VALID BIT(9)
> > +
> > +#define TMP007_MANUFACTURER_MAGIC 0x5449
> > +#define TMP007_DEVICE_MAGIC 0x0078
> > +
> > +#define TMP007_TEMP_SHIFT 2
> > +
> > +struct tmp007_data {
> > + struct i2c_client *client;
>
> The fact you are caching values here and that everything is register
> based suggests to me that it might make sense to use regmap and take
> advantage of it's built in caching and masked write functions.
>
> If you pefer to stick to direct smbus calls that is fine.
I'd prefer to use smbus calls over regmap here. As the usage is quite less and I don't think it'll be needed for such
simple interface.
>
> > + u16 config;
>
> > + u16 status_mask;
> Why cache this register? It is directly read then written
> whenever used.
ACK.
>
> > +};
> > +
> > +static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
> > + {0, 500000}, {0, 250000} };
> > +
> > +static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
> > +{
> > + s32 ret;
> > + int tries = 50;
> > +
> > + while (tries-- > 0) {
> > + ret = i2c_smbus_read_word_swapped(data->client,
> > + TMP007_STATUS);
> > + if (ret < 0)
> > + return ret;
> > + if ((ret & TMP007_STATUS_CONV_READY) &&
> > + !(ret & TMP007_STATUS_DATA_VALID))
> > + break;
> > + msleep(100);
> > + }
> > +
> > + if (tries < 0)
> > + return -EIO;
> > +
> > + return i2c_smbus_read_word_swapped(data->client, reg);
> > +}
> > +
> > +static int tmp007_powerdown(struct tmp007_data *data)
> > +{
> > + return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config & ~TMP007_CONFIG_CONV_EN);
> > +}
> > +
> > +static int tmp007_read_raw(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *channel, int *val,
> > + int *val2, long mask)
> > +{
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > + s32 ret;
> > + int conv_rate;
> > +
> > + switch (mask) {
> > + case IIO_CHAN_INFO_RAW:
> > + switch (channel->channel2) {
> > + case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
> > + if (ret < 0)
> > + return ret;
> > + break;
> > + case IIO_MOD_TEMP_OBJECT:
> > + ret = tmp007_read_temperature(data, TMP007_TOBJECT);
> > + if (ret < 0)
> > + return ret;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
> > +
> > + return IIO_VAL_INT;
> > + case IIO_CHAN_INFO_SCALE:
> > + *val = 31;
> > + *val2 = 250000;
> > +
> > + return IIO_VAL_INT_PLUS_MICRO;
> > + case IIO_CHAN_INFO_SAMP_FREQ:
> > + conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
> > + >> TMP007_CONFIG_CR_SHIFT;
> > + *val = tmp007_avgs[conv_rate][0];
> > + *val2 = tmp007_avgs[conv_rate][1];
> > +
> > + return IIO_VAL_INT_PLUS_MICRO;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > +static int tmp007_write_raw(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *channel, int val,
> > + int val2, long mask)
> > +{
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > + int i;
> > + u16 tmp;
> > +
> > + if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
> > + for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
> > + if ((val == tmp007_avgs[i][0]) &&
> > + (val2 == tmp007_avgs[i][1])) {
> > + tmp = data->config & ~TMP007_CONFIG_CR_MASK;
> > + tmp |= (i << TMP007_CONFIG_CR_SHIFT);
> > +
> > + return i2c_smbus_write_word_swapped(data->client,
> > + TMP007_CONFIG,
> > + data->config = tmp);
> > + }
> > + }
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
> > +
> > +static struct attribute *tmp007_attributes[] = {
> > + &iio_const_attr_sampling_frequency_available.dev_attr.attr,
> > + NULL
> > +};
> > +
> > +static const struct attribute_group tmp007_attribute_group = {
> > + .attrs = tmp007_attributes,
> > +};
> > +
> > +static const struct iio_chan_spec tmp007_channels[] = {
> > + {
> > + .type = IIO_TEMP,
> > + .modified = 1,
> > + .channel2 = IIO_MOD_TEMP_AMBIENT,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> > + BIT(IIO_CHAN_INFO_SCALE),
> > + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> > + },
> > + {
> > + .type = IIO_TEMP,
> > + .modified = 1,
> > + .channel2 = IIO_MOD_TEMP_OBJECT,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> > + BIT(IIO_CHAN_INFO_SCALE),
> > + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> > + }
> > +};
> > +
> > +static const struct iio_info tmp007_info = {
> > + .read_raw = tmp007_read_raw,
> > + .write_raw = tmp007_write_raw,
> > + .attrs = &tmp007_attribute_group,
> > + .driver_module = THIS_MODULE,
> > +};
> > +
> > +static bool tmp007_identify(struct i2c_client *client)
> > +{
> > + int manf_id, dev_id;
> > +
> > + manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
> > + if (manf_id < 0)
> > + return false;
> > +
> > + dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
> > + if (dev_id < 0)
> > + return false;
> > +
> > + return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
> > +}
> > +
> > +static int tmp007_probe(struct i2c_client *client,
> > + const struct i2c_device_id *tmp007_id)
> > +{
> > + struct tmp007_data *data;
> > + struct iio_dev *indio_dev;
> > + int ret;
> > +
> > + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
> > + return -EOPNOTSUPP;
> > +
> > + if (!tmp007_identify(client)) {
> > + dev_err(&client->dev, "TMP007 not found\n");
> > + return -ENODEV;
> > + }
> > +
> > + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > + if (!indio_dev)
> > + return -ENOMEM;
> > +
> > + data = iio_priv(indio_dev);
> > + i2c_set_clientdata(client, indio_dev);
> > + data->client = client;
> > +
> > + indio_dev->dev.parent = &client->dev;
> > + indio_dev->name = dev_name(&client->dev);
> > + indio_dev->modes = INDIO_DIRECT_MODE;
> > + indio_dev->info = &tmp007_info;
> > +
> > + indio_dev->channels = tmp007_channels;
> > + indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
> > +
> > + /*
> > + * Set Configuration register:
> > + * 1. Conversion ON
> > + * 2. Comparator mode
> > + * 3. Transient correction enable
> > + */
> > +
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
> > + if (ret < 0)
> > + return ret;
> > +
> > + data->config = ret;
> > + data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
> > +
> > + ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config);
> > + if (ret < 0)
> > + return ret;
> > +
> > + /*
> > + * Set Status Mask register:
> > + * 1. Conversion ready enable
> 2. Data valid?
ACK.
> > + */
> > +
> > + ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
> > + if (ret < 0)
> > + goto error_powerdown;
> > +
> > + data->status_mask = ret;
> > + data->status_mask |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
> > +
> > + ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
> > + data->status_mask);
> > + if (ret < 0)
> > + goto error_powerdown;
> > +
> > + return iio_device_register(indio_dev);
> > +
> > +error_powerdown:
> > + tmp007_powerdown(data);
> > +
> > + return ret;
> > +}
> > +
> > +static int tmp007_remove(struct i2c_client *client)
> > +{
> > + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> > + struct tmp007_data *data = iio_priv(indio_dev);
> > +
> > + iio_device_unregister(indio_dev);
> > + tmp007_powerdown(data);
> > +
> > + return 0;
> > +}
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int tmp007_suspend(struct device *dev)
> > +{
> > + struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> > + to_i2c_client(dev)));
> > +
> > + return tmp007_powerdown(data);
> > +}
> > +
> > +static int tmp007_resume(struct device *dev)
> > +{
> > + struct tmp007_data *data = iio_priv(i2c_get_clientdata(
> > + to_i2c_client(dev)));
> > +
> > + return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
> > + data->config | TMP007_CONFIG_CONV_EN);
> > +}
> > +#endif
> > +
> > +static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
> > +
> > +static const struct of_device_id tmp007_of_match[] = {
> > + { .compatible = "ti,tmp007", },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, tmp007_of_match);
> > +
> > +static const struct i2c_device_id tmp007_id[] = {
> > + { "tmp007", 0 },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(i2c, tmp007_id);
> > +
> > +static struct i2c_driver tmp007_driver = {
> > + .driver = {
> > + .name = "tmp007",
> > + .of_match_table = of_match_ptr(tmp007_of_match),
> > + .pm = &tmp007_pm_ops,
> > + },
> > + .probe = tmp007_probe,
> > + .remove = tmp007_remove,
> > + .id_table = tmp007_id,
> > +};
> > +module_i2c_driver(tmp007_driver);
> > +
> > +MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
> > +MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
> > +MODULE_LICENSE("GPL");
> >
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
From: Wenyou.Yang-UWL1GkI3JZL3oGB3hsPCZA @ 2017-01-09 1:47 UTC (permalink / raw)
To: alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: linux-lFZ/pmaqli7XmaaqVzeoHQ,
nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170106090517.txcoukisnx43cfqq-m++hUPXGwpdeoWH0uzbU5w@public.gmane.org>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 2150 bytes --]
Hi Alexandre,
> -----Original Message-----
> From: Alexandre Belloni [mailto:alexandre.belloni@free-electrons.com]
> Sent: 2017Äê1ÔÂ6ÈÕ 17:05
> To: Wenyou Yang - A41535 <Wenyou.Yang@microchip.com>
> Cc: Russell King <linux@arm.linux.org.uk>; Nicolas Ferre
> <nicolas.ferre@atmel.com>; Rob Herring <robh+dt@kernel.org>; Mark Rutland
> <mark.rutland@arm.com>; linux-kernel@vger.kernel.org; Wenyou Yang - A41535
> <Wenyou.Yang@microchip.com>; devicetree@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
>
> Hi,
>
> On 06/01/2017 at 14:59:45 +0800, Wenyou Yang wrote :
> > For the SoCs such as SAMA5D2 and SAMA5D4 which have L2 cache, flush
> > the L2 cache first before entering the cpu idle.
> >
> > Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> > ---
> >
> > arch/arm/mach-at91/pm.c | 19 +++++++++++++++++++
> > drivers/memory/atmel-sdramc.c | 1 +
> > 2 files changed, 20 insertions(+)
> >
> > diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
> > b4332b727e9c..1a60dede1a01 100644
> > --- a/arch/arm/mach-at91/pm.c
> > +++ b/arch/arm/mach-at91/pm.c
> > @@ -289,6 +289,24 @@ static void at91_ddr_standby(void)
> > at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); }
> >
> > +static void at91_ddr_cache_standby(void) {
> > + u32 saved_lpr;
> > +
> > + flush_cache_all();
> > + outer_disable();
> > +
> > + saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
> > + at91_ramc_write(0, AT91_DDRSDRC_LPR, (saved_lpr &
> > + (~AT91_DDRSDRC_LPCB)) |
> AT91_DDRSDRC_LPCB_SELF_REFRESH);
> > +
> > + cpu_do_idle();
> > +
> > + at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr);
> > +
> > + outer_resume();
> > +}
> > +
>
> Seems good to me. Did you measure the added latency on sama5d3 if you add the
> cache operations in at91_ddr_standby instead of having a new function?
No, I didn't. How to measure it?
Best Regards,
Wenyou Yang
N§²æìr¸yúèØb²X¬¶Ç§vØ^)Þº{.nÇ+·zøzÚÞz)í
æèw*\x1fjg¬±¨\x1e¶Ý¢j.ïÛ°\½½MúgjÌæa×\x02' ©Þ¢¸\f¢·¦j:+v¨wèjØm¶ÿ¾\a«êçzZ+ùÝ¢j"ú!¶i
^ permalink raw reply
* ATTENTION !
From: Kamal Ali Mohamed @ 2017-01-09 0:03 UTC (permalink / raw)
In-Reply-To: <2061243689.1489900.1483920231155.ref@mail.yahoo.com>
Greetings to you and your families,
I never want to disturb you at all but will like you give me your attention. I need a matured and capable hand in a business deal of $8, 500, 000.00 (Eight Million Five Hundred Thousand USA Dollars).I belief you are suitable to handle such project perfectly .Please answer me.For more details.All details shall be sent to you once I hear from you.Sorry if you received this letter in your spam, Due to recent connection error here in my country.
Thanks and best regards,
Mr.Kamal Ali Mohamed.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/5] drivers: mmc: sunxi: fix A64 calibration routine
From: André Przywara @ 2017-01-08 23:56 UTC (permalink / raw)
To: Maxime Ripard
Cc: Ulf Hansson, Chen-Yu Tsai, Hans De Goede, Icenowy Zheng,
Mark Rutland, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170105174725.kmr25iodjnjozqjm@lukather>
On 05/01/17 17:47, Maxime Ripard wrote:
Hi,
> On Mon, Jan 02, 2017 at 11:03:42PM +0000, Andre Przywara wrote:
>> The calibration facility in the A64 MMC block seems to have been
>> misunderstood: the result value is not the value to program into the
>> delay bits, but is the number of delay cells that result in a full clock
>> cycle delay. So this value has to be scaled by the desired phase, which
>> we still have to know and program.
>> Change the calibration routine to take a phase parameter and scale the
>> calibration value accordingly.
>> Also introduce sun50i-a64 delay parameters to store the required phase.
>> Looking at the BSP kernel the sample delay for anything below HS200 is
>> 0, so we go with that value.
>> Once the driver supports HS200 and faster modes, we can enter confirmed
>> working values in there.
>>
>> Signed-off-by: Andre Przywara <andre.przywara-5wv7dgnIgG8@public.gmane.org>
>
> Exactly how that works hasn't been confirmed, and the only thing that
> this patch actually do is... nothing, since the delay is always 0. If
> and when we get HS400 to work and we know for a fact how the
> calibration works, then we'll be able to use it. Until then, we can
> just clear those bits.
Fair enough, though I am a bit puzzled as what to do here now:
Dropping this patch here entirely causes the wrong calibration settings
to degrade the BananaPi eMMC performance by up to 50% (20 MB/s vs.
40MB/s in hdparm, and 25% longer execution time for a "find / -type f |
xargs md5sum > /dev/null" run). So this is not an option.
1) Shall I simply revert Icenowy's original patch that introduced the
calibration function? That should leave the values at their reset value
of 0. But do we want to make sure that these values are set to 0 by
explicitly zeroing the bits?
Also I guess your HS-400 support will need to write some values in
there, so we will need some code later again?
2) Changing the calibration function to don't do any calibration really
and just write 0 into the delay bits seems like an option, but looks a
bit weird. Also I guess your faster transfer modes support will need to
write _something_, though I don't know what those values are and where
they will come from.
So I am leaning towards 1) for now, unless you send your MMC patches and
we at least merge the patch dealing with the calibration part for the
next release.
Any recommendations? I would love to see the MMC support go into 4.11.
Cheers,
Andre.
^ permalink raw reply
* Re: [PATCH linux 2/6] hwmon: occ: Add sysfs interface
From: Andrew Jeffery @ 2017-01-08 23:52 UTC (permalink / raw)
To: Guenter Roeck, Edward James
Cc: corbet, devicetree, eajames.ibm, jdelvare, joel, linux-doc,
linux-hwmon, linux-i2c, linux-kernel, mark.rutland, robh+dt, wsa
In-Reply-To: <8b182766-32a0-9eb1-7917-14abf811cef5@roeck-us.net>
[-- Attachment #1: Type: text/plain, Size: 4017 bytes --]
On Sat, 2017-01-07 at 09:15 -0800, Guenter Roeck wrote:
> On 01/06/2017 02:17 PM, Edward James wrote:
>
> [ ... ]
>
> > > > +}
> > > > +
> > > > +static DEVICE_ATTR(online, S_IWUSR | S_IRUGO, show_occ_online,
> > > > + store_occ_online);
> > > > +
> > > > +struct occ_sysfs *occ_sysfs_start(struct device *dev, struct occ *occ,
> > > > + struct occ_sysfs_config *config)
> > > > +{
> > > > + struct occ_sysfs *hwmon = devm_kzalloc(dev, sizeof(struct occ_sysfs),
> > > > + GFP_KERNEL);
> > > > + int rc;
> > > > +
> > > > + if (!hwmon)
> > > > + return ERR_PTR(-ENOMEM);
> > > > +
> > > > + hwmon->occ = occ;
> > > > + hwmon->num_caps_fields = config->num_caps_fields;
> > > > + hwmon->caps_names = config->caps_names;
> > > > +
> > > > + dev_set_drvdata(dev, hwmon);
> > > > +
> > > > + rc = device_create_file(dev, &dev_attr_online);
> > > > + if (rc)
> > > > + return ERR_PTR(rc);
> > > > +
> > > > + return hwmon;
> > > > +}
> > > > +EXPORT_SYMBOL(occ_sysfs_start);
> > > > +
> > > > +int occ_sysfs_stop(struct device *dev, struct occ_sysfs *driver)
> > > > +{
> > > > + if (driver->dev) {
> > > > + occ_remove_hwmon_attrs(driver);
> > > > + hwmon_device_unregister(driver->dev);
> > > > + }
> > > > +
> > > > + device_remove_file(driver->dev, &dev_attr_online);
> > > > +
> > > > + devm_kfree(dev, driver);
> > >
> > > Thw point of using devm_ functions is not to require remove/free functions.
> > > Something is completely wrong here if you need that call.
> > >
> > > Overall, this is architectually completely wrong. One does not register
> > > or instantiate drivers based on writing into sysfs attributes. Please
> > > reconsider your approach.
> >
> > We had some trouble designing this driver because the BMC only has
> > access to the OCC once the processor is powered on. This will happen
> > sometime after the BMC boots (this driver runs only on the BMC). With
> > no access to the OCC, we don't know what sensors are present on the
> > system without a large static enumeration. Also any sysfs files created
> > before we have OCC access won't be able to return any data.
> >
> > Instead of the "online" attribute, what do you think about using the
> > "bind"/"unbind" API to probe the device from user space once the system
> > is powered on? All the hwmon registration would take place in the probe
> > function, it would just occur some time after boot.
> >
>
> A more common approach would be to have a platform driver. That platform
> driver would need a means to detect if the OCC is up and running, and
> instantiate everything else once it is.
>
> A trigger from user space is problematic because there is no guarantee
> that the OCC is really up (or that it even exists).
This is true in general, but for the BMC case we have more information:
The host CPU power supply is controlled by several GPIOs from
userspace. Once we receive the "power-good" signal for the host CPU we
can bind the OCC driver and trigger the probe.
Alternatively, in the style of your first para, we could push the host
CPU state management into the kernel and expose a boot/reboot/power-off
API to userspace. That would give us a place to hook calls for
configuring and cleaning up any host-dependent drivers on the BMC.
The solution to the host-power-state problem is also applicable to the
OpenFSI patches that were recently sent out:
https://lkml.org/lkml/2016/12/6/732
The OpenFSI infra needs to re-scan for CFAMs when the host is powered
up.
>
> An alternative might be to have the hwmon driver poll for the OCC,
> but that would be a bit more difficult and might require a kernel thread
> or maybe asynchronous probing.
This was our thought as a fallback solution.
Andrew
>
> Guenter
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v3 3/3] nfc: trf7970a: Prevent repeated polling from crashing the kernel
From: Geoff Lansberry @ 2017-01-08 22:32 UTC (permalink / raw)
To: Mark Greer
Cc: linux-wireless, Lauro Ramos Venancio, Aloisio Almeida Jr,
Samuel Ortiz, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Justin Bronder, Jaret Cantu
In-Reply-To: <20170103212136.GA9899-luAo+O/VEmrlveNOaEYElw@public.gmane.org>
On Tue, Jan 3, 2017 at 4:21 PM, Mark Greer <mgreer-luAo+O/VEmrlveNOaEYElw@public.gmane.org> wrote:
> On Tue, Jan 03, 2017 at 01:35:18PM -0500, Geoff Lansberry wrote:
>> On Tue, Jan 3, 2017 at 11:33 AM, Mark Greer <mgreer-luAo+O/VEmrlveNOaEYElw@public.gmane.org> wrote:
>> > On Tue, Dec 27, 2016 at 09:18:32AM -0500, Geoff Lansberry wrote:
>
>> >> In the meantime - here is some more info about how we use it.
>> >>
>> >> We do use NFC structures. I did find an interesting clue in that
>> >> there are certain bottles that cause neard to segfault, I'm not sure
>> >> what is different about them. We write a string, like
>> >> "coppola_chardonnay_2015" to the bottles.
>> >
>> > Off the top of my head, it could be the length of the text.
>> > It would be useful to compare the data that works to the data
>> > that doesn't work. Can you install NXP's 'TagInfo' app on a
>> > smartphone and scan tags with working & non-working data?
>> > You can email the data from the app to yourself, edit out
>> > the cruft, and share here.
>>
>> The data is always the same - and the tags are all the same. Only
>> difference is that the tag is physically different, and perhaps
>> orientation; distance from antenna to tag is fixed.
>
> Interesting... They're all type 2 tags, right?
Yes type 2.
>
>> I can't even
>> write the tags at all, so reading them will show blank. Also a minor
>> but significant detail, is that the tags are embedded in such a way
>> that the phone cannot get close enough to them to connect.
>
> This section had me completely confused for a couple minutes until I realized
> that you mean that you can read & write the tags using the trf7970a with
> an attached antenna but not with your phone. Is that correct?
Correct, due to the physical arrangement of the part the tag is embedded in.
>
> If so, try a tag that isn't embedded in something else and move it around
> the back of the phone. Try to find where it works best. The phone
> manufacturers are notorius for paying little attention to the NFC antenna
> they put on their products. For example, I have a Samsung S5 next to me
> and it seems to work best around the center of the phone. I've used others
> where I had to use the upper-left or upper-right corner of the phone.
I can borrow a phone and try, I do have some other tags. This will
take me some time and
I'm not optimistic that we will learn much, other than that the tag
was not programmed when
it does not work. Don't wait on this answer.
>
> Mark
> --
^ permalink raw reply
* Re: [PATCH] devicetree: bindings: Add vendor prefix for Shenzhen Xunlong Software
From: Maxime Ripard @ 2017-01-08 21:57 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170107161318.8000-1-icenowy-ymACFijhrKM@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 458 bytes --]
On Sun, Jan 08, 2017 at 12:13:18AM +0800, Icenowy Zheng wrote:
> Shenzhen Xunlong Software CO.,Limited is a SBC vendor, which produces
> the "Orange Pi" series of SBCs.
>
> Add a vendor prefix for it. This prefix is already used in many
> Allwinner H3 boards.
>
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v2 0/8] ASoC: sunxi: Add support for audio codec in A23/H3 SoCs
From: Maxime Ripard @ 2017-01-08 21:56 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <CAGb2v65mo2g90QX6DMpw4dN4=fjccP2kp-NAbUPBzXYTtF8kMg@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2228 bytes --]
On Sun, Jan 08, 2017 at 03:00:40AM +0800, Chen-Yu Tsai wrote:
> Hi Maxime,
>
> On Fri, Nov 25, 2016 at 8:34 PM, Chen-Yu Tsai <wens@csie.org> wrote:
> > Hi everyone,
> >
> > This is v2 of my Allwinner A23 and H3 audio codec support series.
> >
> > Changes since v1:
> >
> > - Use DEFINE_RES_MEM for the analog path controls block resources.
> > - Added Rob's ack.
> >
> > This series adds support for the audio codec found in Allwinner A23 and
> > H3 SoCs. The design and data paths are similar to the audio codec found
> > in earlier SoCs such as the A31. The analog audio paths are symmetrical
> > with left/right channels and down-mix selectors for mono differential
> > output.
> >
> > What deviates from previous SoCs is that the analog path controls have
> > been moved to a separate control bus, accessed through a message box
> > like register interface in the PRCM block. This necessitates writing
> > a separate component driver for it, which is then tied into the sound
> > card as an ASoC auxiliary device.
> >
> > Patch 1 adds the analog path controls block to the sun6i-prcm driver as
> > a sub-device, for the A23. The H3 currently does not use the PRCM driver.
> >
> > Patch 2 adds PCM and card support for the A23 codec to the sun4i-codec
> > driver.
> >
> > Patch 3 adds a device node for the analog path controls block to the A23
> > dtsi.
> >
> > Patch 4 adds a device node for the audio codec, and the phandle for the
> > analog path controls block to the A23 dtsi.
> >
> > Patch 5 enables the audio codec for the A23 Q8 tablets. On these tablets
> > the headphone output is driven in DC coupled, or "direct drive", mode.
> >
> > Patch 6 adds PCM and card support for the H3 codec to the sun4i-codec
> > driver.
> >
> > Patch 7 adds device nodes for the audio codec and analog path controls
> > block to the H3 dtsi.
> >
> > Patch 8 enables the audio codec on the Orange Pi PC. The audio output
> > jack on the board is tied to the line out pins on the SoC.
>
> All the driver bits are in. Can you pick up the dts patches?
I just did.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v7 00/12] mux controller abstraction and iio/i2c muxes
From: Peter Rosin @ 2017-01-08 21:56 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-kernel, Rob Herring, Mark Rutland, Jonathan Cameron,
Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Jonathan Corbet, Arnd Bergmann, Greg Kroah-Hartman, linux-i2c,
devicetree, linux-iio, linux-doc
In-Reply-To: <20170108105129.GB1983@katana>
On 2017-01-08 11:51, Wolfram Sang wrote:
> Hi peda,
>
>> One thing that I would like to do, but don't see a solution
>> for, is to move the mux control code that is present in
>> various drivers in drivers/i2c/muxes to this new minimalistic
>> muxing subsystem, thus converting all present i2c muxes (but
>> perhaps not gates and arbitrators) to be i2c-mux-simple muxes.
>
> In a few lines, what is preventing that?
i2c-mux-gpio has the auto-detect for mux-/parent-locked and (old
style?) support for specifying what gpios to use with platform data
from code (i.e. not from dt/acpi). All of that gets messier if
someone else (the mux) owns the gpios.
i2c-mux-pinctrl has similar issues.
i2c-mux-reg has the platform data from code issue, plus a read-write
mode (mux is write only, at least as-is).
i2c-mux-pca954x has things going on like irqs (not applied yet) and
a reset gpio that makes it a poor candidate for something generic.
i2c-mux-mlxcplc could probably be converted (I don't think it existed
when I wrote the quoted paragraph).
So, since there are issues with just about all of the i2c muxes, the
only way forward that I see would be to instantiate the mux locally
and feed it to the generic i2c-mux-simple, but what would be the point
of that? There would still be a handful of i2c-mux drivers under
drivers/i2c/muxes.
Maybe some of the above are non-issues and maybe I have failed to see
some issue? I didn't think too hard about it...
>> I'm using an rwsem to lock a mux, but that isn't really a
>> perfect fit. Is there a better locking primitive that I don't
>> know about that fits better? I had a mutex at one point, but
>> that didn't allow any concurrent accesses at all. At least
>> the rwsem allows concurrent access as long as all users
>> agree on the mux state, but I suspect that the rwsem will
>> degrade to the mutex situation pretty quickly if there is
>> any contention.
>
> Maybe ask this question in a seperate email thread on lkml cc-ing the
> locking gurus (with a pointer to this thread)?
I don't think there is a suitable primitive. In order to get
something that really matches, I think the users need to hint
how long they (think they) are going to lock the mux. And
then it no longer a primitive, methinks. It something that is
much heavier...
>> Also, the "mux" name feels a bit ambitious, there are many muxes
>> in the world, and this tiny bit of code is probably not good
>> enough to be a nice fit for all...
>
> "... and it probably never will support anything other than
> AT-harddisks, as that's all I have..." ;))
:-)
> Thanks for this work!
And thanks for looking!
Cheers,
peda
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox