All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
@ 2013-03-07 13:17 ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

From: Graeme Gregory <gg@slimlogic.co.uk>

Add the various binding files for the palmas family of chips. There is a
top level MFD binding then a seperate binding for IP blocks on chips.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 .../devicetree/bindings/clock/palmas-clk.txt       |   25 +++
 .../devicetree/bindings/gpio/gpio-palmas.txt       |   21 +++
 .../devicetree/bindings/input/palmas-pwrbutton.txt |   22 +++
 .../devicetree/bindings/leds/leds-palmas.txt       |   35 ++++
 Documentation/devicetree/bindings/mfd/palmas.txt   |   70 ++++++++
 .../devicetree/bindings/regulator/palmas-pmic.txt  |  168 ++++++++++++++++++++
 .../devicetree/bindings/rtc/palmas-rtc.txt         |   22 +++
 .../devicetree/bindings/watchdog/palmas-wdt.txt    |   22 +++
 8 files changed, 385 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/palmas-clk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
 create mode 100644 Documentation/devicetree/bindings/leds/leds-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/mfd/palmas.txt
 create mode 100644 Documentation/devicetree/bindings/regulator/palmas-pmic.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/palmas-rtc.txt
 create mode 100644 Documentation/devicetree/bindings/watchdog/palmas-wdt.txt

diff --git a/Documentation/devicetree/bindings/clock/palmas-clk.txt b/Documentation/devicetree/bindings/clock/palmas-clk.txt
new file mode 100644
index 0000000..a17bc62
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/palmas-clk.txt
@@ -0,0 +1,25 @@
+* palmas and palmas-charger resource clock IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-clk
+  ti,twl6036-clk
+  ti,twl6037-clk
+  ti,tps65913-clk
+  ti,tps65914-clk
+  ti,tps80036-clk
+and also the generic series names
+  ti,palmas-clk
+  ti,palmas-charger-clk
+
+Optional properties:
+- ti,clk32g-mode-sleep		- mode to adopt in pmic sleep 0 - off, 1 - on
+- ti,clkg32kgaudio-mode-sleep	- see above
+
+Examples:
+
+clk {
+    compatible = "ti,twl6035-clk", "ti,palmas-clk";
+    ti,clk32kg-mode-sleep = <0>;
+    ti,clk32kgaudio-mode-sleep = <0>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
new file mode 100644
index 0000000..0b1c629
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
@@ -0,0 +1,21 @@
+* palmas and palmas charger GPIO IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-gpio
+  ti,twl6036-gpio
+  ti,twl6037-gpio
+  ti,tps65913-gpio
+  ti,tps65914-gpio
+  ti,tps80036-gpio
+
+and also the generic series names
+
+  ti,palmas-gpio
+  ti,palmas-charger-gpio
+
+Examples:
+
+gpio {
+    compatible = "ti,twl6035-gpio", "ti,palmas-gpio";
+};
diff --git a/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
new file mode 100644
index 0000000..00739e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger Button IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-pwrbutton
+  ti,twl6036-pwrbutton
+  ti,twl6037-pwrbutton
+  ti,tps65913-pwrbutton
+  ti,tps65914-pwrbutton
+  ti,tps80036-pwrbutton
+and also the generic series names
+  ti,palmas-pwrbutton
+  ti,palmas-charger-pwrbutton
+
+Examples:
+
+pwrbutton {
+    compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
+    interrupt-parent = <&palmas>;
+    interrupts = <1 0>;
+    interrupt-name = "pwron-irq";
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-palmas.txt b/Documentation/devicetree/bindings/leds/leds-palmas.txt
new file mode 100644
index 0000000..9a67858
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-palmas.txt
@@ -0,0 +1,35 @@
+* palmas and palmas-charger LED IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-leds
+  ti,twl6036-leds
+  ti,twl6037-leds
+  ti,tps65913-leds
+  ti,tps65914-leds
+  ti,tps80036-leds
+and also the generic series names
+  ti,palmas-leds
+  ti,palmas-charger-leds
+
+Optional properties:
+-ti,led1-current	- sink current setting 0 - 0mA, 1 - 25mA, 2 - 5mA,
+				3 - 0mA, 4 - 5mA, 5 - 5mA, 6 - 10.0mA, 7 - 0mA
+-ti,led2-current	- see above
+-ti,led3-current	- see above
+-ti,led4-current	- see above
+-ti,chrg-led-mode	- mode for led operation 0 - Charging indicator
+				1 - controlled as a general purpose LED
+-ti,chrg-led-vbat-low	- low battery blinking 0 - blinking is enabled,
+				1 - blinking is disabled
+
+Examples:
+leds {
+	compatible = "ti,twl6035-leds", "ti,palmas-leds";
+	ti,led1-current = <0>;
+	ti,led2-current = <0>;
+	ti,led3-current = <0>;
+	ti,led4-current = <0>;
+	ti,chrg-led-mode = <0>;
+	ti,chrg-led-vbat-low = <0>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt
new file mode 100644
index 0000000..cb34e1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/palmas.txt
@@ -0,0 +1,70 @@
+* palmas and palmas-charger device tree bindings
+
+The TI palmas family current members :-
+twl6035 (palmas)
+twl6036 (palmas-charger)
+twl6037 (palmas)
+tps65913 (palmas)
+tps65914 (palmas)
+tps80036 (palmas-charger)
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035
+  ti,twl6036
+  ti,twl6037
+  ti,tps65913
+  ti,tps65914
+  ti,tps80036
+and also the generic series names
+  ti,palmas
+  ti,palmas-charger
+- interrupt-controller : palmas has its own internal IRQs
+- #interrupt-cells : should be set to 2 for IRQ number and flags
+
+Optional properties:
+  ti,mux_padX : set the pad register X (1-2) to the correct muxing for the hardware,
+	        if not set will use muxing in OTP.
+
+palmas {
+	compatible = "ti,twl6035", "ti,palmas";
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	ti,mux-pad1 = <0>;
+	ti,mux-pad2 = <0>;
+
+	pmic {
+		compatible = "ti,twl6035-pmic", "ti,palmas-pmic";
+		....
+	}
+
+	gpio {
+		compatible = "ti,twl6035-gpio", "ti,palmas-gpio";
+		....
+	};
+
+	wdt {
+		compatible = "ti,twl6035-wdt", "ti,palmas-wdt";
+		....
+	};
+
+	rtc {
+		compatible = "ti,twl6035-rtc", "ti,palmas-rtc";
+		....
+	};
+
+	pwrbutton {
+		compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
+		....
+	};
+
+	leds {
+		compatible = "ti,twl6035-leds", "ti-palmas-leds";
+	}
+
+	clk {
+		compatible = "ti,twl6035-clk", "ti,palmas-clk";
+		....
+	};
+}
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
new file mode 100644
index 0000000..9654179
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -0,0 +1,168 @@
+* palmas and palmas-charger regulator IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-pmic
+  ti,twl6036-pmic
+  ti,twl6037-pmic
+  ti,tps65913-pmic
+  ti,tps65914-pmic
+  ti,tps80036-pmic
+and also the generic series names
+  ti,palmas-pmic
+  ti,palmas-charger-pmic
+
+Optional properties:
+- regulators : should contain the constrains and init information for the
+	       regulators. It should contain a subnode per regulator from the
+	       list.
+	       For palmas - smps12, smps123, smps3 depending on OTP,
+	       smps45, smps457, smps7 depending on varient, smps6, smps[8-10],
+	       ldo[1-9], ldoln, ldousb
+	       For palmas-charger - smps12, smps123, smps3 depending on OTP,
+	       smps[6-9], boost, ldo[1-14], ldoln, ldousb
+
+	       optional chip specific regulator fields :-
+	       ti,warm-reset - maintain voltage during warm reset
+	       ti,roof-floor - control voltage selection by pin
+	       ti,sleep-mode - mode to adopt in pmic sleep 0 - off, 1 - auto, 2 - eco
+	       3 - forced pwm
+	       ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us
+	       ti,smps-range - OTP has the wrong range set for the hardware so override
+	       0 - low range, 1 - high range
+
+- ti,ldo6-vibrator : ldo6 is in vibrator mode
+
+Examples:
+
+pmic@0 {
+	compatible = "ti,twl6035-pmic", "ti,palmas-pmic";
+	interrupt-parent = <&palmas>;
+	interrupts = <14 0>;
+	interrupt-name = "short-irq";
+
+	ti,ldo6_vibrator;
+
+	regulators {
+		smps12_reg : smps12 {
+			regulator-name = "smps12";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			ti,warm-reset;
+			ti,roof-floor;
+			ti,mode-sleep = <0>;
+			ti,tstep = <0>;
+			ti,smps-range = <1>;
+		};
+
+		smps3_reg: smps3 {
+			regulator-name = "smps3";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps45_reg: smps45 {
+			regulator-name = "smps45";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps6_reg: smps6 {
+			regulator-name = "smps6";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+		};
+
+		smps7_reg: smps7 {
+			regulator-name = "smps7";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		smps8_reg: smps8 {
+			regulator-name = "smps8";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps9_reg: smps9 {
+			regulator-name = "smps9";
+			regulator-min-microvolt = <2100000>;
+			regulator-max-microvolt = <2100000>;
+		};
+
+		smps10_reg: smps10 {
+			regulator-name = "smps10";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+
+		ldo1_reg: ldo1 {
+			regulator-name = "ldo1";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+		};
+
+		ldo2_reg: ldo2 {
+			regulator-name = "ldo2";
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+		};
+
+		ldo3_reg: ldo3 {
+			regulator-name = "ldo3";
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+		};
+
+		ldo4_reg: ldo4 {
+			regulator-name = "ldo4";
+			regulator-min-microvolt = <2200000>;
+			regulator-max-microvolt = <2200000>;
+		};
+
+		ldo5_reg: ldo5 {
+			regulator-name = "ldo5";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo6_reg: ldo6 {
+			regulator-name = "ldo6";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo7_reg: ldo7 {
+			regulator-name = "ldo7";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo8_reg: ldo8 {
+			regulator-name = "ldo8";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo9_reg: ldo9 {
+			regulator-name = "ldo9";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldoln_reg: ldoln {
+			regulator-name = "ldoln";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldousb_reg: ldousb {
+			regulator-name = "ldousb";
+			regulator-min-microvolt = <3250000>;
+			regulator-max-microvolt = <3250000>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/rtc/palmas-rtc.txt b/Documentation/devicetree/bindings/rtc/palmas-rtc.txt
new file mode 100644
index 0000000..4e779c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/palmas-rtc.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger RTC IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-rtc
+  ti,twl6036-rtc
+  ti,twl6037-rtc
+  ti,tps65913-rtc
+  ti,tps65914-rtc
+  ti,tps80036-rtc
+and also the generic series names
+  ti,palmas-rtc
+  ti,palmas-charger-rtc
+
+Examples:
+
+rtc {
+    compatible = "ti,twl6035-rtc", "ti,palmas-rtc";
+    interrupt-parent = <&palmas>;
+    interrupts = <8 0 9 0>;
+    interrupt-name = "alarm-irq", "timer-irq";
+};
diff --git a/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt b/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
new file mode 100644
index 0000000..1720f2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger Watchdog IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-wdt
+  ti,twl6036-wdt
+  ti,twl6037-wdt
+  ti,tps65913-wdt
+  ti,tps65914-wdt
+  ti,tps80036-wdt
+and also the generic series names
+  ti,palmas-wdt
+  ti,palmas-charger-wdt
+
+Examples:
+
+wdt {
+    compatible = "ti,twl6035-wdt", "ti,palmas-wdt";
+    interrupt-parent = <&palmas>;
+    interrupts = <10 0>;
+    interrupt-name = "watchdog-irq";
+};
-- 
1.7.0.4


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

* [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
@ 2013-03-07 13:17 ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: Graeme Gregory <gg@slimlogic.co.uk>

Add the various binding files for the palmas family of chips. There is a
top level MFD binding then a seperate binding for IP blocks on chips.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 .../devicetree/bindings/clock/palmas-clk.txt       |   25 +++
 .../devicetree/bindings/gpio/gpio-palmas.txt       |   21 +++
 .../devicetree/bindings/input/palmas-pwrbutton.txt |   22 +++
 .../devicetree/bindings/leds/leds-palmas.txt       |   35 ++++
 Documentation/devicetree/bindings/mfd/palmas.txt   |   70 ++++++++
 .../devicetree/bindings/regulator/palmas-pmic.txt  |  168 ++++++++++++++++++++
 .../devicetree/bindings/rtc/palmas-rtc.txt         |   22 +++
 .../devicetree/bindings/watchdog/palmas-wdt.txt    |   22 +++
 8 files changed, 385 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/palmas-clk.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
 create mode 100644 Documentation/devicetree/bindings/leds/leds-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/mfd/palmas.txt
 create mode 100644 Documentation/devicetree/bindings/regulator/palmas-pmic.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/palmas-rtc.txt
 create mode 100644 Documentation/devicetree/bindings/watchdog/palmas-wdt.txt

diff --git a/Documentation/devicetree/bindings/clock/palmas-clk.txt b/Documentation/devicetree/bindings/clock/palmas-clk.txt
new file mode 100644
index 0000000..a17bc62
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/palmas-clk.txt
@@ -0,0 +1,25 @@
+* palmas and palmas-charger resource clock IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-clk
+  ti,twl6036-clk
+  ti,twl6037-clk
+  ti,tps65913-clk
+  ti,tps65914-clk
+  ti,tps80036-clk
+and also the generic series names
+  ti,palmas-clk
+  ti,palmas-charger-clk
+
+Optional properties:
+- ti,clk32g-mode-sleep		- mode to adopt in pmic sleep 0 - off, 1 - on
+- ti,clkg32kgaudio-mode-sleep	- see above
+
+Examples:
+
+clk {
+    compatible = "ti,twl6035-clk", "ti,palmas-clk";
+    ti,clk32kg-mode-sleep = <0>;
+    ti,clk32kgaudio-mode-sleep = <0>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
new file mode 100644
index 0000000..0b1c629
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt
@@ -0,0 +1,21 @@
+* palmas and palmas charger GPIO IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-gpio
+  ti,twl6036-gpio
+  ti,twl6037-gpio
+  ti,tps65913-gpio
+  ti,tps65914-gpio
+  ti,tps80036-gpio
+
+and also the generic series names
+
+  ti,palmas-gpio
+  ti,palmas-charger-gpio
+
+Examples:
+
+gpio {
+    compatible = "ti,twl6035-gpio", "ti,palmas-gpio";
+};
diff --git a/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
new file mode 100644
index 0000000..00739e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger Button IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-pwrbutton
+  ti,twl6036-pwrbutton
+  ti,twl6037-pwrbutton
+  ti,tps65913-pwrbutton
+  ti,tps65914-pwrbutton
+  ti,tps80036-pwrbutton
+and also the generic series names
+  ti,palmas-pwrbutton
+  ti,palmas-charger-pwrbutton
+
+Examples:
+
+pwrbutton {
+    compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
+    interrupt-parent = <&palmas>;
+    interrupts = <1 0>;
+    interrupt-name = "pwron-irq";
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-palmas.txt b/Documentation/devicetree/bindings/leds/leds-palmas.txt
new file mode 100644
index 0000000..9a67858
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-palmas.txt
@@ -0,0 +1,35 @@
+* palmas and palmas-charger LED IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-leds
+  ti,twl6036-leds
+  ti,twl6037-leds
+  ti,tps65913-leds
+  ti,tps65914-leds
+  ti,tps80036-leds
+and also the generic series names
+  ti,palmas-leds
+  ti,palmas-charger-leds
+
+Optional properties:
+-ti,led1-current	- sink current setting 0 - 0mA, 1 - 25mA, 2 - 5mA,
+				3 - 0mA, 4 - 5mA, 5 - 5mA, 6 - 10.0mA, 7 - 0mA
+-ti,led2-current	- see above
+-ti,led3-current	- see above
+-ti,led4-current	- see above
+-ti,chrg-led-mode	- mode for led operation 0 - Charging indicator
+				1 - controlled as a general purpose LED
+-ti,chrg-led-vbat-low	- low battery blinking 0 - blinking is enabled,
+				1 - blinking is disabled
+
+Examples:
+leds {
+	compatible = "ti,twl6035-leds", "ti,palmas-leds";
+	ti,led1-current = <0>;
+	ti,led2-current = <0>;
+	ti,led3-current = <0>;
+	ti,led4-current = <0>;
+	ti,chrg-led-mode = <0>;
+	ti,chrg-led-vbat-low = <0>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt
new file mode 100644
index 0000000..cb34e1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/palmas.txt
@@ -0,0 +1,70 @@
+* palmas and palmas-charger device tree bindings
+
+The TI palmas family current members :-
+twl6035 (palmas)
+twl6036 (palmas-charger)
+twl6037 (palmas)
+tps65913 (palmas)
+tps65914 (palmas)
+tps80036 (palmas-charger)
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035
+  ti,twl6036
+  ti,twl6037
+  ti,tps65913
+  ti,tps65914
+  ti,tps80036
+and also the generic series names
+  ti,palmas
+  ti,palmas-charger
+- interrupt-controller : palmas has its own internal IRQs
+- #interrupt-cells : should be set to 2 for IRQ number and flags
+
+Optional properties:
+  ti,mux_padX : set the pad register X (1-2) to the correct muxing for the hardware,
+	        if not set will use muxing in OTP.
+
+palmas {
+	compatible = "ti,twl6035", "ti,palmas";
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	ti,mux-pad1 = <0>;
+	ti,mux-pad2 = <0>;
+
+	pmic {
+		compatible = "ti,twl6035-pmic", "ti,palmas-pmic";
+		....
+	}
+
+	gpio {
+		compatible = "ti,twl6035-gpio", "ti,palmas-gpio";
+		....
+	};
+
+	wdt {
+		compatible = "ti,twl6035-wdt", "ti,palmas-wdt";
+		....
+	};
+
+	rtc {
+		compatible = "ti,twl6035-rtc", "ti,palmas-rtc";
+		....
+	};
+
+	pwrbutton {
+		compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
+		....
+	};
+
+	leds {
+		compatible = "ti,twl6035-leds", "ti-palmas-leds";
+	}
+
+	clk {
+		compatible = "ti,twl6035-clk", "ti,palmas-clk";
+		....
+	};
+}
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
new file mode 100644
index 0000000..9654179
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -0,0 +1,168 @@
+* palmas and palmas-charger regulator IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-pmic
+  ti,twl6036-pmic
+  ti,twl6037-pmic
+  ti,tps65913-pmic
+  ti,tps65914-pmic
+  ti,tps80036-pmic
+and also the generic series names
+  ti,palmas-pmic
+  ti,palmas-charger-pmic
+
+Optional properties:
+- regulators : should contain the constrains and init information for the
+	       regulators. It should contain a subnode per regulator from the
+	       list.
+	       For palmas - smps12, smps123, smps3 depending on OTP,
+	       smps45, smps457, smps7 depending on varient, smps6, smps[8-10],
+	       ldo[1-9], ldoln, ldousb
+	       For palmas-charger - smps12, smps123, smps3 depending on OTP,
+	       smps[6-9], boost, ldo[1-14], ldoln, ldousb
+
+	       optional chip specific regulator fields :-
+	       ti,warm-reset - maintain voltage during warm reset
+	       ti,roof-floor - control voltage selection by pin
+	       ti,sleep-mode - mode to adopt in pmic sleep 0 - off, 1 - auto, 2 - eco
+	       3 - forced pwm
+	       ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us
+	       ti,smps-range - OTP has the wrong range set for the hardware so override
+	       0 - low range, 1 - high range
+
+- ti,ldo6-vibrator : ldo6 is in vibrator mode
+
+Examples:
+
+pmic at 0 {
+	compatible = "ti,twl6035-pmic", "ti,palmas-pmic";
+	interrupt-parent = <&palmas>;
+	interrupts = <14 0>;
+	interrupt-name = "short-irq";
+
+	ti,ldo6_vibrator;
+
+	regulators {
+		smps12_reg : smps12 {
+			regulator-name = "smps12";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			ti,warm-reset;
+			ti,roof-floor;
+			ti,mode-sleep = <0>;
+			ti,tstep = <0>;
+			ti,smps-range = <1>;
+		};
+
+		smps3_reg: smps3 {
+			regulator-name = "smps3";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps45_reg: smps45 {
+			regulator-name = "smps45";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps6_reg: smps6 {
+			regulator-name = "smps6";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+		};
+
+		smps7_reg: smps7 {
+			regulator-name = "smps7";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		smps8_reg: smps8 {
+			regulator-name = "smps8";
+			regulator-min-microvolt = < 600000>;
+			regulator-max-microvolt = <1310000>;
+		};
+
+		smps9_reg: smps9 {
+			regulator-name = "smps9";
+			regulator-min-microvolt = <2100000>;
+			regulator-max-microvolt = <2100000>;
+		};
+
+		smps10_reg: smps10 {
+			regulator-name = "smps10";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+
+		ldo1_reg: ldo1 {
+			regulator-name = "ldo1";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+		};
+
+		ldo2_reg: ldo2 {
+			regulator-name = "ldo2";
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+		};
+
+		ldo3_reg: ldo3 {
+			regulator-name = "ldo3";
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+		};
+
+		ldo4_reg: ldo4 {
+			regulator-name = "ldo4";
+			regulator-min-microvolt = <2200000>;
+			regulator-max-microvolt = <2200000>;
+		};
+
+		ldo5_reg: ldo5 {
+			regulator-name = "ldo5";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldo6_reg: ldo6 {
+			regulator-name = "ldo6";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo7_reg: ldo7 {
+			regulator-name = "ldo7";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo8_reg: ldo8 {
+			regulator-name = "ldo8";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+		};
+
+		ldo9_reg: ldo9 {
+			regulator-name = "ldo9";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldoln_reg: ldoln {
+			regulator-name = "ldoln";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+		};
+
+		ldousb_reg: ldousb {
+			regulator-name = "ldousb";
+			regulator-min-microvolt = <3250000>;
+			regulator-max-microvolt = <3250000>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/rtc/palmas-rtc.txt b/Documentation/devicetree/bindings/rtc/palmas-rtc.txt
new file mode 100644
index 0000000..4e779c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/palmas-rtc.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger RTC IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-rtc
+  ti,twl6036-rtc
+  ti,twl6037-rtc
+  ti,tps65913-rtc
+  ti,tps65914-rtc
+  ti,tps80036-rtc
+and also the generic series names
+  ti,palmas-rtc
+  ti,palmas-charger-rtc
+
+Examples:
+
+rtc {
+    compatible = "ti,twl6035-rtc", "ti,palmas-rtc";
+    interrupt-parent = <&palmas>;
+    interrupts = <8 0 9 0>;
+    interrupt-name = "alarm-irq", "timer-irq";
+};
diff --git a/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt b/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
new file mode 100644
index 0000000..1720f2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
@@ -0,0 +1,22 @@
+* palmas and palmas-charger Watchdog IP block devicetree bindings
+
+Required properties:
+- compatible : Should be from the list
+  ti,twl6035-wdt
+  ti,twl6036-wdt
+  ti,twl6037-wdt
+  ti,tps65913-wdt
+  ti,tps65914-wdt
+  ti,tps80036-wdt
+and also the generic series names
+  ti,palmas-wdt
+  ti,palmas-charger-wdt
+
+Examples:
+
+wdt {
+    compatible = "ti,twl6035-wdt", "ti,palmas-wdt";
+    interrupt-parent = <&palmas>;
+    interrupts = <10 0>;
+    interrupt-name = "watchdog-irq";
+};
-- 
1.7.0.4

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

* [PATCH v8 02/12] mfd: palmas: is_palmas_charger needed by multiple drivers
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

is_palmas_charger checks for the presence of charging
functionality in the device

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Acked-by: Laxman Dewangani <ldewangan@nvidia.com>
---
 include/linux/mfd/palmas.h |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index a4d13d7..f66ef32 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -1,9 +1,10 @@
 /*
  * TI Palmas
  *
- * Copyright 2011 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under  the terms of the GNU General  Public License as published by the
@@ -22,6 +23,15 @@
 
 #define PALMAS_NUM_CLIENTS		3
 
+/* The ID_REVISION NUMBERS */
+#define PALMAS_CHIP_OLD_ID		0x0000
+#define PALMAS_CHIP_ID			0xC035
+#define PALMAS_CHIP_CHARGER_ID		0xC036
+
+#define is_palmas(a)	(((a) == PALMAS_CHIP_OLD_ID) || \
+			((a) == PALMAS_CHIP_ID))
+#define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID)
+
 struct palmas_pmic;
 struct palmas_gpadc;
 struct palmas_resource;
-- 
1.7.0.4


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

* [PATCH v8 02/12] mfd: palmas: is_palmas_charger needed by multiple drivers
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

is_palmas_charger checks for the presence of charging
functionality in the device

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Acked-by: Laxman Dewangani <ldewangan@nvidia.com>
---
 include/linux/mfd/palmas.h |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index a4d13d7..f66ef32 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -1,9 +1,10 @@
 /*
  * TI Palmas
  *
- * Copyright 2011 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under  the terms of the GNU General  Public License as published by the
@@ -22,6 +23,15 @@
 
 #define PALMAS_NUM_CLIENTS		3
 
+/* The ID_REVISION NUMBERS */
+#define PALMAS_CHIP_OLD_ID		0x0000
+#define PALMAS_CHIP_ID			0xC035
+#define PALMAS_CHIP_CHARGER_ID		0xC036
+
+#define is_palmas(a)	(((a) == PALMAS_CHIP_OLD_ID) || \
+			((a) == PALMAS_CHIP_ID))
+#define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID)
+
 struct palmas_pmic;
 struct palmas_gpadc;
 struct palmas_resource;
-- 
1.7.0.4

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

* [PATCH v8 03/12] mfd: palmas add variant and OTP detection
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

From: Graeme Gregory <gg@slimlogic.co.uk>

Read the chip varient and the OTP information from the chip and display
this on probe to aid in debugging of issues.

Older palmas chips do not have the USB_ID programmed and will therefore
return 0x0000 for this field.

palmas register read/write/update API is now used

palmas_read_product_id_and_revs used by palmas_i2c_probe to get
the device id, design and software revisions

id field of pamas struct renamed to device_id

Updated the DT parsing to agree with the bindings document, just some minor
value name changes.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/mfd/palmas.c       |  103 ++++++++++++++++++++++++++++++++++----------
 include/linux/mfd/palmas.h |   35 ++++++++++++++-
 2 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index bbdbc50..9d1adfe 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -1,9 +1,10 @@
 /*
  * TI Palmas MFD Driver
  *
- * Copyright 2011-2012 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under  the terms of the GNU General  Public License as published by the
@@ -257,26 +258,76 @@ static struct regmap_irq_chip palmas_irq_chip = {
 			PALMAS_INT1_MASK),
 };
 
+static int palmas_read_product_id_and_revs(struct palmas *palmas)
+{
+	int ret;
+	unsigned int reg;
+
+	/* Read variant info from the device */
+	ret = palmas_read(palmas, PALMAS_ID_BASE, PALMAS_PRODUCT_ID_LSB, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read ID err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->product_id = reg;
+
+	ret = palmas_read(palmas, PALMAS_ID_BASE, PALMAS_PRODUCT_ID_MSB, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read ID err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->product_id |= reg << 8;
+
+	dev_info(palmas->dev, "Product ID %x\n", palmas->product_id);
+
+	ret = palmas_read(palmas, PALMAS_DESIGNREV_BASE,
+				PALMAS_DESIGNREV, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read DESIGNREV err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->designrev = reg & PALMAS_DESIGNREV_DESIGNREV_MASK;
+
+	dev_info(palmas->dev, "Product Design Rev %x\n", palmas->designrev);
+
+	ret = palmas_read(palmas, PALMAS_PMU_CONTROL_BASE, PALMAS_SW_REVISION,
+			&reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read SW_REVISION err: %d\n",
+				ret);
+		return ret;
+	}
+
+	palmas->sw_revision = reg;
+
+	dev_info(palmas->dev, "Product SW Rev %x\n", palmas->sw_revision);
+
+	return 0;
+}
+
 static void palmas_dt_to_pdata(struct device_node *node,
 		struct palmas_platform_data *pdata)
 {
 	int ret;
 	u32 prop;
 
-	ret = of_property_read_u32(node, "ti,mux_pad1", &prop);
+	ret = of_property_read_u32(node, "ti,mux-pad1", &prop);
 	if (!ret) {
 		pdata->mux_from_pdata = 1;
 		pdata->pad1 = prop;
 	}
 
-	ret = of_property_read_u32(node, "ti,mux_pad2", &prop);
+	ret = of_property_read_u32(node, "ti,mux-pad2", &prop);
 	if (!ret) {
 		pdata->mux_from_pdata = 1;
 		pdata->pad2 = prop;
 	}
 
 	/* The default for this register is all masked */
-	ret = of_property_read_u32(node, "ti,power_ctrl", &prop);
+	ret = of_property_read_u32(node, "ti,power-ctrl", &prop);
 	if (!ret)
 		pdata->power_ctrl = prop;
 	else
@@ -292,7 +343,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	struct palmas_platform_data *pdata;
 	struct device_node *node = i2c->dev.of_node;
 	int ret = 0, i;
-	unsigned int reg, addr;
+	unsigned int reg;
 	int slave;
 	struct mfd_cell *children;
 
@@ -316,7 +367,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, palmas);
 	palmas->dev = &i2c->dev;
-	palmas->id = id->driver_data;
+	palmas->product_id = id->driver_data;
 	palmas->irq = i2c->irq;
 
 	for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
@@ -344,12 +395,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 		}
 	}
 
+	/* Read variant info from the device */
+	ret = palmas_read_product_id_and_revs(palmas);
+	if (ret < 0)
+		goto err;
+
 	/* Change IRQ into clear on read mode for efficiency */
 	slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
 	reg = PALMAS_INT_CTRL_INT_CLEAR;
 
-	regmap_write(palmas->regmap[slave], addr, reg);
+	ret = palmas_write(palmas, PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL, reg);
 
 	ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
 			IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
@@ -357,17 +412,15 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	if (ret < 0)
 		goto err;
 
-	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
-			PALMAS_PRIMARY_SECONDARY_PAD1);
-
 	if (pdata->mux_from_pdata) {
 		reg = pdata->pad1;
-		ret = regmap_write(palmas->regmap[slave], addr, reg);
+		ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD1, reg);
 		if (ret)
 			goto err_irq;
 	} else {
-		ret = regmap_read(palmas->regmap[slave], addr, &reg);
+		ret = palmas_read(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD1, &reg);
 		if (ret)
 			goto err_irq;
 	}
@@ -393,16 +446,15 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3))
 		palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED;
 
-	addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
-			PALMAS_PRIMARY_SECONDARY_PAD2);
-
 	if (pdata->mux_from_pdata) {
 		reg = pdata->pad2;
-		ret = regmap_write(palmas->regmap[slave], addr, reg);
+		ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD2, reg);
 		if (ret)
 			goto err_irq;
 	} else {
-		ret = regmap_read(palmas->regmap[slave], addr, &reg);
+		ret = palmas_read(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD2, &reg);
 		if (ret)
 			goto err_irq;
 	}
@@ -422,10 +474,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 
 	reg = pdata->power_ctrl;
 
-	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL);
-
-	ret = regmap_write(palmas->regmap[slave], addr, reg);
+	ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+			PALMAS_PRIMARY_SECONDARY_PAD2, reg);
 	if (ret)
 		goto err_irq;
 
@@ -504,6 +554,13 @@ MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
 
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas", },
+	{ .compatible = "ti,palmas-charger", },
+	{ .compatible = "ti,twl6035", },
+	{ .compatible = "ti,twl6036", },
+	{ .compatible = "ti,twl6037", },
+	{ .compatible = "ti,tps65913", },
+	{ .compatible = "ti,tps65914", },
+	{ .compatible = "ti,tps80036", },
 	{ /* end */ }
 };
 
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index f66ef32..0427165 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -44,7 +44,9 @@ struct palmas {
 	struct regmap *regmap[PALMAS_NUM_CLIENTS];
 
 	/* Stored chip id */
-	int id;
+	int product_id;
+	int designrev;
+	int sw_revision;
 
 	/* IRQ Data */
 	int irq;
@@ -437,11 +439,13 @@ enum usb_irq_events {
 #define PALMAS_PU_PD_OD_BASE					0x1F4
 #define PALMAS_LED_BASE						0x200
 #define PALMAS_INTERRUPT_BASE					0x210
+#define PALMAS_ID_BASE						0x24F
 #define PALMAS_USB_OTG_BASE					0x250
 #define PALMAS_VIBRATOR_BASE					0x270
 #define PALMAS_GPIO_BASE					0x280
 #define PALMAS_USB_BASE						0x290
 #define PALMAS_GPADC_BASE					0x2C0
+#define PALMAS_DESIGNREV_BASE					0x357
 #define PALMAS_TRIM_GPADC_BASE					0x3CD
 
 /* Registers for function RTC */
@@ -2159,6 +2163,28 @@ enum usb_irq_events {
 #define PALMAS_INT_CTRL_INT_CLEAR				0x01
 #define PALMAS_INT_CTRL_INT_CLEAR_SHIFT				0
 
+/* Registers for function ID */
+#define PALMAS_VENDOR_ID_LSB					0x0
+#define PALMAS_VENDOR_ID_MSB					0x1
+#define PALMAS_PRODUCT_ID_LSB					0x2
+#define PALMAS_PRODUCT_ID_MSB					0x3
+
+/* Bit definitions for VENDOR_ID_LSB */
+#define PALMAS_VENDOR_ID_LSB_VENDOR_ID_MASK			0xff
+#define PALMAS_VENDOR_ID_LSB_VENDOR_ID_SHIFT			0
+
+/* Bit definitions for VENDOR_ID_MSB */
+#define PALMAS_VENDOR_ID_MSB_VENDOR_ID_MASK			0xff
+#define PALMAS_VENDOR_ID_MSB_VENDOR_ID_SHIFT			0
+
+/* Bit definitions for PRODUCT_ID_LSB */
+#define PALMAS_PRODUCT_ID_LSB_PRODUCT_ID_MASK			0xff
+#define PALMAS_PRODUCT_ID_LSB_PRODUCT_ID_SHIFT			0
+
+/* Bit definitions for PRODUCT_ID_MSB */
+#define PALMAS_PRODUCT_ID_MSB_PRODUCT_ID_MASK			0xff
+#define PALMAS_PRODUCT_ID_MSB_PRODUCT_ID_SHIFT			0
+
 /* Registers for function USB_OTG */
 #define PALMAS_USB_WAKEUP					0x3
 #define PALMAS_USB_VBUS_CTRL_SET				0x4
@@ -2781,6 +2807,13 @@ enum usb_irq_events {
 #define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_MASK	0x7f
 #define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_SHIFT	0
 
+/* Registers for function DESIGNREV */
+#define PALMAS_DESIGNREV					0x0
+
+/* Bit definitions for DESIGNREV */
+#define PALMAS_DESIGNREV_DESIGNREV_MASK				0x0f
+#define PALMAS_DESIGNREV_DESIGNREV_SHIFT			0
+
 /* Registers for function GPADC */
 #define PALMAS_GPADC_TRIM1					0x0
 #define PALMAS_GPADC_TRIM2					0x1
-- 
1.7.0.4


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

* [PATCH v8 03/12] mfd: palmas add variant and OTP detection
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: Graeme Gregory <gg@slimlogic.co.uk>

Read the chip varient and the OTP information from the chip and display
this on probe to aid in debugging of issues.

Older palmas chips do not have the USB_ID programmed and will therefore
return 0x0000 for this field.

palmas register read/write/update API is now used

palmas_read_product_id_and_revs used by palmas_i2c_probe to get
the device id, design and software revisions

id field of pamas struct renamed to device_id

Updated the DT parsing to agree with the bindings document, just some minor
value name changes.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/mfd/palmas.c       |  103 ++++++++++++++++++++++++++++++++++----------
 include/linux/mfd/palmas.h |   35 ++++++++++++++-
 2 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index bbdbc50..9d1adfe 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -1,9 +1,10 @@
 /*
  * TI Palmas MFD Driver
  *
- * Copyright 2011-2012 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under  the terms of the GNU General  Public License as published by the
@@ -257,26 +258,76 @@ static struct regmap_irq_chip palmas_irq_chip = {
 			PALMAS_INT1_MASK),
 };
 
+static int palmas_read_product_id_and_revs(struct palmas *palmas)
+{
+	int ret;
+	unsigned int reg;
+
+	/* Read variant info from the device */
+	ret = palmas_read(palmas, PALMAS_ID_BASE, PALMAS_PRODUCT_ID_LSB, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read ID err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->product_id = reg;
+
+	ret = palmas_read(palmas, PALMAS_ID_BASE, PALMAS_PRODUCT_ID_MSB, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read ID err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->product_id |= reg << 8;
+
+	dev_info(palmas->dev, "Product ID %x\n", palmas->product_id);
+
+	ret = palmas_read(palmas, PALMAS_DESIGNREV_BASE,
+				PALMAS_DESIGNREV, &reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read DESIGNREV err: %d\n", ret);
+		return ret;
+	}
+
+	palmas->designrev = reg & PALMAS_DESIGNREV_DESIGNREV_MASK;
+
+	dev_info(palmas->dev, "Product Design Rev %x\n", palmas->designrev);
+
+	ret = palmas_read(palmas, PALMAS_PMU_CONTROL_BASE, PALMAS_SW_REVISION,
+			&reg);
+	if (ret < 0) {
+		dev_err(palmas->dev, "Unable to read SW_REVISION err: %d\n",
+				ret);
+		return ret;
+	}
+
+	palmas->sw_revision = reg;
+
+	dev_info(palmas->dev, "Product SW Rev %x\n", palmas->sw_revision);
+
+	return 0;
+}
+
 static void palmas_dt_to_pdata(struct device_node *node,
 		struct palmas_platform_data *pdata)
 {
 	int ret;
 	u32 prop;
 
-	ret = of_property_read_u32(node, "ti,mux_pad1", &prop);
+	ret = of_property_read_u32(node, "ti,mux-pad1", &prop);
 	if (!ret) {
 		pdata->mux_from_pdata = 1;
 		pdata->pad1 = prop;
 	}
 
-	ret = of_property_read_u32(node, "ti,mux_pad2", &prop);
+	ret = of_property_read_u32(node, "ti,mux-pad2", &prop);
 	if (!ret) {
 		pdata->mux_from_pdata = 1;
 		pdata->pad2 = prop;
 	}
 
 	/* The default for this register is all masked */
-	ret = of_property_read_u32(node, "ti,power_ctrl", &prop);
+	ret = of_property_read_u32(node, "ti,power-ctrl", &prop);
 	if (!ret)
 		pdata->power_ctrl = prop;
 	else
@@ -292,7 +343,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	struct palmas_platform_data *pdata;
 	struct device_node *node = i2c->dev.of_node;
 	int ret = 0, i;
-	unsigned int reg, addr;
+	unsigned int reg;
 	int slave;
 	struct mfd_cell *children;
 
@@ -316,7 +367,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, palmas);
 	palmas->dev = &i2c->dev;
-	palmas->id = id->driver_data;
+	palmas->product_id = id->driver_data;
 	palmas->irq = i2c->irq;
 
 	for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
@@ -344,12 +395,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 		}
 	}
 
+	/* Read variant info from the device */
+	ret = palmas_read_product_id_and_revs(palmas);
+	if (ret < 0)
+		goto err;
+
 	/* Change IRQ into clear on read mode for efficiency */
 	slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
 	reg = PALMAS_INT_CTRL_INT_CLEAR;
 
-	regmap_write(palmas->regmap[slave], addr, reg);
+	ret = palmas_write(palmas, PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL, reg);
 
 	ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
 			IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
@@ -357,17 +412,15 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	if (ret < 0)
 		goto err;
 
-	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
-			PALMAS_PRIMARY_SECONDARY_PAD1);
-
 	if (pdata->mux_from_pdata) {
 		reg = pdata->pad1;
-		ret = regmap_write(palmas->regmap[slave], addr, reg);
+		ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD1, reg);
 		if (ret)
 			goto err_irq;
 	} else {
-		ret = regmap_read(palmas->regmap[slave], addr, &reg);
+		ret = palmas_read(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD1, &reg);
 		if (ret)
 			goto err_irq;
 	}
@@ -393,16 +446,15 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3))
 		palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED;
 
-	addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
-			PALMAS_PRIMARY_SECONDARY_PAD2);
-
 	if (pdata->mux_from_pdata) {
 		reg = pdata->pad2;
-		ret = regmap_write(palmas->regmap[slave], addr, reg);
+		ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD2, reg);
 		if (ret)
 			goto err_irq;
 	} else {
-		ret = regmap_read(palmas->regmap[slave], addr, &reg);
+		ret = palmas_read(palmas, PALMAS_PU_PD_OD_BASE,
+				PALMAS_PRIMARY_SECONDARY_PAD2, &reg);
 		if (ret)
 			goto err_irq;
 	}
@@ -422,10 +474,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 
 	reg = pdata->power_ctrl;
 
-	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
-	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL);
-
-	ret = regmap_write(palmas->regmap[slave], addr, reg);
+	ret = palmas_write(palmas, PALMAS_PU_PD_OD_BASE,
+			PALMAS_PRIMARY_SECONDARY_PAD2, reg);
 	if (ret)
 		goto err_irq;
 
@@ -504,6 +554,13 @@ MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
 
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas", },
+	{ .compatible = "ti,palmas-charger", },
+	{ .compatible = "ti,twl6035", },
+	{ .compatible = "ti,twl6036", },
+	{ .compatible = "ti,twl6037", },
+	{ .compatible = "ti,tps65913", },
+	{ .compatible = "ti,tps65914", },
+	{ .compatible = "ti,tps80036", },
 	{ /* end */ }
 };
 
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index f66ef32..0427165 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -44,7 +44,9 @@ struct palmas {
 	struct regmap *regmap[PALMAS_NUM_CLIENTS];
 
 	/* Stored chip id */
-	int id;
+	int product_id;
+	int designrev;
+	int sw_revision;
 
 	/* IRQ Data */
 	int irq;
@@ -437,11 +439,13 @@ enum usb_irq_events {
 #define PALMAS_PU_PD_OD_BASE					0x1F4
 #define PALMAS_LED_BASE						0x200
 #define PALMAS_INTERRUPT_BASE					0x210
+#define PALMAS_ID_BASE						0x24F
 #define PALMAS_USB_OTG_BASE					0x250
 #define PALMAS_VIBRATOR_BASE					0x270
 #define PALMAS_GPIO_BASE					0x280
 #define PALMAS_USB_BASE						0x290
 #define PALMAS_GPADC_BASE					0x2C0
+#define PALMAS_DESIGNREV_BASE					0x357
 #define PALMAS_TRIM_GPADC_BASE					0x3CD
 
 /* Registers for function RTC */
@@ -2159,6 +2163,28 @@ enum usb_irq_events {
 #define PALMAS_INT_CTRL_INT_CLEAR				0x01
 #define PALMAS_INT_CTRL_INT_CLEAR_SHIFT				0
 
+/* Registers for function ID */
+#define PALMAS_VENDOR_ID_LSB					0x0
+#define PALMAS_VENDOR_ID_MSB					0x1
+#define PALMAS_PRODUCT_ID_LSB					0x2
+#define PALMAS_PRODUCT_ID_MSB					0x3
+
+/* Bit definitions for VENDOR_ID_LSB */
+#define PALMAS_VENDOR_ID_LSB_VENDOR_ID_MASK			0xff
+#define PALMAS_VENDOR_ID_LSB_VENDOR_ID_SHIFT			0
+
+/* Bit definitions for VENDOR_ID_MSB */
+#define PALMAS_VENDOR_ID_MSB_VENDOR_ID_MASK			0xff
+#define PALMAS_VENDOR_ID_MSB_VENDOR_ID_SHIFT			0
+
+/* Bit definitions for PRODUCT_ID_LSB */
+#define PALMAS_PRODUCT_ID_LSB_PRODUCT_ID_MASK			0xff
+#define PALMAS_PRODUCT_ID_LSB_PRODUCT_ID_SHIFT			0
+
+/* Bit definitions for PRODUCT_ID_MSB */
+#define PALMAS_PRODUCT_ID_MSB_PRODUCT_ID_MASK			0xff
+#define PALMAS_PRODUCT_ID_MSB_PRODUCT_ID_SHIFT			0
+
 /* Registers for function USB_OTG */
 #define PALMAS_USB_WAKEUP					0x3
 #define PALMAS_USB_VBUS_CTRL_SET				0x4
@@ -2781,6 +2807,13 @@ enum usb_irq_events {
 #define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_MASK	0x7f
 #define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_SHIFT	0
 
+/* Registers for function DESIGNREV */
+#define PALMAS_DESIGNREV					0x0
+
+/* Bit definitions for DESIGNREV */
+#define PALMAS_DESIGNREV_DESIGNREV_MASK				0x0f
+#define PALMAS_DESIGNREV_DESIGNREV_SHIFT			0
+
 /* Registers for function GPADC */
 #define PALMAS_GPADC_TRIM1					0x0
 #define PALMAS_GPADC_TRIM2					0x1
-- 
1.7.0.4

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

* [PATCH v8 04/12] regulator: palmas correct dt parsing
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo

From: Graeme Gregory <gg@slimlogic.co.uk>

Fix the DT parsing to agree with the bindings document. Some small changes
to the value names and also fix the handling of boolean values. They were
previously using prop = 1/0, now just use of_property_read_bool calls.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/regulator/palmas-regulator.c |   36 ++++++++++++++++++---------------
 1 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 8a716a9..b2b1baa 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Regulator part of Palmas PMIC Chips
  *
- * Copyright 2011-2012 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
  * Author: Ian Lartey <ian@slimlogic.co.uk>
@@ -553,15 +553,13 @@ static void palmas_dt_to_pdata(struct device *dev,
 		pdata->reg_init[idx] = devm_kzalloc(dev,
 				sizeof(struct palmas_reg_init), GFP_KERNEL);
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,warm-reset", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->warm_reset = prop;
+		pdata->reg_init[idx]->warm_reset =
+			of_property_read_u32(palmas_matches[idx].of_node,
+					     "ti,warm-reset", &prop);
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,roof-floor", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->roof_floor = prop;
+		pdata->reg_init[idx]->roof_floor =
+			of_property_read_bool(palmas_matches[idx].of_node,
+					      "ti,roof-floor");
 
 		ret = of_property_read_u32(palmas_matches[idx].of_node,
 				"ti,mode-sleep", &prop);
@@ -573,15 +571,14 @@ static void palmas_dt_to_pdata(struct device *dev,
 		if (!ret)
 			pdata->reg_init[idx]->tstep = prop;
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,vsel", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->vsel = prop;
+		ret = of_property_read_bool(palmas_matches[idx].of_node,
+					    "ti,smps-range");
+		if (ret)
+			pdata->reg_init[idx]->vsel =
+				PALMAS_SMPS12_VOLTAGE_RANGE;
 	}
 
-	ret = of_property_read_u32(node, "ti,ldo6-vibrator", &prop);
-	if (!ret)
-		pdata->ldo6_vibrator = prop;
+	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
 
@@ -806,6 +803,13 @@ static int palmas_remove(struct platform_device *pdev)
 
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas-pmic", },
+	{ .compatible = "ti,palmas-charger-pmic", },
+	{ .compatible = "ti,twl6035-pmic", },
+	{ .compatible = "ti,twl6036-pmic", },
+	{ .compatible = "ti,twl6037-pmic", },
+	{ .compatible = "ti,tps65913-pmic", },
+	{ .compatible = "ti,tps65914-pmic", },
+	{ .compatible = "ti,tps80036-pmic", },
 	{ /* end */ }
 };
 
-- 
1.7.0.4


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

* [PATCH v8 04/12] regulator: palmas correct dt parsing
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: Graeme Gregory <gg@slimlogic.co.uk>

Fix the DT parsing to agree with the bindings document. Some small changes
to the value names and also fix the handling of boolean values. They were
previously using prop = 1/0, now just use of_property_read_bool calls.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/regulator/palmas-regulator.c |   36 ++++++++++++++++++---------------
 1 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 8a716a9..b2b1baa 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Regulator part of Palmas PMIC Chips
  *
- * Copyright 2011-2012 Texas Instruments Inc.
+ * Copyright 2011-2013 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
  * Author: Ian Lartey <ian@slimlogic.co.uk>
@@ -553,15 +553,13 @@ static void palmas_dt_to_pdata(struct device *dev,
 		pdata->reg_init[idx] = devm_kzalloc(dev,
 				sizeof(struct palmas_reg_init), GFP_KERNEL);
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,warm-reset", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->warm_reset = prop;
+		pdata->reg_init[idx]->warm_reset =
+			of_property_read_u32(palmas_matches[idx].of_node,
+					     "ti,warm-reset", &prop);
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,roof-floor", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->roof_floor = prop;
+		pdata->reg_init[idx]->roof_floor =
+			of_property_read_bool(palmas_matches[idx].of_node,
+					      "ti,roof-floor");
 
 		ret = of_property_read_u32(palmas_matches[idx].of_node,
 				"ti,mode-sleep", &prop);
@@ -573,15 +571,14 @@ static void palmas_dt_to_pdata(struct device *dev,
 		if (!ret)
 			pdata->reg_init[idx]->tstep = prop;
 
-		ret = of_property_read_u32(palmas_matches[idx].of_node,
-				"ti,vsel", &prop);
-		if (!ret)
-			pdata->reg_init[idx]->vsel = prop;
+		ret = of_property_read_bool(palmas_matches[idx].of_node,
+					    "ti,smps-range");
+		if (ret)
+			pdata->reg_init[idx]->vsel =
+				PALMAS_SMPS12_VOLTAGE_RANGE;
 	}
 
-	ret = of_property_read_u32(node, "ti,ldo6-vibrator", &prop);
-	if (!ret)
-		pdata->ldo6_vibrator = prop;
+	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
 
@@ -806,6 +803,13 @@ static int palmas_remove(struct platform_device *pdev)
 
 static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas-pmic", },
+	{ .compatible = "ti,palmas-charger-pmic", },
+	{ .compatible = "ti,twl6035-pmic", },
+	{ .compatible = "ti,twl6036-pmic", },
+	{ .compatible = "ti,twl6037-pmic", },
+	{ .compatible = "ti,tps65913-pmic", },
+	{ .compatible = "ti,tps65914-pmic", },
+	{ .compatible = "ti,tps80036-pmic", },
 	{ /* end */ }
 };
 
-- 
1.7.0.4

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

* [PATCH v8 05/12] watchdog: add Palmas Watchdog support
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

From: Graeme Gregory <gg@slimlogic.co.uk>

Add support for the Palmas watchdog timer which has a timeout configurable
from 1s to 128s.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/watchdog/palmas_wdt.c |  170 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)
 create mode 100644 drivers/watchdog/palmas_wdt.c

diff --git a/drivers/watchdog/palmas_wdt.c b/drivers/watchdog/palmas_wdt.c
new file mode 100644
index 0000000..5bdd78a
--- /dev/null
+++ b/drivers/watchdog/palmas_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Driver for Watchdog part of Palmas PMIC Chips
+ *
+ * Copyright 2011-2013 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
+ *
+ * Based on twl4030_wdt.c
+ *
+ * Author: Timo Kokkonen <timo.t.kokkonen at nokia.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/mfd/palmas.h>
+
+struct palmas_wdt {
+	struct palmas *palmas;
+	struct watchdog_device wdt;
+	struct device *dev;
+
+	int timer_margin;
+};
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+	"(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int palmas_wdt_write(struct palmas *palmas, unsigned int data)
+{
+	unsigned int addr;
+
+	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_WATCHDOG);
+
+	return palmas_write(palmas, PALMAS_PMU_CONTROL_BASE, addr, addr);
+}
+
+static int palmas_wdt_enable(struct watchdog_device *wdt)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+	struct palmas *palmas = driver_data->palmas;
+
+	return palmas_wdt_write(palmas, driver_data->timer_margin |
+				PALMAS_WATCHDOG_ENABLE);
+}
+
+static int palmas_wdt_disable(struct watchdog_device *wdt)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+	struct palmas *palmas = driver_data->palmas;
+
+	return palmas_wdt_write(palmas, driver_data->timer_margin);
+}
+
+static int palmas_wdt_set_timeout(struct watchdog_device *wdt, unsigned timeout)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+
+	if (timeout < 1 || timeout > 128) {
+		dev_warn(driver_data->dev,
+			"Timeout can only be in the range [1-128] seconds");
+		return -EINVAL;
+	}
+	driver_data->timer_margin = fls(timeout) - 1;
+	return 0;
+}
+
+static const struct watchdog_info palmas_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "Palmas Watchdog",
+	.firmware_version = 0,
+};
+
+static const struct watchdog_ops palmas_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = palmas_wdt_enable,
+	.stop = palmas_wdt_disable,
+	.ping = palmas_wdt_enable,
+	.set_timeout = palmas_wdt_set_timeout,
+};
+
+static int palmas_wdt_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_wdt *driver_data;
+	struct watchdog_device *palmas_wdt;
+	int ret = 0;
+
+	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
+				   GFP_KERNEL);
+	if (!driver_data) {
+		dev_err(&pdev->dev, "Unable to alloacate watchdog device\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	driver_data->palmas = palmas;
+
+	palmas_wdt = &driver_data->wdt;
+
+	palmas_wdt->info = &palmas_wdt_info;
+	palmas_wdt->ops = &palmas_wdt_ops;
+	watchdog_set_nowayout(palmas_wdt, nowayout);
+	watchdog_set_drvdata(palmas_wdt, driver_data);
+
+	ret = watchdog_register_device(&driver_data->wdt);
+	if (ret) {
+		platform_set_drvdata(pdev, NULL);
+		goto err;
+	}
+
+	dev_set_drvdata(&pdev->dev, driver_data);
+
+	return 0;
+err:
+	return ret;
+}
+
+static int palmas_wdt_remove(struct platform_device *pdev)
+{
+	struct palmas_wdt *driver_data = dev_get_drvdata(&pdev->dev);
+
+	watchdog_unregister_device(&driver_data->wdt);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-wdt", },
+	{ .compatible = "ti,palmas-charger-wdt", },
+	{ .compatible = "ti,twl6035-wdt", },
+	{ .compatible = "ti,twl6036-wdt", },
+	{ .compatible = "ti,twl6037-wdt", },
+	{ .compatible = "ti,tps65913-wdt", },
+	{ .compatible = "ti,tps65914-wdt", },
+	{ .compatible = "ti,tps80036-wdt", },
+	{ /* end */ }
+};
+
+static struct platform_driver palmas_wdt_driver = {
+	.probe = palmas_wdt_probe,
+	.remove = palmas_wdt_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.of_match_table = of_palmas_match_tbl,
+		.name = "palmas-wdt",
+	},
+};
+
+module_platform_driver(palmas_wdt_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-wdt");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
-- 
1.7.0.4


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

* [PATCH v8 05/12] watchdog: add Palmas Watchdog support
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: Graeme Gregory <gg@slimlogic.co.uk>

Add support for the Palmas watchdog timer which has a timeout configurable
from 1s to 128s.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/watchdog/palmas_wdt.c |  170 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)
 create mode 100644 drivers/watchdog/palmas_wdt.c

diff --git a/drivers/watchdog/palmas_wdt.c b/drivers/watchdog/palmas_wdt.c
new file mode 100644
index 0000000..5bdd78a
--- /dev/null
+++ b/drivers/watchdog/palmas_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Driver for Watchdog part of Palmas PMIC Chips
+ *
+ * Copyright 2011-2013 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
+ *
+ * Based on twl4030_wdt.c
+ *
+ * Author: Timo Kokkonen <timo.t.kokkonen@nokia.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/mfd/palmas.h>
+
+struct palmas_wdt {
+	struct palmas *palmas;
+	struct watchdog_device wdt;
+	struct device *dev;
+
+	int timer_margin;
+};
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+	"(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int palmas_wdt_write(struct palmas *palmas, unsigned int data)
+{
+	unsigned int addr;
+
+	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_WATCHDOG);
+
+	return palmas_write(palmas, PALMAS_PMU_CONTROL_BASE, addr, addr);
+}
+
+static int palmas_wdt_enable(struct watchdog_device *wdt)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+	struct palmas *palmas = driver_data->palmas;
+
+	return palmas_wdt_write(palmas, driver_data->timer_margin |
+				PALMAS_WATCHDOG_ENABLE);
+}
+
+static int palmas_wdt_disable(struct watchdog_device *wdt)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+	struct palmas *palmas = driver_data->palmas;
+
+	return palmas_wdt_write(palmas, driver_data->timer_margin);
+}
+
+static int palmas_wdt_set_timeout(struct watchdog_device *wdt, unsigned timeout)
+{
+	struct palmas_wdt *driver_data = watchdog_get_drvdata(wdt);
+
+	if (timeout < 1 || timeout > 128) {
+		dev_warn(driver_data->dev,
+			"Timeout can only be in the range [1-128] seconds");
+		return -EINVAL;
+	}
+	driver_data->timer_margin = fls(timeout) - 1;
+	return 0;
+}
+
+static const struct watchdog_info palmas_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "Palmas Watchdog",
+	.firmware_version = 0,
+};
+
+static const struct watchdog_ops palmas_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = palmas_wdt_enable,
+	.stop = palmas_wdt_disable,
+	.ping = palmas_wdt_enable,
+	.set_timeout = palmas_wdt_set_timeout,
+};
+
+static int palmas_wdt_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_wdt *driver_data;
+	struct watchdog_device *palmas_wdt;
+	int ret = 0;
+
+	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
+				   GFP_KERNEL);
+	if (!driver_data) {
+		dev_err(&pdev->dev, "Unable to alloacate watchdog device\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	driver_data->palmas = palmas;
+
+	palmas_wdt = &driver_data->wdt;
+
+	palmas_wdt->info = &palmas_wdt_info;
+	palmas_wdt->ops = &palmas_wdt_ops;
+	watchdog_set_nowayout(palmas_wdt, nowayout);
+	watchdog_set_drvdata(palmas_wdt, driver_data);
+
+	ret = watchdog_register_device(&driver_data->wdt);
+	if (ret) {
+		platform_set_drvdata(pdev, NULL);
+		goto err;
+	}
+
+	dev_set_drvdata(&pdev->dev, driver_data);
+
+	return 0;
+err:
+	return ret;
+}
+
+static int palmas_wdt_remove(struct platform_device *pdev)
+{
+	struct palmas_wdt *driver_data = dev_get_drvdata(&pdev->dev);
+
+	watchdog_unregister_device(&driver_data->wdt);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-wdt", },
+	{ .compatible = "ti,palmas-charger-wdt", },
+	{ .compatible = "ti,twl6035-wdt", },
+	{ .compatible = "ti,twl6036-wdt", },
+	{ .compatible = "ti,twl6037-wdt", },
+	{ .compatible = "ti,tps65913-wdt", },
+	{ .compatible = "ti,tps65914-wdt", },
+	{ .compatible = "ti,tps80036-wdt", },
+	{ /* end */ }
+};
+
+static struct platform_driver palmas_wdt_driver = {
+	.probe = palmas_wdt_probe,
+	.remove = palmas_wdt_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.of_match_table = of_palmas_match_tbl,
+		.name = "palmas-wdt",
+	},
+};
+
+module_platform_driver(palmas_wdt_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-wdt");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
-- 
1.7.0.4

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

* [PATCH v8 06/12] watchdog: Kconfig for Palmas watchdog
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

Add the Kconfig and Makefile for the Palmas watchdog driver

Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/watchdog/Kconfig  |    8 ++++++++
 drivers/watchdog/Makefile |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9fcc70c..d48cb0e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -103,6 +103,14 @@ config WM8350_WATCHDOG
 	  Support for the watchdog in the WM8350 AudioPlus PMIC.  When
 	  the watchdog triggers the system will be reset.
 
+config PALMAS_WATCHDOG
+	tristate "Palmas Watchdog"
+	depends on MFD_PALMAS
+	select WATCHDOG_CORE
+	help
+	  Support for the watchdog in the Palmas family of PMICs. When the
+	  watchdog times out system will be reset.
+
 # ALPHA Architecture
 
 # ARM Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a300b94..e845c21 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -171,3 +171,4 @@ obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
 obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_PALMAS_WATCHDOG) += palmas_wdt.o
-- 
1.7.0.4


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

* [PATCH v8 06/12] watchdog: Kconfig for Palmas watchdog
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Add the Kconfig and Makefile for the Palmas watchdog driver

Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/watchdog/Kconfig  |    8 ++++++++
 drivers/watchdog/Makefile |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9fcc70c..d48cb0e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -103,6 +103,14 @@ config WM8350_WATCHDOG
 	  Support for the watchdog in the WM8350 AudioPlus PMIC.  When
 	  the watchdog triggers the system will be reset.
 
+config PALMAS_WATCHDOG
+	tristate "Palmas Watchdog"
+	depends on MFD_PALMAS
+	select WATCHDOG_CORE
+	help
+	  Support for the watchdog in the Palmas family of PMICs. When the
+	  watchdog times out system will be reset.
+
 # ALPHA Architecture
 
 # ARM Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a300b94..e845c21 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -171,3 +171,4 @@ obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
 obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_PALMAS_WATCHDOG) += palmas_wdt.o
-- 
1.7.0.4

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

* [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

Palmas charger has 16 GPIOs
add palmas_gpio_[read|write|update] api to take account
second bank of GPIOs

Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/gpio/gpio-palmas.c |   77 ++++++++++++++++++++++++++++++++++++--------
 include/linux/mfd/palmas.h |   12 ++++++-
 2 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index e3a4e56..636648c 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -1,7 +1,7 @@
 /*
- * TI Palma series PMIC's GPIO driver.
+ * TI Palmas series PMIC's GPIO driver.
  *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2012, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author: Laxman Dewangan <ldewangan@nvidia.com>
  *
@@ -31,6 +31,36 @@ struct palmas_gpio {
 	struct palmas *palmas;
 };
 
+static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int *dest)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
+}
+
+static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int data)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
+}
+
+static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int mask, unsigned int data)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
+}
+
 static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)
 {
 	return container_of(chip, struct palmas_gpio, gpio_chip);
@@ -43,12 +73,12 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
 	unsigned int val;
 	int ret;
 
-	ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
+	ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);
 	if (ret < 0) {
 		dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret);
 		return ret;
 	}
-	return !!(val & BIT(offset));
+	return !!(val & BIT(offset % 8));
 }
 
 static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
@@ -59,11 +89,11 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
 	int ret;
 
 	if (value)
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_SET_DATA_OUT, BIT(offset));
+		ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
+				offset, BIT(offset % 8));
 	else
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset));
+		ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
+				offset, BIT(offset % 8));
 	if (ret < 0)
 		dev_err(gc->dev, "%s write failed, err = %d\n",
 			(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT",
@@ -80,8 +110,8 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
 	/* Set the initial value */
 	palmas_gpio_set(gc, offset, value);
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset));
+	ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
+			offset, 1 << (offset % 8), 1 << (offset % 8));
 	if (ret < 0)
 		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
 	return ret;
@@ -93,8 +123,8 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
 	struct palmas *palmas = pg->palmas;
 	int ret;
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), 0);
+	ret =  palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
+				offset, 1 << (offset % 8), 0);
 	if (ret < 0)
 		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
 	return ret;
@@ -108,7 +138,21 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
 }
 
-static int palmas_gpio_probe(struct platform_device *pdev)
+static int palmas_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
+				    unsigned debounce)
+{
+	struct palmas_gpio *palmas_gpio = to_palmas_gpio(gc);
+	struct palmas *palmas = palmas_gpio->palmas;
+	unsigned int data = 0;
+
+	if (debounce)
+		data = 0xff;
+
+	return palmas_gpio_update_bits(palmas, PALMAS_GPIO_DEBOUNCE_EN,
+			offset, 1 << (offset % 8), data);
+}
+
+static int  palmas_gpio_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_platform_data *palmas_pdata;
@@ -125,10 +169,15 @@ static int palmas_gpio_probe(struct platform_device *pdev)
 	palmas_gpio->palmas = palmas;
 	palmas_gpio->gpio_chip.owner = THIS_MODULE;
 	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
-	palmas_gpio->gpio_chip.ngpio = 8;
+	/* palmas charger has 16 gpios */
+	if (is_palmas_charger(palmas->product_id))
+		palmas_gpio->gpio_chip.ngpio = 16;
+	else
+		palmas_gpio->gpio_chip.ngpio = 8;
 	palmas_gpio->gpio_chip.can_sleep = 1;
 	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
 	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
+	palmas_gpio->gpio_chip.set_debounce = palmas_gpio_set_debounce,
 	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
 	palmas_gpio->gpio_chip.set	= palmas_gpio_set;
 	palmas_gpio->gpio_chip.get	= palmas_gpio_get;
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 0427165..5661f2d 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -243,7 +243,7 @@ struct palmas_platform_data {
 	 * then the two value to load into the registers if true
 	 */
 	int mux_from_pdata;
-	u8 pad1, pad2;
+	u8 pad1, pad2, pad3, pad4;
 
 	struct palmas_pmic_platform_data *pmic_pdata;
 	struct palmas_gpadc_platform_data *gpadc_pdata;
@@ -2512,6 +2512,16 @@ enum usb_irq_events {
 #define PALMAS_PU_PD_GPIO_CTRL1					0x6
 #define PALMAS_PU_PD_GPIO_CTRL2					0x7
 #define PALMAS_OD_OUTPUT_GPIO_CTRL				0x8
+#define PALMAS_GPIO_DATA_IN2					0x9
+#define PALMAS_GPIO_DATA_DIR2					0xA
+#define PALMAS_GPIO_DATA_OUT2					0xB
+#define PALMAS_GPIO_DEBOUNCE_EN2				0xC
+#define PALMAS_GPIO_CLEAR_DATA_OUT2				0xD
+#define PALMAS_GPIO_SET_DATA_OUT2				0xE
+#define PALMAS_PU_PD_GPIO_CTRL3					0xF
+#define PALMAS_PU_PD_GPIO_CTRL4					0x10
+#define PALMAS_OD_OUTPUT_GPIO_CTRL2				0x11
+#define PALMAS_GPO_CTRL						0x12
 
 /* Bit definitions for GPIO_DATA_IN */
 #define PALMAS_GPIO_DATA_IN_GPIO_7_IN				0x80
-- 
1.7.0.4


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

* [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Palmas charger has 16 GPIOs
add palmas_gpio_[read|write|update] api to take account
second bank of GPIOs

Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
---
 drivers/gpio/gpio-palmas.c |   77 ++++++++++++++++++++++++++++++++++++--------
 include/linux/mfd/palmas.h |   12 ++++++-
 2 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index e3a4e56..636648c 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -1,7 +1,7 @@
 /*
- * TI Palma series PMIC's GPIO driver.
+ * TI Palmas series PMIC's GPIO driver.
  *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2012, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author: Laxman Dewangan <ldewangan@nvidia.com>
  *
@@ -31,6 +31,36 @@ struct palmas_gpio {
 	struct palmas *palmas;
 };
 
+static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int *dest)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
+}
+
+static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int data)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
+}
+
+static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
+		int gpio, unsigned int mask, unsigned int data)
+{
+	/* registers for second bank are identical and offset by 0x9 */
+	if (gpio > 7)
+		reg += PALMAS_GPIO_DATA_IN2;
+
+	return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
+}
+
 static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)
 {
 	return container_of(chip, struct palmas_gpio, gpio_chip);
@@ -43,12 +73,12 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
 	unsigned int val;
 	int ret;
 
-	ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
+	ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);
 	if (ret < 0) {
 		dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret);
 		return ret;
 	}
-	return !!(val & BIT(offset));
+	return !!(val & BIT(offset % 8));
 }
 
 static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
@@ -59,11 +89,11 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
 	int ret;
 
 	if (value)
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_SET_DATA_OUT, BIT(offset));
+		ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
+				offset, BIT(offset % 8));
 	else
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset));
+		ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
+				offset, BIT(offset % 8));
 	if (ret < 0)
 		dev_err(gc->dev, "%s write failed, err = %d\n",
 			(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT",
@@ -80,8 +110,8 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
 	/* Set the initial value */
 	palmas_gpio_set(gc, offset, value);
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset));
+	ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
+			offset, 1 << (offset % 8), 1 << (offset % 8));
 	if (ret < 0)
 		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
 	return ret;
@@ -93,8 +123,8 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
 	struct palmas *palmas = pg->palmas;
 	int ret;
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), 0);
+	ret =  palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
+				offset, 1 << (offset % 8), 0);
 	if (ret < 0)
 		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
 	return ret;
@@ -108,7 +138,21 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
 }
 
-static int palmas_gpio_probe(struct platform_device *pdev)
+static int palmas_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
+				    unsigned debounce)
+{
+	struct palmas_gpio *palmas_gpio = to_palmas_gpio(gc);
+	struct palmas *palmas = palmas_gpio->palmas;
+	unsigned int data = 0;
+
+	if (debounce)
+		data = 0xff;
+
+	return palmas_gpio_update_bits(palmas, PALMAS_GPIO_DEBOUNCE_EN,
+			offset, 1 << (offset % 8), data);
+}
+
+static int  palmas_gpio_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_platform_data *palmas_pdata;
@@ -125,10 +169,15 @@ static int palmas_gpio_probe(struct platform_device *pdev)
 	palmas_gpio->palmas = palmas;
 	palmas_gpio->gpio_chip.owner = THIS_MODULE;
 	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
-	palmas_gpio->gpio_chip.ngpio = 8;
+	/* palmas charger has 16 gpios */
+	if (is_palmas_charger(palmas->product_id))
+		palmas_gpio->gpio_chip.ngpio = 16;
+	else
+		palmas_gpio->gpio_chip.ngpio = 8;
 	palmas_gpio->gpio_chip.can_sleep = 1;
 	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
 	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
+	palmas_gpio->gpio_chip.set_debounce = palmas_gpio_set_debounce,
 	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
 	palmas_gpio->gpio_chip.set	= palmas_gpio_set;
 	palmas_gpio->gpio_chip.get	= palmas_gpio_get;
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 0427165..5661f2d 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -243,7 +243,7 @@ struct palmas_platform_data {
 	 * then the two value to load into the registers if true
 	 */
 	int mux_from_pdata;
-	u8 pad1, pad2;
+	u8 pad1, pad2, pad3, pad4;
 
 	struct palmas_pmic_platform_data *pmic_pdata;
 	struct palmas_gpadc_platform_data *gpadc_pdata;
@@ -2512,6 +2512,16 @@ enum usb_irq_events {
 #define PALMAS_PU_PD_GPIO_CTRL1					0x6
 #define PALMAS_PU_PD_GPIO_CTRL2					0x7
 #define PALMAS_OD_OUTPUT_GPIO_CTRL				0x8
+#define PALMAS_GPIO_DATA_IN2					0x9
+#define PALMAS_GPIO_DATA_DIR2					0xA
+#define PALMAS_GPIO_DATA_OUT2					0xB
+#define PALMAS_GPIO_DEBOUNCE_EN2				0xC
+#define PALMAS_GPIO_CLEAR_DATA_OUT2				0xD
+#define PALMAS_GPIO_SET_DATA_OUT2				0xE
+#define PALMAS_PU_PD_GPIO_CTRL3					0xF
+#define PALMAS_PU_PD_GPIO_CTRL4					0x10
+#define PALMAS_OD_OUTPUT_GPIO_CTRL2				0x11
+#define PALMAS_GPO_CTRL						0x12
 
 /* Bit definitions for GPIO_DATA_IN */
 #define PALMAS_GPIO_DATA_IN_GPIO_7_IN				0x80
-- 
1.7.0.4

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

* [PATCH v8 08/12] gpio: palmas: Enable DT support for palmas gpio.
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo

From: J Keerthy <j-keerthy@ti.com>

Enable DT support for palmas gpio.

Signed-off-by: J Keerthy <j-keerthy@ti.com>
---
 drivers/gpio/gpio-palmas.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index 636648c..04da57a 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -208,9 +208,22 @@ static int palmas_gpio_remove(struct platform_device *pdev)
 	return gpiochip_remove(&palmas_gpio->gpio_chip);
 }
 
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-gpio", },
+	{ .compatible = "ti,palmas-charger-gpio", },
+	{ .compatible = "ti,twl6035-gpio", },
+	{ .compatible = "ti,twl6036-gpio", },
+	{ .compatible = "ti,twl6037-gpio", },
+	{ .compatible = "ti,tps65913-gpio", },
+	{ .compatible = "ti,tps65914-gpio", },
+	{ .compatible = "ti,tps80036-gpio", },
+	{ /* end */ }
+};
+
 static struct platform_driver palmas_gpio_driver = {
 	.driver.name	= "palmas-gpio",
 	.driver.owner	= THIS_MODULE,
+	.driver.of_match_table = of_palmas_match_tbl,
 	.probe		= palmas_gpio_probe,
 	.remove		= palmas_gpio_remove,
 };
-- 
1.7.0.4


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

* [PATCH v8 08/12] gpio: palmas: Enable DT support for palmas gpio.
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

From: J Keerthy <j-keerthy@ti.com>

Enable DT support for palmas gpio.

Signed-off-by: J Keerthy <j-keerthy@ti.com>
---
 drivers/gpio/gpio-palmas.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index 636648c..04da57a 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -208,9 +208,22 @@ static int palmas_gpio_remove(struct platform_device *pdev)
 	return gpiochip_remove(&palmas_gpio->gpio_chip);
 }
 
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-gpio", },
+	{ .compatible = "ti,palmas-charger-gpio", },
+	{ .compatible = "ti,twl6035-gpio", },
+	{ .compatible = "ti,twl6036-gpio", },
+	{ .compatible = "ti,twl6037-gpio", },
+	{ .compatible = "ti,tps65913-gpio", },
+	{ .compatible = "ti,tps65914-gpio", },
+	{ .compatible = "ti,tps80036-gpio", },
+	{ /* end */ }
+};
+
 static struct platform_driver palmas_gpio_driver = {
 	.driver.name	= "palmas-gpio",
 	.driver.owner	= THIS_MODULE,
+	.driver.of_match_table = of_palmas_match_tbl,
 	.probe		= palmas_gpio_probe,
 	.remove		= palmas_gpio_remove,
 };
-- 
1.7.0.4

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

* [PATCH v8 09/12] leds: Add support for Palmas LEDs
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

The Palmas familly of chips has LED support. This is not always muxed
to output pins so depending on the setting of the mux this driver
will create the appropriate LED class devices.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/leds/leds-palmas.c |  567 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/palmas.h |   60 +++++
 2 files changed, 627 insertions(+), 0 deletions(-)
 create mode 100644 drivers/leds/leds-palmas.c

diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c
new file mode 100644
index 0000000..4a35352
--- /dev/null
+++ b/drivers/leds/leds-palmas.c
@@ -0,0 +1,567 @@
+/*
+ * Driver for LED part of Palmas PMIC Chips
+ *
+ * Copyright 2011-2013 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/mfd/palmas.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct palmas_leds_data;
+
+struct palmas_led {
+	struct led_classdev cdev;
+	struct palmas_leds_data *leds_data;
+	int led_no;
+	struct work_struct work;
+	struct mutex mutex;
+
+	spinlock_t value_lock;
+
+	int blink;
+	int on_time;
+	int period;
+	enum led_brightness brightness;
+};
+
+struct palmas_leds_data {
+	struct device *dev;
+	struct led_classdev cdev;
+	struct palmas *palmas;
+
+	struct palmas_led *palmas_led;
+	int no_leds;
+};
+
+#define to_palmas_led(led_cdev) \
+	container_of(led_cdev, struct palmas_led, cdev)
+
+#define LED_ON_62_5MS		0x00
+#define LED_ON_125MS		0x01
+#define LED_ON_250MS		0x02
+#define LED_ON_500MS		0x03
+
+#define LED_PERIOD_OFF		0x00
+#define LED_PERIOD_125MS	0x01
+#define LED_PERIOD_250MS	0x02
+#define LED_PERIOD_500MS	0x03
+#define LED_PERIOD_1000MS	0x04
+#define LED_PERIOD_2000MS	0x05
+#define LED_PERIOD_4000MS	0x06
+#define LED_PERIOD_8000MS	0x07
+
+
+static char *palmas_led_names[] = {
+	"palmas:led1",
+	"palmas:led2",
+	"palmas:led3",
+	"palmas:led4",
+};
+
+static int palmas_led_read(struct palmas_leds_data *leds, unsigned int reg,
+		unsigned int *dest)
+{
+	return palmas_read(leds->palmas, PALMAS_LED_BASE, reg, dest);
+}
+
+static int palmas_led_write(struct palmas_leds_data *leds, unsigned int reg,
+		unsigned int value)
+{
+	return palmas_write(leds->palmas, PALMAS_LED_BASE, reg, value);
+}
+
+static int palmas_led_update_bits(struct palmas_leds_data *leds,
+		unsigned int reg, unsigned int mask, unsigned int value)
+{
+	return palmas_update_bits(leds->palmas, PALMAS_LED_BASE,
+			reg, mask, value);
+}
+
+static void palmas_leds_work(struct work_struct *work)
+{
+	struct palmas_led *led = container_of(work, struct palmas_led, work);
+	unsigned int period, ctrl;
+	unsigned long flags;
+
+	mutex_lock(&led->mutex);
+
+	palmas_led_read(led->leds_data, PALMAS_LED_CTRL, &ctrl);
+	palmas_led_read(led->leds_data, PALMAS_LED_PERIOD_CTRL, &period);
+
+	spin_lock_irqsave(&led->value_lock, flags);
+
+	switch (led->led_no) {
+	case 1:
+		ctrl &= ~PALMAS_LED_CTRL_LED_1_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT;
+			}
+		}
+	case 2:
+		ctrl &= ~PALMAS_LED_CTRL_LED_2_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT;
+			}
+		}
+	case 3:
+		ctrl &= ~PALMAS_LED_CTRL2_LED_3_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT;
+			}
+		}
+		break;
+	case 4:
+		ctrl &= ~PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT;
+			}
+		}
+		break;
+	}
+
+	spin_unlock_irqrestore(&led->value_lock, flags);
+
+	if (led->led_no < 3) {
+		palmas_led_write(led->leds_data, PALMAS_LED_CTRL, ctrl);
+		palmas_led_write(led->leds_data, PALMAS_LED_PERIOD_CTRL,
+				period);
+	} else {
+		palmas_led_write(led->leds_data, PALMAS_LED_CTRL2, ctrl);
+		palmas_led_write(led->leds_data, PALMAS_LED_PERIOD2_CTRL,
+				period);
+	}
+
+	if (is_palmas_charger(led->leds_data->palmas->product_id)) {
+		if (led->brightness || led->blink)
+			palmas_led_update_bits(led->leds_data, PALMAS_LED_EN,
+					1 << (led->led_no - 1), 0xFF);
+		else
+			palmas_led_update_bits(led->leds_data, PALMAS_LED_EN,
+					1 << (led->led_no - 1), 0x00);
+	}
+	mutex_unlock(&led->mutex);
+}
+
+static void palmas_leds_set(struct led_classdev *led_cdev,
+			   enum led_brightness value)
+{
+	struct palmas_led *led = to_palmas_led(led_cdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&led->value_lock, flags);
+	led->brightness = value;
+	led->blink = 0;
+	schedule_work(&led->work);
+	spin_unlock_irqrestore(&led->value_lock, flags);
+}
+
+static int palmas_leds_blink_set(struct led_classdev *led_cdev,
+				   unsigned long *delay_on,
+				   unsigned long *delay_off)
+{
+	struct palmas_led *led = to_palmas_led(led_cdev);
+	unsigned long flags;
+	int ret = 0;
+	int period;
+
+	/* Pick some defaults if we've not been given times */
+	if (*delay_on == 0 && *delay_off == 0) {
+		*delay_on = 250;
+		*delay_off = 250;
+	}
+
+	spin_lock_irqsave(&led->value_lock, flags);
+
+	/*
+	 * We only have a limited selection of settings, see if we can
+	 * support the configuration we're being given
+	 */
+	switch (*delay_on) {
+	case 500:
+		led->on_time = LED_ON_500MS;
+		break;
+	case 250:
+		led->on_time = LED_ON_250MS;
+		break;
+	case 125:
+		led->on_time = LED_ON_125MS;
+		break;
+	case 62:
+	case 63:
+		/* Actually 62.5ms */
+		led->on_time = LED_ON_62_5MS;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	period = *delay_on + *delay_off;
+
+	if (ret == 0) {
+		switch (period) {
+		case 124:
+		case 125:
+		case 126:
+			/* All possible variations of 62.5 + 62.5 */
+			led->period = LED_PERIOD_125MS;
+			break;
+		case 250:
+			led->period = LED_PERIOD_250MS;
+			break;
+		case 500:
+			led->period = LED_PERIOD_500MS;
+			break;
+		case 1000:
+			led->period = LED_PERIOD_1000MS;
+			break;
+		case 2000:
+			led->period = LED_PERIOD_2000MS;
+			break;
+		case 4000:
+			led->period = LED_PERIOD_4000MS;
+			break;
+		case 8000:
+			led->period = LED_PERIOD_8000MS;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	if (ret == 0)
+		led->blink = 1;
+	else
+		led->blink = 0;
+
+	/*
+	 * Always update; if we fail turn off blinking since we expect
+	 * a software fallback.
+	 */
+	schedule_work(&led->work);
+
+	spin_unlock_irqrestore(&led->value_lock, flags);
+
+	return ret;
+}
+
+static void palmas_init_led(struct palmas_leds_data *leds_data, int offset,
+		int led_no)
+{
+	mutex_init(&leds_data->palmas_led[offset].mutex);
+	INIT_WORK(&leds_data->palmas_led[offset].work, palmas_leds_work);
+	spin_lock_init(&leds_data->palmas_led[offset].value_lock);
+
+	leds_data->palmas_led[offset].leds_data = leds_data;
+	leds_data->palmas_led[offset].led_no = led_no;
+	leds_data->palmas_led[offset].cdev.name = palmas_led_names[led_no - 1];
+	leds_data->palmas_led[offset].cdev.default_trigger = NULL;
+	leds_data->palmas_led[offset].cdev.brightness_set = palmas_leds_set;
+	leds_data->palmas_led[offset].cdev.blink_set = palmas_leds_blink_set;
+}
+
+static int  palmas_dt_to_pdata(struct device *dev,
+		struct device_node *node,
+		struct palmas_leds_platform_data *pdata)
+{
+	struct device_node *child_node;
+	int ret;
+	u32 prop;
+
+	child_node = of_get_child_by_name(node, "leds");
+	if (!child_node) {
+		dev_err(dev, "child node 'palmas_leds' not found\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(child_node, "ti,led1-current", &prop);
+	if (!ret)
+		pdata->led1_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led2-current", &prop);
+	if (!ret)
+		pdata->led2_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led3-current", &prop);
+	if (!ret)
+		pdata->led3_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led4-current", &prop);
+	if (!ret)
+		pdata->led4_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,chrg-led-mode", &prop);
+	if (!ret)
+		pdata->chrg_led_mode = prop;
+
+	ret = of_property_read_u32(child_node, "ti,chrg-led-vbat-low", &prop);
+	if (!ret)
+		pdata->chrg_led_vbat_low = prop;
+
+	return 0;
+}
+
+static int palmas_leds_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct palmas_leds_data *leds_data;
+	struct device_node *node = pdev->dev.of_node;
+	int ret, i;
+	int offset = 0;
+
+	if (!palmas->led_muxed && !is_palmas_charger(palmas->product_id)) {
+		dev_err(&pdev->dev, "there are no LEDs muxed\n");
+		return -EINVAL;
+	}
+
+	/* Palmas charger requires platform data */
+	if (is_palmas_charger(palmas->product_id) && node && !pdata) {
+
+		if (!pdata)
+			return -ENOMEM;
+
+		ret = palmas_dt_to_pdata(&pdev->dev, node, pdata);
+		if (ret)
+			return ret;
+	}
+
+	if (is_palmas_charger(palmas->product_id) && !pdata)
+		return -EINVAL;
+
+	leds_data = devm_kzalloc(&pdev->dev, sizeof(*leds_data), GFP_KERNEL);
+	if (!leds_data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, leds_data);
+
+	leds_data->palmas = palmas;
+
+	switch (palmas->led_muxed) {
+	case PALMAS_LED1_MUXED | PALMAS_LED2_MUXED:
+		leds_data->no_leds = 2;
+		break;
+	case PALMAS_LED1_MUXED:
+	case PALMAS_LED2_MUXED:
+		leds_data->no_leds = 1;
+		break;
+	default:
+		leds_data->no_leds = 0;
+		break;
+	}
+
+	if (is_palmas_charger(palmas->product_id)) {
+		if (pdata->chrg_led_mode)
+			leds_data->no_leds += 2;
+		else
+			leds_data->no_leds++;
+	}
+
+	if (leds_data->no_leds == 0)
+		leds_data->palmas_led = NULL;
+	else
+		leds_data = devm_kzalloc(&pdev->dev,
+				leds_data->no_leds * sizeof(*leds_data),
+				GFP_KERNEL);
+
+	/* Initialise LED1 */
+	if (palmas->led_muxed & PALMAS_LED1_MUXED) {
+		palmas_init_led(leds_data, offset, 1);
+		offset++;
+	}
+
+	/* Initialise LED2 */
+	if (palmas->led_muxed & PALMAS_LED2_MUXED) {
+		palmas_init_led(leds_data, offset, 2);
+		offset++;
+	}
+
+	if (is_palmas_charger(palmas->product_id)) {
+		palmas_init_led(leds_data, offset, 3);
+		offset++;
+
+		if (pdata->chrg_led_mode) {
+			palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE,
+					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE);
+
+			palmas_init_led(leds_data, offset, 4);
+		}
+	}
+
+	for (i = 0; i < leds_data->no_leds; i++) {
+		ret = led_classdev_register(leds_data->dev,
+				&leds_data->palmas_led[i].cdev);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"Failed to register LED no: %d err: %d\n",
+				i, ret);
+			goto err_led;
+		}
+	}
+
+	if (!is_palmas_charger(palmas->product_id))
+		return 0;
+
+	/* Set the LED current registers if set in platform data */
+	if (pdata->led1_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
+				PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK,
+				pdata->led1_current);
+
+	if (pdata->led2_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
+				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK,
+				pdata->led2_current <<
+				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT);
+
+	if (pdata->led3_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
+				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
+				pdata->led3_current);
+
+	if (pdata->led3_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
+				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
+				pdata->led3_current);
+
+	if (pdata->led4_current)
+		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK,
+				pdata->led4_current <<
+				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT);
+
+	if (pdata->chrg_led_vbat_low)
+		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS,
+				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS);
+
+	return 0;
+
+err_led:
+	for (i = 0; i < leds_data->no_leds; i++)
+		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
+	kfree(leds_data->palmas_led);
+	kfree(leds_data);
+	return ret;
+}
+
+static int palmas_leds_remove(struct platform_device *pdev)
+{
+	struct palmas_leds_data *leds_data = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < leds_data->no_leds; i++)
+		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
+	if (i)
+		kfree(leds_data->palmas_led);
+	kfree(leds_data);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-leds", },
+	{ .compatible = "ti,palmas-charger-leds", },
+	{ .compatible = "ti,twl6035-leds", },
+	{ .compatible = "ti,twl6036-leds", },
+	{ .compatible = "ti,twl6037-leds", },
+	{ .compatible = "ti,tps65913-leds", },
+	{ .compatible = "ti,tps65914-leds", },
+	{ .compatible = "ti,tps80036-leds", },
+	{ /* end */ }
+};
+
+static struct platform_driver palmas_leds_driver = {
+	.driver = {
+		.name = "palmas-leds",
+		.of_match_table = of_palmas_match_tbl,
+		.owner = THIS_MODULE,
+	},
+	.probe = palmas_leds_probe,
+	.remove = palmas_leds_remove,
+};
+
+module_platform_driver(palmas_leds_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("Palmas LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-leds");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 5661f2d..7399c71 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -232,6 +232,16 @@ struct palmas_clk_platform_data {
 	int clk32kgaudio_mode_sleep;
 };
 
+struct palmas_leds_platform_data {
+	int led1_current;
+	int led2_current;
+	int led3_current;
+	int led4_current;
+
+	int chrg_led_mode;
+	int chrg_led_vbat_low;
+};
+
 struct palmas_platform_data {
 	int gpio_base;
 
@@ -1855,6 +1865,12 @@ enum usb_irq_events {
 #define PALMAS_LED_CTRL						0x1
 #define PALMAS_PWM_CTRL1					0x2
 #define PALMAS_PWM_CTRL2					0x3
+#define PALMAS_LED_PERIOD2_CTRL					0x4
+#define PALMAS_LED_CTRL2					0x5
+#define PALMAS_LED_CURRENT_CTRL1				0x6
+#define PALMAS_LED_CURRENT_CTRL2				0x7
+#define PALMAS_CHRG_LED_CTRL					0x8
+#define PALMAS_LED_EN						0x9
 
 /* Bit definitions for LED_PERIOD_CTRL */
 #define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK		0x38
@@ -1882,6 +1898,50 @@ enum usb_irq_events {
 #define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_MASK			0xff
 #define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_SHIFT			0
 
+/* Bit definitions for LED_PERIOD2_CTRL */
+#define PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_MASK		0x38
+#define PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT		3
+#define PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_MASK		0x07
+#define PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT		0
+
+/* Bit definitions for LED_CTRL2 */
+#define PALMAS_LED_CTRL2_CHRG_LED_SEQ				0x20
+#define PALMAS_LED_CTRL2_CHRG_LED_SEQ_SHIFT			5
+#define PALMAS_LED_CTRL2_LED_3_SEQ				0x10
+#define PALMAS_LED_CTRL2_LED_3_SEQ_SHIFT			4
+#define PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_MASK			0x0c
+#define PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT			2
+#define PALMAS_LED_CTRL2_LED_3_ON_TIME_MASK			0x03
+#define PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT			0
+
+/* Bit definitions for LED_CURRENT_CTRL1 */
+#define PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK		0x38
+#define PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT		3
+#define PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK		0x07
+#define PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_SHIFT		0
+
+/* Bit definitions for LED_CURRENT_CTRL2 */
+#define PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK		0x07
+#define PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_SHIFT		0
+
+/* Bit definitions for CHRG_LED_CTRL */
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK		0x38
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT		3
+#define PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS		0x02
+#define PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS_SHIFT		1
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE			0x01
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE_SHIFT		0
+
+/* Bit definitions for LED_EN */
+#define PALMAS_LED_EN_CHRG_LED_EN				0x08
+#define PALMAS_LED_EN_CHRG_LED_EN_SHIFT				3
+#define PALMAS_LED_EN_LED_3_EN					0x04
+#define PALMAS_LED_EN_LED_3_EN_SHIFT				2
+#define PALMAS_LED_EN_LED_2_EN					0x02
+#define PALMAS_LED_EN_LED_2_EN_SHIFT				1
+#define PALMAS_LED_EN_LED_1_EN					0x01
+#define PALMAS_LED_EN_LED_1_EN_SHIFT				0
+
 /* Registers for function INTERRUPT */
 #define PALMAS_INT1_STATUS					0x0
 #define PALMAS_INT1_MASK					0x1
-- 
1.7.0.4


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

* [PATCH v8 09/12] leds: Add support for Palmas LEDs
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

The Palmas familly of chips has LED support. This is not always muxed
to output pins so depending on the setting of the mux this driver
will create the appropriate LED class devices.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/leds/leds-palmas.c |  567 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/palmas.h |   60 +++++
 2 files changed, 627 insertions(+), 0 deletions(-)
 create mode 100644 drivers/leds/leds-palmas.c

diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c
new file mode 100644
index 0000000..4a35352
--- /dev/null
+++ b/drivers/leds/leds-palmas.c
@@ -0,0 +1,567 @@
+/*
+ * Driver for LED part of Palmas PMIC Chips
+ *
+ * Copyright 2011-2013 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/mfd/palmas.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct palmas_leds_data;
+
+struct palmas_led {
+	struct led_classdev cdev;
+	struct palmas_leds_data *leds_data;
+	int led_no;
+	struct work_struct work;
+	struct mutex mutex;
+
+	spinlock_t value_lock;
+
+	int blink;
+	int on_time;
+	int period;
+	enum led_brightness brightness;
+};
+
+struct palmas_leds_data {
+	struct device *dev;
+	struct led_classdev cdev;
+	struct palmas *palmas;
+
+	struct palmas_led *palmas_led;
+	int no_leds;
+};
+
+#define to_palmas_led(led_cdev) \
+	container_of(led_cdev, struct palmas_led, cdev)
+
+#define LED_ON_62_5MS		0x00
+#define LED_ON_125MS		0x01
+#define LED_ON_250MS		0x02
+#define LED_ON_500MS		0x03
+
+#define LED_PERIOD_OFF		0x00
+#define LED_PERIOD_125MS	0x01
+#define LED_PERIOD_250MS	0x02
+#define LED_PERIOD_500MS	0x03
+#define LED_PERIOD_1000MS	0x04
+#define LED_PERIOD_2000MS	0x05
+#define LED_PERIOD_4000MS	0x06
+#define LED_PERIOD_8000MS	0x07
+
+
+static char *palmas_led_names[] = {
+	"palmas:led1",
+	"palmas:led2",
+	"palmas:led3",
+	"palmas:led4",
+};
+
+static int palmas_led_read(struct palmas_leds_data *leds, unsigned int reg,
+		unsigned int *dest)
+{
+	return palmas_read(leds->palmas, PALMAS_LED_BASE, reg, dest);
+}
+
+static int palmas_led_write(struct palmas_leds_data *leds, unsigned int reg,
+		unsigned int value)
+{
+	return palmas_write(leds->palmas, PALMAS_LED_BASE, reg, value);
+}
+
+static int palmas_led_update_bits(struct palmas_leds_data *leds,
+		unsigned int reg, unsigned int mask, unsigned int value)
+{
+	return palmas_update_bits(leds->palmas, PALMAS_LED_BASE,
+			reg, mask, value);
+}
+
+static void palmas_leds_work(struct work_struct *work)
+{
+	struct palmas_led *led = container_of(work, struct palmas_led, work);
+	unsigned int period, ctrl;
+	unsigned long flags;
+
+	mutex_lock(&led->mutex);
+
+	palmas_led_read(led->leds_data, PALMAS_LED_CTRL, &ctrl);
+	palmas_led_read(led->leds_data, PALMAS_LED_PERIOD_CTRL, &period);
+
+	spin_lock_irqsave(&led->value_lock, flags);
+
+	switch (led->led_no) {
+	case 1:
+		ctrl &= ~PALMAS_LED_CTRL_LED_1_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT;
+			}
+		}
+	case 2:
+		ctrl &= ~PALMAS_LED_CTRL_LED_2_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT;
+			}
+		}
+	case 3:
+		ctrl &= ~PALMAS_LED_CTRL2_LED_3_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT;
+			}
+		}
+		break;
+	case 4:
+		ctrl &= ~PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_MASK;
+		period &= ~PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_MASK;
+
+		if (led->blink) {
+			ctrl |= led->on_time <<
+				PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT;
+			period |= led->period <<
+				PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT;
+		} else {
+			/*
+			 * for off value is zero which we already set by
+			 * masking earlier.
+			 */
+			if (led->brightness) {
+				ctrl |= LED_ON_500MS <<
+					PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT;
+				period |= LED_PERIOD_500MS <<
+				PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT;
+			}
+		}
+		break;
+	}
+
+	spin_unlock_irqrestore(&led->value_lock, flags);
+
+	if (led->led_no < 3) {
+		palmas_led_write(led->leds_data, PALMAS_LED_CTRL, ctrl);
+		palmas_led_write(led->leds_data, PALMAS_LED_PERIOD_CTRL,
+				period);
+	} else {
+		palmas_led_write(led->leds_data, PALMAS_LED_CTRL2, ctrl);
+		palmas_led_write(led->leds_data, PALMAS_LED_PERIOD2_CTRL,
+				period);
+	}
+
+	if (is_palmas_charger(led->leds_data->palmas->product_id)) {
+		if (led->brightness || led->blink)
+			palmas_led_update_bits(led->leds_data, PALMAS_LED_EN,
+					1 << (led->led_no - 1), 0xFF);
+		else
+			palmas_led_update_bits(led->leds_data, PALMAS_LED_EN,
+					1 << (led->led_no - 1), 0x00);
+	}
+	mutex_unlock(&led->mutex);
+}
+
+static void palmas_leds_set(struct led_classdev *led_cdev,
+			   enum led_brightness value)
+{
+	struct palmas_led *led = to_palmas_led(led_cdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&led->value_lock, flags);
+	led->brightness = value;
+	led->blink = 0;
+	schedule_work(&led->work);
+	spin_unlock_irqrestore(&led->value_lock, flags);
+}
+
+static int palmas_leds_blink_set(struct led_classdev *led_cdev,
+				   unsigned long *delay_on,
+				   unsigned long *delay_off)
+{
+	struct palmas_led *led = to_palmas_led(led_cdev);
+	unsigned long flags;
+	int ret = 0;
+	int period;
+
+	/* Pick some defaults if we've not been given times */
+	if (*delay_on == 0 && *delay_off == 0) {
+		*delay_on = 250;
+		*delay_off = 250;
+	}
+
+	spin_lock_irqsave(&led->value_lock, flags);
+
+	/*
+	 * We only have a limited selection of settings, see if we can
+	 * support the configuration we're being given
+	 */
+	switch (*delay_on) {
+	case 500:
+		led->on_time = LED_ON_500MS;
+		break;
+	case 250:
+		led->on_time = LED_ON_250MS;
+		break;
+	case 125:
+		led->on_time = LED_ON_125MS;
+		break;
+	case 62:
+	case 63:
+		/* Actually 62.5ms */
+		led->on_time = LED_ON_62_5MS;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	period = *delay_on + *delay_off;
+
+	if (ret == 0) {
+		switch (period) {
+		case 124:
+		case 125:
+		case 126:
+			/* All possible variations of 62.5 + 62.5 */
+			led->period = LED_PERIOD_125MS;
+			break;
+		case 250:
+			led->period = LED_PERIOD_250MS;
+			break;
+		case 500:
+			led->period = LED_PERIOD_500MS;
+			break;
+		case 1000:
+			led->period = LED_PERIOD_1000MS;
+			break;
+		case 2000:
+			led->period = LED_PERIOD_2000MS;
+			break;
+		case 4000:
+			led->period = LED_PERIOD_4000MS;
+			break;
+		case 8000:
+			led->period = LED_PERIOD_8000MS;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	if (ret == 0)
+		led->blink = 1;
+	else
+		led->blink = 0;
+
+	/*
+	 * Always update; if we fail turn off blinking since we expect
+	 * a software fallback.
+	 */
+	schedule_work(&led->work);
+
+	spin_unlock_irqrestore(&led->value_lock, flags);
+
+	return ret;
+}
+
+static void palmas_init_led(struct palmas_leds_data *leds_data, int offset,
+		int led_no)
+{
+	mutex_init(&leds_data->palmas_led[offset].mutex);
+	INIT_WORK(&leds_data->palmas_led[offset].work, palmas_leds_work);
+	spin_lock_init(&leds_data->palmas_led[offset].value_lock);
+
+	leds_data->palmas_led[offset].leds_data = leds_data;
+	leds_data->palmas_led[offset].led_no = led_no;
+	leds_data->palmas_led[offset].cdev.name = palmas_led_names[led_no - 1];
+	leds_data->palmas_led[offset].cdev.default_trigger = NULL;
+	leds_data->palmas_led[offset].cdev.brightness_set = palmas_leds_set;
+	leds_data->palmas_led[offset].cdev.blink_set = palmas_leds_blink_set;
+}
+
+static int  palmas_dt_to_pdata(struct device *dev,
+		struct device_node *node,
+		struct palmas_leds_platform_data *pdata)
+{
+	struct device_node *child_node;
+	int ret;
+	u32 prop;
+
+	child_node = of_get_child_by_name(node, "leds");
+	if (!child_node) {
+		dev_err(dev, "child node 'palmas_leds' not found\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(child_node, "ti,led1-current", &prop);
+	if (!ret)
+		pdata->led1_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led2-current", &prop);
+	if (!ret)
+		pdata->led2_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led3-current", &prop);
+	if (!ret)
+		pdata->led3_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,led4-current", &prop);
+	if (!ret)
+		pdata->led4_current = prop;
+
+	ret = of_property_read_u32(child_node, "ti,chrg-led-mode", &prop);
+	if (!ret)
+		pdata->chrg_led_mode = prop;
+
+	ret = of_property_read_u32(child_node, "ti,chrg-led-vbat-low", &prop);
+	if (!ret)
+		pdata->chrg_led_vbat_low = prop;
+
+	return 0;
+}
+
+static int palmas_leds_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct palmas_leds_data *leds_data;
+	struct device_node *node = pdev->dev.of_node;
+	int ret, i;
+	int offset = 0;
+
+	if (!palmas->led_muxed && !is_palmas_charger(palmas->product_id)) {
+		dev_err(&pdev->dev, "there are no LEDs muxed\n");
+		return -EINVAL;
+	}
+
+	/* Palmas charger requires platform data */
+	if (is_palmas_charger(palmas->product_id) && node && !pdata) {
+
+		if (!pdata)
+			return -ENOMEM;
+
+		ret = palmas_dt_to_pdata(&pdev->dev, node, pdata);
+		if (ret)
+			return ret;
+	}
+
+	if (is_palmas_charger(palmas->product_id) && !pdata)
+		return -EINVAL;
+
+	leds_data = devm_kzalloc(&pdev->dev, sizeof(*leds_data), GFP_KERNEL);
+	if (!leds_data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, leds_data);
+
+	leds_data->palmas = palmas;
+
+	switch (palmas->led_muxed) {
+	case PALMAS_LED1_MUXED | PALMAS_LED2_MUXED:
+		leds_data->no_leds = 2;
+		break;
+	case PALMAS_LED1_MUXED:
+	case PALMAS_LED2_MUXED:
+		leds_data->no_leds = 1;
+		break;
+	default:
+		leds_data->no_leds = 0;
+		break;
+	}
+
+	if (is_palmas_charger(palmas->product_id)) {
+		if (pdata->chrg_led_mode)
+			leds_data->no_leds += 2;
+		else
+			leds_data->no_leds++;
+	}
+
+	if (leds_data->no_leds == 0)
+		leds_data->palmas_led = NULL;
+	else
+		leds_data = devm_kzalloc(&pdev->dev,
+				leds_data->no_leds * sizeof(*leds_data),
+				GFP_KERNEL);
+
+	/* Initialise LED1 */
+	if (palmas->led_muxed & PALMAS_LED1_MUXED) {
+		palmas_init_led(leds_data, offset, 1);
+		offset++;
+	}
+
+	/* Initialise LED2 */
+	if (palmas->led_muxed & PALMAS_LED2_MUXED) {
+		palmas_init_led(leds_data, offset, 2);
+		offset++;
+	}
+
+	if (is_palmas_charger(palmas->product_id)) {
+		palmas_init_led(leds_data, offset, 3);
+		offset++;
+
+		if (pdata->chrg_led_mode) {
+			palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE,
+					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE);
+
+			palmas_init_led(leds_data, offset, 4);
+		}
+	}
+
+	for (i = 0; i < leds_data->no_leds; i++) {
+		ret = led_classdev_register(leds_data->dev,
+				&leds_data->palmas_led[i].cdev);
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"Failed to register LED no: %d err: %d\n",
+				i, ret);
+			goto err_led;
+		}
+	}
+
+	if (!is_palmas_charger(palmas->product_id))
+		return 0;
+
+	/* Set the LED current registers if set in platform data */
+	if (pdata->led1_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
+				PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK,
+				pdata->led1_current);
+
+	if (pdata->led2_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
+				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK,
+				pdata->led2_current <<
+				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT);
+
+	if (pdata->led3_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
+				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
+				pdata->led3_current);
+
+	if (pdata->led3_current)
+		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
+				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
+				pdata->led3_current);
+
+	if (pdata->led4_current)
+		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK,
+				pdata->led4_current <<
+				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT);
+
+	if (pdata->chrg_led_vbat_low)
+		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
+				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS,
+				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS);
+
+	return 0;
+
+err_led:
+	for (i = 0; i < leds_data->no_leds; i++)
+		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
+	kfree(leds_data->palmas_led);
+	kfree(leds_data);
+	return ret;
+}
+
+static int palmas_leds_remove(struct platform_device *pdev)
+{
+	struct palmas_leds_data *leds_data = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < leds_data->no_leds; i++)
+		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
+	if (i)
+		kfree(leds_data->palmas_led);
+	kfree(leds_data);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-leds", },
+	{ .compatible = "ti,palmas-charger-leds", },
+	{ .compatible = "ti,twl6035-leds", },
+	{ .compatible = "ti,twl6036-leds", },
+	{ .compatible = "ti,twl6037-leds", },
+	{ .compatible = "ti,tps65913-leds", },
+	{ .compatible = "ti,tps65914-leds", },
+	{ .compatible = "ti,tps80036-leds", },
+	{ /* end */ }
+};
+
+static struct platform_driver palmas_leds_driver = {
+	.driver = {
+		.name = "palmas-leds",
+		.of_match_table = of_palmas_match_tbl,
+		.owner = THIS_MODULE,
+	},
+	.probe = palmas_leds_probe,
+	.remove = palmas_leds_remove,
+};
+
+module_platform_driver(palmas_leds_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("Palmas LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-leds");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 5661f2d..7399c71 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -232,6 +232,16 @@ struct palmas_clk_platform_data {
 	int clk32kgaudio_mode_sleep;
 };
 
+struct palmas_leds_platform_data {
+	int led1_current;
+	int led2_current;
+	int led3_current;
+	int led4_current;
+
+	int chrg_led_mode;
+	int chrg_led_vbat_low;
+};
+
 struct palmas_platform_data {
 	int gpio_base;
 
@@ -1855,6 +1865,12 @@ enum usb_irq_events {
 #define PALMAS_LED_CTRL						0x1
 #define PALMAS_PWM_CTRL1					0x2
 #define PALMAS_PWM_CTRL2					0x3
+#define PALMAS_LED_PERIOD2_CTRL					0x4
+#define PALMAS_LED_CTRL2					0x5
+#define PALMAS_LED_CURRENT_CTRL1				0x6
+#define PALMAS_LED_CURRENT_CTRL2				0x7
+#define PALMAS_CHRG_LED_CTRL					0x8
+#define PALMAS_LED_EN						0x9
 
 /* Bit definitions for LED_PERIOD_CTRL */
 #define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK		0x38
@@ -1882,6 +1898,50 @@ enum usb_irq_events {
 #define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_MASK			0xff
 #define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_SHIFT			0
 
+/* Bit definitions for LED_PERIOD2_CTRL */
+#define PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_MASK		0x38
+#define PALMAS_LED_PERIOD2_CTRL_CHRG_LED_PERIOD_SHIFT		3
+#define PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_MASK		0x07
+#define PALMAS_LED_PERIOD2_CTRL_LED_3_PERIOD_SHIFT		0
+
+/* Bit definitions for LED_CTRL2 */
+#define PALMAS_LED_CTRL2_CHRG_LED_SEQ				0x20
+#define PALMAS_LED_CTRL2_CHRG_LED_SEQ_SHIFT			5
+#define PALMAS_LED_CTRL2_LED_3_SEQ				0x10
+#define PALMAS_LED_CTRL2_LED_3_SEQ_SHIFT			4
+#define PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_MASK			0x0c
+#define PALMAS_LED_CTRL2_CHRG_LED_ON_TIME_SHIFT			2
+#define PALMAS_LED_CTRL2_LED_3_ON_TIME_MASK			0x03
+#define PALMAS_LED_CTRL2_LED_3_ON_TIME_SHIFT			0
+
+/* Bit definitions for LED_CURRENT_CTRL1 */
+#define PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK		0x38
+#define PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT		3
+#define PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK		0x07
+#define PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_SHIFT		0
+
+/* Bit definitions for LED_CURRENT_CTRL2 */
+#define PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK		0x07
+#define PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_SHIFT		0
+
+/* Bit definitions for CHRG_LED_CTRL */
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK		0x38
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT		3
+#define PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS		0x02
+#define PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS_SHIFT		1
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE			0x01
+#define PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE_SHIFT		0
+
+/* Bit definitions for LED_EN */
+#define PALMAS_LED_EN_CHRG_LED_EN				0x08
+#define PALMAS_LED_EN_CHRG_LED_EN_SHIFT				3
+#define PALMAS_LED_EN_LED_3_EN					0x04
+#define PALMAS_LED_EN_LED_3_EN_SHIFT				2
+#define PALMAS_LED_EN_LED_2_EN					0x02
+#define PALMAS_LED_EN_LED_2_EN_SHIFT				1
+#define PALMAS_LED_EN_LED_1_EN					0x01
+#define PALMAS_LED_EN_LED_1_EN_SHIFT				0
+
 /* Registers for function INTERRUPT */
 #define PALMAS_INT1_STATUS					0x0
 #define PALMAS_INT1_MASK					0x1
-- 
1.7.0.4

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

* [PATCH v8 10/12] clk: Kconfig for Palmas clock driver
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/clk/Kconfig        |    8 ++++++++
 drivers/clk/Makefile       |    1 +
 drivers/leds/leds-palmas.c |   19 ++++++-------------
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a47e6ee..a8e0655 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -63,6 +63,14 @@ config CLK_TWL6040
 	  McPDM. McPDM module is using the external bit clock on the McPDM bus
 	  as functional clock.
 
+config CLK_PALMAS
+	tristate "Palmas PMIC Clock Support"
+	depends on MFD_PALMAS
+	---help---
+	  Enable clock support for the two clocks on Palmas PMIC chips:
+	  - A 32KHz audio-gated clock (primarily for audio devices)
+	  - A digitally-gated 32KHz clock
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 300d477..77dc283 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_X86)		+= x86/
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
+obj-$(CONFIG_CLK_PALMAS)	+= clk-palmas.o
diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c
index 4a35352..ea53bfe 100644
--- a/drivers/leds/leds-palmas.c
+++ b/drivers/leds/leds-palmas.c
@@ -341,37 +341,30 @@ static int  palmas_dt_to_pdata(struct device *dev,
 		struct device_node *node,
 		struct palmas_leds_platform_data *pdata)
 {
-	struct device_node *child_node;
 	int ret;
 	u32 prop;
 
-	child_node = of_get_child_by_name(node, "leds");
-	if (!child_node) {
-		dev_err(dev, "child node 'palmas_leds' not found\n");
-		return -EINVAL;
-	}
-
-	ret = of_property_read_u32(child_node, "ti,led1-current", &prop);
+	ret = of_property_read_u32(node, "ti,led1-current", &prop);
 	if (!ret)
 		pdata->led1_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led2-current", &prop);
+	ret = of_property_read_u32(node, "ti,led2-current", &prop);
 	if (!ret)
 		pdata->led2_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led3-current", &prop);
+	ret = of_property_read_u32(node, "ti,led3-current", &prop);
 	if (!ret)
 		pdata->led3_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led4-current", &prop);
+	ret = of_property_read_u32(node, "ti,led4-current", &prop);
 	if (!ret)
 		pdata->led4_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,chrg-led-mode", &prop);
+	ret = of_property_read_u32(node, "ti,chrg-led-mode", &prop);
 	if (!ret)
 		pdata->chrg_led_mode = prop;
 
-	ret = of_property_read_u32(child_node, "ti,chrg-led-vbat-low", &prop);
+	ret = of_property_read_u32(node, "ti,chrg-led-vbat-low", &prop);
 	if (!ret)
 		pdata->chrg_led_vbat_low = prop;
 
-- 
1.7.0.4


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

* [PATCH v8 10/12] clk: Kconfig for Palmas clock driver
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/clk/Kconfig        |    8 ++++++++
 drivers/clk/Makefile       |    1 +
 drivers/leds/leds-palmas.c |   19 ++++++-------------
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a47e6ee..a8e0655 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -63,6 +63,14 @@ config CLK_TWL6040
 	  McPDM. McPDM module is using the external bit clock on the McPDM bus
 	  as functional clock.
 
+config CLK_PALMAS
+	tristate "Palmas PMIC Clock Support"
+	depends on MFD_PALMAS
+	---help---
+	  Enable clock support for the two clocks on Palmas PMIC chips:
+	  - A 32KHz audio-gated clock (primarily for audio devices)
+	  - A digitally-gated 32KHz clock
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 300d477..77dc283 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_X86)		+= x86/
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
+obj-$(CONFIG_CLK_PALMAS)	+= clk-palmas.o
diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c
index 4a35352..ea53bfe 100644
--- a/drivers/leds/leds-palmas.c
+++ b/drivers/leds/leds-palmas.c
@@ -341,37 +341,30 @@ static int  palmas_dt_to_pdata(struct device *dev,
 		struct device_node *node,
 		struct palmas_leds_platform_data *pdata)
 {
-	struct device_node *child_node;
 	int ret;
 	u32 prop;
 
-	child_node = of_get_child_by_name(node, "leds");
-	if (!child_node) {
-		dev_err(dev, "child node 'palmas_leds' not found\n");
-		return -EINVAL;
-	}
-
-	ret = of_property_read_u32(child_node, "ti,led1-current", &prop);
+	ret = of_property_read_u32(node, "ti,led1-current", &prop);
 	if (!ret)
 		pdata->led1_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led2-current", &prop);
+	ret = of_property_read_u32(node, "ti,led2-current", &prop);
 	if (!ret)
 		pdata->led2_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led3-current", &prop);
+	ret = of_property_read_u32(node, "ti,led3-current", &prop);
 	if (!ret)
 		pdata->led3_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,led4-current", &prop);
+	ret = of_property_read_u32(node, "ti,led4-current", &prop);
 	if (!ret)
 		pdata->led4_current = prop;
 
-	ret = of_property_read_u32(child_node, "ti,chrg-led-mode", &prop);
+	ret = of_property_read_u32(node, "ti,chrg-led-mode", &prop);
 	if (!ret)
 		pdata->chrg_led_mode = prop;
 
-	ret = of_property_read_u32(child_node, "ti,chrg-led-vbat-low", &prop);
+	ret = of_property_read_u32(node, "ti,chrg-led-vbat-low", &prop);
 	if (!ret)
 		pdata->chrg_led_vbat_low = prop;
 
-- 
1.7.0.4

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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

Add the Kconfig and Makefile for the Palmas LED driver.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/leds/Kconfig  |    9 +++++++++
 drivers/leds/Makefile |    1 +
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ec50824..a070e29 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -469,6 +469,15 @@ config LEDS_BLINKM
 	  This option enables support for the BlinkM RGB LED connected
 	  through I2C. Say Y to enable support for the BlinkM LED.
 
+config LEDS_PALMAS
+	bool "LED support for the Palmas family of PMICs"
+	depends on LEDS_CLASS
+	depends on MFD_PALMAS
+	help
+	  This option enables the driver for LED1 & LED2 pins on Palmas PMIC
+	  if these pins are enabled in the mux configuration. The driver support
+	  ON/OFF and blinking with hardware control.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 215e7e3..233023e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
+obj-$(CONFIG_LEDS_PALMAS)		+= leds-palmas.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
-- 
1.7.0.4


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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Add the Kconfig and Makefile for the Palmas LED driver.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/leds/Kconfig  |    9 +++++++++
 drivers/leds/Makefile |    1 +
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ec50824..a070e29 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -469,6 +469,15 @@ config LEDS_BLINKM
 	  This option enables support for the BlinkM RGB LED connected
 	  through I2C. Say Y to enable support for the BlinkM LED.
 
+config LEDS_PALMAS
+	bool "LED support for the Palmas family of PMICs"
+	depends on LEDS_CLASS
+	depends on MFD_PALMAS
+	help
+	  This option enables the driver for LED1 & LED2 pins on Palmas PMIC
+	  if these pins are enabled in the mux configuration. The driver support
+	  ON/OFF and blinking with hardware control.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 215e7e3..233023e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
+obj-$(CONFIG_LEDS_PALMAS)		+= leds-palmas.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
-- 
1.7.0.4

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

* [PATCH v8 12/12] clk: add a clock driver for palmas
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:17   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, mturquette,
	linus.walleij, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, Ian Lartey

Palmas has two clock generators in it, clk32kg and clk32kg audio. They
are fixed frequency clocks that only have enable/disable functionality.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/clk/clk-palmas.c |  268 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-palmas.c

diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
new file mode 100644
index 0000000..328eea4
--- /dev/null
+++ b/drivers/clk/clk-palmas.c
@@ -0,0 +1,268 @@
+/*
+ * PALMAS resource clock module driver
+ *
+ * Copyright (C) 2011-2013 Texas Instruments Inc.
+ * Graeme Gregory <gg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/palmas.h>
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+
+struct palmas_clk {
+	struct palmas *palmas;
+	struct device *dev;
+	struct clk_hw clk32kg;
+	struct clk_hw clk32kgaudio;
+	int clk32kgaudio_mode_sleep;
+	int clk32kg_mode_sleep;
+};
+
+static int palmas_clock_setbits(struct palmas *palmas, unsigned int reg,
+		unsigned int data)
+{
+	return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+			reg, data, data);
+}
+
+static int palmas_clock_clrbits(struct palmas *palmas, unsigned int reg,
+		unsigned int data)
+{
+	return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+			reg, data, 0);
+}
+
+static int palmas_prepare_clk32kg(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kg);
+	int ret;
+
+	ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
+
+	return ret;
+}
+
+static void palmas_unprepare_clk32kg(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kg);
+	int ret;
+
+	ret = palmas_clock_clrbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
+
+	return;
+}
+
+static const struct clk_ops palmas_clk32kg_ops = {
+	.prepare = palmas_prepare_clk32kg,
+	.unprepare = palmas_unprepare_clk32kg,
+};
+
+static int palmas_prepare_clk32kgaudio(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kgaudio);
+	int ret;
+
+	ret = palmas_clock_setbits(palmas_clk->palmas,
+		PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev,
+				"Failed to enable clk32kgaudio: %d\n", ret);
+
+	return ret;
+}
+
+static void palmas_unprepare_clk32kgaudio(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kgaudio);
+	int ret;
+
+	ret = palmas_clock_clrbits(palmas_clk->palmas,
+		PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev,
+				"Failed to enable clk32kgaudio: %d\n", ret);
+
+	return;
+}
+
+static const struct clk_ops palmas_clk32kgaudio_ops = {
+	.prepare = palmas_prepare_clk32kgaudio,
+	.unprepare = palmas_unprepare_clk32kgaudio,
+};
+
+static int palmas_initialise_clk(struct palmas_clk *palmas_clk)
+{
+	int ret;
+
+	if (palmas_clk->clk32kg_mode_sleep) {
+		ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_SLEEP);
+		if (ret)
+			return ret;
+	}
+
+	if (palmas_clk->clk32kgaudio_mode_sleep) {
+		ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KGAUDIO_CTRL,
+			PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void palmas_dt_to_pdata(struct device_node *node,
+		struct palmas_clk_platform_data *pdata)
+{
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "ti,clk32kg-mode-sleep", &prop);
+	if (!ret)
+		pdata->clk32kg_mode_sleep = prop;
+
+	ret = of_property_read_u32(node, "ti,clk32kgaudio-mode-sleep", &prop);
+	if (!ret)
+		pdata->clk32kgaudio_mode_sleep = prop;
+}
+
+static int palmas_clk_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_clk_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
+	struct palmas_clk *palmas_clk;
+	struct clk *clk;
+	struct clk_init_data init_clk32g, init_clk32gaudio;
+	int ret;
+
+	if (node && !pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+
+		if (!pdata)
+			return -ENOMEM;
+
+		palmas_dt_to_pdata(node, pdata);
+	}
+
+	palmas_clk = devm_kzalloc(&pdev->dev, sizeof(*palmas_clk), GFP_KERNEL);
+	if (!palmas_clk)
+		return -ENOMEM;
+
+	palmas_clk->palmas = palmas;
+	palmas_clk->dev = &pdev->dev;
+
+	init_clk32g.name = "clk32kg";
+	init_clk32g.ops = &palmas_clk32kg_ops;
+	init_clk32g.parent_names = NULL;
+	init_clk32g.num_parents = 0;
+	palmas_clk->clk32kg.init = &init_clk32g;
+
+	clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kg);
+	if (IS_ERR(clk)) {
+		dev_dbg(&pdev->dev, "clk32kg clock register failed %ld\n",
+				PTR_ERR(clk));
+		ret = PTR_ERR(clk);
+		goto err_clk32kg;
+	}
+
+	init_clk32gaudio.name = "clk32kgaudio";
+	init_clk32gaudio.ops = &palmas_clk32kgaudio_ops;
+	init_clk32gaudio.parent_names = NULL;
+	init_clk32gaudio.num_parents = 0;
+	palmas_clk->clk32kgaudio.init = &init_clk32gaudio;
+
+	clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kgaudio);
+	if (IS_ERR(clk)) {
+		dev_dbg(&pdev->dev, "clk32kgaudio clock register failed %ld\n",
+		PTR_ERR(clk));
+		ret = PTR_ERR(clk);
+		goto err_audio;
+	}
+
+	ret = palmas_initialise_clk(palmas_clk);
+	if (ret)
+		goto err;
+
+	dev_set_drvdata(&pdev->dev, palmas_clk);
+
+	return 0;
+
+err:
+	clk_unregister(palmas_clk->clk32kgaudio.clk);
+err_audio:
+	clk_unregister(palmas_clk->clk32kg.clk);
+err_clk32kg:
+
+	return ret;
+}
+
+static int palmas_clk_remove(struct platform_device *pdev)
+{
+	struct palmas_clk *palmas_clk = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(palmas_clk->clk32kgaudio.clk);
+	clk_unregister(palmas_clk->clk32kg.clk);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-clk", },
+	{ .compatible = "ti,palmas-charger-clk", },
+	{ .compatible = "ti,twl6035-clk", },
+	{ .compatible = "ti,twl6036-clk", },
+	{ .compatible = "ti,twl6037-clk", },
+	{ .compatible = "ti,tps65913-clk", },
+	{ .compatible = "ti,tps65914-clk", },
+	{ .compatible = "ti,tps80036-clk", },
+	{ /* end */ }
+};
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
+
+static struct platform_driver palmas_clk_driver = {
+	.probe = palmas_clk_probe,
+	.remove = palmas_clk_remove,
+	.driver = {
+		.name = "palmas-clk",
+		.of_match_table = of_palmas_match_tbl,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmas_clk_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("PALMAS clock driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-clk");
-- 
1.7.0.4


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

* [PATCH v8 12/12] clk: add a clock driver for palmas
@ 2013-03-07 13:17   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Palmas has two clock generators in it, clk32kg and clk32kg audio. They
are fixed frequency clocks that only have enable/disable functionality.

Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
Signed-off-by: J Keerthy <j-keerthy@ti.com>
Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>
---
 drivers/clk/clk-palmas.c |  268 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-palmas.c

diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
new file mode 100644
index 0000000..328eea4
--- /dev/null
+++ b/drivers/clk/clk-palmas.c
@@ -0,0 +1,268 @@
+/*
+ * PALMAS resource clock module driver
+ *
+ * Copyright (C) 2011-2013 Texas Instruments Inc.
+ * Graeme Gregory <gg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/palmas.h>
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+
+struct palmas_clk {
+	struct palmas *palmas;
+	struct device *dev;
+	struct clk_hw clk32kg;
+	struct clk_hw clk32kgaudio;
+	int clk32kgaudio_mode_sleep;
+	int clk32kg_mode_sleep;
+};
+
+static int palmas_clock_setbits(struct palmas *palmas, unsigned int reg,
+		unsigned int data)
+{
+	return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+			reg, data, data);
+}
+
+static int palmas_clock_clrbits(struct palmas *palmas, unsigned int reg,
+		unsigned int data)
+{
+	return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+			reg, data, 0);
+}
+
+static int palmas_prepare_clk32kg(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kg);
+	int ret;
+
+	ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
+
+	return ret;
+}
+
+static void palmas_unprepare_clk32kg(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kg);
+	int ret;
+
+	ret = palmas_clock_clrbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
+
+	return;
+}
+
+static const struct clk_ops palmas_clk32kg_ops = {
+	.prepare = palmas_prepare_clk32kg,
+	.unprepare = palmas_unprepare_clk32kg,
+};
+
+static int palmas_prepare_clk32kgaudio(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kgaudio);
+	int ret;
+
+	ret = palmas_clock_setbits(palmas_clk->palmas,
+		PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev,
+				"Failed to enable clk32kgaudio: %d\n", ret);
+
+	return ret;
+}
+
+static void palmas_unprepare_clk32kgaudio(struct clk_hw *hw)
+{
+	struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
+			clk32kgaudio);
+	int ret;
+
+	ret = palmas_clock_clrbits(palmas_clk->palmas,
+		PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
+	if (ret)
+		dev_err(palmas_clk->dev,
+				"Failed to enable clk32kgaudio: %d\n", ret);
+
+	return;
+}
+
+static const struct clk_ops palmas_clk32kgaudio_ops = {
+	.prepare = palmas_prepare_clk32kgaudio,
+	.unprepare = palmas_unprepare_clk32kgaudio,
+};
+
+static int palmas_initialise_clk(struct palmas_clk *palmas_clk)
+{
+	int ret;
+
+	if (palmas_clk->clk32kg_mode_sleep) {
+		ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_SLEEP);
+		if (ret)
+			return ret;
+	}
+
+	if (palmas_clk->clk32kgaudio_mode_sleep) {
+		ret = palmas_clock_setbits(palmas_clk->palmas,
+			PALMAS_CLK32KGAUDIO_CTRL,
+			PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void palmas_dt_to_pdata(struct device_node *node,
+		struct palmas_clk_platform_data *pdata)
+{
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "ti,clk32kg-mode-sleep", &prop);
+	if (!ret)
+		pdata->clk32kg_mode_sleep = prop;
+
+	ret = of_property_read_u32(node, "ti,clk32kgaudio-mode-sleep", &prop);
+	if (!ret)
+		pdata->clk32kgaudio_mode_sleep = prop;
+}
+
+static int palmas_clk_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_clk_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
+	struct palmas_clk *palmas_clk;
+	struct clk *clk;
+	struct clk_init_data init_clk32g, init_clk32gaudio;
+	int ret;
+
+	if (node && !pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+
+		if (!pdata)
+			return -ENOMEM;
+
+		palmas_dt_to_pdata(node, pdata);
+	}
+
+	palmas_clk = devm_kzalloc(&pdev->dev, sizeof(*palmas_clk), GFP_KERNEL);
+	if (!palmas_clk)
+		return -ENOMEM;
+
+	palmas_clk->palmas = palmas;
+	palmas_clk->dev = &pdev->dev;
+
+	init_clk32g.name = "clk32kg";
+	init_clk32g.ops = &palmas_clk32kg_ops;
+	init_clk32g.parent_names = NULL;
+	init_clk32g.num_parents = 0;
+	palmas_clk->clk32kg.init = &init_clk32g;
+
+	clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kg);
+	if (IS_ERR(clk)) {
+		dev_dbg(&pdev->dev, "clk32kg clock register failed %ld\n",
+				PTR_ERR(clk));
+		ret = PTR_ERR(clk);
+		goto err_clk32kg;
+	}
+
+	init_clk32gaudio.name = "clk32kgaudio";
+	init_clk32gaudio.ops = &palmas_clk32kgaudio_ops;
+	init_clk32gaudio.parent_names = NULL;
+	init_clk32gaudio.num_parents = 0;
+	palmas_clk->clk32kgaudio.init = &init_clk32gaudio;
+
+	clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kgaudio);
+	if (IS_ERR(clk)) {
+		dev_dbg(&pdev->dev, "clk32kgaudio clock register failed %ld\n",
+		PTR_ERR(clk));
+		ret = PTR_ERR(clk);
+		goto err_audio;
+	}
+
+	ret = palmas_initialise_clk(palmas_clk);
+	if (ret)
+		goto err;
+
+	dev_set_drvdata(&pdev->dev, palmas_clk);
+
+	return 0;
+
+err:
+	clk_unregister(palmas_clk->clk32kgaudio.clk);
+err_audio:
+	clk_unregister(palmas_clk->clk32kg.clk);
+err_clk32kg:
+
+	return ret;
+}
+
+static int palmas_clk_remove(struct platform_device *pdev)
+{
+	struct palmas_clk *palmas_clk = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(palmas_clk->clk32kgaudio.clk);
+	clk_unregister(palmas_clk->clk32kg.clk);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-clk", },
+	{ .compatible = "ti,palmas-charger-clk", },
+	{ .compatible = "ti,twl6035-clk", },
+	{ .compatible = "ti,twl6036-clk", },
+	{ .compatible = "ti,twl6037-clk", },
+	{ .compatible = "ti,tps65913-clk", },
+	{ .compatible = "ti,tps65914-clk", },
+	{ .compatible = "ti,tps80036-clk", },
+	{ /* end */ }
+};
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
+
+static struct platform_driver palmas_clk_driver = {
+	.probe = palmas_clk_probe,
+	.remove = palmas_clk_remove,
+	.driver = {
+		.name = "palmas-clk",
+		.of_match_table = of_palmas_match_tbl,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmas_clk_driver);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("PALMAS clock driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palmas-clk");
-- 
1.7.0.4

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

* [PATCH v8 0/12] Palmas Updates
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-07 13:23   ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:23 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, broonie, rob.herring, rob,
	mturquette, linus.walleij, cooloney, rpurdie, sameo, wim,
	lgirdwood, gg, j-keerthy, ldewangan, t-kristo

This patchset adds to the support for the Palmas iseries of PMIC chips.

Some of the patches have previously been submitted individually.
The DT bindings doc has been added first due to comments that it was 
missing.

Patches based on linux-next-20130306

mfd: DT bindings for the palmas family MFD
mfd: palmas: is_palmas_charger needed by multiple driv
mfd: palmas add variant and OTP detection
regulator: palmas correct dt parsing
watchdog: add Palmas Watchdog support
watchdog: Kconfig for Palmas watchdog
gpio: palmas: add in GPIO support for palmas charger
gpio: palmas: Enable DT support for palmas gpio
leds: Add support for Palmas LEDs
leds: Kconfig for Palmas LEDs
clk: add a clock driver for palmas
clk: Kconfig for Palmas clock driver

  .../devicetree/bindings/clock/palmas-clk.txt       |   25 +
  .../devicetree/bindings/gpio/gpio-palmas.txt       |   21 +
  .../devicetree/bindings/input/palmas-pwrbutton.txt |   22 +
  .../devicetree/bindings/leds/leds-palmas.txt       |   35 ++
  Documentation/devicetree/bindings/mfd/palmas.txt   |   70 +++
  .../devicetree/bindings/regulator/palmas-pmic.txt  |  168 ++++++
  .../devicetree/bindings/rtc/palmas-rtc.txt         |   22 +
  .../devicetree/bindings/watchdog/palmas-wdt.txt    |   22 +
  drivers/clk/Kconfig                                |    8 +
  drivers/clk/Makefile                               |    1 +
  drivers/clk/clk-palmas.c                           |  268 ++++++++++
  drivers/gpio/gpio-palmas.c                         |   90 +++-
  drivers/leds/Kconfig                               |    9 +
  drivers/leds/Makefile                              |    1 +
  drivers/leds/leds-palmas.c                         |  560 
++++++++++++++++++++
  drivers/mfd/palmas.c                               |  103 +++-
  drivers/regulator/palmas-regulator.c               |   36 +-
  drivers/watchdog/Kconfig                           |    8 +
  drivers/watchdog/Makefile                          |    1 +
  drivers/watchdog/palmas_wdt.c                      |  170 ++++++
  include/linux/mfd/palmas.h                         |  119 ++++-
  21 files changed, 1703 insertions(+), 56 deletions(-)
  create mode 100644 Documentation/devicetree/bindings/clock/palmas-clk.txt
  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-palmas.txt
  create mode 100644 
Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
  create mode 100644 Documentation/devicetree/bindings/leds/leds-palmas.txt
  create mode 100644 Documentation/devicetree/bindings/mfd/palmas.txt
  create mode 100644 
Documentation/devicetree/bindings/regulator/palmas-pmic.txt
  create mode 100644 Documentation/devicetree/bindings/rtc/palmas-rtc.txt
  create mode 100644 
Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
  create mode 100644 drivers/clk/clk-palmas.c
  create mode 100644 drivers/leds/leds-palmas.c
  create mode 100644 drivers/watchdog/palmas_wdt.c

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

* [PATCH v8 0/12] Palmas Updates
@ 2013-03-07 13:23   ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-07 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds to the support for the Palmas iseries of PMIC chips.

Some of the patches have previously been submitted individually.
The DT bindings doc has been added first due to comments that it was 
missing.

Patches based on linux-next-20130306

mfd: DT bindings for the palmas family MFD
mfd: palmas: is_palmas_charger needed by multiple driv
mfd: palmas add variant and OTP detection
regulator: palmas correct dt parsing
watchdog: add Palmas Watchdog support
watchdog: Kconfig for Palmas watchdog
gpio: palmas: add in GPIO support for palmas charger
gpio: palmas: Enable DT support for palmas gpio
leds: Add support for Palmas LEDs
leds: Kconfig for Palmas LEDs
clk: add a clock driver for palmas
clk: Kconfig for Palmas clock driver

  .../devicetree/bindings/clock/palmas-clk.txt       |   25 +
  .../devicetree/bindings/gpio/gpio-palmas.txt       |   21 +
  .../devicetree/bindings/input/palmas-pwrbutton.txt |   22 +
  .../devicetree/bindings/leds/leds-palmas.txt       |   35 ++
  Documentation/devicetree/bindings/mfd/palmas.txt   |   70 +++
  .../devicetree/bindings/regulator/palmas-pmic.txt  |  168 ++++++
  .../devicetree/bindings/rtc/palmas-rtc.txt         |   22 +
  .../devicetree/bindings/watchdog/palmas-wdt.txt    |   22 +
  drivers/clk/Kconfig                                |    8 +
  drivers/clk/Makefile                               |    1 +
  drivers/clk/clk-palmas.c                           |  268 ++++++++++
  drivers/gpio/gpio-palmas.c                         |   90 +++-
  drivers/leds/Kconfig                               |    9 +
  drivers/leds/Makefile                              |    1 +
  drivers/leds/leds-palmas.c                         |  560 
++++++++++++++++++++
  drivers/mfd/palmas.c                               |  103 +++-
  drivers/regulator/palmas-regulator.c               |   36 +-
  drivers/watchdog/Kconfig                           |    8 +
  drivers/watchdog/Makefile                          |    1 +
  drivers/watchdog/palmas_wdt.c                      |  170 ++++++
  include/linux/mfd/palmas.h                         |  119 ++++-
  21 files changed, 1703 insertions(+), 56 deletions(-)
  create mode 100644 Documentation/devicetree/bindings/clock/palmas-clk.txt
  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-palmas.txt
  create mode 100644 
Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
  create mode 100644 Documentation/devicetree/bindings/leds/leds-palmas.txt
  create mode 100644 Documentation/devicetree/bindings/mfd/palmas.txt
  create mode 100644 
Documentation/devicetree/bindings/regulator/palmas-pmic.txt
  create mode 100644 Documentation/devicetree/bindings/rtc/palmas-rtc.txt
  create mode 100644 
Documentation/devicetree/bindings/watchdog/palmas-wdt.txt
  create mode 100644 drivers/clk/clk-palmas.c
  create mode 100644 drivers/leds/leds-palmas.c
  create mode 100644 drivers/watchdog/palmas_wdt.c

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

* [PATCH v8 10/12] clk: Kconfig for Palmas clock driver
  2013-03-07 13:17   ` Ian Lartey
  (?)
@ 2013-03-08  1:13   ` Kim, Milo
  2013-03-08 17:14     ` Ian Lartey
  -1 siblings, 1 reply; 51+ messages in thread
From: Kim, Milo @ 2013-03-08  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

>  drivers/clk/Kconfig        |    8 ++++++++
>  drivers/clk/Makefile       |    1 +
>  drivers/leds/leds-palmas.c |   19 ++++++-------------

If this patch is for only clock module, then LED patch should be detached.

[PATCH v8 10/12] clk: Kconfig for Palmas clock driver
[PATCH v8 12/12] clk: add a clock driver for palmas
It could be joined into one patch file.

Best Regards,
Milo

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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
  2013-03-07 13:17   ` Ian Lartey
  (?)
@ 2013-03-08  1:13   ` Kim, Milo
  2013-03-08 17:13     ` Ian Lartey
  -1 siblings, 1 reply; 51+ messages in thread
From: Kim, Milo @ 2013-03-08  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

> Add the Kconfig and Makefile for the Palmas LED driver.

It would be better if the Palmas LED driver files are combined into one patch.
[PATCH v8 09/12] leds: Add support for Palmas LEDs
[PATCH v8 11/12] leds: Kconfig for Palmas LEDs

Best Regards,
Milo 

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

* [PATCH v8 09/12] leds: Add support for Palmas LEDs
  2013-03-07 13:17   ` Ian Lartey
  (?)
@ 2013-03-08  1:13   ` Kim, Milo
  2013-03-11 15:16     ` Ian Lartey
  -1 siblings, 1 reply; 51+ messages in thread
From: Kim, Milo @ 2013-03-08  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

> The Palmas familly of chips has LED support. This is not always muxed
> to output pins so depending on the setting of the mux this driver
> will create the appropriate LED class devices.

It looks good and I've added few comments.

> diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c

> +static int palmas_leds_blink_set(struct led_classdev *led_cdev,
> +				   unsigned long *delay_on,
> +				   unsigned long *delay_off)
> +{
> +	struct palmas_led *led = to_palmas_led(led_cdev);
> +	unsigned long flags;
> +	int ret = 0;
> +	int period;
> +
> +	/* Pick some defaults if we've not been given times */
> +	if (*delay_on == 0 && *delay_off == 0) {
> +		*delay_on = 250;
> +		*delay_off = 250;
> +	}
> +
> +	spin_lock_irqsave(&led->value_lock, flags);
> +
> +	/*
> +	 * We only have a limited selection of settings, see if we can
> +	 * support the configuration we're being given
> +	 */
> +	switch (*delay_on) {
> +	case 500:
> +		led->on_time = LED_ON_500MS;
> +		break;
> +	case 250:
> +		led->on_time = LED_ON_250MS;
> +		break;
> +	case 125:
> +		led->on_time = LED_ON_125MS;
> +		break;
> +	case 62:
> +	case 63:
> +		/* Actually 62.5ms */
> +		led->on_time = LED_ON_62_5MS;
> +		break;
> +	default:
> +		ret = -EINVAL;

Invalid delay on time,
Can it return here quickly if updating the period is not mandatory?

> +static int palmas_leds_probe(struct platform_device *pdev)
> +{
> +	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
> +	struct palmas_leds_platform_data *pdata = pdev->dev.platform_data;
> +	struct palmas_leds_data *leds_data;
> +	struct device_node *node = pdev->dev.of_node;
> +	int ret, i;
> +	int offset = 0;
> +
> +	if (!palmas->led_muxed && !is_palmas_charger(palmas->product_id))
> {
> +		dev_err(&pdev->dev, "there are no LEDs muxed\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Palmas charger requires platform data */
> +	if (is_palmas_charger(palmas->product_id) && node && !pdata) {
> +
> +		if (!pdata)
> +			return -ENOMEM;
> +
> +		ret = palmas_dt_to_pdata(&pdev->dev, node, pdata);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (is_palmas_charger(palmas->product_id) && !pdata)
> +		return -EINVAL;

In _probe(), is_palmas_charger() is called several times.
Any reason to get the charger at each time?
If it's not, just get once and store the value in the variable.
Then many calls can be replaced with it simply.

> +
> +	leds_data = devm_kzalloc(&pdev->dev, sizeof(*leds_data),
> GFP_KERNEL);
> +	if (!leds_data)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, leds_data);
> +
> +	leds_data->palmas = palmas;
> +
> +	switch (palmas->led_muxed) {
> +	case PALMAS_LED1_MUXED | PALMAS_LED2_MUXED:
> +		leds_data->no_leds = 2;
> +		break;
> +	case PALMAS_LED1_MUXED:
> +	case PALMAS_LED2_MUXED:
> +		leds_data->no_leds = 1;
> +		break;
> +	default:
> +		leds_data->no_leds = 0;
> +		break;
> +	}
> +
> +	if (is_palmas_charger(palmas->product_id)) {
> +		if (pdata->chrg_led_mode)
> +			leds_data->no_leds += 2;
> +		else
> +			leds_data->no_leds++;
> +	}
> +
> +	if (leds_data->no_leds == 0)
> +		leds_data->palmas_led = NULL;
> +	else
> +		leds_data = devm_kzalloc(&pdev->dev,
> +				leds_data->no_leds * sizeof(*leds_data),
> +				GFP_KERNEL);
> +
> +	/* Initialise LED1 */
> +	if (palmas->led_muxed & PALMAS_LED1_MUXED) {
> +		palmas_init_led(leds_data, offset, 1);
> +		offset++;
> +	}
> +
> +	/* Initialise LED2 */
> +	if (palmas->led_muxed & PALMAS_LED2_MUXED) {
> +		palmas_init_led(leds_data, offset, 2);
> +		offset++;
> +	}
> +
> +	if (is_palmas_charger(palmas->product_id)) {
> +		palmas_init_led(leds_data, offset, 3);
> +		offset++;
> +
> +		if (pdata->chrg_led_mode) {
> +			palmas_led_update_bits(leds_data,
> PALMAS_CHRG_LED_CTRL,
> +					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE,
> +					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE);
> +
> +			palmas_init_led(leds_data, offset, 4);
> +		}
> +	}
> +
> +	for (i = 0; i < leds_data->no_leds; i++) {
> +		ret = led_classdev_register(leds_data->dev,
> +				&leds_data->palmas_led[i].cdev);
> +		if (ret < 0) {
> +			dev_err(&pdev->dev,
> +				"Failed to register LED no: %d err: %d\n",
> +				i, ret);
> +			goto err_led;
> +		}
> +	}
> +
> +	if (!is_palmas_charger(palmas->product_id))
> +		return 0;
> +
> +	/* Set the LED current registers if set in platform data */
> +	if (pdata->led1_current)
> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
> +				PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK,
> +				pdata->led1_current);

It looks buggy when 'led1_current' is negative value or out-of-range.
Why don't you define ledN_current as enum type?
Then it guarantees exact range of configurable value.

For example,
enum palmas_led_current {
	PALMAS_ILED_1mA,
	PALMAS_ILED_2mA,
...
};

> +
> +	if (pdata->led2_current)
> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
> +				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK,
> +				pdata->led2_current <<
> +				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT);
> +
> +	if (pdata->led3_current)
> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
> +				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
> +				pdata->led3_current);
> +
> +	if (pdata->led3_current)
> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
> +				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
> +				pdata->led3_current);
> +
> +	if (pdata->led4_current)
> +		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
> +				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK,
> +				pdata->led4_current <<
> +				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT);
> +
> +	if (pdata->chrg_led_vbat_low)
> +		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
> +				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS,
> +				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS);
> +
> +	return 0;
> +
> +err_led:
> +	for (i = 0; i < leds_data->no_leds; i++)
> +		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
> +	kfree(leds_data->palmas_led);
> +	kfree(leds_data);

The kfree()s can be ignored because of memory allocation with devm_zalloc().

> +static int palmas_leds_remove(struct platform_device *pdev)
> +{
> +	struct palmas_leds_data *leds_data = platform_get_drvdata(pdev);
> +	int i;
> +
> +	for (i = 0; i < leds_data->no_leds; i++)
> +		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
> +	if (i)
> +		kfree(leds_data->palmas_led);
> +	kfree(leds_data);

Ditto. The kfree()s are not required with devm_zalloc().

> diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
> index 5661f2d..7399c71 100644
> --- a/include/linux/mfd/palmas.h
> +++ b/include/linux/mfd/palmas.h
> @@ -232,6 +232,16 @@ struct palmas_clk_platform_data {
>  	int clk32kgaudio_mode_sleep;
>  };
> 
> +struct palmas_leds_platform_data {
> +	int led1_current;
> +	int led2_current;
> +	int led3_current;
> +	int led4_current;

Ditto, replaceable with enum type ?

Thanks.

Best Regards,
Milo

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

* Re: [PATCH v8 0/12] Palmas Updates
  2013-03-07 13:23   ` Ian Lartey
@ 2013-03-08  7:12     ` Linus Walleij
  -1 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-08  7:12 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, broonie, rob.herring, rob,
	mturquette, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo

On Thu, Mar 7, 2013 at 2:23 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> This patchset adds to the support for the Palmas iseries of PMIC chips.
>
> Some of the patches have previously been submitted individually.
> The DT bindings doc has been added first due to comments that it was
> missing.

Can the patches to the individual subsystems be applied individually
(like can we apply the two GPIO patches to the GPIO tree) or are
the deps such that the whole shebang needs to go in at once and you're
just harvesting ACKs to take it all into MFD or similar?

Yours,
Linus Walleij

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

* [PATCH v8 0/12] Palmas Updates
@ 2013-03-08  7:12     ` Linus Walleij
  0 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-08  7:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 7, 2013 at 2:23 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> This patchset adds to the support for the Palmas iseries of PMIC chips.
>
> Some of the patches have previously been submitted individually.
> The DT bindings doc has been added first due to comments that it was
> missing.

Can the patches to the individual subsystems be applied individually
(like can we apply the two GPIO patches to the GPIO tree) or are
the deps such that the whole shebang needs to go in at once and you're
just harvesting ACKs to take it all into MFD or similar?

Yours,
Linus Walleij

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

* Re: [PATCH v8 04/12] regulator: palmas correct dt parsing
  2013-03-07 13:17   ` Ian Lartey
@ 2013-03-08  9:44     ` Mark Brown
  -1 siblings, 0 replies; 51+ messages in thread
From: Mark Brown @ 2013-03-08  9:44 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, rob.herring, rob,
	mturquette, linus.walleij, cooloney, rpurdie, sameo, wim,
	lgirdwood, gg, j-keerthy, ldewangan, t-kristo

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]

On Thu, Mar 07, 2013 at 01:17:48PM +0000, Ian Lartey wrote:
> From: Graeme Gregory <gg@slimlogic.co.uk>
> 
> Fix the DT parsing to agree with the bindings document. Some small changes
> to the value names and also fix the handling of boolean values. They were
> previously using prop = 1/0, now just use of_property_read_bool calls.

Applied, thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* [PATCH v8 04/12] regulator: palmas correct dt parsing
@ 2013-03-08  9:44     ` Mark Brown
  0 siblings, 0 replies; 51+ messages in thread
From: Mark Brown @ 2013-03-08  9:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 07, 2013 at 01:17:48PM +0000, Ian Lartey wrote:
> From: Graeme Gregory <gg@slimlogic.co.uk>
> 
> Fix the DT parsing to agree with the bindings document. Some small changes
> to the value names and also fix the handling of boolean values. They were
> previously using prop = 1/0, now just use of_property_read_bool calls.

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130308/3dc92202/attachment.sig>

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

* Re: [PATCH v8 0/12] Palmas Updates
  2013-03-08  7:12     ` Linus Walleij
@ 2013-03-08 17:12       ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-08 17:12 UTC (permalink / raw)
  To: Linus Walleij
  Cc: t-kristo, broonie, mturquette, linux-watchdog, swarren,
	j-keerthy, linux-doc, linux-kernel, rob.herring, lgirdwood,
	grant.likely, wim, ldewangan, rpurdie, linux-arm-kernel, rob,
	cooloney, gg, linux-leds, sameo

On 08/03/13 07:12, Linus Walleij wrote:
> On Thu, Mar 7, 2013 at 2:23 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:
>
>> This patchset adds to the support for the Palmas iseries of PMIC chips.
>>
>> Some of the patches have previously been submitted individually.
>> The DT bindings doc has been added first due to comments that it was
>> missing.
>
> Can the patches to the individual subsystems be applied individually
> (like can we apply the two GPIO patches to the GPIO tree) or are
> the deps such that the whole shebang needs to go in at once and you're
> just harvesting ACKs to take it all into MFD or similar?

There are a few dependencies:

The GPIO and LEDS subsystem patches both depend on:
[PATCH v8 02/12] mfd: palmas: is_palmas_charger needed by multiple drivers

all the subsystems depend on:
[PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
for their DT documentation.

so taking the whole shooting match in one go seems the safest.

>
> Yours,
> Linus Walleij


Regards,

Ian

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

* [PATCH v8 0/12] Palmas Updates
@ 2013-03-08 17:12       ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-08 17:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/03/13 07:12, Linus Walleij wrote:
> On Thu, Mar 7, 2013 at 2:23 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:
>
>> This patchset adds to the support for the Palmas iseries of PMIC chips.
>>
>> Some of the patches have previously been submitted individually.
>> The DT bindings doc has been added first due to comments that it was
>> missing.
>
> Can the patches to the individual subsystems be applied individually
> (like can we apply the two GPIO patches to the GPIO tree) or are
> the deps such that the whole shebang needs to go in at once and you're
> just harvesting ACKs to take it all into MFD or similar?

There are a few dependencies:

The GPIO and LEDS subsystem patches both depend on:
[PATCH v8 02/12] mfd: palmas: is_palmas_charger needed by multiple drivers

all the subsystems depend on:
[PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
for their DT documentation.

so taking the whole shooting match in one go seems the safest.

>
> Yours,
> Linus Walleij


Regards,

Ian

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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
  2013-03-08  1:13   ` Kim, Milo
@ 2013-03-08 17:13     ` Ian Lartey
  2013-03-13 20:31       ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Ian Lartey @ 2013-03-08 17:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/03/13 01:13, Kim, Milo wrote:
>> Add the Kconfig and Makefile for the Palmas LED driver.
>
> It would be better if the Palmas LED driver files are combined into one patch.
> [PATCH v8 09/12] leds: Add support for Palmas LEDs
> [PATCH v8 11/12] leds: Kconfig for Palmas LEDs

[PATCH v8 11/12] leds: Kconfig for Palmas LEDs
can often cause a merge conflict if there are already
additional drivers/files in the leds directory

[PATCH v8 09/12] leds: Add support for Palmas LEDs
has more chance of being applied without any issues
(unless the person taking the patch already has
their own leds-palmas.c.

>
> Best Regards,
> Milo
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* [PATCH v8 10/12] clk: Kconfig for Palmas clock driver
  2013-03-08  1:13   ` Kim, Milo
@ 2013-03-08 17:14     ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-08 17:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/03/13 01:13, Kim, Milo wrote:
>>   drivers/clk/Kconfig        |    8 ++++++++
>>   drivers/clk/Makefile       |    1 +
>>   drivers/leds/leds-palmas.c |   19 ++++++-------------
>
> If this patch is for only clock module, then LED patch should be detached.

Yes indeed.
>
> [PATCH v8 10/12] clk: Kconfig for Palmas clock driver
> [PATCH v8 12/12] clk: add a clock driver for palmas
> It could be joined into one patch file.

Kind of safer to keep them separate:

[PATCH v8 10/12] clk: Kconfig for Palmas clock driver
can often cause a merge conflict if there are already
additional drivers/files in the clk directory

[PATCH v8 12/12] clk: add a clock driver for palmas
has more chance of being applied without any issues
(unless the person taking the patch already has
their own clk-palmas.c.


>
> Best Regards,
> Milo
>


Regards,

Ian

> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* [PATCH v8 09/12] leds: Add support for Palmas LEDs
  2013-03-08  1:13   ` Kim, Milo
@ 2013-03-11 15:16     ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-11 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/03/13 01:13, Kim, Milo wrote:
>> The Palmas familly of chips has LED support. This is not always muxed
>> to output pins so depending on the setting of the mux this driver
>> will create the appropriate LED class devices.
>
> It looks good and I've added few comments.

Thanks for your comments Kim.

>
>> diff --git a/drivers/leds/leds-palmas.c b/drivers/leds/leds-palmas.c
>
>> +static int palmas_leds_blink_set(struct led_classdev *led_cdev,
>> +				   unsigned long *delay_on,
>> +				   unsigned long *delay_off)
>> +{
>> +	struct palmas_led *led = to_palmas_led(led_cdev);
>> +	unsigned long flags;
>> +	int ret = 0;
>> +	int period;
>> +
>> +	/* Pick some defaults if we've not been given times */
>> +	if (*delay_on == 0 && *delay_off == 0) {
>> +		*delay_on = 250;
>> +		*delay_off = 250;
>> +	}
>> +
>> +	spin_lock_irqsave(&led->value_lock, flags);
>> +
>> +	/*
>> +	 * We only have a limited selection of settings, see if we can
>> +	 * support the configuration we're being given
>> +	 */
>> +	switch (*delay_on) {
>> +	case 500:
>> +		led->on_time = LED_ON_500MS;
>> +		break;
>> +	case 250:
>> +		led->on_time = LED_ON_250MS;
>> +		break;
>> +	case 125:
>> +		led->on_time = LED_ON_125MS;
>> +		break;
>> +	case 62:
>> +	case 63:
>> +		/* Actually 62.5ms */
>> +		led->on_time = LED_ON_62_5MS;
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>
> Invalid delay on time,
> Can it return here quickly if updating the period is not mandatory?

The led still needs to be turned off later on in the procedure.
led_blink = 0;
so we can't return early.


>
>> +static int palmas_leds_probe(struct platform_device *pdev)
>> +{
>> +	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
>> +	struct palmas_leds_platform_data *pdata = pdev->dev.platform_data;
>> +	struct palmas_leds_data *leds_data;
>> +	struct device_node *node = pdev->dev.of_node;
>> +	int ret, i;
>> +	int offset = 0;
>> +
>> +	if (!palmas->led_muxed && !is_palmas_charger(palmas->product_id))
>> {
>> +		dev_err(&pdev->dev, "there are no LEDs muxed\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Palmas charger requires platform data */
>> +	if (is_palmas_charger(palmas->product_id) && node && !pdata) {
>> +
>> +		if (!pdata)
>> +			return -ENOMEM;
>> +
>> +		ret = palmas_dt_to_pdata(&pdev->dev, node, pdata);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	if (is_palmas_charger(palmas->product_id) && !pdata)
>> +		return -EINVAL;
>
> In _probe(), is_palmas_charger() is called several times.
> Any reason to get the charger at each time?
> If it's not, just get once and store the value in the variable.
> Then many calls can be replaced with it simply.

is_palmas_charger is simply a macro which checks a value so it
is as simple as it gets.

>
>> +
>> +	leds_data = devm_kzalloc(&pdev->dev, sizeof(*leds_data),
>> GFP_KERNEL);
>> +	if (!leds_data)
>> +		return -ENOMEM;
>> +	platform_set_drvdata(pdev, leds_data);
>> +
>> +	leds_data->palmas = palmas;
>> +
>> +	switch (palmas->led_muxed) {
>> +	case PALMAS_LED1_MUXED | PALMAS_LED2_MUXED:
>> +		leds_data->no_leds = 2;
>> +		break;
>> +	case PALMAS_LED1_MUXED:
>> +	case PALMAS_LED2_MUXED:
>> +		leds_data->no_leds = 1;
>> +		break;
>> +	default:
>> +		leds_data->no_leds = 0;
>> +		break;
>> +	}
>> +
>> +	if (is_palmas_charger(palmas->product_id)) {
>> +		if (pdata->chrg_led_mode)
>> +			leds_data->no_leds += 2;
>> +		else
>> +			leds_data->no_leds++;
>> +	}
>> +
>> +	if (leds_data->no_leds == 0)
>> +		leds_data->palmas_led = NULL;
>> +	else
>> +		leds_data = devm_kzalloc(&pdev->dev,
>> +				leds_data->no_leds * sizeof(*leds_data),
>> +				GFP_KERNEL);
>> +
>> +	/* Initialise LED1 */
>> +	if (palmas->led_muxed & PALMAS_LED1_MUXED) {
>> +		palmas_init_led(leds_data, offset, 1);
>> +		offset++;
>> +	}
>> +
>> +	/* Initialise LED2 */
>> +	if (palmas->led_muxed & PALMAS_LED2_MUXED) {
>> +		palmas_init_led(leds_data, offset, 2);
>> +		offset++;
>> +	}
>> +
>> +	if (is_palmas_charger(palmas->product_id)) {
>> +		palmas_init_led(leds_data, offset, 3);
>> +		offset++;
>> +
>> +		if (pdata->chrg_led_mode) {
>> +			palmas_led_update_bits(leds_data,
>> PALMAS_CHRG_LED_CTRL,
>> +					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE,
>> +					PALMAS_CHRG_LED_CTRL_CHRG_LED_MODE);
>> +
>> +			palmas_init_led(leds_data, offset, 4);
>> +		}
>> +	}
>> +
>> +	for (i = 0; i < leds_data->no_leds; i++) {
>> +		ret = led_classdev_register(leds_data->dev,
>> +				&leds_data->palmas_led[i].cdev);
>> +		if (ret < 0) {
>> +			dev_err(&pdev->dev,
>> +				"Failed to register LED no: %d err: %d\n",
>> +				i, ret);
>> +			goto err_led;
>> +		}
>> +	}
>> +
>> +	if (!is_palmas_charger(palmas->product_id))
>> +		return 0;
>> +
>> +	/* Set the LED current registers if set in platform data */
>> +	if (pdata->led1_current)
>> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
>> +				PALMAS_LED_CURRENT_CTRL1_LED_1_CURRENT_MASK,
>> +				pdata->led1_current);
>
> It looks buggy when 'led1_current' is negative value or out-of-range.
> Why don't you define ledN_current as enum type?
> Then it guarantees exact range of configurable value.
>
> For example,
> enum palmas_led_current {
> 	PALMAS_ILED_1mA,
> 	PALMAS_ILED_2mA,
> ...
> };

Your right it does need some bounds checking here, I'll put some in.

>
>> +
>> +	if (pdata->led2_current)
>> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL1,
>> +				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_MASK,
>> +				pdata->led2_current <<
>> +				PALMAS_LED_CURRENT_CTRL1_LED_2_CURRENT_SHIFT);
>> +
>> +	if (pdata->led3_current)
>> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
>> +				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
>> +				pdata->led3_current);
>> +
>> +	if (pdata->led3_current)
>> +		palmas_led_update_bits(leds_data, PALMAS_LED_CURRENT_CTRL2,
>> +				PALMAS_LED_CURRENT_CTRL2_LED_3_CURRENT_MASK,
>> +				pdata->led3_current);
>> +
>> +	if (pdata->led4_current)
>> +		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
>> +				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_MASK,
>> +				pdata->led4_current <<
>> +				PALMAS_CHRG_LED_CTRL_CHRG_LED_CURRENT_SHIFT);
>> +
>> +	if (pdata->chrg_led_vbat_low)
>> +		palmas_led_update_bits(leds_data, PALMAS_CHRG_LED_CTRL,
>> +				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS,
>> +				PALMAS_CHRG_LED_CTRL_CHRG_LOWBAT_BLK_DIS);
>> +
>> +	return 0;
>> +
>> +err_led:
>> +	for (i = 0; i < leds_data->no_leds; i++)
>> +		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
>> +	kfree(leds_data->palmas_led);
>> +	kfree(leds_data);
>
> The kfree()s can be ignored because of memory allocation with devm_zalloc().

Yes, thanks for that.
>
>> +static int palmas_leds_remove(struct platform_device *pdev)
>> +{
>> +	struct palmas_leds_data *leds_data = platform_get_drvdata(pdev);
>> +	int i;
>> +
>> +	for (i = 0; i < leds_data->no_leds; i++)
>> +		led_classdev_unregister(&leds_data->palmas_led[i].cdev);
>> +	if (i)
>> +		kfree(leds_data->palmas_led);
>> +	kfree(leds_data);
>
> Ditto. The kfree()s are not required with devm_zalloc().

agreed

>
>> diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
>> index 5661f2d..7399c71 100644
>> --- a/include/linux/mfd/palmas.h
>> +++ b/include/linux/mfd/palmas.h
>> @@ -232,6 +232,16 @@ struct palmas_clk_platform_data {
>>   	int clk32kgaudio_mode_sleep;
>>   };
>>
>> +struct palmas_leds_platform_data {
>> +	int led1_current;
>> +	int led2_current;
>> +	int led3_current;
>> +	int led4_current;
>
> Ditto, replaceable with enum type ?
>
> Thanks.
>
> Best Regards,
> Milo
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
  2013-03-07 13:17   ` Ian Lartey
@ 2013-03-13 14:15     ` Linus Walleij
  -1 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-13 14:15 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, broonie, rob.herring, rob,
	mturquette, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo

Sorry for slow replies :-(

On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> +static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int *dest)

I don't like "int gpio" here, please use "int offset".

This is not a global GPIO number, it is an offset in the local gpio_chip,
right?

> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
> +}
> +
> +static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int data)
> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
> +}
> +
> +static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int mask, unsigned int data)
> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
> +}


> -       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
> +       ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);

(Obviously you are passing the offset.)

> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
> +                               offset, BIT(offset % 8));
(..)
> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
> +                               offset, BIT(offset % 8));
(...)
> +       ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
> +                       offset, 1 << (offset % 8), 1 << (offset % 8));

Why aren't you using the BIT() macro here too?

Further: if these functions are always used like this, with offset
and some BIT() or (1 << (offset % 8)) why don't you move that
latter part into the static helper and just pass offset into the
helper?

Yours,
Linus Walleij

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

* [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
@ 2013-03-13 14:15     ` Linus Walleij
  0 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-13 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

Sorry for slow replies :-(

On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> +static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int *dest)

I don't like "int gpio" here, please use "int offset".

This is not a global GPIO number, it is an offset in the local gpio_chip,
right?

> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
> +}
> +
> +static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int data)
> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
> +}
> +
> +static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
> +               int gpio, unsigned int mask, unsigned int data)
> +{
> +       /* registers for second bank are identical and offset by 0x9 */
> +       if (gpio > 7)
> +               reg += PALMAS_GPIO_DATA_IN2;
> +
> +       return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
> +}


> -       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
> +       ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);

(Obviously you are passing the offset.)

> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
> +                               offset, BIT(offset % 8));
(..)
> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
> +                               offset, BIT(offset % 8));
(...)
> +       ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
> +                       offset, 1 << (offset % 8), 1 << (offset % 8));

Why aren't you using the BIT() macro here too?

Further: if these functions are always used like this, with offset
and some BIT() or (1 << (offset % 8)) why don't you move that
latter part into the static helper and just pass offset into the
helper?

Yours,
Linus Walleij

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

* Re: [PATCH v8 08/12] gpio: palmas: Enable DT support for palmas gpio.
  2013-03-07 13:17   ` Ian Lartey
@ 2013-03-13 14:20     ` Linus Walleij
  -1 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-13 14:20 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, broonie, rob.herring, rob,
	mturquette, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo, devicetree-discuss

On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> From: J Keerthy <j-keerthy@ti.com>
>
> Enable DT support for palmas gpio.
>
> Signed-off-by: J Keerthy <j-keerthy@ti.com>

This needs to be CC: to devicetree-discuss.

> +static struct of_device_id of_palmas_match_tbl[] = {
> +       { .compatible = "ti,palmas-gpio", },
> +       { .compatible = "ti,palmas-charger-gpio", },
> +       { .compatible = "ti,twl6035-gpio", },
> +       { .compatible = "ti,twl6036-gpio", },
> +       { .compatible = "ti,twl6037-gpio", },
> +       { .compatible = "ti,tps65913-gpio", },
> +       { .compatible = "ti,tps65914-gpio", },
> +       { .compatible = "ti,tps80036-gpio", },
> +       { /* end */ }
> +};

I can see that the binding came in a previous patch in this series, OK.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* [PATCH v8 08/12] gpio: palmas: Enable DT support for palmas gpio.
@ 2013-03-13 14:20     ` Linus Walleij
  0 siblings, 0 replies; 51+ messages in thread
From: Linus Walleij @ 2013-03-13 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:

> From: J Keerthy <j-keerthy@ti.com>
>
> Enable DT support for palmas gpio.
>
> Signed-off-by: J Keerthy <j-keerthy@ti.com>

This needs to be CC: to devicetree-discuss.

> +static struct of_device_id of_palmas_match_tbl[] = {
> +       { .compatible = "ti,palmas-gpio", },
> +       { .compatible = "ti,palmas-charger-gpio", },
> +       { .compatible = "ti,twl6035-gpio", },
> +       { .compatible = "ti,twl6036-gpio", },
> +       { .compatible = "ti,twl6037-gpio", },
> +       { .compatible = "ti,tps65913-gpio", },
> +       { .compatible = "ti,tps65914-gpio", },
> +       { .compatible = "ti,tps80036-gpio", },
> +       { /* end */ }
> +};

I can see that the binding came in a previous patch in this series, OK.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
  2013-03-07 13:17 ` Ian Lartey
@ 2013-03-13 20:28   ` Stephen Warren
  -1 siblings, 0 replies; 51+ messages in thread
From: Stephen Warren @ 2013-03-13 20:28 UTC (permalink / raw)
  To: Ian Lartey
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, grant.likely, broonie, rob.herring, rob,
	mturquette, linus.walleij, cooloney, rpurdie, sameo, wim,
	lgirdwood, gg, j-keerthy, ldewangan, t-kristo

On 03/07/2013 06:17 AM, Ian Lartey wrote:
> From: Graeme Gregory <gg@slimlogic.co.uk>
> 
> Add the various binding files for the palmas family of chips. There is a
> top level MFD binding then a seperate binding for IP blocks on chips.

Sorry for the slow review. Thanks for the binding docs. I understand the
structure a bit better now.

> diff --git a/Documentation/devicetree/bindings/clock/palmas-clk.txt b/Documentation/devicetree/bindings/clock/palmas-clk.txt

> +* palmas and palmas-charger resource clock IP block devicetree bindings
> +
> +Required properties:
> +- compatible : Should be from the list
> +  ti,twl6035-clk
...
> +and also the generic series names
> +  ti,palmas-clk
> +  ti,palmas-charger-clk

(Most of these comments apply to all the binding files).

How do I know which one of those to pick; I guess you intend it to be
based on whether the top-level chip is a charger or not?

I don't see why the clock sub-module would care about that; isn't it
just an (the same) IP block that has been slapped inside some top-level
chip?

In other words, do we really need two separate compatible values here,
or should there just be a single generic "ti,palmas-clk"?

> +Optional properties:
> +- ti,clk32g-mode-sleep		- mode to adopt in pmic sleep 0 - off, 1 - on
> +- ti,clkg32kgaudio-mode-sleep	- see above

If this is a clock provider (i.e. the HW has clock output signals),
shouldn't it also have #clock-cells, and a description of the clock
specifier format?

If this is a clock consumer (i.e. the HW has clock input signals),
shouldn't it also have clocks/clock-names properties to describe what
the source of those clocks is?

Did you omit the reg property from this document just because it's so
standard you didn't think describing it was necessary? Certainly the
final DT file must have a reg property if the use of sub-nodes is to be
useful; the block could easily be instantiated at different addresses in
different top-level chips, so the base register address for this block
has to be defined in DT, I think.

> +Examples:
> +
> +clk {
> +    compatible = "ti,twl6035-clk", "ti,palmas-clk";
> +    ti,clk32kg-mode-sleep = <0>;
> +    ti,clk32kgaudio-mode-sleep = <0>;
> +};

It might be nice to show the sub-block examples within a parent
top-level Palmas node just to make it clear. But probably not a big deal.

> diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt

This document needs to describe the #gpio-cells property, and the format
of the GPIO specifier.

Can the GPIOs be used for a purpose other than plain GPIO (i.e. dedicate
signals such as IRQ output?). If so, don't you need to describe that pin
setup here? Perhaps that'd be part of the top-level MFD node or a
separate pinctrl node though.

Can the GPIOs act as interrupt inputs i.e. generate interrupts on
change/level? In which case, the interrupt-controller and
#interrupt-cells properties must be present, and the format of the IRQ
specifier documented.

> diff --git a/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
> new file mode 100644
> index 0000000..00739e9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
> @@ -0,0 +1,22 @@
> +* palmas and palmas-charger Button IP block devicetree bindings
> +
> +Required properties:
> +- compatible : Should be from the list
> +  ti,twl6035-pwrbutton
...
> +
> +Examples:

s/Examples/Example/. Same elsewhere.

> +pwrbutton {
> +    compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
> +    interrupt-parent = <&palmas>;
> +    interrupts = <1 0>;
> +    interrupt-name = "pwron-irq";

Don't you need to describe the interrupt-related properties in the list
of required properties above? This is especially true since this example
implies that a particular interrupt-names (which incidentally should be
plural in the example above) value is required.

> diff --git a/Documentation/devicetree/bindings/leds/leds-palmas.txt b/Documentation/devicetree/bindings/leds/leds-palmas.txt

> +-ti,chrg-led-mode	- mode for led operation 0 - Charging indicator
> +				1 - controlled as a general purpose LED
> +-ti,chrg-led-vbat-low	- low battery blinking 0 - blinking is enabled,
> +				1 - blinking is disabled

Which LED(s) do those two properties apply to?

> diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt

> +- interrupt-controller : palmas has its own internal IRQs
> +- #interrupt-cells : should be set to 2 for IRQ number and flags

At least a mention of the valid IRQ flags (or pointer to another
document which defines this) should be included.

> +Optional properties:
> +  ti,mux_padX : set the pad register X (1-2) to the correct muxing for the hardware,
> +	        if not set will use muxing in OTP.

This doesn't really describe what value to put here. I assume it's the
raw value to write into the register?

Is there any need to expose a full pinctrl driver here, for dynamic pin
muxing?

Since this node is a bus which has child devices on it, you should
include either a ranges property (if the children fit directly into the
parent bus's address space), or more likely if the address space "starts
over" at this point, you need #address-cells and #size-cells to describe
the format of child nodes' reg properties.

> diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt

> +Optional properties:

"regulators" below isn't a property, it's a node.

> +- regulators : should contain the constrains and init information for the
> +	       regulators. It should contain a subnode per regulator from the
> +	       list.
> +	       For palmas - smps12, smps123, smps3 depending on OTP,
> +	       smps45, smps457, smps7 depending on varient, smps6, smps[8-10],
> +	       ldo[1-9], ldoln, ldousb
> +	       For palmas-charger - smps12, smps123, smps3 depending on OTP,
> +	       smps[6-9], boost, ldo[1-14], ldoln, ldousb

Rather than "For palmas" and "For palmas-charger", shouldn't that say
"For ti,palmas-pmic" and "For ti,palmas-charger-pmic", since the
internals of this node should be entirely self-contained and defined by
this one binding, rather than being influenced by the top-level chip
that contains this block.

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

* [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD
@ 2013-03-13 20:28   ` Stephen Warren
  0 siblings, 0 replies; 51+ messages in thread
From: Stephen Warren @ 2013-03-13 20:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/07/2013 06:17 AM, Ian Lartey wrote:
> From: Graeme Gregory <gg@slimlogic.co.uk>
> 
> Add the various binding files for the palmas family of chips. There is a
> top level MFD binding then a seperate binding for IP blocks on chips.

Sorry for the slow review. Thanks for the binding docs. I understand the
structure a bit better now.

> diff --git a/Documentation/devicetree/bindings/clock/palmas-clk.txt b/Documentation/devicetree/bindings/clock/palmas-clk.txt

> +* palmas and palmas-charger resource clock IP block devicetree bindings
> +
> +Required properties:
> +- compatible : Should be from the list
> +  ti,twl6035-clk
...
> +and also the generic series names
> +  ti,palmas-clk
> +  ti,palmas-charger-clk

(Most of these comments apply to all the binding files).

How do I know which one of those to pick; I guess you intend it to be
based on whether the top-level chip is a charger or not?

I don't see why the clock sub-module would care about that; isn't it
just an (the same) IP block that has been slapped inside some top-level
chip?

In other words, do we really need two separate compatible values here,
or should there just be a single generic "ti,palmas-clk"?

> +Optional properties:
> +- ti,clk32g-mode-sleep		- mode to adopt in pmic sleep 0 - off, 1 - on
> +- ti,clkg32kgaudio-mode-sleep	- see above

If this is a clock provider (i.e. the HW has clock output signals),
shouldn't it also have #clock-cells, and a description of the clock
specifier format?

If this is a clock consumer (i.e. the HW has clock input signals),
shouldn't it also have clocks/clock-names properties to describe what
the source of those clocks is?

Did you omit the reg property from this document just because it's so
standard you didn't think describing it was necessary? Certainly the
final DT file must have a reg property if the use of sub-nodes is to be
useful; the block could easily be instantiated at different addresses in
different top-level chips, so the base register address for this block
has to be defined in DT, I think.

> +Examples:
> +
> +clk {
> +    compatible = "ti,twl6035-clk", "ti,palmas-clk";
> +    ti,clk32kg-mode-sleep = <0>;
> +    ti,clk32kgaudio-mode-sleep = <0>;
> +};

It might be nice to show the sub-block examples within a parent
top-level Palmas node just to make it clear. But probably not a big deal.

> diff --git a/Documentation/devicetree/bindings/gpio/gpio-palmas.txt b/Documentation/devicetree/bindings/gpio/gpio-palmas.txt

This document needs to describe the #gpio-cells property, and the format
of the GPIO specifier.

Can the GPIOs be used for a purpose other than plain GPIO (i.e. dedicate
signals such as IRQ output?). If so, don't you need to describe that pin
setup here? Perhaps that'd be part of the top-level MFD node or a
separate pinctrl node though.

Can the GPIOs act as interrupt inputs i.e. generate interrupts on
change/level? In which case, the interrupt-controller and
#interrupt-cells properties must be present, and the format of the IRQ
specifier documented.

> diff --git a/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
> new file mode 100644
> index 0000000..00739e9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/palmas-pwrbutton.txt
> @@ -0,0 +1,22 @@
> +* palmas and palmas-charger Button IP block devicetree bindings
> +
> +Required properties:
> +- compatible : Should be from the list
> +  ti,twl6035-pwrbutton
...
> +
> +Examples:

s/Examples/Example/. Same elsewhere.

> +pwrbutton {
> +    compatible = "ti,twl6035-pwrbutton", "ti,palmas-pwrbutton";
> +    interrupt-parent = <&palmas>;
> +    interrupts = <1 0>;
> +    interrupt-name = "pwron-irq";

Don't you need to describe the interrupt-related properties in the list
of required properties above? This is especially true since this example
implies that a particular interrupt-names (which incidentally should be
plural in the example above) value is required.

> diff --git a/Documentation/devicetree/bindings/leds/leds-palmas.txt b/Documentation/devicetree/bindings/leds/leds-palmas.txt

> +-ti,chrg-led-mode	- mode for led operation 0 - Charging indicator
> +				1 - controlled as a general purpose LED
> +-ti,chrg-led-vbat-low	- low battery blinking 0 - blinking is enabled,
> +				1 - blinking is disabled

Which LED(s) do those two properties apply to?

> diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt

> +- interrupt-controller : palmas has its own internal IRQs
> +- #interrupt-cells : should be set to 2 for IRQ number and flags

At least a mention of the valid IRQ flags (or pointer to another
document which defines this) should be included.

> +Optional properties:
> +  ti,mux_padX : set the pad register X (1-2) to the correct muxing for the hardware,
> +	        if not set will use muxing in OTP.

This doesn't really describe what value to put here. I assume it's the
raw value to write into the register?

Is there any need to expose a full pinctrl driver here, for dynamic pin
muxing?

Since this node is a bus which has child devices on it, you should
include either a ranges property (if the children fit directly into the
parent bus's address space), or more likely if the address space "starts
over" at this point, you need #address-cells and #size-cells to describe
the format of child nodes' reg properties.

> diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt

> +Optional properties:

"regulators" below isn't a property, it's a node.

> +- regulators : should contain the constrains and init information for the
> +	       regulators. It should contain a subnode per regulator from the
> +	       list.
> +	       For palmas - smps12, smps123, smps3 depending on OTP,
> +	       smps45, smps457, smps7 depending on varient, smps6, smps[8-10],
> +	       ldo[1-9], ldoln, ldousb
> +	       For palmas-charger - smps12, smps123, smps3 depending on OTP,
> +	       smps[6-9], boost, ldo[1-14], ldoln, ldousb

Rather than "For palmas" and "For palmas-charger", shouldn't that say
"For ti,palmas-pmic" and "For ti,palmas-charger-pmic", since the
internals of this node should be entirely self-contained and defined by
this one binding, rather than being influenced by the top-level chip
that contains this block.

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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
  2013-03-08 17:13     ` Ian Lartey
@ 2013-03-13 20:31       ` Stephen Warren
  2013-03-13 23:48         ` Ian Lartey
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2013-03-13 20:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/08/2013 10:13 AM, Ian Lartey wrote:
> On 08/03/13 01:13, Kim, Milo wrote:
>>> Add the Kconfig and Makefile for the Palmas LED driver.
>>
>> It would be better if the Palmas LED driver files are combined into
>> one patch.
>> [PATCH v8 09/12] leds: Add support for Palmas LEDs
>> [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
> 
> [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
> can often cause a merge conflict if there are already
> additional drivers/files in the leds directory
> 
> [PATCH v8 09/12] leds: Add support for Palmas LEDs
> has more chance of being applied without any issues
> (unless the person taking the patch already has
> their own leds-palmas.c.

A merge conflict isn't really influenced at all by how many other files
are included in the patch that causes it, and both files are going to
end up going through the same tree at the same time. So, there's no
benefit at all that I can see from splitting the C file and Kconfig.

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

* [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
  2013-03-13 20:31       ` Stephen Warren
@ 2013-03-13 23:48         ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-13 23:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 13/03/13 20:31, Stephen Warren wrote:
> On 03/08/2013 10:13 AM, Ian Lartey wrote:
>> On 08/03/13 01:13, Kim, Milo wrote:
>>>> Add the Kconfig and Makefile for the Palmas LED driver.
>>>
>>> It would be better if the Palmas LED driver files are combined into
>>> one patch.
>>> [PATCH v8 09/12] leds: Add support for Palmas LEDs
>>> [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
>>
>> [PATCH v8 11/12] leds: Kconfig for Palmas LEDs
>> can often cause a merge conflict if there are already
>> additional drivers/files in the leds directory
>>
>> [PATCH v8 09/12] leds: Add support for Palmas LEDs
>> has more chance of being applied without any issues
>> (unless the person taking the patch already has
>> their own leds-palmas.c.
>
> A merge conflict isn't really influenced at all by how many other files
> are included in the patch that causes it,

Ah, I was thinking more of additional files in the destination
directory of the patch compared to when the patch was generated
giving a higher likelihood of multiple changes to the Makefile and 
Kconfig clashing with the Makefile and Kconfig patch changes.

> and both files are going to
> end up going through the same tree at the same time. So, there's no
> benefit at all that I can see from splitting the C file and Kconfig.

At least one of the LED maintainers has agreed with both of you
so it looks like I'm making things worse (not better as intended !)
I'll merge for the next patch mail.


Thanks for this and your other review comments.

Ian
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
  2013-03-13 14:15     ` Linus Walleij
@ 2013-03-14 11:58       ` Ian Lartey
  -1 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-14 11:58 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-doc, linux-arm-kernel, linux-leds,
	linux-watchdog, swarren, grant.likely, broonie, rob.herring, rob,
	mturquette, cooloney, rpurdie, sameo, wim, lgirdwood, gg,
	j-keerthy, ldewangan, t-kristo

On 13/03/13 14:15, Linus Walleij wrote:
> Sorry for slow replies :-(
>
> On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:
>
>> +static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int *dest)
>
> I don't like "int gpio" here, please use "int offset".
>
> This is not a global GPIO number, it is an offset in the local gpio_chip,
> right?

Correct.
>
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
>> +}
>> +
>> +static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int data)
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
>> +}
>> +
>> +static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int mask, unsigned int data)
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
>> +}
>
>
>> -       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
>> +       ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);
>
> (Obviously you are passing the offset.)
>
>> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
>> +                               offset, BIT(offset % 8));
> (..)
>> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
>> +                               offset, BIT(offset % 8));
> (...)
>> +       ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
>> +                       offset, 1 << (offset % 8), 1 << (offset % 8));
>
> Why aren't you using the BIT() macro here too?
>
> Further: if these functions are always used like this, with offset
> and some BIT() or (1 << (offset % 8)) why don't you move that
> latter part into the static helper and just pass offset into the
> helper?
>

Good points  - I missed the other bit shifts.


> Yours,
> Linus Walleij


Thanks

Ian
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>


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

* [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger
@ 2013-03-14 11:58       ` Ian Lartey
  0 siblings, 0 replies; 51+ messages in thread
From: Ian Lartey @ 2013-03-14 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 13/03/13 14:15, Linus Walleij wrote:
> Sorry for slow replies :-(
>
> On Thu, Mar 7, 2013 at 2:17 PM, Ian Lartey <ian@slimlogic.co.uk> wrote:
>
>> +static int palmas_gpio_read(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int *dest)
>
> I don't like "int gpio" here, please use "int offset".
>
> This is not a global GPIO number, it is an offset in the local gpio_chip,
> right?

Correct.
>
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_read(palmas, PALMAS_GPIO_BASE, reg, dest);
>> +}
>> +
>> +static int palmas_gpio_write(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int data)
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_write(palmas, PALMAS_GPIO_BASE, reg, data);
>> +}
>> +
>> +static int palmas_gpio_update_bits(struct palmas *palmas, unsigned int reg,
>> +               int gpio, unsigned int mask, unsigned int data)
>> +{
>> +       /* registers for second bank are identical and offset by 0x9 */
>> +       if (gpio > 7)
>> +               reg += PALMAS_GPIO_DATA_IN2;
>> +
>> +       return palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, mask, data);
>> +}
>
>
>> -       ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val);
>> +       ret = palmas_gpio_read(palmas, PALMAS_GPIO_DATA_IN, offset, &val);
>
> (Obviously you are passing the offset.)
>
>> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_SET_DATA_OUT,
>> +                               offset, BIT(offset % 8));
> (..)
>> +               ret = palmas_gpio_write(palmas, PALMAS_GPIO_CLEAR_DATA_OUT,
>> +                               offset, BIT(offset % 8));
> (...)
>> +       ret = palmas_gpio_update_bits(palmas, PALMAS_GPIO_DATA_DIR,
>> +                       offset, 1 << (offset % 8), 1 << (offset % 8));
>
> Why aren't you using the BIT() macro here too?
>
> Further: if these functions are always used like this, with offset
> and some BIT() or (1 << (offset % 8)) why don't you move that
> latter part into the static helper and just pass offset into the
> helper?
>

Good points  - I missed the other bit shifts.


> Yours,
> Linus Walleij


Thanks

Ian
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>

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

* Re: [PATCH v8 12/12] clk: add a clock driver for palmas
  2013-03-07 13:17   ` Ian Lartey
  (?)
@ 2013-03-21 21:23     ` Mike Turquette
  -1 siblings, 0 replies; 51+ messages in thread
From: Mike Turquette @ 2013-03-21 21:23 UTC (permalink / raw)
  To: Ian Lartey, linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, linus.walleij, cooloney,
	rpurdie, sameo, wim, lgirdwood, gg, j-keerthy, ldewangan,
	t-kristo, Ian Lartey

Quoting Ian Lartey (2013-03-07 05:17:56)
> Palmas has two clock generators in it, clk32kg and clk32kg audio. They
> are fixed frequency clocks that only have enable/disable functionality.
> 
> Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
> Signed-off-by: J Keerthy <j-keerthy@ti.com>
> Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>

My only complaint with this driver is that there are two sets of ops and
prepare/unprepare functions when there could be just one set.  If there
existed some struct palmas_clk_hw which included members "reg" and
"ctrl_mode" (or even "enable_bit") then a single set of ops would do
just fine, instead of hard-coding those values into the functions.

Either way it's a small thing and there are only two clocks per palmas
here.  Hopefully it will get cleaned up in an update some day.

Acked-by: Mike Turquette <mturquette@linaro.org>

> ---
>  drivers/clk/clk-palmas.c |  268 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 268 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-palmas.c
> 
> diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
> new file mode 100644
> index 0000000..328eea4
> --- /dev/null
> +++ b/drivers/clk/clk-palmas.c
> @@ -0,0 +1,268 @@
> +/*
> + * PALMAS resource clock module driver
> + *
> + * Copyright (C) 2011-2013 Texas Instruments Inc.
> + * Graeme Gregory <gg@slimlogic.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/palmas.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of_platform.h>
> +
> +struct palmas_clk {
> +       struct palmas *palmas;
> +       struct device *dev;
> +       struct clk_hw clk32kg;
> +       struct clk_hw clk32kgaudio;
> +       int clk32kgaudio_mode_sleep;
> +       int clk32kg_mode_sleep;
> +};
> +
> +static int palmas_clock_setbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, data);
> +}
> +
> +static int palmas_clock_clrbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, 0);
> +}
> +
> +static int palmas_prepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kg_ops = {
> +       .prepare = palmas_prepare_clk32kg,
> +       .unprepare = palmas_unprepare_clk32kg,
> +};
> +
> +static int palmas_prepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kgaudio_ops = {
> +       .prepare = palmas_prepare_clk32kgaudio,
> +       .unprepare = palmas_unprepare_clk32kgaudio,
> +};
> +
> +static int palmas_initialise_clk(struct palmas_clk *palmas_clk)
> +{
> +       int ret;
> +
> +       if (palmas_clk->clk32kg_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       if (palmas_clk->clk32kgaudio_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KGAUDIO_CTRL,
> +                       PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static void palmas_dt_to_pdata(struct device_node *node,
> +               struct palmas_clk_platform_data *pdata)
> +{
> +       int ret;
> +       u32 prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kg-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kg_mode_sleep = prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kgaudio-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kgaudio_mode_sleep = prop;
> +}
> +
> +static int palmas_clk_probe(struct platform_device *pdev)
> +{
> +       struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
> +       struct palmas_clk_platform_data *pdata = pdev->dev.platform_data;
> +       struct device_node *node = pdev->dev.of_node;
> +       struct palmas_clk *palmas_clk;
> +       struct clk *clk;
> +       struct clk_init_data init_clk32g, init_clk32gaudio;
> +       int ret;
> +
> +       if (node && !pdata) {
> +               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +
> +               if (!pdata)
> +                       return -ENOMEM;
> +
> +               palmas_dt_to_pdata(node, pdata);
> +       }
> +
> +       palmas_clk = devm_kzalloc(&pdev->dev, sizeof(*palmas_clk), GFP_KERNEL);
> +       if (!palmas_clk)
> +               return -ENOMEM;
> +
> +       palmas_clk->palmas = palmas;
> +       palmas_clk->dev = &pdev->dev;
> +
> +       init_clk32g.name = "clk32kg";
> +       init_clk32g.ops = &palmas_clk32kg_ops;
> +       init_clk32g.parent_names = NULL;
> +       init_clk32g.num_parents = 0;
> +       palmas_clk->clk32kg.init = &init_clk32g;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kg);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kg clock register failed %ld\n",
> +                               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_clk32kg;
> +       }
> +
> +       init_clk32gaudio.name = "clk32kgaudio";
> +       init_clk32gaudio.ops = &palmas_clk32kgaudio_ops;
> +       init_clk32gaudio.parent_names = NULL;
> +       init_clk32gaudio.num_parents = 0;
> +       palmas_clk->clk32kgaudio.init = &init_clk32gaudio;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kgaudio);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kgaudio clock register failed %ld\n",
> +               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_audio;
> +       }
> +
> +       ret = palmas_initialise_clk(palmas_clk);
> +       if (ret)
> +               goto err;
> +
> +       dev_set_drvdata(&pdev->dev, palmas_clk);
> +
> +       return 0;
> +
> +err:
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +err_audio:
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +err_clk32kg:
> +
> +       return ret;
> +}
> +
> +static int palmas_clk_remove(struct platform_device *pdev)
> +{
> +       struct palmas_clk *palmas_clk = dev_get_drvdata(&pdev->dev);
> +
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +
> +       return 0;
> +}
> +
> +static struct of_device_id of_palmas_match_tbl[] = {
> +       { .compatible = "ti,palmas-clk", },
> +       { .compatible = "ti,palmas-charger-clk", },
> +       { .compatible = "ti,twl6035-clk", },
> +       { .compatible = "ti,twl6036-clk", },
> +       { .compatible = "ti,twl6037-clk", },
> +       { .compatible = "ti,tps65913-clk", },
> +       { .compatible = "ti,tps65914-clk", },
> +       { .compatible = "ti,tps80036-clk", },
> +       { /* end */ }
> +};
> +MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
> +
> +static struct platform_driver palmas_clk_driver = {
> +       .probe = palmas_clk_probe,
> +       .remove = palmas_clk_remove,
> +       .driver = {
> +               .name = "palmas-clk",
> +               .of_match_table = of_palmas_match_tbl,
> +               .owner = THIS_MODULE,
> +       },
> +};
> +
> +module_platform_driver(palmas_clk_driver);
> +
> +MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
> +MODULE_DESCRIPTION("PALMAS clock driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:palmas-clk");
> -- 
> 1.7.0.4

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

* Re: [PATCH v8 12/12] clk: add a clock driver for palmas
@ 2013-03-21 21:23     ` Mike Turquette
  0 siblings, 0 replies; 51+ messages in thread
From: Mike Turquette @ 2013-03-21 21:23 UTC (permalink / raw)
  To: Ian Lartey, linux-kernel
  Cc: linux-doc, linux-arm-kernel, linux-leds, linux-watchdog, swarren,
	grant.likely, broonie, rob.herring, rob, linus.walleij, cooloney,
	rpurdie, sameo, wim, lgirdwood, gg, j-keerthy, ldewangan,
	t-kristo, Ian Lartey

Quoting Ian Lartey (2013-03-07 05:17:56)
> Palmas has two clock generators in it, clk32kg and clk32kg audio. They
> are fixed frequency clocks that only have enable/disable functionality.
> 
> Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
> Signed-off-by: J Keerthy <j-keerthy@ti.com>
> Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>

My only complaint with this driver is that there are two sets of ops and
prepare/unprepare functions when there could be just one set.  If there
existed some struct palmas_clk_hw which included members "reg" and
"ctrl_mode" (or even "enable_bit") then a single set of ops would do
just fine, instead of hard-coding those values into the functions.

Either way it's a small thing and there are only two clocks per palmas
here.  Hopefully it will get cleaned up in an update some day.

Acked-by: Mike Turquette <mturquette@linaro.org>

> ---
>  drivers/clk/clk-palmas.c |  268 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 268 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-palmas.c
> 
> diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
> new file mode 100644
> index 0000000..328eea4
> --- /dev/null
> +++ b/drivers/clk/clk-palmas.c
> @@ -0,0 +1,268 @@
> +/*
> + * PALMAS resource clock module driver
> + *
> + * Copyright (C) 2011-2013 Texas Instruments Inc.
> + * Graeme Gregory <gg@slimlogic.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/palmas.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of_platform.h>
> +
> +struct palmas_clk {
> +       struct palmas *palmas;
> +       struct device *dev;
> +       struct clk_hw clk32kg;
> +       struct clk_hw clk32kgaudio;
> +       int clk32kgaudio_mode_sleep;
> +       int clk32kg_mode_sleep;
> +};
> +
> +static int palmas_clock_setbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, data);
> +}
> +
> +static int palmas_clock_clrbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, 0);
> +}
> +
> +static int palmas_prepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kg_ops = {
> +       .prepare = palmas_prepare_clk32kg,
> +       .unprepare = palmas_unprepare_clk32kg,
> +};
> +
> +static int palmas_prepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kgaudio_ops = {
> +       .prepare = palmas_prepare_clk32kgaudio,
> +       .unprepare = palmas_unprepare_clk32kgaudio,
> +};
> +
> +static int palmas_initialise_clk(struct palmas_clk *palmas_clk)
> +{
> +       int ret;
> +
> +       if (palmas_clk->clk32kg_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       if (palmas_clk->clk32kgaudio_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KGAUDIO_CTRL,
> +                       PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static void palmas_dt_to_pdata(struct device_node *node,
> +               struct palmas_clk_platform_data *pdata)
> +{
> +       int ret;
> +       u32 prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kg-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kg_mode_sleep = prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kgaudio-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kgaudio_mode_sleep = prop;
> +}
> +
> +static int palmas_clk_probe(struct platform_device *pdev)
> +{
> +       struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
> +       struct palmas_clk_platform_data *pdata = pdev->dev.platform_data;
> +       struct device_node *node = pdev->dev.of_node;
> +       struct palmas_clk *palmas_clk;
> +       struct clk *clk;
> +       struct clk_init_data init_clk32g, init_clk32gaudio;
> +       int ret;
> +
> +       if (node && !pdata) {
> +               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +
> +               if (!pdata)
> +                       return -ENOMEM;
> +
> +               palmas_dt_to_pdata(node, pdata);
> +       }
> +
> +       palmas_clk = devm_kzalloc(&pdev->dev, sizeof(*palmas_clk), GFP_KERNEL);
> +       if (!palmas_clk)
> +               return -ENOMEM;
> +
> +       palmas_clk->palmas = palmas;
> +       palmas_clk->dev = &pdev->dev;
> +
> +       init_clk32g.name = "clk32kg";
> +       init_clk32g.ops = &palmas_clk32kg_ops;
> +       init_clk32g.parent_names = NULL;
> +       init_clk32g.num_parents = 0;
> +       palmas_clk->clk32kg.init = &init_clk32g;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kg);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kg clock register failed %ld\n",
> +                               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_clk32kg;
> +       }
> +
> +       init_clk32gaudio.name = "clk32kgaudio";
> +       init_clk32gaudio.ops = &palmas_clk32kgaudio_ops;
> +       init_clk32gaudio.parent_names = NULL;
> +       init_clk32gaudio.num_parents = 0;
> +       palmas_clk->clk32kgaudio.init = &init_clk32gaudio;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kgaudio);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kgaudio clock register failed %ld\n",
> +               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_audio;
> +       }
> +
> +       ret = palmas_initialise_clk(palmas_clk);
> +       if (ret)
> +               goto err;
> +
> +       dev_set_drvdata(&pdev->dev, palmas_clk);
> +
> +       return 0;
> +
> +err:
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +err_audio:
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +err_clk32kg:
> +
> +       return ret;
> +}
> +
> +static int palmas_clk_remove(struct platform_device *pdev)
> +{
> +       struct palmas_clk *palmas_clk = dev_get_drvdata(&pdev->dev);
> +
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +
> +       return 0;
> +}
> +
> +static struct of_device_id of_palmas_match_tbl[] = {
> +       { .compatible = "ti,palmas-clk", },
> +       { .compatible = "ti,palmas-charger-clk", },
> +       { .compatible = "ti,twl6035-clk", },
> +       { .compatible = "ti,twl6036-clk", },
> +       { .compatible = "ti,twl6037-clk", },
> +       { .compatible = "ti,tps65913-clk", },
> +       { .compatible = "ti,tps65914-clk", },
> +       { .compatible = "ti,tps80036-clk", },
> +       { /* end */ }
> +};
> +MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
> +
> +static struct platform_driver palmas_clk_driver = {
> +       .probe = palmas_clk_probe,
> +       .remove = palmas_clk_remove,
> +       .driver = {
> +               .name = "palmas-clk",
> +               .of_match_table = of_palmas_match_tbl,
> +               .owner = THIS_MODULE,
> +       },
> +};
> +
> +module_platform_driver(palmas_clk_driver);
> +
> +MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
> +MODULE_DESCRIPTION("PALMAS clock driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:palmas-clk");
> -- 
> 1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v8 12/12] clk: add a clock driver for palmas
@ 2013-03-21 21:23     ` Mike Turquette
  0 siblings, 0 replies; 51+ messages in thread
From: Mike Turquette @ 2013-03-21 21:23 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Ian Lartey (2013-03-07 05:17:56)
> Palmas has two clock generators in it, clk32kg and clk32kg audio. They
> are fixed frequency clocks that only have enable/disable functionality.
> 
> Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk>
> Signed-off-by: J Keerthy <j-keerthy@ti.com>
> Signed-off-by: Ian Lartey <ian@slimlogic.co.uk>

My only complaint with this driver is that there are two sets of ops and
prepare/unprepare functions when there could be just one set.  If there
existed some struct palmas_clk_hw which included members "reg" and
"ctrl_mode" (or even "enable_bit") then a single set of ops would do
just fine, instead of hard-coding those values into the functions.

Either way it's a small thing and there are only two clocks per palmas
here.  Hopefully it will get cleaned up in an update some day.

Acked-by: Mike Turquette <mturquette@linaro.org>

> ---
>  drivers/clk/clk-palmas.c |  268 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 268 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-palmas.c
> 
> diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
> new file mode 100644
> index 0000000..328eea4
> --- /dev/null
> +++ b/drivers/clk/clk-palmas.c
> @@ -0,0 +1,268 @@
> +/*
> + * PALMAS resource clock module driver
> + *
> + * Copyright (C) 2011-2013 Texas Instruments Inc.
> + * Graeme Gregory <gg@slimlogic.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/palmas.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of_platform.h>
> +
> +struct palmas_clk {
> +       struct palmas *palmas;
> +       struct device *dev;
> +       struct clk_hw clk32kg;
> +       struct clk_hw clk32kgaudio;
> +       int clk32kgaudio_mode_sleep;
> +       int clk32kg_mode_sleep;
> +};
> +
> +static int palmas_clock_setbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, data);
> +}
> +
> +static int palmas_clock_clrbits(struct palmas *palmas, unsigned int reg,
> +               unsigned int data)
> +{
> +       return palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
> +                       reg, data, 0);
> +}
> +
> +static int palmas_prepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kg(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kg);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev, "Failed to enable clk32kg: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kg_ops = {
> +       .prepare = palmas_prepare_clk32kg,
> +       .unprepare = palmas_unprepare_clk32kg,
> +};
> +
> +static int palmas_prepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_setbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return ret;
> +}
> +
> +static void palmas_unprepare_clk32kgaudio(struct clk_hw *hw)
> +{
> +       struct palmas_clk *palmas_clk = container_of(hw, struct palmas_clk,
> +                       clk32kgaudio);
> +       int ret;
> +
> +       ret = palmas_clock_clrbits(palmas_clk->palmas,
> +               PALMAS_CLK32KGAUDIO_CTRL, PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE);
> +       if (ret)
> +               dev_err(palmas_clk->dev,
> +                               "Failed to enable clk32kgaudio: %d\n", ret);
> +
> +       return;
> +}
> +
> +static const struct clk_ops palmas_clk32kgaudio_ops = {
> +       .prepare = palmas_prepare_clk32kgaudio,
> +       .unprepare = palmas_unprepare_clk32kgaudio,
> +};
> +
> +static int palmas_initialise_clk(struct palmas_clk *palmas_clk)
> +{
> +       int ret;
> +
> +       if (palmas_clk->clk32kg_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KG_CTRL, PALMAS_CLK32KG_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       if (palmas_clk->clk32kgaudio_mode_sleep) {
> +               ret = palmas_clock_setbits(palmas_clk->palmas,
> +                       PALMAS_CLK32KGAUDIO_CTRL,
> +                       PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static void palmas_dt_to_pdata(struct device_node *node,
> +               struct palmas_clk_platform_data *pdata)
> +{
> +       int ret;
> +       u32 prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kg-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kg_mode_sleep = prop;
> +
> +       ret = of_property_read_u32(node, "ti,clk32kgaudio-mode-sleep", &prop);
> +       if (!ret)
> +               pdata->clk32kgaudio_mode_sleep = prop;
> +}
> +
> +static int palmas_clk_probe(struct platform_device *pdev)
> +{
> +       struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
> +       struct palmas_clk_platform_data *pdata = pdev->dev.platform_data;
> +       struct device_node *node = pdev->dev.of_node;
> +       struct palmas_clk *palmas_clk;
> +       struct clk *clk;
> +       struct clk_init_data init_clk32g, init_clk32gaudio;
> +       int ret;
> +
> +       if (node && !pdata) {
> +               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +
> +               if (!pdata)
> +                       return -ENOMEM;
> +
> +               palmas_dt_to_pdata(node, pdata);
> +       }
> +
> +       palmas_clk = devm_kzalloc(&pdev->dev, sizeof(*palmas_clk), GFP_KERNEL);
> +       if (!palmas_clk)
> +               return -ENOMEM;
> +
> +       palmas_clk->palmas = palmas;
> +       palmas_clk->dev = &pdev->dev;
> +
> +       init_clk32g.name = "clk32kg";
> +       init_clk32g.ops = &palmas_clk32kg_ops;
> +       init_clk32g.parent_names = NULL;
> +       init_clk32g.num_parents = 0;
> +       palmas_clk->clk32kg.init = &init_clk32g;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kg);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kg clock register failed %ld\n",
> +                               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_clk32kg;
> +       }
> +
> +       init_clk32gaudio.name = "clk32kgaudio";
> +       init_clk32gaudio.ops = &palmas_clk32kgaudio_ops;
> +       init_clk32gaudio.parent_names = NULL;
> +       init_clk32gaudio.num_parents = 0;
> +       palmas_clk->clk32kgaudio.init = &init_clk32gaudio;
> +
> +       clk = clk_register(palmas_clk->dev, &palmas_clk->clk32kgaudio);
> +       if (IS_ERR(clk)) {
> +               dev_dbg(&pdev->dev, "clk32kgaudio clock register failed %ld\n",
> +               PTR_ERR(clk));
> +               ret = PTR_ERR(clk);
> +               goto err_audio;
> +       }
> +
> +       ret = palmas_initialise_clk(palmas_clk);
> +       if (ret)
> +               goto err;
> +
> +       dev_set_drvdata(&pdev->dev, palmas_clk);
> +
> +       return 0;
> +
> +err:
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +err_audio:
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +err_clk32kg:
> +
> +       return ret;
> +}
> +
> +static int palmas_clk_remove(struct platform_device *pdev)
> +{
> +       struct palmas_clk *palmas_clk = dev_get_drvdata(&pdev->dev);
> +
> +       clk_unregister(palmas_clk->clk32kgaudio.clk);
> +       clk_unregister(palmas_clk->clk32kg.clk);
> +
> +       return 0;
> +}
> +
> +static struct of_device_id of_palmas_match_tbl[] = {
> +       { .compatible = "ti,palmas-clk", },
> +       { .compatible = "ti,palmas-charger-clk", },
> +       { .compatible = "ti,twl6035-clk", },
> +       { .compatible = "ti,twl6036-clk", },
> +       { .compatible = "ti,twl6037-clk", },
> +       { .compatible = "ti,tps65913-clk", },
> +       { .compatible = "ti,tps65914-clk", },
> +       { .compatible = "ti,tps80036-clk", },
> +       { /* end */ }
> +};
> +MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
> +
> +static struct platform_driver palmas_clk_driver = {
> +       .probe = palmas_clk_probe,
> +       .remove = palmas_clk_remove,
> +       .driver = {
> +               .name = "palmas-clk",
> +               .of_match_table = of_palmas_match_tbl,
> +               .owner = THIS_MODULE,
> +       },
> +};
> +
> +module_platform_driver(palmas_clk_driver);
> +
> +MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
> +MODULE_DESCRIPTION("PALMAS clock driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:palmas-clk");
> -- 
> 1.7.0.4

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

end of thread, other threads:[~2013-03-21 21:31 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-07 13:17 [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD Ian Lartey
2013-03-07 13:17 ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 02/12] mfd: palmas: is_palmas_charger needed by multiple drivers Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 03/12] mfd: palmas add variant and OTP detection Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 04/12] regulator: palmas correct dt parsing Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-08  9:44   ` Mark Brown
2013-03-08  9:44     ` Mark Brown
2013-03-07 13:17 ` [PATCH v8 05/12] watchdog: add Palmas Watchdog support Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 06/12] watchdog: Kconfig for Palmas watchdog Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 07/12] gpio: palmas: add in GPIO support for palmas charger Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-13 14:15   ` Linus Walleij
2013-03-13 14:15     ` Linus Walleij
2013-03-14 11:58     ` Ian Lartey
2013-03-14 11:58       ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 08/12] gpio: palmas: Enable DT support for palmas gpio Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-13 14:20   ` Linus Walleij
2013-03-13 14:20     ` Linus Walleij
2013-03-07 13:17 ` [PATCH v8 09/12] leds: Add support for Palmas LEDs Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-08  1:13   ` Kim, Milo
2013-03-11 15:16     ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 10/12] clk: Kconfig for Palmas clock driver Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-08  1:13   ` Kim, Milo
2013-03-08 17:14     ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 11/12] leds: Kconfig for Palmas LEDs Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-08  1:13   ` Kim, Milo
2013-03-08 17:13     ` Ian Lartey
2013-03-13 20:31       ` Stephen Warren
2013-03-13 23:48         ` Ian Lartey
2013-03-07 13:17 ` [PATCH v8 12/12] clk: add a clock driver for palmas Ian Lartey
2013-03-07 13:17   ` Ian Lartey
2013-03-21 21:23   ` Mike Turquette
2013-03-21 21:23     ` Mike Turquette
2013-03-21 21:23     ` Mike Turquette
2013-03-07 13:23 ` [PATCH v8 0/12] Palmas Updates Ian Lartey
2013-03-07 13:23   ` Ian Lartey
2013-03-08  7:12   ` Linus Walleij
2013-03-08  7:12     ` Linus Walleij
2013-03-08 17:12     ` Ian Lartey
2013-03-08 17:12       ` Ian Lartey
2013-03-13 20:28 ` [PATCH v8 01/12] mfd: DT bindings for the palmas family MFD Stephen Warren
2013-03-13 20:28   ` Stephen Warren

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.