summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacek Anaszewski <jacek.anaszewski@gmail.com>2019-06-11 17:46:37 -0400
committerJacek Anaszewski <jacek.anaszewski@gmail.com>2019-06-11 17:46:37 -0400
commit25529edef561ca51dadcbb6e97b1c40d2dbc5bae (patch)
tree601201c4c9d00959ecb2ea8a8f9b2335ae332a4e
parent09bfa5f6833a62bd6669d3ba7f83105181287b92 (diff)
parent11e1bbc116a75d4a93122ea0a3b2be814922d864 (diff)
Merge tag 'ti-lmu-led-drivers' into for-next
Merge immutable branch between LEDs, MFD and REGULATOR due to TI LMU LED support rework and introduction of two new drivers with DT bindings. * tag 'ti-lmu-led-drivers': leds: lm36274: Introduce the TI LM36274 LED driver dt-bindings: leds: Add LED bindings for the LM36274 regulator: lm363x: Add support for LM36274 mfd: ti-lmu: Add LM36274 support to the ti-lmu dt-bindings: mfd: Add lm36274 bindings to ti-lmu leds: lm3697: Introduce the lm3697 driver mfd: ti-lmu: Remove support for LM3697 dt-bindings: ti-lmu: Modify dt bindings for the LM3697 leds: TI LMU: Add common code for TI LMU devices dt-bindings: mfd: LMU: Add ti,brightness-resolution dt-bindings: mfd: LMU: Add the ramp up/down property
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lm36274.txt85
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lm3697.txt73
-rw-r--r--Documentation/devicetree/bindings/mfd/ti-lmu.txt88
-rw-r--r--drivers/leds/Kconfig25
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/leds-lm36274.c172
-rw-r--r--drivers/leds/leds-lm3697.c395
-rw-r--r--drivers/leds/leds-ti-lmu-common.c156
-rw-r--r--drivers/mfd/Kconfig5
-rw-r--r--drivers/mfd/ti-lmu.c23
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/lm363x-regulator.c78
-rw-r--r--include/linux/leds-ti-lmu-common.h47
-rw-r--r--include/linux/mfd/ti-lmu-register.h63
-rw-r--r--include/linux/mfd/ti-lmu.h5
15 files changed, 1135 insertions, 85 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-lm36274.txt b/Documentation/devicetree/bindings/leds/leds-lm36274.txt
new file mode 100644
index 000000000000..456a589c65f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm36274.txt
@@ -0,0 +1,85 @@
1* Texas Instruments LM36274 4-Channel LCD Backlight Driver w/Integrated Bias
2
3The LM36274 is an integrated four-channel WLED driver and LCD bias supply.
4The backlight boost provides the power to bias four parallel LED strings with
5up to 29V total output voltage. The 11-bit LED current is programmable via
6the I2C bus and/or controlled via a logic level PWM input from 60 uA to 30 mA.
7
8Parent device properties are documented in
9Documentation/devicetree/bindings/mfd/ti_lmu.txt
10
11Regulator properties are documented in
12Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
13
14Required backlight properties:
15 - compatible:
16 "ti,lm36274-backlight"
17 - reg : 0
18 - #address-cells : 1
19 - #size-cells : 0
20 - led-sources : Indicates which LED strings will be enabled.
21 Values from 0-3, sources is 0 based so strings will be
22 source value + 1.
23
24Optional backlight properties:
25 - label : see Documentation/devicetree/bindings/leds/common.txt
26 - linux,default-trigger :
27 see Documentation/devicetree/bindings/leds/common.txt
28
29Example:
30
31HVLED string 1 and 3 are controlled by control bank A and HVLED 2 string is
32controlled by control bank B.
33
34lm36274@11 {
35 compatible = "ti,lm36274";
36 #address-cells = <1>;
37 #size-cells = <0>;
38 reg = <0x11>;
39
40 enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
41
42 regulators {
43 #address-cells = <1>;
44 #size-cells = <0>;
45 compatible = "ti,lm363x-regulator";
46
47 enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>,
48 <&pioC 1 GPIO_ACTIVE_HIGH>;
49
50 vboost {
51 regulator-name = "lcd_boost";
52 regulator-min-microvolt = <4000000>;
53 regulator-max-microvolt = <7150000>;
54 regulator-always-on;
55 };
56
57 vpos {
58 regulator-name = "lcd_vpos";
59 regulator-min-microvolt = <4000000>;
60 regulator-max-microvolt = <6500000>;
61 };
62
63 vneg {
64 regulator-name = "lcd_vneg";
65 regulator-min-microvolt = <4000000>;
66 regulator-max-microvolt = <6500000>;
67 };
68 };
69
70 backlight {
71 #address-cells = <1>;
72 #size-cells = <0>;
73 compatible = "ti,lm36274-backlight";
74
75 led@0 {
76 reg = <0>;
77 led-sources = <0 2>;
78 label = "white:backlight_cluster";
79 linux,default-trigger = "backlight";
80 };
81 };
82};
83
84For more product information please see the link below:
85http://www.ti.com/lit/ds/symlink/lm36274.pdf
diff --git a/Documentation/devicetree/bindings/leds/leds-lm3697.txt b/Documentation/devicetree/bindings/leds/leds-lm3697.txt
new file mode 100644
index 000000000000..63992d732959
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm3697.txt
@@ -0,0 +1,73 @@
1* Texas Instruments - LM3697 Highly Efficient White LED Driver
2
3The LM3697 11-bit LED driver provides high-
4performance backlight dimming for 1, 2, or 3 series
5LED strings while delivering up to 90% efficiency.
6
7This device is suitable for display and keypad lighting
8
9Required properties:
10 - compatible:
11 "ti,lm3697"
12 - reg : I2C slave address
13 - #address-cells : 1
14 - #size-cells : 0
15
16Optional properties:
17 - enable-gpios : GPIO pin to enable/disable the device
18 - vled-supply : LED supply
19
20Required child properties:
21 - reg : 0 - LED is Controlled by bank A
22 1 - LED is Controlled by bank B
23 - led-sources : Indicates which HVLED string is associated to which
24 control bank. This is a zero based property so
25 HVLED1 = 0, HVLED2 = 1, HVLED3 = 2.
26 Additional information is contained
27 in Documentation/devicetree/bindings/leds/common.txt
28
29Optional child properties:
30 - ti,brightness-resolution - see Documentation/devicetree/bindings/mfd/ti-lmu.txt
31 - ramp-up-us: see Documentation/devicetree/bindings/mfd/ti-lmu.txt
32 - ramp-down-us: see Documentation/devicetree/bindings/mfd/ti-lmu.txt
33 - label : see Documentation/devicetree/bindings/leds/common.txt
34 - linux,default-trigger :
35 see Documentation/devicetree/bindings/leds/common.txt
36
37Example:
38
39HVLED string 1 and 3 are controlled by control bank A and HVLED 2 string is
40controlled by control bank B.
41
42led-controller@36 {
43 compatible = "ti,lm3697";
44 #address-cells = <1>;
45 #size-cells = <0>;
46 reg = <0x36>;
47
48 enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
49 vled-supply = <&vbatt>;
50
51 led@0 {
52 reg = <0>;
53 led-sources = <0 2>;
54 ti,brightness-resolution = <2047>;
55 ramp-up-us = <5000>;
56 ramp-down-us = <1000>;
57 label = "white:first_backlight_cluster";
58 linux,default-trigger = "backlight";
59 };
60
61 led@1 {
62 reg = <1>;
63 led-sources = <1>;
64 ti,brightness-resolution = <255>;
65 ramp-up-us = <500>;
66 ramp-down-us = <1000>;
67 label = "white:second_backlight_cluster";
68 linux,default-trigger = "backlight";
69 };
70}
71
72For more product information please see the link below:
73http://www.ti.com/lit/ds/symlink/lm3697.pdf
diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
index 86ca786d54fc..2296b8f24de4 100644
--- a/Documentation/devicetree/bindings/mfd/ti-lmu.txt
+++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
@@ -8,7 +8,7 @@ TI LMU driver supports lighting devices below.
8 LM3632 Backlight and regulator 8 LM3632 Backlight and regulator
9 LM3633 Backlight, LED and fault monitor 9 LM3633 Backlight, LED and fault monitor
10 LM3695 Backlight 10 LM3695 Backlight
11 LM3697 Backlight and fault monitor 11 LM36274 Backlight and regulator
12 12
13Required properties: 13Required properties:
14 - compatible: Should be one of: 14 - compatible: Should be one of:
@@ -16,15 +16,32 @@ Required properties:
16 "ti,lm3632" 16 "ti,lm3632"
17 "ti,lm3633" 17 "ti,lm3633"
18 "ti,lm3695" 18 "ti,lm3695"
19 "ti,lm3697" 19 "ti,lm36274"
20 - reg: I2C slave address. 20 - reg: I2C slave address.
21 0x11 for LM3632 21 0x11 for LM3632
22 0x29 for LM3631 22 0x29 for LM3631
23 0x36 for LM3633, LM3697 23 0x36 for LM3633
24 0x63 for LM3695 24 0x63 for LM3695
25 0x11 for LM36274
25 26
26Optional property: 27Optional properties:
27 - enable-gpios: A GPIO specifier for hardware enable pin. 28 - enable-gpios: A GPIO specifier for hardware enable pin.
29 - ramp-up-us: Current ramping from one brightness level to
30 the a higher brightness level.
31 Range from 2048 us - 117.44 s
32 - ramp-down-us: Current ramping from one brightness level to
33 the a lower brightness level.
34 Range from 2048 us - 117.44 s
35 - ti,brightness-resolution - This determines whether to use 8 bit brightness
36 mode or 11 bit brightness mode. If this value is
37 not set the device is defaulted to the preferred
38 8bit brightness mode per 7.3.4.1 of the data
39 sheet. This setting can either be in the parent
40 node or as part of the LED child nodes. This
41 is determined by the part itself if the strings
42 have a common brightness register or individual
43 brightness registers.
44 The values are 255 (8bit) or 2047 (11bit).
28 45
29Required node: 46Required node:
30 - backlight: All LMU devices have backlight child nodes. 47 - backlight: All LMU devices have backlight child nodes.
@@ -35,14 +52,15 @@ Optional nodes:
35 Required properties: 52 Required properties:
36 - compatible: Should be one of: 53 - compatible: Should be one of:
37 "ti,lm3633-fault-monitor" 54 "ti,lm3633-fault-monitor"
38 "ti,lm3697-fault-monitor"
39 - leds: LED properties for LM3633. Please refer to [2]. 55 - leds: LED properties for LM3633. Please refer to [2].
56 LED properties for LM36274. Please refer to [4].
40 - regulators: Regulator properties for LM3631 and LM3632. 57 - regulators: Regulator properties for LM3631 and LM3632.
41 Please refer to [3]. 58 Please refer to [3].
42 59
43[1] ../leds/backlight/ti-lmu-backlight.txt 60[1] ../leds/backlight/ti-lmu-backlight.txt
44[2] ../leds/leds-lm3633.txt 61[2] ../leds/leds-lm3633.txt
45[3] ../regulator/lm363x-regulator.txt 62[3] ../regulator/lm363x-regulator.txt
63[4] ../leds/leds-lm36274.txt
46 64
47lm3631@29 { 65lm3631@29 {
48 compatible = "ti,lm3631"; 66 compatible = "ti,lm3631";
@@ -90,7 +108,7 @@ lm3631@29 {
90 108
91 lcd_bl { 109 lcd_bl {
92 led-sources = <0 1>; 110 led-sources = <0 1>;
93 ramp-up-msec = <300>; 111 ramp-up-us = <300000>;
94 }; 112 };
95 }; 113 };
96}; 114};
@@ -152,15 +170,15 @@ lm3633@36 {
152 main { 170 main {
153 label = "main_lcd"; 171 label = "main_lcd";
154 led-sources = <1 2>; 172 led-sources = <1 2>;
155 ramp-up-msec = <500>; 173 ramp-up-us = <500000>;
156 ramp-down-msec = <500>; 174 ramp-down-us = <500000>;
157 }; 175 };
158 176
159 front { 177 front {
160 label = "front_lcd"; 178 label = "front_lcd";
161 led-sources = <0>; 179 led-sources = <0>;
162 ramp-up-msec = <1000>; 180 ramp-up-us = <1000000>;
163 ramp-down-msec = <0>; 181 ramp-down-us = <0>;
164 }; 182 };
165 }; 183 };
166 184
@@ -201,23 +219,51 @@ lm3695@63 {
201 }; 219 };
202}; 220};
203 221
204lm3697@36 { 222lm36274@11 {
205 compatible = "ti,lm3697"; 223 compatible = "ti,lm36274";
206 reg = <0x36>; 224 #address-cells = <1>;
225 #size-cells = <0>;
226 reg = <0x11>;
207 227
208 enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>; 228 enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>;
229 regulators {
230 #address-cells = <1>;
231 #size-cells = <0>;
232 compatible = "ti,lm363x-regulator";
209 233
210 backlight { 234 enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>,
211 compatible = "ti,lm3697-backlight"; 235 <&pioC 1 GPIO_ACTIVE_HIGH>;
212 236
213 lcd { 237 vboost {
214 led-sources = <0 1 2>; 238 regulator-name = "lcd_boost";
215 ramp-up-msec = <200>; 239 regulator-min-microvolt = <4000000>;
216 ramp-down-msec = <200>; 240 regulator-max-microvolt = <7150000>;
241 regulator-always-on;
242 };
243
244 vpos {
245 regulator-name = "lcd_vpos";
246 regulator-min-microvolt = <4000000>;
247 regulator-max-microvolt = <6500000>;
248 };
249
250 vneg {
251 regulator-name = "lcd_vneg";
252 regulator-min-microvolt = <4000000>;
253 regulator-max-microvolt = <6500000>;
217 }; 254 };
218 }; 255 };
219 256
220 fault-monitor { 257 backlight {
221 compatible = "ti,lm3697-fault-monitor"; 258 #address-cells = <1>;
259 #size-cells = <0>;
260 compatible = "ti,lm36274-backlight";
261
262 led@0 {
263 reg = <0>;
264 led-sources = <0 2>;
265 label = "white:backlight_cluster";
266 linux,default-trigger = "backlight";
267 };
222 }; 268 };
223}; 269};
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 35fcddb7ac2a..fb8072303ee8 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -793,6 +793,31 @@ config LEDS_SPI_BYTE
793 for controlling the brightness. Currently the following controller is 793 for controlling the brightness. Currently the following controller is
794 supported: Ubiquiti airCube ISP microcontroller based LED controller. 794 supported: Ubiquiti airCube ISP microcontroller based LED controller.
795 795
796config LEDS_TI_LMU_COMMON
797 tristate "LED driver for TI LMU"
798 depends on LEDS_CLASS
799 depends on REGMAP
800 help
801 Say Y to enable the LED driver for TI LMU devices.
802 This supports common features between the TI LM3532, LM3631, LM3632,
803 LM3633, LM3695 and LM3697.
804
805config LEDS_LM3697
806 tristate "LED driver for LM3697"
807 depends on LEDS_TI_LMU_COMMON
808 depends on I2C && OF
809 help
810 Say Y to enable the LM3697 LED driver for TI LMU devices.
811 This supports the LED device LM3697.
812
813config LEDS_LM36274
814 tristate "LED driver for LM36274"
815 depends on LEDS_TI_LMU_COMMON
816 depends on MFD_TI_LMU
817 help
818 Say Y to enable the LM36274 LED driver for TI LMU devices.
819 This supports the LED device LM36274.
820
796comment "LED Triggers" 821comment "LED Triggers"
797source "drivers/leds/trigger/Kconfig" 822source "drivers/leds/trigger/Kconfig"
798 823
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 2e8bff590700..41fb073a39c1 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -82,6 +82,9 @@ obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o
82obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o 82obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o
83obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o 83obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
84obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o 84obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o
85obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o
86obj-$(CONFIG_LEDS_LM3697) += leds-lm3697.o
87obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o
85 88
86# LED SPI Drivers 89# LED SPI Drivers
87obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o 90obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c
new file mode 100644
index 000000000000..ed9dc857ec8f
--- /dev/null
+++ b/drivers/leds/leds-lm36274.c
@@ -0,0 +1,172 @@
1// SPDX-License-Identifier: GPL-2.0
2// TI LM36274 LED chip family driver
3// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
4
5#include <linux/bitops.h>
6#include <linux/device.h>
7#include <linux/err.h>
8#include <linux/leds.h>
9#include <linux/leds-ti-lmu-common.h>
10#include <linux/module.h>
11#include <linux/of_device.h>
12#include <linux/platform_device.h>
13
14#include <linux/mfd/ti-lmu.h>
15#include <linux/mfd/ti-lmu-register.h>
16
17#include <uapi/linux/uleds.h>
18
19#define LM36274_MAX_STRINGS 4
20#define LM36274_BL_EN BIT(4)
21
22/**
23 * struct lm36274
24 * @pdev: platform device
25 * @led_dev: led class device
26 * @lmu_data: Register and setting values for common code
27 * @regmap: Devices register map
28 * @dev: Pointer to the devices device struct
29 * @led_sources - The LED strings supported in this array
30 * @num_leds - Number of LED strings are supported in this array
31 */
32struct lm36274 {
33 struct platform_device *pdev;
34 struct led_classdev led_dev;
35 struct ti_lmu_bank lmu_data;
36 struct regmap *regmap;
37 struct device *dev;
38
39 u32 led_sources[LM36274_MAX_STRINGS];
40 int num_leds;
41};
42
43static int lm36274_brightness_set(struct led_classdev *led_cdev,
44 enum led_brightness brt_val)
45{
46 struct lm36274 *led = container_of(led_cdev, struct lm36274, led_dev);
47
48 return ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
49}
50
51static int lm36274_init(struct lm36274 *lm36274_data)
52{
53 int enable_val = 0;
54 int i;
55
56 for (i = 0; i < lm36274_data->num_leds; i++)
57 enable_val |= (1 << lm36274_data->led_sources[i]);
58
59 if (!enable_val) {
60 dev_err(lm36274_data->dev, "No LEDs were enabled\n");
61 return -EINVAL;
62 }
63
64 enable_val |= LM36274_BL_EN;
65
66 return regmap_write(lm36274_data->regmap, LM36274_REG_BL_EN,
67 enable_val);
68}
69
70static int lm36274_parse_dt(struct lm36274 *lm36274_data)
71{
72 struct fwnode_handle *child = NULL;
73 char label[LED_MAX_NAME_SIZE];
74 struct device *dev = &lm36274_data->pdev->dev;
75 const char *name;
76 int child_cnt;
77 int ret = -EINVAL;
78
79 /* There should only be 1 node */
80 child_cnt = device_get_child_node_count(dev);
81 if (child_cnt != 1)
82 return -EINVAL;
83
84 device_for_each_child_node(dev, child) {
85 ret = fwnode_property_read_string(child, "label", &name);
86 if (ret)
87 snprintf(label, sizeof(label),
88 "%s::", lm36274_data->pdev->name);
89 else
90 snprintf(label, sizeof(label),
91 "%s:%s", lm36274_data->pdev->name, name);
92
93 lm36274_data->num_leds = fwnode_property_read_u32_array(child,
94 "led-sources",
95 NULL, 0);
96 if (lm36274_data->num_leds <= 0)
97 return -ENODEV;
98
99 ret = fwnode_property_read_u32_array(child, "led-sources",
100 lm36274_data->led_sources,
101 lm36274_data->num_leds);
102 if (ret) {
103 dev_err(dev, "led-sources property missing\n");
104 return ret;
105 }
106
107 fwnode_property_read_string(child, "linux,default-trigger",
108 &lm36274_data->led_dev.default_trigger);
109
110 }
111
112 lm36274_data->lmu_data.regmap = lm36274_data->regmap;
113 lm36274_data->lmu_data.max_brightness = MAX_BRIGHTNESS_11BIT;
114 lm36274_data->lmu_data.msb_brightness_reg = LM36274_REG_BRT_MSB;
115 lm36274_data->lmu_data.lsb_brightness_reg = LM36274_REG_BRT_LSB;
116
117 lm36274_data->led_dev.name = label;
118 lm36274_data->led_dev.max_brightness = MAX_BRIGHTNESS_11BIT;
119 lm36274_data->led_dev.brightness_set_blocking = lm36274_brightness_set;
120
121 return 0;
122}
123
124static int lm36274_probe(struct platform_device *pdev)
125{
126 struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
127 struct lm36274 *lm36274_data;
128 int ret;
129
130 lm36274_data = devm_kzalloc(&pdev->dev, sizeof(*lm36274_data),
131 GFP_KERNEL);
132 if (!lm36274_data)
133 return -ENOMEM;
134
135 lm36274_data->pdev = pdev;
136 lm36274_data->dev = lmu->dev;
137 lm36274_data->regmap = lmu->regmap;
138 dev_set_drvdata(&pdev->dev, lm36274_data);
139
140 ret = lm36274_parse_dt(lm36274_data);
141 if (ret) {
142 dev_err(lm36274_data->dev, "Failed to parse DT node\n");
143 return ret;
144 }
145
146 ret = lm36274_init(lm36274_data);
147 if (ret) {
148 dev_err(lm36274_data->dev, "Failed to init the device\n");
149 return ret;
150 }
151
152 return devm_led_classdev_register(lm36274_data->dev,
153 &lm36274_data->led_dev);
154}
155
156static const struct of_device_id of_lm36274_leds_match[] = {
157 { .compatible = "ti,lm36274-backlight", },
158 {},
159};
160MODULE_DEVICE_TABLE(of, of_lm36274_leds_match);
161
162static struct platform_driver lm36274_driver = {
163 .probe = lm36274_probe,
164 .driver = {
165 .name = "lm36274-leds",
166 },
167};
168module_platform_driver(lm36274_driver)
169
170MODULE_DESCRIPTION("Texas Instruments LM36274 LED driver");
171MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
172MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c
new file mode 100644
index 000000000000..54e0e35df824
--- /dev/null
+++ b/drivers/leds/leds-lm3697.c
@@ -0,0 +1,395 @@
1// SPDX-License-Identifier: GPL-2.0
2// TI LM3697 LED chip family driver
3// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
4
5#include <linux/gpio/consumer.h>
6#include <linux/i2c.h>
7#include <linux/of.h>
8#include <linux/of_gpio.h>
9#include <linux/regulator/consumer.h>
10#include <linux/leds-ti-lmu-common.h>
11
12#define LM3697_REV 0x0
13#define LM3697_RESET 0x1
14#define LM3697_OUTPUT_CONFIG 0x10
15#define LM3697_CTRL_A_RAMP 0x11
16#define LM3697_CTRL_B_RAMP 0x12
17#define LM3697_CTRL_A_B_RT_RAMP 0x13
18#define LM3697_CTRL_A_B_RAMP_CFG 0x14
19#define LM3697_CTRL_A_B_BRT_CFG 0x16
20#define LM3697_CTRL_A_FS_CURR_CFG 0x17
21#define LM3697_CTRL_B_FS_CURR_CFG 0x18
22#define LM3697_PWM_CFG 0x1c
23#define LM3697_CTRL_A_BRT_LSB 0x20
24#define LM3697_CTRL_A_BRT_MSB 0x21
25#define LM3697_CTRL_B_BRT_LSB 0x22
26#define LM3697_CTRL_B_BRT_MSB 0x23
27#define LM3697_CTRL_ENABLE 0x24
28
29#define LM3697_SW_RESET BIT(0)
30
31#define LM3697_CTRL_A_EN BIT(0)
32#define LM3697_CTRL_B_EN BIT(1)
33#define LM3697_CTRL_A_B_EN (LM3697_CTRL_A_EN | LM3697_CTRL_B_EN)
34
35#define LM3697_MAX_LED_STRINGS 3
36
37#define LM3697_CONTROL_A 0
38#define LM3697_CONTROL_B 1
39#define LM3697_MAX_CONTROL_BANKS 2
40
41/**
42 * struct lm3697_led -
43 * @hvled_strings: Array of LED strings associated with a control bank
44 * @label: LED label
45 * @led_dev: LED class device
46 * @priv: Pointer to the device struct
47 * @lmu_data: Register and setting values for common code
48 * @control_bank: Control bank the LED is associated to. 0 is control bank A
49 * 1 is control bank B
50 */
51struct lm3697_led {
52 u32 hvled_strings[LM3697_MAX_LED_STRINGS];
53 char label[LED_MAX_NAME_SIZE];
54 struct led_classdev led_dev;
55 struct lm3697 *priv;
56 struct ti_lmu_bank lmu_data;
57 int control_bank;
58 int enabled;
59 int num_leds;
60};
61
62/**
63 * struct lm3697 -
64 * @enable_gpio: Hardware enable gpio
65 * @regulator: LED supply regulator pointer
66 * @client: Pointer to the I2C client
67 * @regmap: Devices register map
68 * @dev: Pointer to the devices device struct
69 * @lock: Lock for reading/writing the device
70 * @leds: Array of LED strings
71 */
72struct lm3697 {
73 struct gpio_desc *enable_gpio;
74 struct regulator *regulator;
75 struct i2c_client *client;
76 struct regmap *regmap;
77 struct device *dev;
78 struct mutex lock;
79
80 int bank_cfg;
81
82 struct lm3697_led leds[];
83};
84
85static const struct reg_default lm3697_reg_defs[] = {
86 {LM3697_OUTPUT_CONFIG, 0x6},
87 {LM3697_CTRL_A_RAMP, 0x0},
88 {LM3697_CTRL_B_RAMP, 0x0},
89 {LM3697_CTRL_A_B_RT_RAMP, 0x0},
90 {LM3697_CTRL_A_B_RAMP_CFG, 0x0},
91 {LM3697_CTRL_A_B_BRT_CFG, 0x0},
92 {LM3697_CTRL_A_FS_CURR_CFG, 0x13},
93 {LM3697_CTRL_B_FS_CURR_CFG, 0x13},
94 {LM3697_PWM_CFG, 0xc},
95 {LM3697_CTRL_A_BRT_LSB, 0x0},
96 {LM3697_CTRL_A_BRT_MSB, 0x0},
97 {LM3697_CTRL_B_BRT_LSB, 0x0},
98 {LM3697_CTRL_B_BRT_MSB, 0x0},
99 {LM3697_CTRL_ENABLE, 0x0},
100};
101
102static const struct regmap_config lm3697_regmap_config = {
103 .reg_bits = 8,
104 .val_bits = 8,
105
106 .max_register = LM3697_CTRL_ENABLE,
107 .reg_defaults = lm3697_reg_defs,
108 .num_reg_defaults = ARRAY_SIZE(lm3697_reg_defs),
109 .cache_type = REGCACHE_FLAT,
110};
111
112static int lm3697_brightness_set(struct led_classdev *led_cdev,
113 enum led_brightness brt_val)
114{
115 struct lm3697_led *led = container_of(led_cdev, struct lm3697_led,
116 led_dev);
117 int ctrl_en_val = (1 << led->control_bank);
118 int ret;
119
120 mutex_lock(&led->priv->lock);
121
122 if (brt_val == LED_OFF) {
123 ret = regmap_update_bits(led->priv->regmap, LM3697_CTRL_ENABLE,
124 ctrl_en_val, ~ctrl_en_val);
125 if (ret) {
126 dev_err(&led->priv->client->dev, "Cannot write ctrl register\n");
127 goto brightness_out;
128 }
129
130 led->enabled = LED_OFF;
131 } else {
132 ret = ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
133 if (ret) {
134 dev_err(&led->priv->client->dev,
135 "Cannot write brightness\n");
136 goto brightness_out;
137 }
138
139 if (!led->enabled) {
140 ret = regmap_update_bits(led->priv->regmap,
141 LM3697_CTRL_ENABLE,
142 ctrl_en_val, ctrl_en_val);
143 if (ret) {
144 dev_err(&led->priv->client->dev,
145 "Cannot enable the device\n");
146 goto brightness_out;
147 }
148
149 led->enabled = brt_val;
150 }
151 }
152
153brightness_out:
154 mutex_unlock(&led->priv->lock);
155 return ret;
156}
157
158static int lm3697_init(struct lm3697 *priv)
159{
160 struct lm3697_led *led;
161 int i, ret;
162
163 if (priv->enable_gpio) {
164 gpiod_direction_output(priv->enable_gpio, 1);
165 } else {
166 ret = regmap_write(priv->regmap, LM3697_RESET, LM3697_SW_RESET);
167 if (ret) {
168 dev_err(&priv->client->dev, "Cannot reset the device\n");
169 goto out;
170 }
171 }
172
173 ret = regmap_write(priv->regmap, LM3697_CTRL_ENABLE, 0x0);
174 if (ret) {
175 dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
176 goto out;
177 }
178
179 ret = regmap_write(priv->regmap, LM3697_OUTPUT_CONFIG, priv->bank_cfg);
180 if (ret)
181 dev_err(&priv->client->dev, "Cannot write OUTPUT config\n");
182
183 for (i = 0; i < LM3697_MAX_CONTROL_BANKS; i++) {
184 led = &priv->leds[i];
185 ret = ti_lmu_common_set_ramp(&led->lmu_data);
186 if (ret)
187 dev_err(&priv->client->dev, "Setting the ramp rate failed\n");
188 }
189out:
190 return ret;
191}
192
193static int lm3697_probe_dt(struct lm3697 *priv)
194{
195 struct fwnode_handle *child = NULL;
196 struct lm3697_led *led;
197 const char *name;
198 int control_bank;
199 size_t i = 0;
200 int ret = -EINVAL;
201 int j;
202
203 priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
204 "enable", GPIOD_OUT_LOW);
205 if (IS_ERR(priv->enable_gpio)) {
206 ret = PTR_ERR(priv->enable_gpio);
207 dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
208 ret);
209 return ret;
210 }
211
212 priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
213 if (IS_ERR(priv->regulator))
214 priv->regulator = NULL;
215
216 device_for_each_child_node(priv->dev, child) {
217 ret = fwnode_property_read_u32(child, "reg", &control_bank);
218 if (ret) {
219 dev_err(&priv->client->dev, "reg property missing\n");
220 fwnode_handle_put(child);
221 goto child_out;
222 }
223
224 if (control_bank > LM3697_CONTROL_B) {
225 dev_err(&priv->client->dev, "reg property is invalid\n");
226 ret = -EINVAL;
227 fwnode_handle_put(child);
228 goto child_out;
229 }
230
231 led = &priv->leds[i];
232
233 ret = ti_lmu_common_get_brt_res(&priv->client->dev,
234 child, &led->lmu_data);
235 if (ret)
236 dev_warn(&priv->client->dev, "brightness resolution property missing\n");
237
238 led->control_bank = control_bank;
239 led->lmu_data.regmap = priv->regmap;
240 led->lmu_data.runtime_ramp_reg = LM3697_CTRL_A_RAMP +
241 control_bank;
242 led->lmu_data.msb_brightness_reg = LM3697_CTRL_A_BRT_MSB +
243 led->control_bank * 2;
244 led->lmu_data.lsb_brightness_reg = LM3697_CTRL_A_BRT_LSB +
245 led->control_bank * 2;
246
247 led->num_leds = fwnode_property_read_u32_array(child,
248 "led-sources",
249 NULL, 0);
250
251 if (led->num_leds > LM3697_MAX_LED_STRINGS) {
252 dev_err(&priv->client->dev, "To many LED strings defined\n");
253 continue;
254 }
255
256 ret = fwnode_property_read_u32_array(child, "led-sources",
257 led->hvled_strings,
258 led->num_leds);
259 if (ret) {
260 dev_err(&priv->client->dev, "led-sources property missing\n");
261 fwnode_handle_put(child);
262 goto child_out;
263 }
264
265 for (j = 0; j < led->num_leds; j++)
266 priv->bank_cfg |=
267 (led->control_bank << led->hvled_strings[j]);
268
269 ret = ti_lmu_common_get_ramp_params(&priv->client->dev,
270 child, &led->lmu_data);
271 if (ret)
272 dev_warn(&priv->client->dev, "runtime-ramp properties missing\n");
273
274 fwnode_property_read_string(child, "linux,default-trigger",
275 &led->led_dev.default_trigger);
276
277 ret = fwnode_property_read_string(child, "label", &name);
278 if (ret)
279 snprintf(led->label, sizeof(led->label),
280 "%s::", priv->client->name);
281 else
282 snprintf(led->label, sizeof(led->label),
283 "%s:%s", priv->client->name, name);
284
285 led->priv = priv;
286 led->led_dev.name = led->label;
287 led->led_dev.max_brightness = led->lmu_data.max_brightness;
288 led->led_dev.brightness_set_blocking = lm3697_brightness_set;
289
290 ret = devm_led_classdev_register(priv->dev, &led->led_dev);
291 if (ret) {
292 dev_err(&priv->client->dev, "led register err: %d\n",
293 ret);
294 fwnode_handle_put(child);
295 goto child_out;
296 }
297
298 i++;
299 }
300
301child_out:
302 return ret;
303}
304
305static int lm3697_probe(struct i2c_client *client,
306 const struct i2c_device_id *id)
307{
308 struct lm3697 *led;
309 int count;
310 int ret;
311
312 count = device_get_child_node_count(&client->dev);
313 if (!count) {
314 dev_err(&client->dev, "LEDs are not defined in device tree!");
315 return -ENODEV;
316 }
317
318 led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
319 GFP_KERNEL);
320 if (!led)
321 return -ENOMEM;
322
323 mutex_init(&led->lock);
324 i2c_set_clientdata(client, led);
325
326 led->client = client;
327 led->dev = &client->dev;
328 led->regmap = devm_regmap_init_i2c(client, &lm3697_regmap_config);
329 if (IS_ERR(led->regmap)) {
330 ret = PTR_ERR(led->regmap);
331 dev_err(&client->dev, "Failed to allocate register map: %d\n",
332 ret);
333 return ret;
334 }
335
336 ret = lm3697_probe_dt(led);
337 if (ret)
338 return ret;
339
340 return lm3697_init(led);
341}
342
343static int lm3697_remove(struct i2c_client *client)
344{
345 struct lm3697 *led = i2c_get_clientdata(client);
346 int ret;
347
348 ret = regmap_update_bits(led->regmap, LM3697_CTRL_ENABLE,
349 LM3697_CTRL_A_B_EN, 0);
350 if (ret) {
351 dev_err(&led->client->dev, "Failed to disable the device\n");
352 return ret;
353 }
354
355 if (led->enable_gpio)
356 gpiod_direction_output(led->enable_gpio, 0);
357
358 if (led->regulator) {
359 ret = regulator_disable(led->regulator);
360 if (ret)
361 dev_err(&led->client->dev,
362 "Failed to disable regulator\n");
363 }
364
365 mutex_destroy(&led->lock);
366
367 return 0;
368}
369
370static const struct i2c_device_id lm3697_id[] = {
371 { "lm3697", 0 },
372 { }
373};
374MODULE_DEVICE_TABLE(i2c, lm3697_id);
375
376static const struct of_device_id of_lm3697_leds_match[] = {
377 { .compatible = "ti,lm3697", },
378 {},
379};
380MODULE_DEVICE_TABLE(of, of_lm3697_leds_match);
381
382static struct i2c_driver lm3697_driver = {
383 .driver = {
384 .name = "lm3697",
385 .of_match_table = of_lm3697_leds_match,
386 },
387 .probe = lm3697_probe,
388 .remove = lm3697_remove,
389 .id_table = lm3697_id,
390};
391module_i2c_driver(lm3697_driver);
392
393MODULE_DESCRIPTION("Texas Instruments LM3697 LED driver");
394MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
395MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-ti-lmu-common.c b/drivers/leds/leds-ti-lmu-common.c
new file mode 100644
index 000000000000..adc7293004f1
--- /dev/null
+++ b/drivers/leds/leds-ti-lmu-common.c
@@ -0,0 +1,156 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright 2015 Texas Instruments
3// Copyright 2018 Sebastian Reichel
4// Copyright 2018 Pavel Machek <pavel@ucw.cz>
5// TI LMU LED common framework, based on previous work from
6// Milo Kim <milo.kim@ti.com>
7
8#include <linux/bitops.h>
9#include <linux/err.h>
10#include <linux/of_device.h>
11
12#include <linux/leds-ti-lmu-common.h>
13
14const static int ramp_table[16] = {2048, 262000, 524000, 1049000, 2090000,
15 4194000, 8389000, 16780000, 33550000, 41940000,
16 50330000, 58720000, 67110000, 83880000,
17 100660000, 117440000};
18
19static int ti_lmu_common_update_brightness(struct ti_lmu_bank *lmu_bank,
20 int brightness)
21{
22 struct regmap *regmap = lmu_bank->regmap;
23 u8 reg, val;
24 int ret;
25
26 /*
27 * Brightness register update
28 *
29 * 11 bit dimming: update LSB bits and write MSB byte.
30 * MSB brightness should be shifted.
31 * 8 bit dimming: write MSB byte.
32 */
33 if (lmu_bank->max_brightness == MAX_BRIGHTNESS_11BIT) {
34 reg = lmu_bank->lsb_brightness_reg;
35 ret = regmap_update_bits(regmap, reg,
36 LMU_11BIT_LSB_MASK,
37 brightness);
38 if (ret)
39 return ret;
40
41 val = brightness >> LMU_11BIT_MSB_SHIFT;
42 } else {
43 val = brightness;
44 }
45
46 reg = lmu_bank->msb_brightness_reg;
47
48 return regmap_write(regmap, reg, val);
49}
50
51int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness)
52{
53 return ti_lmu_common_update_brightness(lmu_bank, brightness);
54}
55EXPORT_SYMBOL(ti_lmu_common_set_brightness);
56
57static int ti_lmu_common_convert_ramp_to_index(unsigned int usec)
58{
59 int size = ARRAY_SIZE(ramp_table);
60 int i;
61
62 if (usec <= ramp_table[0])
63 return 0;
64
65 if (usec > ramp_table[size - 1])
66 return size - 1;
67
68 for (i = 1; i < size; i++) {
69 if (usec == ramp_table[i])
70 return i;
71
72 /* Find an approximate index by looking up the table */
73 if (usec > ramp_table[i - 1] && usec < ramp_table[i]) {
74 if (usec - ramp_table[i - 1] < ramp_table[i] - usec)
75 return i - 1;
76 else
77 return i;
78 }
79 }
80
81 return -EINVAL;
82}
83
84int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank)
85{
86 struct regmap *regmap = lmu_bank->regmap;
87 u8 ramp, ramp_up, ramp_down;
88
89 if (lmu_bank->ramp_up_usec == 0 && lmu_bank->ramp_down_usec == 0) {
90 ramp_up = 0;
91 ramp_down = 0;
92 } else {
93 ramp_up = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_up_usec);
94 ramp_down = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_down_usec);
95 }
96
97 if (ramp_up < 0 || ramp_down < 0)
98 return -EINVAL;
99
100 ramp = (ramp_up << 4) | ramp_down;
101
102 return regmap_write(regmap, lmu_bank->runtime_ramp_reg, ramp);
103
104}
105EXPORT_SYMBOL(ti_lmu_common_set_ramp);
106
107int ti_lmu_common_get_ramp_params(struct device *dev,
108 struct fwnode_handle *child,
109 struct ti_lmu_bank *lmu_data)
110{
111 int ret;
112
113 ret = fwnode_property_read_u32(child, "ramp-up-us",
114 &lmu_data->ramp_up_usec);
115 if (ret)
116 dev_warn(dev, "ramp-up-us property missing\n");
117
118
119 ret = fwnode_property_read_u32(child, "ramp-down-us",
120 &lmu_data->ramp_down_usec);
121 if (ret)
122 dev_warn(dev, "ramp-down-us property missing\n");
123
124 return 0;
125}
126EXPORT_SYMBOL(ti_lmu_common_get_ramp_params);
127
128int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child,
129 struct ti_lmu_bank *lmu_data)
130{
131 int ret;
132
133 ret = device_property_read_u32(dev, "ti,brightness-resolution",
134 &lmu_data->max_brightness);
135 if (ret)
136 ret = fwnode_property_read_u32(child,
137 "ti,brightness-resolution",
138 &lmu_data->max_brightness);
139 if (lmu_data->max_brightness <= 0) {
140 lmu_data->max_brightness = MAX_BRIGHTNESS_8BIT;
141 return ret;
142 }
143
144 if (lmu_data->max_brightness > MAX_BRIGHTNESS_11BIT)
145 lmu_data->max_brightness = MAX_BRIGHTNESS_11BIT;
146
147
148 return 0;
149}
150EXPORT_SYMBOL(ti_lmu_common_get_brt_res);
151
152MODULE_DESCRIPTION("TI LMU common LED framework");
153MODULE_AUTHOR("Sebastian Reichel");
154MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
155MODULE_LICENSE("GPL v2");
156MODULE_ALIAS("ti-lmu-led-common");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 294d9567cc71..a69aca3c2dab 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1335,9 +1335,8 @@ config MFD_TI_LMU
1335 select REGMAP_I2C 1335 select REGMAP_I2C
1336 help 1336 help
1337 Say yes here to enable support for TI LMU chips. 1337 Say yes here to enable support for TI LMU chips.
1338 1338 TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and
1339 TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697. 1339 LM36274. It consists of backlight, LED and regulator driver.
1340 It consists of backlight, LED and regulator driver.
1341 It provides consistent device controls for lighting functions. 1340 It provides consistent device controls for lighting functions.
1342 1341
1343config MFD_OMAP_USB_HOST 1342config MFD_OMAP_USB_HOST
diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
index b06cb908d1aa..691ab9dd6236 100644
--- a/drivers/mfd/ti-lmu.c
+++ b/drivers/mfd/ti-lmu.c
@@ -111,17 +111,14 @@ static const struct mfd_cell lm3695_devices[] = {
111 }, 111 },
112}; 112};
113 113
114static const struct mfd_cell lm3697_devices[] = { 114static const struct mfd_cell lm36274_devices[] = {
115 LM363X_REGULATOR(LM36274_BOOST),
116 LM363X_REGULATOR(LM36274_LDO_POS),
117 LM363X_REGULATOR(LM36274_LDO_NEG),
115 { 118 {
116 .name = "ti-lmu-backlight", 119 .name = "lm36274-leds",
117 .id = LM3697, 120 .id = LM36274,
118 .of_compatible = "ti,lm3697-backlight", 121 .of_compatible = "ti,lm36274-backlight",
119 },
120 /* Monitoring driver for open/short circuit detection */
121 {
122 .name = "ti-lmu-fault-monitor",
123 .id = LM3697,
124 .of_compatible = "ti,lm3697-fault-monitor",
125 }, 122 },
126}; 123};
127 124
@@ -137,7 +134,7 @@ TI_LMU_DATA(lm3631, LM3631_MAX_REG);
137TI_LMU_DATA(lm3632, LM3632_MAX_REG); 134TI_LMU_DATA(lm3632, LM3632_MAX_REG);
138TI_LMU_DATA(lm3633, LM3633_MAX_REG); 135TI_LMU_DATA(lm3633, LM3633_MAX_REG);
139TI_LMU_DATA(lm3695, LM3695_MAX_REG); 136TI_LMU_DATA(lm3695, LM3695_MAX_REG);
140TI_LMU_DATA(lm3697, LM3697_MAX_REG); 137TI_LMU_DATA(lm36274, LM36274_MAX_REG);
141 138
142static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) 139static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id)
143{ 140{
@@ -206,7 +203,7 @@ static const struct of_device_id ti_lmu_of_match[] = {
206 { .compatible = "ti,lm3632", .data = &lm3632_data }, 203 { .compatible = "ti,lm3632", .data = &lm3632_data },
207 { .compatible = "ti,lm3633", .data = &lm3633_data }, 204 { .compatible = "ti,lm3633", .data = &lm3633_data },
208 { .compatible = "ti,lm3695", .data = &lm3695_data }, 205 { .compatible = "ti,lm3695", .data = &lm3695_data },
209 { .compatible = "ti,lm3697", .data = &lm3697_data }, 206 { .compatible = "ti,lm36274", .data = &lm36274_data },
210 { } 207 { }
211}; 208};
212MODULE_DEVICE_TABLE(of, ti_lmu_of_match); 209MODULE_DEVICE_TABLE(of, ti_lmu_of_match);
@@ -216,7 +213,7 @@ static const struct i2c_device_id ti_lmu_ids[] = {
216 { "lm3632", LM3632 }, 213 { "lm3632", LM3632 },
217 { "lm3633", LM3633 }, 214 { "lm3633", LM3633 },
218 { "lm3695", LM3695 }, 215 { "lm3695", LM3695 },
219 { "lm3697", LM3697 }, 216 { "lm36274", LM36274 },
220 { } 217 { }
221}; 218};
222MODULE_DEVICE_TABLE(i2c, ti_lmu_ids); 219MODULE_DEVICE_TABLE(i2c, ti_lmu_ids);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6c37f0df9323..34e03691dd00 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -363,7 +363,7 @@ config REGULATOR_LM363X
363 tristate "TI LM363X voltage regulators" 363 tristate "TI LM363X voltage regulators"
364 depends on MFD_TI_LMU 364 depends on MFD_TI_LMU
365 help 365 help
366 This driver supports LM3631 and LM3632 voltage regulators for 366 This driver supports LM3631, LM3632 and LM36274 voltage regulators for
367 the LCD bias. 367 the LCD bias.
368 One boost output voltage is configurable and always on. 368 One boost output voltage is configurable and always on.
369 Other LDOs are used for the display module. 369 Other LDOs are used for the display module.
diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c
index e02fdd1dd092..12b6007a23ad 100644
--- a/drivers/regulator/lm363x-regulator.c
+++ b/drivers/regulator/lm363x-regulator.c
@@ -37,6 +37,11 @@
37#define LM3632_VBOOST_MIN 4500000 37#define LM3632_VBOOST_MIN 4500000
38#define LM3632_VLDO_MIN 4000000 38#define LM3632_VLDO_MIN 4000000
39 39
40/* LM36274 */
41#define LM36274_BOOST_VSEL_MAX 0x3f
42#define LM36274_LDO_VSEL_MAX 0x34
43#define LM36274_VOLTAGE_MIN 4000000
44
40/* Common */ 45/* Common */
41#define LM363X_STEP_50mV 50000 46#define LM363X_STEP_50mV 50000
42#define LM363X_STEP_500mV 500000 47#define LM363X_STEP_500mV 500000
@@ -217,6 +222,51 @@ static const struct regulator_desc lm363x_regulator_desc[] = {
217 .enable_reg = LM3632_REG_BIAS_CONFIG, 222 .enable_reg = LM3632_REG_BIAS_CONFIG,
218 .enable_mask = LM3632_EN_VNEG_MASK, 223 .enable_mask = LM3632_EN_VNEG_MASK,
219 }, 224 },
225
226 /* LM36274 */
227 {
228 .name = "vboost",
229 .of_match = "vboost",
230 .id = LM36274_BOOST,
231 .ops = &lm363x_boost_voltage_table_ops,
232 .n_voltages = LM36274_BOOST_VSEL_MAX,
233 .min_uV = LM36274_VOLTAGE_MIN,
234 .uV_step = LM363X_STEP_50mV,
235 .type = REGULATOR_VOLTAGE,
236 .owner = THIS_MODULE,
237 .vsel_reg = LM36274_REG_VOUT_BOOST,
238 .vsel_mask = LM36274_VOUT_MASK,
239 },
240 {
241 .name = "ldo_vpos",
242 .of_match = "vpos",
243 .id = LM36274_LDO_POS,
244 .ops = &lm363x_regulator_voltage_table_ops,
245 .n_voltages = LM36274_LDO_VSEL_MAX,
246 .min_uV = LM36274_VOLTAGE_MIN,
247 .uV_step = LM363X_STEP_50mV,
248 .type = REGULATOR_VOLTAGE,
249 .owner = THIS_MODULE,
250 .vsel_reg = LM36274_REG_VOUT_POS,
251 .vsel_mask = LM36274_VOUT_MASK,
252 .enable_reg = LM36274_REG_BIAS_CONFIG_1,
253 .enable_mask = LM36274_EN_VPOS_MASK,
254 },
255 {
256 .name = "ldo_vneg",
257 .of_match = "vneg",
258 .id = LM36274_LDO_NEG,
259 .ops = &lm363x_regulator_voltage_table_ops,
260 .n_voltages = LM36274_LDO_VSEL_MAX,
261 .min_uV = LM36274_VOLTAGE_MIN,
262 .uV_step = LM363X_STEP_50mV,
263 .type = REGULATOR_VOLTAGE,
264 .owner = THIS_MODULE,
265 .vsel_reg = LM36274_REG_VOUT_NEG,
266 .vsel_mask = LM36274_VOUT_MASK,
267 .enable_reg = LM36274_REG_BIAS_CONFIG_1,
268 .enable_mask = LM36274_EN_VNEG_MASK,
269 },
220}; 270};
221 271
222static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id) 272static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
@@ -229,9 +279,11 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
229 */ 279 */
230 switch (id) { 280 switch (id) {
231 case LM3632_LDO_POS: 281 case LM3632_LDO_POS:
282 case LM36274_LDO_POS:
232 return gpiod_get_index_optional(dev, "enable", 0, 283 return gpiod_get_index_optional(dev, "enable", 0,
233 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 284 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
234 case LM3632_LDO_NEG: 285 case LM3632_LDO_NEG:
286 case LM36274_LDO_NEG:
235 return gpiod_get_index_optional(dev, "enable", 1, 287 return gpiod_get_index_optional(dev, "enable", 1,
236 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 288 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
237 default: 289 default:
@@ -239,6 +291,27 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
239 } 291 }
240} 292}
241 293
294static int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
295{
296 int ext_en_mask = 0;
297
298 switch (id) {
299 case LM3632_LDO_POS:
300 case LM3632_LDO_NEG:
301 ext_en_mask = LM3632_EXT_EN_MASK;
302 break;
303 case LM36274_LDO_POS:
304 case LM36274_LDO_NEG:
305 ext_en_mask = LM36274_EXT_EN_MASK;
306 break;
307 default:
308 return -ENODEV;
309 }
310
311 return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
312 ext_en_mask, ext_en_mask);
313}
314
242static int lm363x_regulator_probe(struct platform_device *pdev) 315static int lm363x_regulator_probe(struct platform_device *pdev)
243{ 316{
244 struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent); 317 struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
@@ -263,10 +336,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
263 336
264 if (gpiod) { 337 if (gpiod) {
265 cfg.ena_gpiod = gpiod; 338 cfg.ena_gpiod = gpiod;
266 339 ret = lm363x_regulator_set_ext_en(regmap, id);
267 ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG,
268 LM3632_EXT_EN_MASK,
269 LM3632_EXT_EN_MASK);
270 if (ret) { 340 if (ret) {
271 gpiod_put(gpiod); 341 gpiod_put(gpiod);
272 dev_err(dev, "External pin err: %d\n", ret); 342 dev_err(dev, "External pin err: %d\n", ret);
diff --git a/include/linux/leds-ti-lmu-common.h b/include/linux/leds-ti-lmu-common.h
new file mode 100644
index 000000000000..5eb111f38803
--- /dev/null
+++ b/include/linux/leds-ti-lmu-common.h
@@ -0,0 +1,47 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2// TI LMU Common Core
3// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
4
5#ifndef _TI_LMU_COMMON_H_
6#define _TI_LMU_COMMON_H_
7
8#include <linux/delay.h>
9#include <linux/device.h>
10#include <linux/init.h>
11#include <linux/leds.h>
12#include <linux/module.h>
13#include <linux/regmap.h>
14#include <linux/slab.h>
15#include <uapi/linux/uleds.h>
16
17#define LMU_11BIT_LSB_MASK (BIT(0) | BIT(1) | BIT(2))
18#define LMU_11BIT_MSB_SHIFT 3
19
20#define MAX_BRIGHTNESS_8BIT 255
21#define MAX_BRIGHTNESS_11BIT 2047
22
23struct ti_lmu_bank {
24 struct regmap *regmap;
25
26 int max_brightness;
27
28 u8 lsb_brightness_reg;
29 u8 msb_brightness_reg;
30
31 u8 runtime_ramp_reg;
32 u32 ramp_up_usec;
33 u32 ramp_down_usec;
34};
35
36int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness);
37
38int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank);
39
40int ti_lmu_common_get_ramp_params(struct device *dev,
41 struct fwnode_handle *child,
42 struct ti_lmu_bank *lmu_data);
43
44int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child,
45 struct ti_lmu_bank *lmu_data);
46
47#endif /* _TI_LMU_COMMON_H_ */
diff --git a/include/linux/mfd/ti-lmu-register.h b/include/linux/mfd/ti-lmu-register.h
index f09510561a55..076d8dea38fd 100644
--- a/include/linux/mfd/ti-lmu-register.h
+++ b/include/linux/mfd/ti-lmu-register.h
@@ -190,47 +190,26 @@
190 190
191#define LM3695_MAX_REG 0x14 191#define LM3695_MAX_REG 0x14
192 192
193/* LM3697 */ 193/* LM36274 */
194#define LM3697_REG_HVLED_OUTPUT_CFG 0x10 194#define LM36274_REG_REV 0x01
195#define LM3697_HVLED1_CFG_MASK BIT(0) 195#define LM36274_REG_BL_CFG_1 0x02
196#define LM3697_HVLED2_CFG_MASK BIT(1) 196#define LM36274_REG_BL_CFG_2 0x03
197#define LM3697_HVLED3_CFG_MASK BIT(2) 197#define LM36274_REG_BRT_LSB 0x04
198#define LM3697_HVLED1_CFG_SHIFT 0 198#define LM36274_REG_BRT_MSB 0x05
199#define LM3697_HVLED2_CFG_SHIFT 1 199#define LM36274_REG_BL_EN 0x08
200#define LM3697_HVLED3_CFG_SHIFT 2 200
201#define LM36274_REG_BIAS_CONFIG_1 0x09
202#define LM36274_EXT_EN_MASK BIT(0)
203#define LM36274_EN_VNEG_MASK BIT(1)
204#define LM36274_EN_VPOS_MASK BIT(2)
205
206#define LM36274_REG_BIAS_CONFIG_2 0x0a
207#define LM36274_REG_BIAS_CONFIG_3 0x0b
208#define LM36274_REG_VOUT_BOOST 0x0c
209#define LM36274_REG_VOUT_POS 0x0d
210#define LM36274_REG_VOUT_NEG 0x0e
211#define LM36274_VOUT_MASK 0x3F
212
213#define LM36274_MAX_REG 0x13
201 214
202#define LM3697_REG_BL0_RAMP 0x11
203#define LM3697_REG_BL1_RAMP 0x12
204#define LM3697_RAMPUP_MASK 0xF0
205#define LM3697_RAMPUP_SHIFT 4
206#define LM3697_RAMPDN_MASK 0x0F
207#define LM3697_RAMPDN_SHIFT 0
208
209#define LM3697_REG_RAMP_CONF 0x14
210#define LM3697_RAMP_MASK 0x0F
211#define LM3697_RAMP_EACH 0x05
212
213#define LM3697_REG_PWM_CFG 0x1C
214#define LM3697_PWM_A_MASK BIT(0)
215#define LM3697_PWM_B_MASK BIT(1)
216
217#define LM3697_REG_IMAX_A 0x17
218#define LM3697_REG_IMAX_B 0x18
219
220#define LM3697_REG_FEEDBACK_ENABLE 0x19
221
222#define LM3697_REG_BRT_A_LSB 0x20
223#define LM3697_REG_BRT_A_MSB 0x21
224#define LM3697_REG_BRT_B_LSB 0x22
225#define LM3697_REG_BRT_B_MSB 0x23
226
227#define LM3697_REG_ENABLE 0x24
228
229#define LM3697_REG_OPEN_FAULT_STATUS 0xB0
230
231#define LM3697_REG_SHORT_FAULT_STATUS 0xB2
232
233#define LM3697_REG_MONITOR_ENABLE 0xB4
234
235#define LM3697_MAX_REG 0xB4
236#endif 215#endif
diff --git a/include/linux/mfd/ti-lmu.h b/include/linux/mfd/ti-lmu.h
index 7762c1bce55d..0957598c7d41 100644
--- a/include/linux/mfd/ti-lmu.h
+++ b/include/linux/mfd/ti-lmu.h
@@ -26,7 +26,7 @@ enum ti_lmu_id {
26 LM3632, 26 LM3632,
27 LM3633, 27 LM3633,
28 LM3695, 28 LM3695,
29 LM3697, 29 LM36274,
30 LMU_MAX_ID, 30 LMU_MAX_ID,
31}; 31};
32 32
@@ -68,6 +68,9 @@ enum lm363x_regulator_id {
68 LM3632_BOOST, /* Boost output */ 68 LM3632_BOOST, /* Boost output */
69 LM3632_LDO_POS, /* Positive display bias output */ 69 LM3632_LDO_POS, /* Positive display bias output */
70 LM3632_LDO_NEG, /* Negative display bias output */ 70 LM3632_LDO_NEG, /* Negative display bias output */
71 LM36274_BOOST, /* Boost output */
72 LM36274_LDO_POS, /* Positive display bias output */
73 LM36274_LDO_NEG, /* Negative display bias output */
71}; 74};
72 75
73/** 76/**