mfd: add LM3632 driver
authorMilo Kim <milo.kim@ti.com>
Wed, 25 Feb 2015 07:27:32 +0000 (16:27 +0900)
committerMilo Kim <milo.kim@ti.com>
Wed, 25 Feb 2015 07:27:32 +0000 (16:27 +0900)
- mfd, regulator and backlight driver
- Device tree bindings included
- Example code for LCD bias regulator consumer.

Signed-off-by: Milo Kim <milo.kim@ti.com>
Documentation/devicetree/bindings/mfd/lm3632.txt
Documentation/devicetree/bindings/regulator/lm3632-regulator.txt
Documentation/devicetree/bindings/video/backlight/lm3632_bl.txt
Examples/board-plat-lm3631.c [deleted file]
Examples/lm-lcd-driver.c
drivers/mfd/Kconfig
drivers/mfd/lm3632.c
drivers/regulator/lm3632-regulator.c
drivers/video/backlight/lm3632_bl.c
include/linux/mfd/lm3632.h

index f670058c8c67868bfe4dd6e0ecc8fafc5e92a270..3ab8ef544213c988ace8c1f6ff9d9367205e803f 100644 (file)
@@ -2,10 +2,10 @@ TI LM3632 MFD Driver
 
 Required properties:
   - compatible: "ti,lm3632"
-  - reg: I2C slave address. 0x29.
-  - ti,en-gpio: GPIO number of LM3632 nRST pin.
+  - reg: I2C slave address. 0x11.
+  - ti,en-gpio: GPIO number of LM3632 EN pin.
 
-LM3632 consists of two sub-devices, lm3632-regulator and lm3632-bl.
+LM3632 consists of lm3632-regulator and lm3632-bl.
 
 For the LM3632 regulator properties please refer to:
 Documentation/devicetree/bindings/regulator/lm3632-regulator.txt
@@ -19,17 +19,21 @@ lm3632@11 {
        compatible = "ti,lm3632";
        reg = <0x11>;
 
-       /* GPIO134 for HWEN pin */
-       ti,en-gpio = <&gpio5 6 0>;
+       /* GPIO for EN pin */
+       ti,en-gpio = <&gpio0 3 0>;
 
-       /* Only Vpos and Vneg are used with LCD boost */
+       /* Vpos and Vneg are used with LCD boost */
        regulators {
                compatible = "ti,lm3632-regulator";
 
+               /* GPIOs for LCM_EN1 and LCM_EN2 pins */
+               ti,lcm-en1-gpio = <&gpio0 2 0>;
+               ti,lcm-en2-gpio = <&gpio0 4 0>;
+
                vboost {
                        regulator-name = "lcd_boost";
                        regulator-min-microvolt = <4500000>;
-                       regulator-max-microvolt = <6350000>;
+                       regulator-max-microvolt = <6400000>;
                        regulator-always-on;
                };
 
@@ -48,12 +52,14 @@ lm3632@11 {
                };
        };
 
-       /* Backlight mode is I2C + PWM, two strings used */
+       /* Backlight mode is PWM, two strings used */
        backlight {
                compatible = "ti,lm3632-backlight";
 
                bl-name = "lcd";
                full-strings-used;
-               mode-comb1;
+
+               pwm-period = <10000>;
+               pwm-max-brightness = <1637>; /* 20mA */
        };
 };
index 7edb7bae5c58dca8fd314f0eae61aa256f92f872..fa9531d366fffad76d729cf0f3ba904a964363d5 100644 (file)
@@ -5,53 +5,47 @@ Required properties:
   - Regulator init data from of-regulator structure.
     Please refer to regulator.txt in this directory.
 
+Optional properties:
+  Two GPIO pins are used for enabling/disabling VPOS and VNEG.
+  These properties can be ignored if two LDOs are controlled through the I2C register.
+  - ti,lcm-en1-gpio: GPIO number of LCM_EN1 pin.
+  - ti,lcm-en2-gpio: GPIO number of LCM_EN2 pin.
+
 Example:
 
-&i2c4 {
-       clock-frequency = <400000>;
-
-       lm3632@11 {
-               compatible = "ti,lm3632";
-               reg = <0x29>;
-
-               /* GPIO134 for HWEN pin */
-               ti,en-gpio = <&gpio5 6 0>;
-
-               regulators {
-                       compatible = "ti,lm3632-regulator";
-
-                       vboost {
-                               regulator-name = "lcd_boost";
-                               regulator-min-microvolt = <4500000>;
-                               regulator-max-microvolt = <6350000>;
-                               regulator-always-on;
-                       };
-
-                       vcont {
-                               regulator-name = "lcd_cont";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3300000>;
-                       };
-
-                       voref {
-                               regulator-compatible = "voref";
-                               regulator-name = "lcd_oref";
-                               regulator-min-microvolt = <4000000>;
-                               regulator-max-microvolt = <6000000>;
-                       };
-
-                       vpos {
-                               regulator-name = "lcd_vpos";
-                               regulator-min-microvolt = <4000000>;
-                               regulator-max-microvolt = <6000000>;
-                               regulator-boot-on;
-                       };
-
-                       vneg {
-                               regulator-name = "lcd_vneg";
-                               regulator-min-microvolt = <4000000>;
-                               regulator-max-microvolt = <6000000>;
-                               regulator-boot-on;
-                       };
+lm3632@11 {
+       compatible = "ti,lm3632";
+       reg = <0x11>;
+
+       ti,en-gpio = <&gpio0 3 0>;
+
+       /* Vpos and Vneg are used with LCD boost */
+       regulators {
+               compatible = "ti,lm3632-regulator";
+
+               /* GPIOs for LCM_EN1 and LCM_EN2 pins */
+               ti,lcm-en1-gpio = <&gpio0 2 0>;
+               ti,lcm-en2-gpio = <&gpio0 4 0>;
+
+               vboost {
+                       regulator-name = "lcd_boost";
+                       regulator-min-microvolt = <4500000>;
+                       regulator-max-microvolt = <6400000>;
+                       regulator-always-on;
+               };
+
+               vpos {
+                       regulator-name = "lcd_vpos";
+                       regulator-min-microvolt = <4000000>;
+                       regulator-max-microvolt = <6000000>;
+                       regulator-boot-on;
+               };
+
+               vneg {
+                       regulator-name = "lcd_vneg";
+                       regulator-min-microvolt = <4000000>;
+                       regulator-max-microvolt = <6000000>;
+                       regulator-boot-on;
                };
+       };
 };
index 256b053d3bfc0c1279886828016f80d3ce8bee33..c09b911d7557a86898d7ac1e6d9faa26c491736f 100644 (file)
@@ -6,60 +6,28 @@ Required properties:
 Optional properties:
   - bl-name: Backlight device name
   - full-strings-used: Define it in case of two LED strings used.
-  - mode-pwm-only: PWM input mode
-    or mode-comb1: I2C x PWM befoer sloping
-    or mode-comb2: Sloped I2C x PWM
-    The default mode is the I2C only.
-  - initial-brightness: Initial brightness value
 
 PWM specific optional properties:
   - pwm-period: PWM period value. Define it in case of PWM based control mode.
-  - pwms and pwm-names: Please refer to Documentation/devicetree/bindings/pwm/pwm.txt.
+                If this property is not defined, then brightness control mode is I2C.
+  - pwm-max-brightness: Max current value in register 0x04 and 0x05.
+                        Range is from 0 to 2047.
 
+Example:
+lm3632@11 {
+       compatible = "ti,lm3632";
+       reg = <0x11>;
 
-Example 1:
-Brightness is I2C only mode. Backlight device name is 'lcd'.
+       ti,en-gpio = <&gpio0 3 0>;
 
-&i2c4 {
-       clock-frequency = <400000>;
+       /* Backlight mode is PWM, two strings used */
+       backlight {
+               compatible = "ti,lm3632-backlight";
 
-       lm3632@11 {
-               compatible = "ti,lm3632";
-               reg = <0x11>;
+               bl-name = "lcd";
+               full-strings-used;
 
-               /* GPIO134 for HWEN pin */
-               ti,en-gpio = <&gpio5 6 0>;
-
-               backlight {
-                       compatible = "ti,lm3632-backlight";
-                       bl-name = "lcd";
-                       full-strings-used;
-               };
-};
-
-Example 2:
-LM3632 brightness is controlled by PWM3943 controller.
-PWM3943 is a PWM controller. PWM#1 is port number of PMW3943.
-
-&i2c4 {
-       clock-frequency = <400000>;
-
-       lm3632@11 {
-               compatible = "ti,lm3632";
-               reg = <0x11>;
-
-               /* GPIO134 for HWEN pin */
-               ti,en-gpio = <&gpio5 6 0>;
-
-               backlight {
-                       compatible = "ti,lm3632-backlight";
-                       bl-name = "lcd";
-                       full-strings-used;
-                       mode-pwm-only;
-
-                       pwm-period = <10000>;
-
-                       pwms = <&pwm3943 1 10000>;
-                       pwm-names = "lm3632-backlight";
-               };
+               pwm-period = <10000>;
+               pwm-max-brightness = <1637>; /* 20mA */
+       };
 };
diff --git a/Examples/board-plat-lm3631.c b/Examples/board-plat-lm3631.c
deleted file mode 100644 (file)
index 5787c56..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *     Platform Specific LM3631 Example
- *
- *                     Copyright (C) 2013 Texas Instruments
- *
- * 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.
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/mfd/lm3631.h>
-#include <linux/pwm.h>
-
-#include "mux.h"
-#include "board-plat-lm3631.h"
-
-static struct regulator_consumer_supply lcd_vboost[] = {
-       REGULATOR_SUPPLY("lcd_boost", NULL),
-};
-
-static struct regulator_consumer_supply lcd_vio[] = {
-       REGULATOR_SUPPLY("lcd_io", NULL),
-};
-
-static struct regulator_consumer_supply lcd_vpos[] = {
-       REGULATOR_SUPPLY("lcd_vpos", NULL),
-};
-
-static struct regulator_consumer_supply lcd_vneg[] = {
-       REGULATOR_SUPPLY("lcd_vneg", NULL),
-};
-
-static struct regulator_consumer_supply lcd_vgamma[] = {
-       REGULATOR_SUPPLY("lcd_gamma", NULL),
-};
-
-struct regulator_init_data lcd_boost = {
-       .constraints = {
-               .name = "LCD_BOOST",
-               .min_uV = 4500000,
-               .max_uV = 6350000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-               .always_on = 1,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(lcd_vboost),
-       .consumer_supplies      = lcd_vboost,
-};
-
-struct regulator_init_data lcd_cont = {
-       .constraints = {
-               .name = "LCD_CONT",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(lcd_vio),
-       .consumer_supplies      = lcd_vio,
-};
-
-struct regulator_init_data lcd_oref = {
-       .constraints = {
-               .name = "LCD_OREF",
-               .min_uV = 4000000,
-               .max_uV = 6000000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(lcd_vgamma),
-       .consumer_supplies      = lcd_vgamma,
-};
-
-struct regulator_init_data lcd_pos = {
-       .constraints = {
-               .name = "LCD_VPOS",
-               .min_uV = 4000000,
-               .max_uV = 6000000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(lcd_vpos),
-       .consumer_supplies      = lcd_vpos,
-};
-
-struct regulator_init_data lcd_neg = {
-       .constraints = {
-               .name = "LCD_VNEG",
-               .min_uV = 4000000,
-               .max_uV = 6000000,
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
-               .boot_on = 1,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(lcd_vneg),
-       .consumer_supplies      = lcd_vneg,
-};
-
-struct lm3631_backlight_platform_data lm3631_bl_pdata = {
-       .name = "lcd-bl",
-       .is_full_strings = true,
-       .mode = LM3631_COMB1,
-};
-
-#define LM3631_EN_GPIO         134
-static struct lm3631_platform_data lm3631_pdata = {
-       .en_gpio = LM3631_EN_GPIO,
-       .regulator_data = {
-               &lcd_boost,
-               &lcd_cont,
-               &lcd_oref,
-               &lcd_pos,
-               &lcd_neg,
-       }, 
-       .bl_pdata = &lm3631_bl_pdata,
-};
-
-static struct i2c_board_info __initdata led_i2c_boardinfo[] = {
-       {
-               I2C_BOARD_INFO("lm3631", 0x29),
-               .platform_data = &lm3631_pdata,
-       },
-};
-
-int plat_lm3631_init(void)
-{
-       i2c_register_board_info(4, led_i2c_boardinfo,
-                               ARRAY_SIZE(led_i2c_boardinfo));
-       return 0;
-}
index a6705b949e7a0a5042e48c3590f154d85d70579d..27be5e1e1176205ea8a8086e4a07878994dec3a7 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#define LCD_BOOST_VOUT         5800000
+#define LCD_BOOST_VOUT         6000000
 #define LCD_BIAS_VOUT          5500000
 
 enum lcd_ldo_id {
index 3d250c5c291fcf1be5699124fa4e2f0409364ba4..27355da5eeba6151909cc1622e36dec8f5325cd9 100644 (file)
@@ -59,13 +59,14 @@ config MFD_LM3631
          LM3631 has 2 strings for backlight with 5 regulators for LCD bias.
 
 config MFD_LM3632
-       tristate "TI LM3632 Backlight and Bias Power Driver"
+       tristate "TI LM3632 Backlight with Bias Power and Flash Driver"
        depends on I2C
        select MFD_CORE
        select REGMAP_I2C
        help
          Say yes here to enable support for TI LM3632 chip.
-         LM3632 has 2 strings for backlight with 5 regulators for LCD bias.
+         LM3632 consists of 2 strings backlight with 3 regulators for LCD bias
+         and flash LED driver.
 
 config MFD_AAT2870_CORE
        bool "AnalogicTech AAT2870"
index 8b2401f164367036f53bb939df1ee0969ce96b26..9bc32ccf014f0dc164288dc7b59459d7b302a193 100644 (file)
 }
 
 static struct mfd_cell lm3632_devs[] = {
-       /* 5 Regulators */
+       /* 3 Regulators */
        LM3632_DEV_LCD_BIAS(1),
        LM3632_DEV_LCD_BIAS(2),
        LM3632_DEV_LCD_BIAS(3),
-       LM3632_DEV_LCD_BIAS(4),
-       LM3632_DEV_LCD_BIAS(5),
 
        /* Backlight */
        LM3632_DEV_BL,
@@ -92,9 +90,12 @@ static int lm3632_init_device(struct lm3632 *lm3632)
 
        usleep_range(1000, 1500);
 
+       return 0;
+/*
        return lm3632_update_bits(lm3632, LM3632_REG_DEVCTRL,
                                  LM3632_LCD_EN_MASK,
                                  1 << LM3632_LCD_EN_SHIFT);
+*/
 }
 
 static void lm3632_deinit_device(struct lm3632 *lm3632)
index 36b821a3ad7970cfda61ecec71b25fe22f739fa7..90b68a0b09ad32966e7d3f9fc3fbdf2f6fc2bb45 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2015 Texas Instruments
  *
- * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ * Author: Milo Kim <milo.kim@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <linux/mfd/lm3632.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
 
-#define ENABLE_TIME_USEC               1000
-
 enum lm3632_regulator_id {
        LM3632_REGULATOR_BOOST,
-       LM3632_LDO_CONT,
-       LM3632_LDO_OREF,
        LM3632_LDO_POS,
        LM3632_LDO_NEG,
 };
 
 struct lm3632_regulator {
+       int ena_gpio;
        struct lm3632 *lm3632;
        struct regulator_desc *desc;
        struct regulator_dev *regulator;
@@ -42,14 +40,10 @@ static const int lm3632_boost_vtbl[] = {
        4900000, 4950000, 5000000, 5050000, 5100000, 5150000, 5200000, 5250000,
        5300000, 5350000, 5400000, 5450000, 5500000, 5550000, 5600000, 5650000,
        5700000, 5750000, 5800000, 5850000, 5900000, 5950000, 6000000, 6050000,
-       6100000, 6150000, 6200000, 6250000, 6300000, 6350000,
-};
-
-static const int lm3632_ldo_cont_vtbl[] = {
-       1800000, 2300000, 2800000, 3300000,
+       6100000, 6150000, 6200000, 6250000, 6300000, 6350000, 6400000,
 };
 
-static const int lm3632_ldo_target_vtbl[] = {
+static const int lm3632_ldo_vtbl[] = {
        4000000, 4050000, 4100000, 4150000, 4200000, 4250000, 4300000, 4350000,
        4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000,
        4800000, 4850000, 4900000, 4950000, 5000000, 5050000, 5100000, 5150000,
@@ -58,48 +52,6 @@ static const int lm3632_ldo_target_vtbl[] = {
        6000000,
 };
 
-const int ldo_cont_enable_time[] = {
-       0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
-};
-
-static int lm3632_regulator_enable_time(struct regulator_dev *rdev)
-{
-       struct lm3632_regulator *lm3632_regulator = rdev_get_drvdata(rdev);
-       enum lm3632_regulator_id id = rdev_get_id(rdev);
-       u8 val, addr, mask;
-
-       switch (id) {
-       case LM3632_LDO_CONT:
-               addr = LM3632_REG_ENTIME_VCONT;
-               mask = LM3632_ENTIME_CONT_MASK;
-               break;
-       case LM3632_LDO_OREF:
-               addr = LM3632_REG_ENTIME_VOREF;
-               mask = LM3632_ENTIME_MASK;
-               break;
-       case LM3632_LDO_POS:
-               addr = LM3632_REG_ENTIME_VPOS;
-               mask = LM3632_ENTIME_MASK;
-               break;
-       case LM3632_LDO_NEG:
-               addr = LM3632_REG_ENTIME_VNEG;
-               mask = LM3632_ENTIME_MASK;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (lm3632_read_byte(lm3632_regulator->lm3632, addr, &val))
-               return -EINVAL;
-
-       val = (val & mask) >> LM3632_ENTIME_SHIFT;
-
-       if (id == LM3632_LDO_CONT)
-               return ldo_cont_enable_time[val];
-       else
-               return ENABLE_TIME_USEC * val;
-}
-
 static struct regulator_ops lm3632_boost_voltage_table_ops = {
        .list_voltage     = regulator_list_voltage_table,
        .set_voltage_sel  = regulator_set_voltage_sel_regmap,
@@ -113,7 +65,6 @@ static struct regulator_ops lm3632_regulator_voltage_table_ops = {
        .enable           = regulator_enable_regmap,
        .disable          = regulator_disable_regmap,
        .is_enabled       = regulator_is_enabled_regmap,
-       .enable_time      = lm3632_regulator_enable_time,
 };
 
 static struct regulator_desc lm3632_regulator_desc[] = {
@@ -128,64 +79,36 @@ static struct regulator_desc lm3632_regulator_desc[] = {
                .vsel_reg       = LM3632_REG_VOUT_BOOST,
                .vsel_mask      = LM3632_VOUT_MASK,
        },
-       {
-               .name           = "ldo_cont",
-               .id             = LM3632_LDO_CONT,
-               .ops            = &lm3632_regulator_voltage_table_ops,
-               .n_voltages     = ARRAY_SIZE(lm3632_ldo_cont_vtbl),
-               .volt_table     = lm3632_ldo_cont_vtbl,
-               .type           = REGULATOR_VOLTAGE,
-               .owner          = THIS_MODULE,
-               .vsel_reg       = LM3632_REG_VOUT_CONT,
-               .vsel_mask      = LM3632_VOUT_CONT_MASK,
-               .enable_reg     = LM3632_REG_LDO_CTRL2,
-               .enable_mask    = LM3632_EN_CONT_MASK,
-       },
-       {
-               .name           = "ldo_oref",
-               .id             = LM3632_LDO_OREF,
-               .ops            = &lm3632_regulator_voltage_table_ops,
-               .n_voltages     = ARRAY_SIZE(lm3632_ldo_target_vtbl),
-               .volt_table     = lm3632_ldo_target_vtbl,
-               .type           = REGULATOR_VOLTAGE,
-               .owner          = THIS_MODULE,
-               .vsel_reg       = LM3632_REG_VOUT_OREF,
-               .vsel_mask      = LM3632_VOUT_MASK,
-               .enable_reg     = LM3632_REG_LDO_CTRL1,
-               .enable_mask    = LM3632_EN_OREF_MASK,
-       },
        {
                .name           = "ldo_vpos",
                .id             = LM3632_LDO_POS,
                .ops            = &lm3632_regulator_voltage_table_ops,
-               .n_voltages     = ARRAY_SIZE(lm3632_ldo_target_vtbl),
-               .volt_table     = lm3632_ldo_target_vtbl,
+               .n_voltages     = ARRAY_SIZE(lm3632_ldo_vtbl),
+               .volt_table     = lm3632_ldo_vtbl,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
                .vsel_reg       = LM3632_REG_VOUT_POS,
                .vsel_mask      = LM3632_VOUT_MASK,
-               .enable_reg     = LM3632_REG_LDO_CTRL1,
+               .enable_reg     = LM3632_REG_BIAS_CONFIG,
                .enable_mask    = LM3632_EN_VPOS_MASK,
        },
        {
                .name           = "ldo_vneg",
                .id             = LM3632_LDO_NEG,
                .ops            = &lm3632_regulator_voltage_table_ops,
-               .n_voltages     = ARRAY_SIZE(lm3632_ldo_target_vtbl),
-               .volt_table     = lm3632_ldo_target_vtbl,
+               .n_voltages     = ARRAY_SIZE(lm3632_ldo_vtbl),
+               .volt_table     = lm3632_ldo_vtbl,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
                .vsel_reg       = LM3632_REG_VOUT_NEG,
                .vsel_mask      = LM3632_VOUT_MASK,
-               .enable_reg     = LM3632_REG_LDO_CTRL1,
+               .enable_reg     = LM3632_REG_BIAS_CONFIG,
                .enable_mask    = LM3632_EN_VNEG_MASK,
        },
 };
 
 static struct of_regulator_match lm3632_regulator_matches[] = {
        { .name = "vboost", .driver_data = (void *)LM3632_REGULATOR_BOOST, },
-       { .name = "vcont",  .driver_data = (void *)LM3632_LDO_CONT, },
-       { .name = "voref",  .driver_data = (void *)LM3632_LDO_OREF, },
        { .name = "vpos",   .driver_data = (void *)LM3632_LDO_POS,  },
        { .name = "vneg",   .driver_data = (void *)LM3632_LDO_NEG,  },
 };
@@ -196,6 +119,7 @@ static int lm3632_regulator_parse_dt(struct device *dev,
 {
        struct device_node *node = dev->of_node;
        int count;
+       int gpio;
 
        count = of_regulator_match(dev, node, &lm3632_regulator_matches[id], 1);
        if (count <= 0)
@@ -203,6 +127,20 @@ static int lm3632_regulator_parse_dt(struct device *dev,
 
        lm3632_regulator->init_data = lm3632_regulator_matches[id].init_data;
 
+       /*
+        * Check LCM_EN1/2_GPIO is configured.
+        * Those pins are used for enabling VPOS/VNEG LDOs.
+        */
+       if (id == LM3632_LDO_POS) {
+               gpio = of_get_named_gpio(node, "ti,lcm-en1-gpio", 0);
+               if (gpio > 0)
+                       lm3632_regulator->ena_gpio = gpio;
+       } else if (id == LM3632_LDO_NEG) {
+               gpio = of_get_named_gpio(node, "ti,lcm-en2-gpio", 0);
+               if (gpio > 0)
+                       lm3632_regulator->ena_gpio = gpio;
+       }
+
        return 0;
 }
 
@@ -220,8 +158,8 @@ static int lm3632_regulator_probe(struct platform_device *pdev)
        if (!lm3632_regulator)
                return -ENOMEM;
 
+       lm3632_regulator->ena_gpio = 0;
        lm3632_regulator->lm3632 = lm3632;
-
        lm3632_regulator->init_data = lm3632->pdata->regulator_data[id];
        if (!lm3632_regulator->init_data) {
                if (IS_ENABLED(CONFIG_OF))
@@ -239,11 +177,26 @@ static int lm3632_regulator_probe(struct platform_device *pdev)
        cfg.driver_data = lm3632_regulator;
        cfg.regmap = lm3632->regmap;
 
+       /* Update register value if external enable pin is used */
+       if (lm3632_regulator->ena_gpio > 0) {
+               cfg.ena_gpio = lm3632_regulator->ena_gpio;
+               cfg.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
+
+               ret = lm3632_update_bits(lm3632_regulator->lm3632,
+                                        LM3632_REG_BIAS_CONFIG,
+                                        LM3632_EXT_EN_MASK,
+                                        LM3632_EXT_EN_MASK);
+               if (ret) {
+                       dev_err(&pdev->dev, "external pin err: %d\n", ret);
+                       return ret;
+               }
+       }
+
        rdev = regulator_register(&lm3632_regulator_desc[id], &cfg);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(&pdev->dev, "[%d] regulator register err: %d\n",
-                       id + 1, ret);
+                       id, ret);
                return ret;
        }
 
index 0459bf179bdabfc35788a7b25debbbcfdeb6d32e..0a69737de88e74ee2e1a55b14fea6aad69001e93 100644 (file)
@@ -41,11 +41,36 @@ struct lm3632_bl {
        struct pwm_device *pwm;
 };
 
+static int lm3632_bl_string_configure(struct lm3632_bl *lm3632_bl, int enable)
+{
+       u8 val;
+
+       if (enable) {
+               if (lm3632_bl->pdata->is_full_strings)
+                       val = LM3632_BL_TWO_STRINGS;
+               else
+                       val = LM3632_BL_ONE_STRING;
+       } else {
+               val = 0;
+       }
+
+       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_ENABLE,
+                                 LM3632_BL_STRING_MASK, val);
+}
+
 static int lm3632_bl_enable(struct lm3632_bl *lm3632_bl, int enable)
 {
-       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_DEVCTRL,
-                                 LM3632_BL_EN_MASK,
-                                 enable << LM3632_BL_EN_SHIFT);
+       int ret;
+
+       ret = lm3632_bl_string_configure(lm3632_bl, enable);
+       if (ret) {
+               dev_err(lm3632_bl->dev,
+                       "Backlight string config error: %d\n", ret);
+               return ret;
+       }
+
+       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_ENABLE,
+                                 LM3632_BL_EN_MASK, enable << LM3632_BL_EN_SHIFT);
 }
 
 static void lm3632_bl_pwm_ctrl(struct lm3632_bl *lm3632_bl, int br, int max_br)
@@ -77,11 +102,12 @@ static void lm3632_bl_pwm_ctrl(struct lm3632_bl *lm3632_bl, int br, int max_br)
                pwm_disable(lm3632_bl->pwm);
 }
 
-static inline int lm3632_bl_set_brightness(struct lm3632_bl *lm3632_bl, int val)
+static int lm3632_bl_set_brightness(struct lm3632_bl *lm3632_bl, int val)
 {
        u8 data;
        int ret;
 
+
        data = val & LM3632_BRT_LSB_MASK;
        ret = lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_BRT_LSB,
                                 LM3632_BRT_LSB_MASK, data);
@@ -89,6 +115,7 @@ static inline int lm3632_bl_set_brightness(struct lm3632_bl *lm3632_bl, int val)
                return ret;
 
        data = (val >> LM3632_BRT_MSB_SHIFT) & 0xFF;
+
        return lm3632_write_byte(lm3632_bl->lm3632, LM3632_REG_BRT_MSB,
                                 data);
 }
@@ -140,7 +167,7 @@ static int lm3632_bl_register(struct lm3632_bl *lm3632_bl)
        char name[20];
 
        props.type = BACKLIGHT_PLATFORM;
-       props.brightness = pdata ? pdata->init_brightness : 0;
+       props.brightness = 0;
        props.max_brightness = LM3632_MAX_BRIGHTNESS;
 
        if (!pdata || !pdata->name)
@@ -164,74 +191,86 @@ static void lm3632_bl_unregister(struct lm3632_bl *lm3632_bl)
                backlight_device_unregister(lm3632_bl->bl_dev);
 }
 
-static int lm3632_bl_set_ctrl_mode(struct lm3632_bl *lm3632_bl)
+static int lm3632_bl_set_ovp(struct lm3632_bl *lm3632_bl)
 {
-       struct lm3632_backlight_platform_data *pdata = lm3632_bl->pdata;
-
-       /* Brightness control mode is I2C only by default */
-       if (!pdata) {
-               lm3632_bl->mode = LMU_BL_I2C;
-               return lm3632_update_bits(lm3632_bl->lm3632,
-                                         LM3632_REG_BRT_MODE, LM3632_BRT_MASK,
-                                         LM3632_I2C_ONLY);
-       }
-
-       if (pdata->pwm_period > 0)
-               lm3632_bl->mode = LMU_BL_PWM;
+       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_CONFIG1,
+                                 LM3632_OVP_MASK, LM3632_OVP_25V);
+}
 
-       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_BRT_MODE,
-                                 LM3632_BRT_MASK, pdata->mode);
+static int lm3632_bl_set_swfreq(struct lm3632_bl *lm3632_bl)
+{
+       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_CONFIG2,
+                                 LM3632_SWFREQ_MASK, LM3632_SWFREQ_1MHZ);
 }
 
-static int lm3632_bl_string_configure(struct lm3632_bl *lm3632_bl)
+static int lm3632_bl_set_ctrl_mode(struct lm3632_bl *lm3632_bl)
 {
-       u8 val;
+       struct lm3632_backlight_platform_data *pdata = lm3632_bl->pdata;
 
-       if (lm3632_bl->pdata->is_full_strings)
-               val = LM3632_BL_TWO_STRINGS;
+       if (pdata->pwm_period > 0)
+               lm3632_bl->mode = LMU_BL_PWM;
        else
-               val = LM3632_BL_ONE_STRING;
+               lm3632_bl->mode = LMU_BL_I2C;
 
-       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_BL_CFG,
-                                 LM3632_BL_STRING_MASK, val);
+       return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_IO_CTRL,
+                                 LM3632_PWM_MASK,
+                                 lm3632_bl->mode << LM3632_PWM_SHIFT);
 }
 
 static int lm3632_bl_configure(struct lm3632_bl *lm3632_bl)
 {
        int ret;
 
-       ret = lm3632_bl_set_ctrl_mode(lm3632_bl);
+       /* Select OVP level */
+       ret = lm3632_bl_set_ovp(lm3632_bl);
+       if (ret)
+               return ret;
+
+       /* Select switch frequency */
+       ret = lm3632_bl_set_swfreq(lm3632_bl);
        if (ret)
                return ret;
 
-       return lm3632_bl_string_configure(lm3632_bl);
+       /* Backlight control mode - PWM or I2C */
+       return lm3632_bl_set_ctrl_mode(lm3632_bl);
 }
 
 static int lm3632_bl_parse_dt(struct device *dev, struct lm3632_bl *lm3632_bl)
 {
        struct device_node *node = dev->of_node;
        struct lm3632_backlight_platform_data *pdata;
+       int brightness = 0;
+       int ret;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return -ENOMEM;
 
+       /* Channel name */
        of_property_read_string(node, "bl-name", &pdata->name);
 
+       /* String configuration */
        if (of_find_property(node, "full-strings-used", NULL))
                pdata->is_full_strings = true;
 
-       if (of_find_property(node, "mode-pwm-only", NULL))
-               pdata->mode = LM3632_PWM_ONLY;
-       else if (of_find_property(node, "mode-comb1", NULL))
-               pdata->mode = LM3632_COMB1;
-       else if (of_find_property(node, "mode-comb2", NULL))
-               pdata->mode = LM3632_COMB2;
+       /* PWM mode */
+       of_property_read_u32(node, "pwm-period", &pdata->pwm_period);
+       of_property_read_u32(node, "pwm-max-brightness", &brightness);
 
-       of_property_read_u8(node, "initial-brightness",
-                           (u8 *)&pdata->init_brightness);
+       if (pdata->pwm_period > 0) {
+               if (brightness == 0) {
+                       dev_err(lm3632_bl->dev,
+                       "PWM max brightness should be greater than 0\n");
+                       return -EINVAL;
+               }
 
-       of_property_read_u32(node, "pwm-period", &pdata->pwm_period);
+               ret = lm3632_bl_set_brightness(lm3632_bl, brightness);
+               if (ret) {
+                       dev_err(lm3632_bl->dev,
+                               "PWM max brightness set error: %d\n", ret);
+                       return ret;
+               }
+       }
 
        lm3632_bl->pdata = pdata;
 
@@ -249,7 +288,10 @@ static int lm3632_bl_probe(struct platform_device *pdev)
        if (!lm3632_bl)
                return -ENOMEM;
 
+       lm3632_bl->dev = &pdev->dev;
+       lm3632_bl->lm3632 = lm3632;
        lm3632_bl->pdata = pdata;
+
        if (!lm3632_bl->pdata) {
                if (IS_ENABLED(CONFIG_OF))
                        ret = lm3632_bl_parse_dt(&pdev->dev, lm3632_bl);
@@ -260,16 +302,16 @@ static int lm3632_bl_probe(struct platform_device *pdev)
                        return ret;
        }
 
-       lm3632_bl->dev = &pdev->dev;
-       lm3632_bl->lm3632 = lm3632;
        platform_set_drvdata(pdev, lm3632_bl);
 
+       /* Backlight configuration */
        ret = lm3632_bl_configure(lm3632_bl);
        if (ret) {
                dev_err(&pdev->dev, "backlight config err: %d\n", ret);
                return ret;
        }
 
+       /* Register backlight subsystem */
        ret = lm3632_bl_register(lm3632_bl);
        if (ret) {
                dev_err(&pdev->dev, "register backlight err: %d\n", ret);
index 84701481eead4df5318139742d198a6dd95ecc9b..bd973c6922971cd0b1550c2e3d1b534a88314183 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * TI LM3631 MFD Driver
+ * TI LM3632 MFD Driver
  *
- * Copyright 2013 Texas Instruments
+ * Copyright 2015 Texas Instruments
  *
  * Author: Milo Kim <milo.kim@ti.com>
  *
@@ -11,8 +11,8 @@
  *
  */
 
-#ifndef __MFD_LM3631_H__
-#define __MFD_LM3631_H__
+#ifndef __MFD_LM3632_H__
+#define __MFD_LM3632_H__
 
 #include <linux/gpio.h>
 #include <linux/pwm.h>
 #include <linux/regulator/machine.h>
 
 /* Registers */
-#define LM3631_REG_DEVCTRL             0x00
-#define LM3631_LCD_EN_MASK             BIT(1)
-#define LM3631_LCD_EN_SHIFT            1
-#define LM3631_BL_EN_MASK              BIT(0)
-#define LM3631_BL_EN_SHIFT             0
-
-#define LM3631_REG_BRT_LSB             0x01
-#define LM3631_BRT_LSB_MASK            (BIT(0) | BIT(1) | BIT(2))
-#define LM3631_REG_BRT_MSB             0x02
-#define LM3631_BRT_MSB_SHIFT           3
-
-#define LM3631_REG_BL_CFG              0x06
-#define LM3631_BL_STRING_MASK          BIT(3)
-#define LM3631_BL_TWO_STRINGS          0
-#define LM3631_BL_ONE_STRING           BIT(3)
-
-#define LM3631_REG_BRT_MODE            0x08
-#define LM3631_BRT_MASK                        (BIT(2) | BIT(3))
-
-#define LM3631_REG_LDO_CTRL1           0x0A
-#define LM3631_EN_OREF_MASK            BIT(0)
-#define LM3631_EN_VNEG_MASK            BIT(1)
-#define LM3631_EN_VPOS_MASK            BIT(2)
-
-#define LM3631_REG_LDO_CTRL2           0x0B
-#define LM3631_EN_CONT_MASK            BIT(0)
-
-#define LM3631_REG_VOUT_CONT           0x0C
-#define LM3631_VOUT_CONT_MASK          (BIT(6) | BIT(7))
-
-#define LM3631_REG_VOUT_BOOST          0x0C
-#define LM3631_REG_VOUT_POS            0x0D
-#define LM3631_REG_VOUT_NEG            0x0E
-#define LM3631_REG_VOUT_OREF           0x0F
-#define LM3631_VOUT_MASK               0x3F
-
-#define LM3631_REG_ENTIME_VCONT                0x0B
-#define LM3631_ENTIME_CONT_MASK                0x70
-
-#define LM3631_REG_ENTIME_VOREF                0x0F
-#define LM3631_REG_ENTIME_VPOS         0x10
-#define LM3631_REG_ENTIME_VNEG         0x11
-#define LM3631_ENTIME_MASK             0xF0
-#define LM3631_ENTIME_SHIFT            4
-
-#define LM3631_MAX_REGISTERS           0x16
-
-#define LM3631_NUM_REGULATORS          5
-
-enum lm3631_brightness_mode {
-       LM3631_I2C_ONLY = 0 << 2,
-       LM3631_PWM_ONLY = 1 << 2,
-       LM3631_COMB1    = 2 << 2,       /* I2C x PWM befoer sloping */
-       LM3631_COMB2    = 3 << 2,       /* Sloped I2C x PWM */
-};
+#define LM3632_REG_CONFIG1             0x02
+#define LM3632_OVP_MASK                        (BIT(5) | BIT(6) | BIT(7))
+#define LM3632_OVP_25V                 BIT(6)
+
+#define LM3632_REG_CONFIG2             0x03
+#define LM3632_SWFREQ_MASK             BIT(7)
+#define LM3632_SWFREQ_1MHZ             BIT(7)
+
+#define LM3632_REG_BRT_LSB             0x04
+#define LM3632_BRT_LSB_MASK            (BIT(0) | BIT(1) | BIT(2))
+#define LM3632_REG_BRT_MSB             0x05
+#define LM3632_BRT_MSB_SHIFT           3
+
+#define LM3632_REG_IO_CTRL             0x09
+#define LM3632_PWM_MASK                        BIT(6)
+#define LM3632_PWM_SHIFT               6
+
+#define LM3632_REG_ENABLE              0x0A
+#define LM3632_BL_EN_MASK              BIT(0)
+#define LM3632_BL_EN_SHIFT             0
+#define LM3632_BL_STRING_MASK          (BIT(3) | BIT(4))
+#define LM3632_BL_ONE_STRING           BIT(4)
+#define LM3632_BL_TWO_STRINGS          BIT(3)
+
+#define LM3632_REG_BIAS_CONFIG         0x0C
+#define LM3632_EXT_EN_MASK             BIT(0)
+#define LM3632_EN_VNEG_MASK            BIT(1)
+#define LM3632_EN_VPOS_MASK            BIT(2)
+
+#define LM3632_REG_VOUT_BOOST          0x0D
+#define LM3632_REG_VOUT_POS            0x0E
+#define LM3632_REG_VOUT_NEG            0x0F
+#define LM3632_VOUT_MASK               0x3F
+
+#define LM3632_MAX_REGISTERS           0x10
+
+#define LM3632_NUM_REGULATORS          3
 
 /*
- * struct lm3633_bl_platform_data
+ * struct lm3632_backlight_platform_data
  * @name: Backlight driver name
  * @is_full_strings: set true if two strings are used
- * @init_brightness: Initial brightness value
- * @mode: Backlight control mode
  * @pwm_period: Platform specific PWM period value. unit is nano
  */
-struct lm3631_backlight_platform_data {
+struct lm3632_backlight_platform_data {
        const char *name;
        bool is_full_strings;
-       u8 init_brightness;
-       enum lm3631_brightness_mode mode;
 
        /* Only valid in case of PWM mode */
        unsigned int pwm_period;
 };
 
 /*
- * struct lmu_platform_data
- * @en_gpio: GPIO for nRST pin
+ * struct lm3632_platform_data
+ * @en_gpio: GPIO for chip enable pin
+ * @lcm_en1_gpio: GPIO for VPOS LDO
+ * @lcm_en2_gpio: GPIO for VNEG LDO
  * @regulator_data: Regulator initial data for LCD bias
  * @bl_pdata: Backlight platform data
  */
-struct lm3631_platform_data {
+struct lm3632_platform_data {
        int en_gpio;
-       struct regulator_init_data *regulator_data[LM3631_NUM_REGULATORS];
-       struct lm3631_backlight_platform_data *bl_pdata;
+       int lcm_en1_gpio;
+       int lcm_en2_gpio;
+       struct regulator_init_data *regulator_data[LM3632_NUM_REGULATORS];
+       struct lm3632_backlight_platform_data *bl_pdata;
 };
 
 /*
- * struct lm3631
+ * struct lm3632
  * @dev: Parent device pointer
  * @regmap: Used for i2c communcation on accessing registers
  * @pdata: LMU platform specific data
  */
-struct lm3631 {
+struct lm3632 {
        struct device *dev;
        struct regmap *regmap;
-       struct lm3631_platform_data *pdata;
+       struct lm3632_platform_data *pdata;
 };
 
-int lm3631_read_byte(struct lm3631 *lm3631, u8 reg, u8 *read);
-int lm3631_write_byte(struct lm3631 *lm3631, u8 reg, u8 data);
-int lm3631_update_bits(struct lm3631 *lm3631, u8 reg, u8 mask, u8 data);
+int lm3632_read_byte(struct lm3632 *lm3632, u8 reg, u8 *read);
+int lm3632_write_byte(struct lm3632 *lm3632, u8 reg, u8 data);
+int lm3632_update_bits(struct lm3632 *lm3632, u8 reg, u8 mask, u8 data);
 #endif