Merge branches 'ib-mfd-arm-leds-5.2', 'ib-mfd-gpio-input-leds-power-5.2', 'ib-mfd...
authorLee Jones <lee.jones@linaro.org>
Tue, 14 May 2019 07:09:23 +0000 (08:09 +0100)
committerLee Jones <lee.jones@linaro.org>
Tue, 14 May 2019 07:09:23 +0000 (08:09 +0100)
Immutable branch between MFD, ARM and Net due for the 5.2 merge window

39 files changed:
Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
Documentation/devicetree/bindings/input/max77650-onkey.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-lm3532.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-max77650.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/max77620.txt
Documentation/devicetree/bindings/mfd/max77650.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/ti-lmu.txt
Documentation/devicetree/bindings/power/supply/max77650-charger.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/configs/socfpga_defconfig
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/configs/defconfig
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-max77650.c [new file with mode: 0644]
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/max77650-onkey.c [new file with mode: 0644]
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-lm3532.c [new file with mode: 0644]
drivers/leds/leds-max77650.c [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/altera-sysmgr.c [new file with mode: 0644]
drivers/mfd/max77620.c
drivers/mfd/max77650.c [new file with mode: 0644]
drivers/mfd/mfd-core.c
drivers/mfd/ti-lmu.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/max77650-charger.c [new file with mode: 0644]
include/linux/mfd/altera-sysmgr.h [new file with mode: 0644]
include/linux/mfd/max77620.h
include/linux/mfd/max77650.h [new file with mode: 0644]
include/linux/mfd/ti-lmu-register.h
include/linux/mfd/ti-lmu.h

index f4d04a0672824087de6987b6be4dfd5c4fd2bf84..82edbaaa3f85beeafdf3b96c957776f8b03e90fc 100644 (file)
@@ -11,3 +11,15 @@ Example:
                reg = <0xffd08000 0x1000>;
                cpu1-start-addr = <0xffd080c4>;
        };
+
+ARM64 - Stratix10
+Required properties:
+- compatible : "altr,sys-mgr-s10"
+- reg : Should contain 1 register range(address and length)
+        for system manager register.
+
+Example:
+        sysmgr@ffd12000 {
+               compatible = "altr,sys-mgr-s10";
+               reg = <0xffd12000 0x228>;
+       };
diff --git a/Documentation/devicetree/bindings/input/max77650-onkey.txt b/Documentation/devicetree/bindings/input/max77650-onkey.txt
new file mode 100644 (file)
index 0000000..477dc74
--- /dev/null
@@ -0,0 +1,26 @@
+Onkey driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The onkey controller is represented as a sub-node of the PMIC node on
+the device tree.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-onkey".
+
+Optional properties:
+- linux,code:          The key-code to be reported when the key is pressed.
+                       Defaults to KEY_POWER.
+- maxim,onkey-slide:   The system's button is a slide switch, not the default
+                       push button.
+
+Example:
+--------
+
+       onkey {
+               compatible = "maxim,max77650-onkey";
+               linux,code = <KEY_END>;
+               maxim,onkey-slide;
+       };
diff --git a/Documentation/devicetree/bindings/leds/leds-lm3532.txt b/Documentation/devicetree/bindings/leds/leds-lm3532.txt
new file mode 100644 (file)
index 0000000..c087f85
--- /dev/null
@@ -0,0 +1,101 @@
+* Texas Instruments - lm3532 White LED driver with ambient light sensing
+capability.
+
+The LM3532 provides the 3 high-voltage, low-side current sinks. The device is
+programmable over an I2C-compatible interface and has independent
+current control for all three channels. The adaptive current regulation
+method allows for different LED currents in each current sink thus allowing
+for a wide variety of backlight and keypad applications.
+
+The main features of the LM3532 include dual ambient light sensor inputs
+each with 32 internal voltage setting resistors, 8-bit logarithmic and linear
+brightness control, dual external PWM brightness control inputs, and up to
+1000:1 dimming ratio with programmable fade in and fade out settings.
+
+Required properties:
+       - compatible : "ti,lm3532"
+       - reg : I2C slave address
+       - #address-cells : 1
+       - #size-cells : 0
+
+Optional properties:
+       - enable-gpios : gpio pin to enable (active high)/disable the device.
+       - ramp-up-us - The Run time ramp rates/step are from one current
+                      set-point to another after the device has reached its
+                      initial target set point from turn-on
+       - ramp-down-us - The Run time ramp rates/step are from one current
+                        set-point to another after the device has reached its
+                        initial target set point from turn-on
+       Range for ramp settings: 8us - 65536us
+
+Optional properties if ALS mode is used:
+       - ti,als-vmin - Minimum ALS voltage defined in Volts
+       - ti,als-vmax - Maximum ALS voltage defined in Volts
+       Per the data sheet the max ALS voltage is 2V and the min is 0V
+
+       - ti,als1-imp-sel - ALS1 impedance resistor selection in Ohms
+       - ti,als2-imp-sel - ALS2 impedance resistor selection in Ohms
+       Range for impedance select: 37000 Ohms - 1190 Ohms
+       Values above 37kohms will be set to the "High Impedance" setting
+
+       - ti,als-avrg-time-us - Determines the length of time the device needs to
+                         average the two ALS inputs.  This is only used if
+                         the input mode is LM3532_ALS_INPUT_AVRG.
+                            Range: 17920us - 2293760us
+       - ti,als-input-mode - Determines how the device uses the attached ALS
+                          devices.
+                          0x00 - ALS1 and ALS2 input average
+                          0x01 - ALS1 Input
+                          0x02 - ALS2 Input
+                          0x03 - Max of ALS1 and ALS2
+
+Required child properties:
+       - reg : Indicates control bank the LED string is controlled by
+       - led-sources : see Documentation/devicetree/bindings/leds/common.txt
+       - ti,led-mode : Defines if the LED strings are manually controlled or
+                       if the LED strings are controlled by the ALS.
+                       0x00 - LED strings are I2C controlled via full scale
+                              brightness control register
+                       0x01 - LED strings are ALS controlled
+
+Optional LED child properties:
+       - label : see Documentation/devicetree/bindings/leds/common.txt
+       - linux,default-trigger :
+          see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+led-controller@38 {
+       compatible = "ti,lm3532";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       reg = <0x38>;
+
+       enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+       ramp-up-us = <1024>;
+       ramp-down-us = <65536>;
+
+       ti,als-vmin = <0>;
+       ti,als-vmax = <2000>;
+       ti,als1-imp-sel = <4110>;
+       ti,als2-imp-sel = <2180>;
+       ti,als-avrg-time-us = <17920>;
+       ti,als-input-mode = <0x00>;
+
+       led@0 {
+               reg = <0>;
+               led-sources = <2>;
+               ti,led-mode = <1>;
+               label = ":backlight";
+               linux,default-trigger = "backlight";
+       };
+
+       led@1 {
+               reg = <1>;
+               led-sources = <1>;
+               ti,led-mode = <0>;
+               label = ":kbd_backlight";
+       };
+};
+
+For more product information please see the links below:
+http://www.ti.com/product/LM3532
diff --git a/Documentation/devicetree/bindings/leds/leds-max77650.txt b/Documentation/devicetree/bindings/leds/leds-max77650.txt
new file mode 100644 (file)
index 0000000..3a67115
--- /dev/null
@@ -0,0 +1,57 @@
+LED driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The LED controller is represented as a sub-node of the PMIC node on
+the device tree.
+
+This device has three current sinks.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-led"
+- #address-cells:      Must be <1>.
+- #size-cells:         Must be <0>.
+
+Each LED is represented as a sub-node of the LED-controller node. Up to
+three sub-nodes can be defined.
+
+Required properties of the sub-node:
+------------------------------------
+
+- reg:                 Must be <0>, <1> or <2>.
+
+Optional properties of the sub-node:
+------------------------------------
+
+- label:               See Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger: See Documentation/devicetree/bindings/leds/common.txt
+
+For more details, please refer to the generic GPIO DT binding document
+<devicetree/bindings/gpio/gpio.txt>.
+
+Example:
+--------
+
+       leds {
+               compatible = "maxim,max77650-led";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               led@0 {
+                       reg = <0>;
+                       label = "blue:usr0";
+               };
+
+               led@1 {
+                       reg = <1>;
+                       label = "red:usr1";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led@2 {
+                       reg = <2>;
+                       label = "green:usr2";
+               };
+       };
index 9c16d51cc15b913ce900c622741eb51904224686..5a642a51d58e6fd0da2cd4d3d76ad1a8bef409af 100644 (file)
@@ -4,7 +4,8 @@ Required properties:
 -------------------
 - compatible: Must be one of
                "maxim,max77620"
-               "maxim,max20024".
+               "maxim,max20024"
+               "maxim,max77663"
 - reg: I2C device address.
 
 Optional properties:
@@ -17,6 +18,11 @@ Optional properties:
                        IRQ numbers for different interrupt source of MAX77620
                        are defined at dt-bindings/mfd/max77620.h.
 
+- system-power-controller: Indicates that this PMIC is controlling the
+                          system power, see [1] for more details.
+
+[1] Documentation/devicetree/bindings/power/power-controller.txt
+
 Optional subnodes and their properties:
 =======================================
 
@@ -105,6 +111,7 @@ Optional properties:
 Here supported time periods by device in microseconds are as follows:
 MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds.
 MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
+MAX77663 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
 
 -maxim,power-ok-control: configure map power ok bit
                        1: Enables POK(Power OK) to control nRST_IO and GPIO1
diff --git a/Documentation/devicetree/bindings/mfd/max77650.txt b/Documentation/devicetree/bindings/mfd/max77650.txt
new file mode 100644 (file)
index 0000000..b529d8d
--- /dev/null
@@ -0,0 +1,46 @@
+MAX77650 ultra low-power PMIC from Maxim Integrated.
+
+Required properties:
+-------------------
+- compatible:          Must be "maxim,max77650"
+- reg:                 I2C device address.
+- interrupts:          The interrupt on the parent the controller is
+                       connected to.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells:    Must be <2>.
+
+- gpio-controller:     Marks the device node as a gpio controller.
+- #gpio-cells:         Must be <2>. The first cell is the pin number and
+                       the second cell is used to specify the gpio active
+                       state.
+
+Optional properties:
+--------------------
+gpio-line-names:       Single string containing the name of the GPIO line.
+
+The GPIO-controller module is represented as part of the top-level PMIC
+node. The device exposes a single GPIO line.
+
+For device-tree bindings of other sub-modules (regulator, power supply,
+LEDs and onkey) refer to the binding documents under the respective
+sub-system directories.
+
+For more details on GPIO bindings, please refer to the generic GPIO DT
+binding document <devicetree/bindings/gpio/gpio.txt>.
+
+Example:
+--------
+
+       pmic@48 {
+               compatible = "maxim,max77650";
+               reg = <0x48>;
+
+               interrupt-controller;
+               interrupt-parent = <&gpio2>;
+               #interrupt-cells = <2>;
+               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+               gpio-line-names = "max77650-charger";
+       };
index c885cf89b8ce83ce29b9d603011859f5962493a4..980394d701a7275f5a26738ec13d90c349998d3b 100644 (file)
@@ -4,7 +4,6 @@ TI LMU driver supports lighting devices below.
 
    Name                  Child nodes
   ------      ---------------------------------
-  LM3532       Backlight
   LM3631       Backlight and regulator
   LM3632       Backlight and regulator
   LM3633       Backlight, LED and fault monitor
@@ -13,7 +12,6 @@ TI LMU driver supports lighting devices below.
 
 Required properties:
   - compatible: Should be one of:
-                "ti,lm3532"
                 "ti,lm3631"
                 "ti,lm3632"
                 "ti,lm3633"
@@ -23,7 +21,6 @@ Required properties:
          0x11 for LM3632
          0x29 for LM3631
          0x36 for LM3633, LM3697
-         0x38 for LM3532
          0x63 for LM3695
 
 Optional property:
@@ -47,23 +44,6 @@ Optional nodes:
 [2] ../leds/leds-lm3633.txt
 [3] ../regulator/lm363x-regulator.txt
 
-lm3532@38 {
-       compatible = "ti,lm3532";
-       reg = <0x38>;
-
-       enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>;
-
-       backlight {
-               compatible = "ti,lm3532-backlight";
-
-               lcd {
-                       led-sources = <0 1 2>;
-                       ramp-up-msec = <30>;
-                       ramp-down-msec = <0>;
-               };
-       };
-};
-
 lm3631@29 {
        compatible = "ti,lm3631";
        reg = <0x29>;
diff --git a/Documentation/devicetree/bindings/power/supply/max77650-charger.txt b/Documentation/devicetree/bindings/power/supply/max77650-charger.txt
new file mode 100644 (file)
index 0000000..e6d0fb6
--- /dev/null
@@ -0,0 +1,28 @@
+Battery charger driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The charger is represented as a sub-node of the PMIC node on the device tree.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-charger"
+
+Optional properties:
+--------------------
+- input-voltage-min-microvolt: Minimum CHGIN regulation voltage. Must be one
+                               of: 4000000, 4100000, 4200000, 4300000,
+                               4400000, 4500000, 4600000, 4700000.
+- input-current-limit-microamp:        CHGIN input current limit (in microamps). Must
+                               be one of: 95000, 190000, 285000, 380000,
+                               475000.
+
+Example:
+--------
+
+       charger {
+               compatible = "maxim,max77650-charger";
+               input-voltage-min-microvolt = <4200000>;
+               input-current-limit-microamp = <285000>;
+       };
index 2c2fce72e694f6ccc2000974e9cba4f6fcafbf48..1effe978902312b1738434ada432b6bcf0b6275d 100644 (file)
@@ -709,6 +709,12 @@ L: linux-gpio@vger.kernel.org
 S:     Maintained
 F:     drivers/gpio/gpio-altera.c
 
+ALTERA SYSTEM MANAGER DRIVER
+M:     Thor Thayer <thor.thayer@linux.intel.com>
+S:     Maintained
+F:     drivers/mfd/altera-sysmgr.c
+F:     include/linux/mfd/altera-sysgmr.h
+
 ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT
 M:     Thor Thayer <thor.thayer@linux.intel.com>
 S:     Maintained
@@ -9408,6 +9414,20 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/sound/max9860.txt
 F:     sound/soc/codecs/max9860.*
 
+MAXIM MAX77650 PMIC MFD DRIVER
+M:     Bartosz Golaszewski <bgolaszewski@baylibre.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/*/*max77650.txt
+F:     Documentation/devicetree/bindings/*/max77650*.txt
+F:     include/linux/mfd/max77650.h
+F:     drivers/mfd/max77650.c
+F:     drivers/regulator/max77650-regulator.c
+F:     drivers/power/supply/max77650-charger.c
+F:     drivers/input/misc/max77650-onkey.c
+F:     drivers/leds/leds-max77650.c
+F:     drivers/gpio/gpio-max77650.c
+
 MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
 M:     Javier Martinez Canillas <javier@dowhile0.org>
 L:     linux-kernel@vger.kernel.org
index e21ec929f096f2634fad94269632f435cc09d5e7..714863f8f261b3ac3ff55a100b5a39a010770233 100644 (file)
 
                width-mm = <50>;
                height-mm = <89>;
-               backlight = <&lcd_backlight>;
 
                panel-timing {
                        clock-frequency = <0>;          /* Calculated by dsi */
 };
 
 &i2c1 {
-       lm3532@38 {
+       led-controller@38 {
                compatible = "ti,lm3532";
+               #address-cells = <1>;
+               #size-cells = <0>;
                reg = <0x38>;
 
                enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
 
-               lcd_backlight: backlight {
-                       compatible = "ti,lm3532-backlight";
+               ramp-up-us = <1024>;
+               ramp-down-us = <8193>;
 
-                       lcd {
-                               led-sources = <0 1 2>;
-                               ramp-up-msec = <1>;
-                               ramp-down-msec = <0>;
-                       };
+               led@0 {
+                       reg = <0>;
+                       led-sources = <2>;
+                       ti,led-mode = <0>;
+                       label = ":backlight";
+                       linux,default-trigger = "backlight";
+               };
+
+               led@1 {
+                       reg = <1>;
+                       led-sources = <1>;
+                       ti,led-mode = <0>;
+                       label = ":kbd_backlight";
                };
        };
 };
index 08d1b3e11d68c81cd917eae56b9d226671888809..2d29992a60d24a5bf009b4802006febfab2a0e02 100644 (file)
@@ -106,6 +106,7 @@ CONFIG_SENSORS_LTC2978_REGULATOR=y
 CONFIG_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_MFD_ALTERA_A10SR=y
+CONFIG_MFD_ALTERA_SYSMGR=y
 CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
index cd7c76e58b09a60f75ccd510083bab730a2378b0..30195843014952525b1de86ef85a821f4000284e 100644 (file)
                };
 
                sysmgr: sysmgr@ffd12000 {
-                       compatible = "altr,sys-mgr", "syscon";
+                       compatible = "altr,sys-mgr-s10","altr,sys-mgr";
                        reg = <0xffd12000 0x228>;
                };
 
index 2d9c39033c1aa91cff516457aed405d5de1dc2c2..9e0b7ab639b3dcd69e385726a60b57f9352a75d4 100644 (file)
@@ -432,6 +432,7 @@ CONFIG_MESON_WATCHDOG=m
 CONFIG_RENESAS_WDT=y
 CONFIG_UNIPHIER_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
+CONFIG_MFD_ALTERA_SYSMGR=y
 CONFIG_MFD_BD9571MWV=y
 CONFIG_MFD_AXP20X_I2C=y
 CONFIG_MFD_AXP20X_RSB=y
index 3f50526a771fe8e21349b0d3c00efefd6cdb4a36..c4f912104440eff2b5fd39b6f8a86831f978aa74 100644 (file)
@@ -1112,6 +1112,13 @@ config GPIO_MAX77620
          driver also provides interrupt support for each of the gpios.
          Say yes here to enable the max77620 to be used as gpio controller.
 
+config GPIO_MAX77650
+       tristate "Maxim MAX77650/77651 GPIO support"
+       depends on MFD_MAX77650
+       help
+         GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.
+         These chips have a single pin that can be configured as GPIO.
+
 config GPIO_MSIC
        bool "Intel MSIC mixed signal gpio support"
        depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
index 54d55274b93aba73f40959a975657aa82a366016..075722d8317db773f614369dc8f581269db98fdd 100644 (file)
@@ -80,6 +80,7 @@ obj-$(CONFIG_GPIO_MAX7300)    += gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
 obj-$(CONFIG_GPIO_MAX77620)    += gpio-max77620.o
+obj-$(CONFIG_GPIO_MAX77650)    += gpio-max77650.o
 obj-$(CONFIG_GPIO_MB86S7X)     += gpio-mb86s7x.o
 obj-$(CONFIG_GPIO_MENZ127)     += gpio-menz127.o
 obj-$(CONFIG_GPIO_MERRIFIELD)  += gpio-merrifield.o
diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c
new file mode 100644 (file)
index 0000000..3f03f4e
--- /dev/null
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// GPIO driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_GPIO_DIR_MASK         BIT(0)
+#define MAX77650_GPIO_INVAL_MASK       BIT(1)
+#define MAX77650_GPIO_DRV_MASK         BIT(2)
+#define MAX77650_GPIO_OUTVAL_MASK      BIT(3)
+#define MAX77650_GPIO_DEBOUNCE_MASK    BIT(4)
+
+#define MAX77650_GPIO_DIR_OUT          0x00
+#define MAX77650_GPIO_DIR_IN           BIT(0)
+#define MAX77650_GPIO_OUT_LOW          0x00
+#define MAX77650_GPIO_OUT_HIGH         BIT(3)
+#define MAX77650_GPIO_DRV_OPEN_DRAIN   0x00
+#define MAX77650_GPIO_DRV_PUSH_PULL    BIT(2)
+#define MAX77650_GPIO_DEBOUNCE         BIT(4)
+
+#define MAX77650_GPIO_DIR_BITS(_reg) \
+               ((_reg) & MAX77650_GPIO_DIR_MASK)
+#define MAX77650_GPIO_INVAL_BITS(_reg) \
+               (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1)
+
+struct max77650_gpio_chip {
+       struct regmap *map;
+       struct gpio_chip gc;
+       int irq;
+};
+
+static int max77650_gpio_direction_input(struct gpio_chip *gc,
+                                        unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       return regmap_update_bits(chip->map,
+                                 MAX77650_REG_CNFG_GPIO,
+                                 MAX77650_GPIO_DIR_MASK,
+                                 MAX77650_GPIO_DIR_IN);
+}
+
+static int max77650_gpio_direction_output(struct gpio_chip *gc,
+                                         unsigned int offset, int value)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       int mask, regval;
+
+       mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK;
+       regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
+       regval |= MAX77650_GPIO_DIR_OUT;
+
+       return regmap_update_bits(chip->map,
+                                 MAX77650_REG_CNFG_GPIO, mask, regval);
+}
+
+static void max77650_gpio_set_value(struct gpio_chip *gc,
+                                   unsigned int offset, int value)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       int rv, regval;
+
+       regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
+
+       rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO,
+                               MAX77650_GPIO_OUTVAL_MASK, regval);
+       if (rv)
+               dev_err(gc->parent, "cannot set GPIO value: %d\n", rv);
+}
+
+static int max77650_gpio_get_value(struct gpio_chip *gc,
+                                  unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       unsigned int val;
+       int rv;
+
+       rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
+       if (rv)
+               return rv;
+
+       return MAX77650_GPIO_INVAL_BITS(val);
+}
+
+static int max77650_gpio_get_direction(struct gpio_chip *gc,
+                                      unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       unsigned int val;
+       int rv;
+
+       rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
+       if (rv)
+               return rv;
+
+       return MAX77650_GPIO_DIR_BITS(val);
+}
+
+static int max77650_gpio_set_config(struct gpio_chip *gc,
+                                   unsigned int offset, unsigned long cfg)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       switch (pinconf_to_config_param(cfg)) {
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DRV_MASK,
+                                         MAX77650_GPIO_DRV_OPEN_DRAIN);
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DRV_MASK,
+                                         MAX77650_GPIO_DRV_PUSH_PULL);
+       case PIN_CONFIG_INPUT_DEBOUNCE:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DEBOUNCE_MASK,
+                                         MAX77650_GPIO_DEBOUNCE);
+       default:
+               return -ENOTSUPP;
+       }
+}
+
+static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       return chip->irq;
+}
+
+static int max77650_gpio_probe(struct platform_device *pdev)
+{
+       struct max77650_gpio_chip *chip;
+       struct device *dev, *parent;
+       struct i2c_client *i2c;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+       i2c = to_i2c_client(parent);
+
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->map = dev_get_regmap(parent, NULL);
+       if (!chip->map)
+               return -ENODEV;
+
+       chip->irq = platform_get_irq_byname(pdev, "GPI");
+       if (chip->irq < 0)
+               return chip->irq;
+
+       chip->gc.base = -1;
+       chip->gc.ngpio = 1;
+       chip->gc.label = i2c->name;
+       chip->gc.parent = dev;
+       chip->gc.owner = THIS_MODULE;
+       chip->gc.can_sleep = true;
+
+       chip->gc.direction_input = max77650_gpio_direction_input;
+       chip->gc.direction_output = max77650_gpio_direction_output;
+       chip->gc.set = max77650_gpio_set_value;
+       chip->gc.get = max77650_gpio_get_value;
+       chip->gc.get_direction = max77650_gpio_get_direction;
+       chip->gc.set_config = max77650_gpio_set_config;
+       chip->gc.to_irq = max77650_gpio_to_irq;
+
+       return devm_gpiochip_add_data(dev, &chip->gc, chip);
+}
+
+static struct platform_driver max77650_gpio_driver = {
+       .driver = {
+               .name = "max77650-gpio",
+       },
+       .probe = max77650_gpio_probe,
+};
+module_platform_driver(max77650_gpio_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index e15ed1bb8558c69e2eda42507953e2e079e759d7..85bc675eecd3c4b1e4e6741950aa4581240a8907 100644 (file)
@@ -190,6 +190,15 @@ config INPUT_M68K_BEEP
        tristate "M68k Beeper support"
        depends on M68K
 
+config INPUT_MAX77650_ONKEY
+       tristate "Maxim MAX77650 ONKEY support"
+       depends on MFD_MAX77650
+       help
+         Support the ONKEY of the MAX77650 PMIC as an input device.
+
+         To compile this driver as a module, choose M here: the module
+         will be called max77650-onkey.
+
 config INPUT_MAX77693_HAPTIC
        tristate "MAXIM MAX77693/MAX77843 haptic controller support"
        depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
index b936c5b1d4ac6ac99f3f86614f886b2bd788637f..ffd72161c79bd67ff1dbfeb9e33c34593df3a1cb 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)     += ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
+obj-$(CONFIG_INPUT_MAX77650_ONKEY)     += max77650-onkey.o
 obj-$(CONFIG_INPUT_MAX77693_HAPTIC)    += max77693-haptic.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
 obj-$(CONFIG_INPUT_MAX8997_HAPTIC)     += max8997_haptic.o
diff --git a/drivers/input/misc/max77650-onkey.c b/drivers/input/misc/max77650-onkey.c
new file mode 100644 (file)
index 0000000..fbf6caa
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// ONKEY driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_ONKEY_MODE_MASK       BIT(3)
+#define MAX77650_ONKEY_MODE_PUSH       0x00
+#define MAX77650_ONKEY_MODE_SLIDE      BIT(3)
+
+struct max77650_onkey {
+       struct input_dev *input;
+       unsigned int code;
+};
+
+static irqreturn_t max77650_onkey_falling(int irq, void *data)
+{
+       struct max77650_onkey *onkey = data;
+
+       input_report_key(onkey->input, onkey->code, 0);
+       input_sync(onkey->input);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t max77650_onkey_rising(int irq, void *data)
+{
+       struct max77650_onkey *onkey = data;
+
+       input_report_key(onkey->input, onkey->code, 1);
+       input_sync(onkey->input);
+
+       return IRQ_HANDLED;
+}
+
+static int max77650_onkey_probe(struct platform_device *pdev)
+{
+       int irq_r, irq_f, error, mode;
+       struct max77650_onkey *onkey;
+       struct device *dev, *parent;
+       struct regmap *map;
+       unsigned int type;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+
+       map = dev_get_regmap(parent, NULL);
+       if (!map)
+               return -ENODEV;
+
+       onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+       if (!onkey)
+               return -ENOMEM;
+
+       error = device_property_read_u32(dev, "linux,code", &onkey->code);
+       if (error)
+               onkey->code = KEY_POWER;
+
+       if (device_property_read_bool(dev, "maxim,onkey-slide")) {
+               mode = MAX77650_ONKEY_MODE_SLIDE;
+               type = EV_SW;
+       } else {
+               mode = MAX77650_ONKEY_MODE_PUSH;
+               type = EV_KEY;
+       }
+
+       error = regmap_update_bits(map, MAX77650_REG_CNFG_GLBL,
+                                  MAX77650_ONKEY_MODE_MASK, mode);
+       if (error)
+               return error;
+
+       irq_f = platform_get_irq_byname(pdev, "nEN_F");
+       if (irq_f < 0)
+               return irq_f;
+
+       irq_r = platform_get_irq_byname(pdev, "nEN_R");
+       if (irq_r < 0)
+               return irq_r;
+
+       onkey->input = devm_input_allocate_device(dev);
+       if (!onkey->input)
+               return -ENOMEM;
+
+       onkey->input->name = "max77650_onkey";
+       onkey->input->phys = "max77650_onkey/input0";
+       onkey->input->id.bustype = BUS_I2C;
+       input_set_capability(onkey->input, type, onkey->code);
+
+       error = devm_request_any_context_irq(dev, irq_f, max77650_onkey_falling,
+                                            IRQF_ONESHOT, "onkey-down", onkey);
+       if (error < 0)
+               return error;
+
+       error = devm_request_any_context_irq(dev, irq_r, max77650_onkey_rising,
+                                            IRQF_ONESHOT, "onkey-up", onkey);
+       if (error < 0)
+               return error;
+
+       return input_register_device(onkey->input);
+}
+
+static struct platform_driver max77650_onkey_driver = {
+       .driver = {
+               .name = "max77650-onkey",
+       },
+       .probe = max77650_onkey_probe,
+};
+module_platform_driver(max77650_onkey_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index a72f97fca57b4898fbd7094e8b646a28397c4cd7..45914c66c8520f3c4952f6d60addd68068df9655 100644 (file)
@@ -138,6 +138,16 @@ config LEDS_LM3530
          controlled manually or using PWM input or using ambient
          light automatically.
 
+config LEDS_LM3532
+       tristate "LCD Backlight driver for LM3532"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for the LCD backlight using
+         LM3532 ambient light sensor chip. This ALS chip can be
+         controlled manually or using PWM input or using ambient
+         light automatically.
+
 config LEDS_LM3533
        tristate "LED support for LM3533"
        depends on LEDS_CLASS
@@ -608,6 +618,12 @@ config LEDS_TLC591XX
          This option enables support for Texas Instruments TLC59108
          and TLC59116 LED controllers.
 
+config LEDS_MAX77650
+       tristate "LED support for Maxim MAX77650 PMIC"
+       depends on LEDS_CLASS && MFD_MAX77650
+       help
+         LEDs driver for MAX77650 family of PMICs from Maxim Integrated.
+
 config LEDS_MAX77693
        tristate "LED support for MAX77693 Flash"
        depends on LEDS_CLASS_FLASH
index 4c1b0054f3797ed8cf4b0d2a47a44a1dc5c3a48b..1e9702ebffeed65064c365df5ea7a7208af8d86e 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)             += leds-bd2802.o
 obj-$(CONFIG_LEDS_CPCAP)               += leds-cpcap.o
 obj-$(CONFIG_LEDS_LOCOMO)              += leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)              += leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3532)              += leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)              += leds-lm3533.o
 obj-$(CONFIG_LEDS_LM3642)              += leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)      += leds-rb532.o
@@ -61,6 +62,7 @@ obj-$(CONFIG_LEDS_MC13783)            += leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)                 += leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)             += leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)               += leds-asic3.o
+obj-$(CONFIG_LEDS_MAX77650)            += leds-max77650.o
 obj-$(CONFIG_LEDS_MAX77693)            += leds-max77693.o
 obj-$(CONFIG_LEDS_MAX8997)             += leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)              += leds-lm355x.o
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
new file mode 100644 (file)
index 0000000..180895b
--- /dev/null
@@ -0,0 +1,683 @@
+// SPDX-License-Identifier: GPL-2.0
+// TI LM3532 LED driver
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <uapi/linux/uleds.h>
+#include <linux/gpio/consumer.h>
+
+#define LM3532_NAME "lm3532-led"
+#define LM3532_BL_MODE_MANUAL  0x00
+#define LM3532_BL_MODE_ALS     0x01
+
+#define LM3532_REG_OUTPUT_CFG  0x10
+#define LM3532_REG_STARTSHUT_RAMP      0x11
+#define LM3532_REG_RT_RAMP     0x12
+#define LM3532_REG_PWM_A_CFG   0x13
+#define LM3532_REG_PWM_B_CFG   0x14
+#define LM3532_REG_PWM_C_CFG   0x15
+#define LM3532_REG_ZONE_CFG_A  0x16
+#define LM3532_REG_CTRL_A_BRT  0x17
+#define LM3532_REG_ZONE_CFG_B  0x18
+#define LM3532_REG_CTRL_B_BRT  0x19
+#define LM3532_REG_ZONE_CFG_C  0x1a
+#define LM3532_REG_CTRL_C_BRT  0x1b
+#define LM3532_REG_ENABLE      0x1d
+#define LM3532_ALS_CONFIG      0x23
+#define LM3532_REG_ZN_0_HI     0x60
+#define LM3532_REG_ZN_0_LO     0x61
+#define LM3532_REG_ZN_1_HI     0x62
+#define LM3532_REG_ZN_1_LO     0x63
+#define LM3532_REG_ZN_2_HI     0x64
+#define LM3532_REG_ZN_2_LO     0x65
+#define LM3532_REG_ZN_3_HI     0x66
+#define LM3532_REG_ZN_3_LO     0x67
+#define LM3532_REG_MAX         0x7e
+
+/* Contorl Enable */
+#define LM3532_CTRL_A_ENABLE   BIT(0)
+#define LM3532_CTRL_B_ENABLE   BIT(1)
+#define LM3532_CTRL_C_ENABLE   BIT(2)
+
+/* PWM Zone Control */
+#define LM3532_PWM_ZONE_MASK   0x7c
+#define LM3532_PWM_ZONE_0_EN   BIT(2)
+#define LM3532_PWM_ZONE_1_EN   BIT(3)
+#define LM3532_PWM_ZONE_2_EN   BIT(4)
+#define LM3532_PWM_ZONE_3_EN   BIT(5)
+#define LM3532_PWM_ZONE_4_EN   BIT(6)
+
+/* Brightness Configuration */
+#define LM3532_I2C_CTRL                BIT(0)
+#define LM3532_ALS_CTRL                0
+#define LM3532_LINEAR_MAP      BIT(1)
+#define LM3532_ZONE_MASK       (BIT(2) | BIT(3) | BIT(4))
+#define LM3532_ZONE_0          0
+#define LM3532_ZONE_1          BIT(2)
+#define LM3532_ZONE_2          BIT(3)
+#define LM3532_ZONE_3          (BIT(2) | BIT(3))
+#define LM3532_ZONE_4          BIT(4)
+
+#define LM3532_ENABLE_ALS      BIT(3)
+#define LM3532_ALS_SEL_SHIFT   6
+
+/* Zone Boundary Register */
+#define LM3532_ALS_WINDOW_mV   2000
+#define LM3532_ALS_ZB_MAX      4
+#define LM3532_ALS_OFFSET_mV   2
+
+#define LM3532_CONTROL_A       0
+#define LM3532_CONTROL_B       1
+#define LM3532_CONTROL_C       2
+#define LM3532_MAX_CONTROL_BANKS 3
+#define LM3532_MAX_LED_STRINGS 3
+
+#define LM3532_OUTPUT_CFG_MASK 0x3
+#define LM3532_BRT_VAL_ADJUST  8
+#define LM3532_RAMP_DOWN_SHIFT 3
+
+#define LM3532_NUM_RAMP_VALS   8
+#define LM3532_NUM_AVG_VALS    8
+#define LM3532_NUM_IMP_VALS    32
+
+/*
+ * struct lm3532_als_data
+ * @config - value of ALS configuration register
+ * @als1_imp_sel - value of ALS1 resistor select register
+ * @als2_imp_sel - value of ALS2 resistor select register
+ * @als_avrg_time - ALS averaging time
+ * @als_input_mode - ALS input mode for brightness control
+ * @als_vmin - Minimum ALS voltage
+ * @als_vmax - Maximum ALS voltage
+ * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
+ * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
+ */
+struct lm3532_als_data {
+       u8 config;
+       u8 als1_imp_sel;
+       u8 als2_imp_sel;
+       u8 als_avrg_time;
+       u8 als_input_mode;
+       u32 als_vmin;
+       u32 als_vmax;
+       u8 zones_lo[LM3532_ALS_ZB_MAX];
+       u8 zones_hi[LM3532_ALS_ZB_MAX];
+};
+
+/**
+ * struct lm3532_led
+ * @led_dev: led class device
+ * @priv - Pointer the device data structure
+ * @control_bank - Control bank the LED is associated to
+ * @mode - Mode of the LED string
+ * @num_leds - Number of LED strings are supported in this array
+ * @led_strings - The LED strings supported in this array
+ * @label - LED label
+ */
+struct lm3532_led {
+       struct led_classdev led_dev;
+       struct lm3532_data *priv;
+
+       int control_bank;
+       int mode;
+       int num_leds;
+       u32 led_strings[LM3532_MAX_CONTROL_BANKS];
+       char label[LED_MAX_NAME_SIZE];
+};
+
+/**
+ * struct lm3532_data
+ * @enable_gpio - Hardware enable gpio
+ * @regulator: regulator
+ * @client: i2c client
+ * @regmap - Devices register map
+ * @dev - Pointer to the devices device struct
+ * @lock - Lock for reading/writing the device
+ * @als_data - Pointer to the als data struct
+ * @runtime_ramp_up - Runtime ramp up setting
+ * @runtime_ramp_down - Runtime ramp down setting
+ * @leds - Array of LED strings
+ */
+struct lm3532_data {
+       struct gpio_desc *enable_gpio;
+       struct regulator *regulator;
+       struct i2c_client *client;
+       struct regmap *regmap;
+       struct device *dev;
+       struct mutex lock;
+
+       struct lm3532_als_data *als_data;
+
+       u32 runtime_ramp_up;
+       u32 runtime_ramp_down;
+
+       struct lm3532_led leds[];
+};
+
+static const struct reg_default lm3532_reg_defs[] = {
+       {LM3532_REG_OUTPUT_CFG, 0xe4},
+       {LM3532_REG_STARTSHUT_RAMP, 0xc0},
+       {LM3532_REG_RT_RAMP, 0xc0},
+       {LM3532_REG_PWM_A_CFG, 0x82},
+       {LM3532_REG_PWM_B_CFG, 0x82},
+       {LM3532_REG_PWM_C_CFG, 0x82},
+       {LM3532_REG_ZONE_CFG_A, 0xf1},
+       {LM3532_REG_CTRL_A_BRT, 0xf3},
+       {LM3532_REG_ZONE_CFG_B, 0xf1},
+       {LM3532_REG_CTRL_B_BRT, 0xf3},
+       {LM3532_REG_ZONE_CFG_C, 0xf1},
+       {LM3532_REG_CTRL_C_BRT, 0xf3},
+       {LM3532_REG_ENABLE, 0xf8},
+       {LM3532_ALS_CONFIG, 0x44},
+       {LM3532_REG_ZN_0_HI, 0x35},
+       {LM3532_REG_ZN_0_LO, 0x33},
+       {LM3532_REG_ZN_1_HI, 0x6a},
+       {LM3532_REG_ZN_1_LO, 0x66},
+       {LM3532_REG_ZN_2_HI, 0xa1},
+       {LM3532_REG_ZN_2_LO, 0x99},
+       {LM3532_REG_ZN_3_HI, 0xdc},
+       {LM3532_REG_ZN_3_LO, 0xcc},
+};
+
+static const struct regmap_config lm3532_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = LM3532_REG_MAX,
+       .reg_defaults = lm3532_reg_defs,
+       .num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
+       .cache_type = REGCACHE_FLAT,
+};
+
+const static int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330,
+                                                      92500, 7400, 6170, 5290,
+                                                      4630, 4110, 3700, 3360,
+                                                      3080, 2850, 2640, 2440,
+                                                      2310, 2180, 2060, 1950,
+                                                      1850, 1760, 1680, 1610,
+                                                      1540, 1480, 1420, 1370,
+                                                      1320, 1280, 1230, 1190};
+static int lm3532_get_als_imp_index(int als_imped)
+{
+       int i;
+
+       if (als_imped > als_imp_table[1])
+               return 0;
+
+       if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1])
+               return LM3532_NUM_IMP_VALS - 1;
+
+       for (i = 1; i < LM3532_NUM_IMP_VALS; i++) {
+               if (als_imped == als_imp_table[i])
+                       return i;
+
+               /* Find an approximate index by looking up the table */
+               if (als_imped < als_imp_table[i - 1] &&
+                   als_imped > als_imp_table[i]) {
+                       if (als_imped - als_imp_table[i - 1] <
+                           als_imp_table[i] - als_imped)
+                               return i + 1;
+                       else
+                               return i;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int lm3532_get_index(const int table[], int size, int value)
+{
+       int i;
+
+       for (i = 1; i < size; i++) {
+               if (value == table[i])
+                       return i;
+
+               /* Find an approximate index by looking up the table */
+               if (value > table[i - 1] &&
+                   value < table[i]) {
+                       if (value - table[i - 1] < table[i] - value)
+                               return i - 1;
+                       else
+                               return i;
+               }
+       }
+
+       return -EINVAL;
+}
+
+const static int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680,
+                                                       1433360, 286720, 573440,
+                                                       1146880, 2293760};
+static int lm3532_get_als_avg_index(int avg_time)
+{
+       if (avg_time <= als_avrg_table[0])
+               return 0;
+
+       if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1])
+               return LM3532_NUM_AVG_VALS - 1;
+
+       return lm3532_get_index(&als_avrg_table[0], LM3532_NUM_AVG_VALS,
+                               avg_time);
+}
+
+const static int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192,
+                                                    16384, 32768, 65536};
+static int lm3532_get_ramp_index(int ramp_time)
+{
+       if (ramp_time <= ramp_table[0])
+               return 0;
+
+       if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1])
+               return LM3532_NUM_RAMP_VALS - 1;
+
+       return lm3532_get_index(&ramp_table[0], LM3532_NUM_RAMP_VALS,
+                               ramp_time);
+}
+
+static int lm3532_led_enable(struct lm3532_led *led_data)
+{
+       int ctrl_en_val = BIT(led_data->control_bank);
+       int ret;
+
+       ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+                                        ctrl_en_val, ctrl_en_val);
+       if (ret) {
+               dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+               return ret;
+       }
+
+       return regulator_enable(led_data->priv->regulator);
+}
+
+static int lm3532_led_disable(struct lm3532_led *led_data)
+{
+       int ctrl_en_val = BIT(led_data->control_bank);
+       int ret;
+
+       ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+                                        ctrl_en_val, ~ctrl_en_val);
+       if (ret) {
+               dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+               return ret;
+       }
+
+       return regulator_disable(led_data->priv->regulator);
+}
+
+static int lm3532_brightness_set(struct led_classdev *led_cdev,
+                                enum led_brightness brt_val)
+{
+       struct lm3532_led *led =
+                       container_of(led_cdev, struct lm3532_led, led_dev);
+       u8 brightness_reg;
+       int ret;
+
+       mutex_lock(&led->priv->lock);
+
+       if (led->mode == LM3532_BL_MODE_ALS) {
+               if (brt_val > LED_OFF)
+                       ret = lm3532_led_enable(led);
+               else
+                       ret = lm3532_led_disable(led);
+
+               goto unlock;
+       }
+
+       if (brt_val == LED_OFF) {
+               ret = lm3532_led_disable(led);
+               goto unlock;
+       }
+
+       ret = lm3532_led_enable(led);
+       if (ret)
+               goto unlock;
+
+       brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2;
+       brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
+
+       ret = regmap_write(led->priv->regmap, brightness_reg, brt_val);
+
+unlock:
+       mutex_unlock(&led->priv->lock);
+       return ret;
+}
+
+static int lm3532_init_registers(struct lm3532_led *led)
+{
+       struct lm3532_data *drvdata = led->priv;
+       unsigned int runtime_ramp_val;
+       unsigned int output_cfg_val = 0;
+       unsigned int output_cfg_shift = 0;
+       unsigned int output_cfg_mask = 0;
+       int ret, i;
+
+       for (i = 0; i < led->num_leds; i++) {
+               output_cfg_shift = led->led_strings[i] * 2;
+               output_cfg_val |= (led->control_bank << output_cfg_shift);
+               output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
+       }
+
+       ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
+                                output_cfg_mask, output_cfg_val);
+       if (ret)
+               return ret;
+
+       runtime_ramp_val = drvdata->runtime_ramp_up |
+                        (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
+
+       return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
+                           runtime_ramp_val);
+}
+
+static int lm3532_als_configure(struct lm3532_data *priv,
+                               struct lm3532_led *led)
+{
+       struct lm3532_als_data *als = priv->als_data;
+       u32 als_vmin, als_vmax, als_vstep;
+       int zone_reg = LM3532_REG_ZN_0_HI;
+       int brightnes_config_reg;
+       int ret;
+       int i;
+
+       als_vmin = als->als_vmin;
+       als_vmax = als->als_vmax;
+
+       als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
+
+       for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
+               als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
+                               LED_FULL) / 1000;
+               als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
+                               als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
+
+               zone_reg = LM3532_REG_ZN_0_HI + i * 2;
+               ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
+               if (ret)
+                       return ret;
+
+               zone_reg += 1;
+               ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
+               if (ret)
+                       return ret;
+       }
+
+       als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
+               (als->als_input_mode << LM3532_ALS_SEL_SHIFT));
+
+       ret = regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
+       if (ret)
+               return ret;
+
+       brightnes_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2;
+
+       return regmap_update_bits(priv->regmap, brightnes_config_reg,
+                                 LM3532_I2C_CTRL, LM3532_ALS_CTRL);
+}
+
+static int lm3532_parse_als(struct lm3532_data *priv)
+{
+       struct lm3532_als_data *als;
+       int als_avg_time;
+       int als_impedance;
+       int ret;
+
+       als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
+       if (als == NULL)
+               return -ENOMEM;
+
+       ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin",
+                                      &als->als_vmin);
+       if (ret)
+               als->als_vmin = 0;
+
+       ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax",
+                                      &als->als_vmax);
+       if (ret)
+               als->als_vmax = LM3532_ALS_WINDOW_mV;
+
+       if (als->als_vmax > LM3532_ALS_WINDOW_mV) {
+               ret = -EINVAL;
+               return ret;
+       }
+
+       ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel",
+                                     &als_impedance);
+       if (ret)
+               als->als1_imp_sel = 0;
+       else
+               als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+       ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel",
+                                     &als_impedance);
+       if (ret)
+               als->als2_imp_sel = 0;
+       else
+               als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+       ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us",
+                                     &als_avg_time);
+       if (ret)
+               als->als_avrg_time = 0;
+       else
+               als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time);
+
+       ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode",
+                                     &als->als_input_mode);
+       if (ret)
+               als->als_input_mode = 0;
+
+       if (als->als_input_mode > LM3532_BL_MODE_ALS) {
+               ret = -EINVAL;
+               return ret;
+       }
+
+       priv->als_data = als;
+
+       return ret;
+}
+
+static int lm3532_parse_node(struct lm3532_data *priv)
+{
+       struct fwnode_handle *child = NULL;
+       struct lm3532_led *led;
+       const char *name;
+       int control_bank;
+       u32 ramp_time;
+       size_t i = 0;
+       int ret;
+
+       priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+                                                  "enable", GPIOD_OUT_LOW);
+       if (IS_ERR(priv->enable_gpio))
+               priv->enable_gpio = NULL;
+
+       priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
+       if (IS_ERR(priv->regulator))
+               priv->regulator = NULL;
+
+       ret = device_property_read_u32(&priv->client->dev, "ramp-up-us",
+                                      &ramp_time);
+       if (ret)
+               dev_info(&priv->client->dev, "ramp-up-ms property missing\n");
+       else
+               priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time);
+
+       ret = device_property_read_u32(&priv->client->dev, "ramp-down-us",
+                                      &ramp_time);
+       if (ret)
+               dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+       else
+               priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time);
+
+       device_for_each_child_node(priv->dev, child) {
+               led = &priv->leds[i];
+
+               ret = fwnode_property_read_u32(child, "reg", &control_bank);
+               if (ret) {
+                       dev_err(&priv->client->dev, "reg property missing\n");
+                       fwnode_handle_put(child);
+                       goto child_out;
+               }
+
+               if (control_bank > LM3532_CONTROL_C) {
+                       dev_err(&priv->client->dev, "Control bank invalid\n");
+                       continue;
+               }
+
+               led->control_bank = control_bank;
+
+               ret = fwnode_property_read_u32(child, "ti,led-mode",
+                                              &led->mode);
+               if (ret) {
+                       dev_err(&priv->client->dev, "ti,led-mode property missing\n");
+                       fwnode_handle_put(child);
+                       goto child_out;
+               }
+
+               if (led->mode == LM3532_BL_MODE_ALS) {
+                       ret = lm3532_parse_als(priv);
+                       if (ret)
+                               dev_err(&priv->client->dev, "Failed to parse als\n");
+                       else
+                               lm3532_als_configure(priv, led);
+               }
+
+               led->num_leds = fwnode_property_read_u32_array(child,
+                                                              "led-sources",
+                                                              NULL, 0);
+
+               if (led->num_leds > LM3532_MAX_LED_STRINGS) {
+                       dev_err(&priv->client->dev, "To many LED string defined\n");
+                       continue;
+               }
+
+               ret = fwnode_property_read_u32_array(child, "led-sources",
+                                                   led->led_strings,
+                                                   led->num_leds);
+               if (ret) {
+                       dev_err(&priv->client->dev, "led-sources property missing\n");
+                       fwnode_handle_put(child);
+                       goto child_out;
+               }
+
+               fwnode_property_read_string(child, "linux,default-trigger",
+                                           &led->led_dev.default_trigger);
+
+               ret = fwnode_property_read_string(child, "label", &name);
+               if (ret)
+                       snprintf(led->label, sizeof(led->label),
+                               "%s::", priv->client->name);
+               else
+                       snprintf(led->label, sizeof(led->label),
+                                "%s:%s", priv->client->name, name);
+
+               led->priv = priv;
+               led->led_dev.name = led->label;
+               led->led_dev.brightness_set_blocking = lm3532_brightness_set;
+
+               ret = devm_led_classdev_register(priv->dev, &led->led_dev);
+               if (ret) {
+                       dev_err(&priv->client->dev, "led register err: %d\n",
+                               ret);
+                       fwnode_handle_put(child);
+                       goto child_out;
+               }
+
+               lm3532_init_registers(led);
+
+               i++;
+       }
+
+child_out:
+       return ret;
+}
+
+static int lm3532_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
+{
+       struct lm3532_data *drvdata;
+       int ret = 0;
+       int count;
+
+       count = device_get_child_node_count(&client->dev);
+       if (!count) {
+               dev_err(&client->dev, "LEDs are not defined in device tree!");
+               return -ENODEV;
+       }
+
+       drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
+                          GFP_KERNEL);
+       if (drvdata == NULL)
+               return -ENOMEM;
+
+       drvdata->client = client;
+       drvdata->dev = &client->dev;
+
+       drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
+       if (IS_ERR(drvdata->regmap)) {
+               ret = PTR_ERR(drvdata->regmap);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       mutex_init(&drvdata->lock);
+       i2c_set_clientdata(client, drvdata);
+
+       ret = lm3532_parse_node(drvdata);
+       if (ret) {
+               dev_err(&client->dev, "Failed to parse node\n");
+               return ret;
+       }
+
+       if (drvdata->enable_gpio)
+               gpiod_direction_output(drvdata->enable_gpio, 1);
+
+       return ret;
+}
+
+static int lm3532_remove(struct i2c_client *client)
+{
+       struct lm3532_data *drvdata = i2c_get_clientdata(client);
+
+       mutex_destroy(&drvdata->lock);
+
+       if (drvdata->enable_gpio)
+               gpiod_direction_output(drvdata->enable_gpio, 0);
+
+       return 0;
+}
+
+static const struct of_device_id of_lm3532_leds_match[] = {
+       { .compatible = "ti,lm3532", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
+
+static const struct i2c_device_id lm3532_id[] = {
+       {LM3532_NAME, 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, lm3532_id);
+
+static struct i2c_driver lm3532_i2c_driver = {
+       .probe = lm3532_probe,
+       .remove = lm3532_remove,
+       .id_table = lm3532_id,
+       .driver = {
+               .name = LM3532_NAME,
+               .of_match_table = of_lm3532_leds_match,
+       },
+};
+module_i2c_driver(lm3532_i2c_driver);
+
+MODULE_DESCRIPTION("Back Light driver for LM3532");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c
new file mode 100644 (file)
index 0000000..6b74ce9
--- /dev/null
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// LED driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_LED_NUM_LEDS          3
+
+#define MAX77650_LED_A_BASE            0x40
+#define MAX77650_LED_B_BASE            0x43
+
+#define MAX77650_LED_BR_MASK           GENMASK(4, 0)
+#define MAX77650_LED_EN_MASK           GENMASK(7, 6)
+
+#define MAX77650_LED_MAX_BRIGHTNESS    MAX77650_LED_BR_MASK
+
+/* Enable EN_LED_MSTR. */
+#define MAX77650_LED_TOP_DEFAULT       BIT(0)
+
+#define MAX77650_LED_ENABLE            GENMASK(7, 6)
+#define MAX77650_LED_DISABLE           0x00
+
+#define MAX77650_LED_A_DEFAULT         MAX77650_LED_DISABLE
+/* 100% on duty */
+#define MAX77650_LED_B_DEFAULT         GENMASK(3, 0)
+
+struct max77650_led {
+       struct led_classdev cdev;
+       struct regmap *map;
+       unsigned int regA;
+       unsigned int regB;
+};
+
+static struct max77650_led *max77650_to_led(struct led_classdev *cdev)
+{
+       return container_of(cdev, struct max77650_led, cdev);
+}
+
+static int max77650_led_brightness_set(struct led_classdev *cdev,
+                                      enum led_brightness brightness)
+{
+       struct max77650_led *led = max77650_to_led(cdev);
+       int val, mask;
+
+       mask = MAX77650_LED_BR_MASK | MAX77650_LED_EN_MASK;
+
+       if (brightness == LED_OFF)
+               val = MAX77650_LED_DISABLE;
+       else
+               val = MAX77650_LED_ENABLE | brightness;
+
+       return regmap_update_bits(led->map, led->regA, mask, val);
+}
+
+static int max77650_led_probe(struct platform_device *pdev)
+{
+       struct device_node *of_node, *child;
+       struct max77650_led *leds, *led;
+       struct device *parent;
+       struct device *dev;
+       struct regmap *map;
+       const char *label;
+       int rv, num_leds;
+       u32 reg;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+       of_node = dev->of_node;
+
+       if (!of_node)
+               return -ENODEV;
+
+       leds = devm_kcalloc(dev, sizeof(*leds),
+                           MAX77650_LED_NUM_LEDS, GFP_KERNEL);
+       if (!leds)
+               return -ENOMEM;
+
+       map = dev_get_regmap(dev->parent, NULL);
+       if (!map)
+               return -ENODEV;
+
+       num_leds = of_get_child_count(of_node);
+       if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS)
+               return -ENODEV;
+
+       for_each_child_of_node(of_node, child) {
+               rv = of_property_read_u32(child, "reg", &reg);
+               if (rv || reg >= MAX77650_LED_NUM_LEDS)
+                       return -EINVAL;
+
+               led = &leds[reg];
+               led->map = map;
+               led->regA = MAX77650_LED_A_BASE + reg;
+               led->regB = MAX77650_LED_B_BASE + reg;
+               led->cdev.brightness_set_blocking = max77650_led_brightness_set;
+               led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS;
+
+               label = of_get_property(child, "label", NULL);
+               if (!label) {
+                       led->cdev.name = "max77650::";
+               } else {
+                       led->cdev.name = devm_kasprintf(dev, GFP_KERNEL,
+                                                       "max77650:%s", label);
+                       if (!led->cdev.name)
+                               return -ENOMEM;
+               }
+
+               of_property_read_string(child, "linux,default-trigger",
+                                       &led->cdev.default_trigger);
+
+               rv = devm_of_led_classdev_register(dev, child, &led->cdev);
+               if (rv)
+                       return rv;
+
+               rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT);
+               if (rv)
+                       return rv;
+
+               rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT);
+               if (rv)
+                       return rv;
+       }
+
+       return regmap_write(map,
+                           MAX77650_REG_CNFG_LED_TOP,
+                           MAX77650_LED_TOP_DEFAULT);
+}
+
+static struct platform_driver max77650_led_driver = {
+       .driver = {
+               .name = "max77650-led",
+       },
+       .probe = max77650_led_probe,
+};
+module_platform_driver(max77650_led_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 87c55249dff25a4dc1ed1cec216e6f173210c707..9d53480352a67cc55ede07819f86b644e832b0bd 100644 (file)
@@ -29,6 +29,16 @@ config MFD_ALTERA_A10SR
          accessing the external gpio extender (LEDs & buttons) and
          power supply alarms (hwmon).
 
+config MFD_ALTERA_SYSMGR
+       bool "Altera SOCFPGA System Manager"
+       depends on (ARCH_SOCFPGA || ARCH_STRATIX10) && OF
+       select MFD_SYSCON
+       help
+         Select this to get System Manager support for all Altera branded
+         SOCFPGAs. The SOCFPGA System Manager handles all SOCFPGAs by
+         using regmap_mmio accesses for ARM32 parts and SMC calls to
+         EL3 for ARM64 parts.
+
 config MFD_ACT8945A
        tristate "Active-semi ACT8945A"
        select MFD_CORE
@@ -733,6 +743,20 @@ config MFD_MAX77620
          provides common support for accessing the device; additional drivers
          must be enabled in order to use the functionality of the device.
 
+config MFD_MAX77650
+       tristate "Maxim MAX77650/77651 PMIC Support"
+       depends on I2C
+       depends on OF || COMPILE_TEST
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Say Y here to add support for Maxim Semiconductor MAX77650 and
+         MAX77651 Power Management ICs. This is the core multifunction
+         driver for interacting with the device. The module name is
+         'max77650'. Additional drivers can be enabled in order to use
+         the following functionalities of the device: GPIO, regulator,
+         charger, LED, onkey.
+
 config MFD_MAX77686
        tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
        depends on I2C
index 614eea87990e5b9d8bf546cb0104173c58578abd..52b1a90ff5159308c984b8ea319d2ba848755b5f 100644 (file)
@@ -155,6 +155,7 @@ obj-$(CONFIG_MFD_DA9150)    += da9150-core.o
 
 obj-$(CONFIG_MFD_MAX14577)     += max14577.o
 obj-$(CONFIG_MFD_MAX77620)     += max77620.o
+obj-$(CONFIG_MFD_MAX77650)     += max77650.o
 obj-$(CONFIG_MFD_MAX77686)     += max77686.o
 obj-$(CONFIG_MFD_MAX77693)     += max77693.o
 obj-$(CONFIG_MFD_MAX77843)     += max77843.o
@@ -237,6 +238,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)       += intel_soc_pmic_chtdc_ti.o
 obj-$(CONFIG_MFD_MT6397)       += mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
 obj-$(CONFIG_MFD_STPMIC1)      += stpmic1.o
 obj-$(CONFIG_MFD_SUN4I_GPADC)  += sun4i-gpadc.o
 
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
new file mode 100644 (file)
index 0000000..8976f82
--- /dev/null
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2018-2019, Intel Corporation.
+ *  Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *  Copyright (C) 2012 Linaro Ltd.
+ *
+ *  Based on syscon driver.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/altera-sysmgr.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/**
+ * struct altr_sysmgr - Altera SOCFPGA System Manager
+ * @regmap: the regmap used for System Manager accesses.
+ * @base  : the base address for the System Manager
+ */
+struct altr_sysmgr {
+       struct regmap   *regmap;
+       resource_size_t *base;
+};
+
+static struct platform_driver altr_sysmgr_driver;
+
+/**
+ * s10_protected_reg_write
+ * Write to a protected SMC register.
+ * @base: Base address of System Manager
+ * @reg:  Address offset of register
+ * @val:  Value to write
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ *        INTEL_SIP_SMC_REG_ERROR on error
+ *        INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_write(void *base,
+                                  unsigned int reg, unsigned int val)
+{
+       struct arm_smccc_res result;
+       unsigned long sysmgr_base = (unsigned long)base;
+
+       arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, sysmgr_base + reg,
+                     val, 0, 0, 0, 0, 0, &result);
+
+       return (int)result.a0;
+}
+
+/**
+ * s10_protected_reg_read
+ * Read the status of a protected SMC register
+ * @base: Base address of System Manager.
+ * @reg:  Address of register
+ * @val:  Value read.
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ *        INTEL_SIP_SMC_REG_ERROR on error
+ *        INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_read(void *base,
+                                 unsigned int reg, unsigned int *val)
+{
+       struct arm_smccc_res result;
+       unsigned long sysmgr_base = (unsigned long)base;
+
+       arm_smccc_smc(INTEL_SIP_SMC_REG_READ, sysmgr_base + reg,
+                     0, 0, 0, 0, 0, 0, &result);
+
+       *val = (unsigned int)result.a1;
+
+       return (int)result.a0;
+}
+
+static struct regmap_config altr_sysmgr_regmap_cfg = {
+       .name = "altr_sysmgr",
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .fast_io = true,
+       .use_single_read = true,
+       .use_single_write = true,
+};
+
+/**
+ * sysmgr_match_phandle
+ * Matching function used by driver_find_device().
+ * Return: True if match is found, otherwise false.
+ */
+static int sysmgr_match_phandle(struct device *dev, void *data)
+{
+       return dev->of_node == (struct device_node *)data;
+}
+
+/**
+ * altr_sysmgr_regmap_lookup_by_phandle
+ * Find the sysmgr previous configured in probe() and return regmap property.
+ * Return: regmap if found or error if not found.
+ */
+struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                                   const char *property)
+{
+       struct device *dev;
+       struct altr_sysmgr *sysmgr;
+       struct device_node *sysmgr_np;
+
+       if (property)
+               sysmgr_np = of_parse_phandle(np, property, 0);
+       else
+               sysmgr_np = np;
+
+       if (!sysmgr_np)
+               return ERR_PTR(-ENODEV);
+
+       dev = driver_find_device(&altr_sysmgr_driver.driver, NULL,
+                                (void *)sysmgr_np, sysmgr_match_phandle);
+       of_node_put(sysmgr_np);
+       if (!dev)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       sysmgr = dev_get_drvdata(dev);
+
+       return sysmgr->regmap;
+}
+EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle);
+
+static int sysmgr_probe(struct platform_device *pdev)
+{
+       struct altr_sysmgr *sysmgr;
+       struct regmap *regmap;
+       struct resource *res;
+       struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+
+       sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL);
+       if (!sysmgr)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       sysmgr_config.max_register = resource_size(res) -
+                                    sysmgr_config.reg_stride;
+       if (of_device_is_compatible(np, "altr,sys-mgr-s10")) {
+               /* Need physical address for SMCC call */
+               sysmgr->base = (resource_size_t *)res->start;
+               sysmgr_config.reg_read = s10_protected_reg_read;
+               sysmgr_config.reg_write = s10_protected_reg_write;
+
+               regmap = devm_regmap_init(dev, NULL, sysmgr->base,
+                                         &sysmgr_config);
+       } else {
+               sysmgr->base = devm_ioremap(dev, res->start,
+                                           resource_size(res));
+               if (!sysmgr->base)
+                       return -ENOMEM;
+
+               sysmgr_config.max_register = res->end - res->start - 3;
+               regmap = devm_regmap_init_mmio(dev, sysmgr->base,
+                                              &sysmgr_config);
+       }
+
+       if (IS_ERR(regmap)) {
+               pr_err("regmap init failed\n");
+               return PTR_ERR(regmap);
+       }
+
+       sysmgr->regmap = regmap;
+
+       platform_set_drvdata(pdev, sysmgr);
+
+       return 0;
+}
+
+static const struct of_device_id altr_sysmgr_of_match[] = {
+       { .compatible = "altr,sys-mgr" },
+       { .compatible = "altr,sys-mgr-s10" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, altr_sysmgr_of_match);
+
+static struct platform_driver altr_sysmgr_driver = {
+       .probe =  sysmgr_probe,
+       .driver = {
+               .name = "altr,system_manager",
+               .of_match_table = altr_sysmgr_of_match,
+       },
+};
+
+static int __init altr_sysmgr_init(void)
+{
+       return platform_driver_register(&altr_sysmgr_driver);
+}
+core_initcall(altr_sysmgr_init);
+
+static void __exit altr_sysmgr_exit(void)
+{
+       platform_driver_unregister(&altr_sysmgr_driver);
+}
+module_exit(altr_sysmgr_exit);
+
+MODULE_AUTHOR("Thor Thayer <>");
+MODULE_DESCRIPTION("SOCFPGA System Manager driver");
+MODULE_LICENSE("GPL v2");
index d8ddd1a6f30497ff7a866b40fe21f25ad45badea..436361ce373758bb6a41d0ef56662e9824d53d9a 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+static struct max77620_chip *max77620_scratch;
+
 static const struct resource gpio_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
 };
@@ -111,6 +113,26 @@ static const struct mfd_cell max20024_children[] = {
        },
 };
 
+static const struct mfd_cell max77663_children[] = {
+       { .name = "max77620-pinctrl", },
+       { .name = "max77620-clock", },
+       { .name = "max77663-pmic", },
+       { .name = "max77620-watchdog", },
+       {
+               .name = "max77620-gpio",
+               .resources = gpio_resources,
+               .num_resources = ARRAY_SIZE(gpio_resources),
+       }, {
+               .name = "max77620-rtc",
+               .resources = rtc_resources,
+               .num_resources = ARRAY_SIZE(rtc_resources),
+       }, {
+               .name = "max77663-power",
+               .resources = power_resources,
+               .num_resources = ARRAY_SIZE(power_resources),
+       },
+};
+
 static const struct regmap_range max77620_readable_ranges[] = {
        regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
 };
@@ -171,6 +193,35 @@ static const struct regmap_config max20024_regmap_config = {
        .volatile_table = &max77620_volatile_table,
 };
 
+static const struct regmap_range max77663_readable_ranges[] = {
+       regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
+};
+
+static const struct regmap_access_table max77663_readable_table = {
+       .yes_ranges = max77663_readable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges),
+};
+
+static const struct regmap_range max77663_writable_ranges[] = {
+       regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
+};
+
+static const struct regmap_access_table max77663_writable_table = {
+       .yes_ranges = max77663_writable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges),
+};
+
+static const struct regmap_config max77663_regmap_config = {
+       .name = "power-slave",
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX77620_REG_CID5 + 1,
+       .cache_type = REGCACHE_RBTREE,
+       .rd_table = &max77663_readable_table,
+       .wr_table = &max77663_writable_table,
+       .volatile_table = &max77620_volatile_table,
+};
+
 /*
  * MAX77620 and MAX20024 has the following steps of the interrupt handling
  * for TOP interrupts:
@@ -240,6 +291,9 @@ static int max77620_get_fps_period_reg_value(struct max77620_chip *chip,
        case MAX77620:
                fps_min_period = MAX77620_FPS_PERIOD_MIN_US;
                break;
+       case MAX77663:
+               fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
+               break;
        default:
                return -EINVAL;
        }
@@ -274,6 +328,9 @@ static int max77620_config_fps(struct max77620_chip *chip,
        case MAX77620:
                fps_max_period = MAX77620_FPS_PERIOD_MAX_US;
                break;
+       case MAX77663:
+               fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
+               break;
        default:
                return -EINVAL;
        }
@@ -375,6 +432,9 @@ static int max77620_initialise_fps(struct max77620_chip *chip)
        }
 
 skip_fps:
+       if (chip->chip_id == MAX77663)
+               return 0;
+
        /* Enable wake on EN0 pin */
        ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
                                 MAX77620_ONOFFCNFG2_WK_EN0,
@@ -423,6 +483,15 @@ static int max77620_read_es_version(struct max77620_chip *chip)
        return ret;
 }
 
+static void max77620_pm_power_off(void)
+{
+       struct max77620_chip *chip = max77620_scratch;
+
+       regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
+                          MAX77620_ONOFFCNFG1_SFT_RST,
+                          MAX77620_ONOFFCNFG1_SFT_RST);
+}
+
 static int max77620_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -430,6 +499,7 @@ static int max77620_probe(struct i2c_client *client,
        struct max77620_chip *chip;
        const struct mfd_cell *mfd_cells;
        int n_mfd_cells;
+       bool pm_off;
        int ret;
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
@@ -453,6 +523,11 @@ static int max77620_probe(struct i2c_client *client,
                n_mfd_cells = ARRAY_SIZE(max20024_children);
                rmap_config = &max20024_regmap_config;
                break;
+       case MAX77663:
+               mfd_cells = max77663_children;
+               n_mfd_cells = ARRAY_SIZE(max77663_children);
+               rmap_config = &max77663_regmap_config;
+               break;
        default:
                dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id);
                return -EINVAL;
@@ -491,6 +566,12 @@ static int max77620_probe(struct i2c_client *client,
                return ret;
        }
 
+       pm_off = of_device_is_system_power_controller(client->dev.of_node);
+       if (pm_off && !pm_power_off) {
+               max77620_scratch = chip;
+               pm_power_off = max77620_pm_power_off;
+       }
+
        return 0;
 }
 
@@ -546,6 +627,9 @@ static int max77620_i2c_suspend(struct device *dev)
                return ret;
        }
 
+       if (chip->chip_id == MAX77663)
+               goto out;
+
        /* Disable WK_EN0 */
        ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
                                 MAX77620_ONOFFCNFG2_WK_EN0, 0);
@@ -581,7 +665,7 @@ static int max77620_i2c_resume(struct device *dev)
         * For MAX20024: No need to configure WKEN0 on resume as
         * it is configured on Init.
         */
-       if (chip->chip_id == MAX20024)
+       if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663)
                goto out;
 
        /* Enable WK_EN0 */
@@ -603,6 +687,7 @@ out:
 static const struct i2c_device_id max77620_id[] = {
        {"max77620", MAX77620},
        {"max20024", MAX20024},
+       {"max77663", MAX77663},
        {},
 };
 
diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c
new file mode 100644 (file)
index 0000000..60e07ac
--- /dev/null
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Core MFD driver for MAXIM 77650/77651 charger/power-supply.
+// Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#define MAX77650_INT_GPI_F_MSK         BIT(0)
+#define MAX77650_INT_GPI_R_MSK         BIT(1)
+#define MAX77650_INT_GPI_MSK \
+                       (MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK)
+#define MAX77650_INT_nEN_F_MSK         BIT(2)
+#define MAX77650_INT_nEN_R_MSK         BIT(3)
+#define MAX77650_INT_TJAL1_R_MSK       BIT(4)
+#define MAX77650_INT_TJAL2_R_MSK       BIT(5)
+#define MAX77650_INT_DOD_R_MSK         BIT(6)
+
+#define MAX77650_INT_THM_MSK           BIT(0)
+#define MAX77650_INT_CHG_MSK           BIT(1)
+#define MAX77650_INT_CHGIN_MSK         BIT(2)
+#define MAX77650_INT_TJ_REG_MSK                BIT(3)
+#define MAX77650_INT_CHGIN_CTRL_MSK    BIT(4)
+#define MAX77650_INT_SYS_CTRL_MSK      BIT(5)
+#define MAX77650_INT_SYS_CNFG_MSK      BIT(6)
+
+#define MAX77650_INT_GLBL_OFFSET       0
+#define MAX77650_INT_CHG_OFFSET                1
+
+#define MAX77650_SBIA_LPM_MASK         BIT(5)
+#define MAX77650_SBIA_LPM_DISABLED     0x00
+
+enum {
+       MAX77650_INT_GPI,
+       MAX77650_INT_nEN_F,
+       MAX77650_INT_nEN_R,
+       MAX77650_INT_TJAL1_R,
+       MAX77650_INT_TJAL2_R,
+       MAX77650_INT_DOD_R,
+       MAX77650_INT_THM,
+       MAX77650_INT_CHG,
+       MAX77650_INT_CHGIN,
+       MAX77650_INT_TJ_REG,
+       MAX77650_INT_CHGIN_CTRL,
+       MAX77650_INT_SYS_CTRL,
+       MAX77650_INT_SYS_CNFG,
+};
+
+static const struct resource max77650_charger_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"),
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"),
+};
+
+static const struct resource max77650_gpio_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"),
+};
+
+static const struct resource max77650_onkey_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"),
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"),
+};
+
+static const struct mfd_cell max77650_cells[] = {
+       {
+               .name           = "max77650-regulator",
+               .of_compatible  = "maxim,max77650-regulator",
+       }, {
+               .name           = "max77650-charger",
+               .of_compatible  = "maxim,max77650-charger",
+               .resources      = max77650_charger_resources,
+               .num_resources  = ARRAY_SIZE(max77650_charger_resources),
+       }, {
+               .name           = "max77650-gpio",
+               .of_compatible  = "maxim,max77650-gpio",
+               .resources      = max77650_gpio_resources,
+               .num_resources  = ARRAY_SIZE(max77650_gpio_resources),
+       }, {
+               .name           = "max77650-led",
+               .of_compatible  = "maxim,max77650-led",
+       }, {
+               .name           = "max77650-onkey",
+               .of_compatible  = "maxim,max77650-onkey",
+               .resources      = max77650_onkey_resources,
+               .num_resources  = ARRAY_SIZE(max77650_onkey_resources),
+       },
+};
+
+static const struct regmap_irq max77650_irqs[] = {
+       [MAX77650_INT_GPI] = {
+               .reg_offset = MAX77650_INT_GLBL_OFFSET,
+               .mask = MAX77650_INT_GPI_MSK,
+               .type = {
+                       .type_falling_val = MAX77650_INT_GPI_F_MSK,
+                       .type_rising_val = MAX77650_INT_GPI_R_MSK,
+                       .types_supported = IRQ_TYPE_EDGE_BOTH,
+               },
+       },
+       REGMAP_IRQ_REG(MAX77650_INT_nEN_F,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_nEN_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_DOD_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_THM,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHGIN,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJ_REG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK),
+};
+
+static const struct regmap_irq_chip max77650_irq_chip = {
+       .name                   = "max77650-irq",
+       .irqs                   = max77650_irqs,
+       .num_irqs               = ARRAY_SIZE(max77650_irqs),
+       .num_regs               = 2,
+       .status_base            = MAX77650_REG_INT_GLBL,
+       .mask_base              = MAX77650_REG_INTM_GLBL,
+       .type_in_mask           = true,
+       .type_invert            = true,
+       .init_ack_masked        = true,
+       .clear_on_unmask        = true,
+};
+
+static const struct regmap_config max77650_regmap_config = {
+       .name           = "max77650",
+       .reg_bits       = 8,
+       .val_bits       = 8,
+};
+
+static int max77650_i2c_probe(struct i2c_client *i2c)
+{
+       struct regmap_irq_chip_data *irq_data;
+       struct device *dev = &i2c->dev;
+       struct irq_domain *domain;
+       struct regmap *map;
+       unsigned int val;
+       int rv, id;
+
+       map = devm_regmap_init_i2c(i2c, &max77650_regmap_config);
+       if (IS_ERR(map)) {
+               dev_err(dev, "Unable to initialise I2C Regmap\n");
+               return PTR_ERR(map);
+       }
+
+       rv = regmap_read(map, MAX77650_REG_CID, &val);
+       if (rv) {
+               dev_err(dev, "Unable to read Chip ID\n");
+               return rv;
+       }
+
+       id = MAX77650_CID_BITS(val);
+       switch (id) {
+       case MAX77650_CID_77650A:
+       case MAX77650_CID_77650C:
+       case MAX77650_CID_77651A:
+       case MAX77650_CID_77651B:
+               break;
+       default:
+               dev_err(dev, "Chip not supported - ID: 0x%02x\n", id);
+               return -ENODEV;
+       }
+
+       /*
+        * This IC has a low-power mode which reduces the quiescent current
+        * consumption to ~5.6uA but is only suitable for systems consuming
+        * less than ~2mA. Since this is not likely the case even on
+        * linux-based wearables - keep the chip in normal power mode.
+        */
+       rv = regmap_update_bits(map,
+                               MAX77650_REG_CNFG_GLBL,
+                               MAX77650_SBIA_LPM_MASK,
+                               MAX77650_SBIA_LPM_DISABLED);
+       if (rv) {
+               dev_err(dev, "Unable to change the power mode\n");
+               return rv;
+       }
+
+       rv = devm_regmap_add_irq_chip(dev, map, i2c->irq,
+                                     IRQF_ONESHOT | IRQF_SHARED, 0,
+                                     &max77650_irq_chip, &irq_data);
+       if (rv) {
+               dev_err(dev, "Unable to add Regmap IRQ chip\n");
+               return rv;
+       }
+
+       domain = regmap_irq_get_domain(irq_data);
+
+       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+                                   max77650_cells, ARRAY_SIZE(max77650_cells),
+                                   NULL, 0, domain);
+}
+
+static const struct of_device_id max77650_of_match[] = {
+       { .compatible = "maxim,max77650" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max77650_of_match);
+
+static struct i2c_driver max77650_i2c_driver = {
+       .driver = {
+               .name = "max77650",
+               .of_match_table = of_match_ptr(max77650_of_match),
+       },
+       .probe_new = max77650_i2c_probe,
+};
+module_i2c_driver(max77650_i2c_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 94e3f32ce935717e97f2e938b433f3673c38f22d..1ade4c8cc91f7dbd185f1b84ccaf815a55c9cd70 100644 (file)
@@ -269,6 +269,19 @@ fail_alloc:
        return ret;
 }
 
+/**
+ * mfd_add_devices - register child devices
+ *
+ * @parent:    Pointer to parent device.
+ * @id:                Can be PLATFORM_DEVID_AUTO to let the Platform API take care
+ *             of device numbering, or will be added to a device's cell_id.
+ * @cells:     Array of (struct mfd_cell)s describing child devices.
+ * @n_devs:    Number of child devices to register.
+ * @mem_base:  Parent register range resource for child devices.
+ * @irq_base:  Base of the range of virtual interrupt numbers allocated for
+ *             this MFD device. Unused if @domain is specified.
+ * @domain:    Interrupt domain to create mappings for hardware interrupts.
+ */
 int mfd_add_devices(struct device *parent, int id,
                    const struct mfd_cell *cells, int n_devs,
                    struct resource *mem_base,
index 37d0bdb291c32fa5c1fe138b082a58af41d694dc..b06cb908d1aa482b16337f38a8de4e506f53f92b 100644 (file)
@@ -54,14 +54,6 @@ static void ti_lmu_disable_hw(void *data)
                gpiod_set_value(lmu->en_gpio, 0);
 }
 
-static const struct mfd_cell lm3532_devices[] = {
-       {
-               .name          = "ti-lmu-backlight",
-               .id            = LM3532,
-               .of_compatible = "ti,lm3532-backlight",
-       },
-};
-
 #define LM363X_REGULATOR(_id)                  \
 {                                              \
        .name          = "lm363x-regulator",    \
@@ -141,7 +133,6 @@ static const struct ti_lmu_data chip##_data =       \
        .max_register = max_reg,                \
 }                                              \
 
-TI_LMU_DATA(lm3532, LM3532_MAX_REG);
 TI_LMU_DATA(lm3631, LM3631_MAX_REG);
 TI_LMU_DATA(lm3632, LM3632_MAX_REG);
 TI_LMU_DATA(lm3633, LM3633_MAX_REG);
@@ -211,7 +202,6 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 }
 
 static const struct of_device_id ti_lmu_of_match[] = {
-       { .compatible = "ti,lm3532", .data = &lm3532_data },
        { .compatible = "ti,lm3631", .data = &lm3631_data },
        { .compatible = "ti,lm3632", .data = &lm3632_data },
        { .compatible = "ti,lm3633", .data = &lm3633_data },
@@ -222,7 +212,6 @@ static const struct of_device_id ti_lmu_of_match[] = {
 MODULE_DEVICE_TABLE(of, ti_lmu_of_match);
 
 static const struct i2c_device_id ti_lmu_ids[] = {
-       { "lm3532", LM3532 },
        { "lm3631", LM3631 },
        { "lm3632", LM3632 },
        { "lm3633", LM3633 },
index 5b3b06a0a3bf53e1eac9572ae8d14add0c3835e7..d466e33635b0cadf19fe1e4bc56dc4ac152fe01b 100644 (file)
@@ -15,7 +15,7 @@
  * Adopted from dwmac-sti.c
  */
 
-#include <linux/mfd/syscon.h>
+#include <linux/mfd/altera-sysmgr.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_net.h>
@@ -114,7 +114,8 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
 
        dwmac->interface = of_get_phy_mode(np);
 
-       sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
+       sys_mgr_base_addr =
+               altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
        if (IS_ERR(sys_mgr_base_addr)) {
                dev_info(dev, "No sysmgr-syscon node found\n");
                return PTR_ERR(sys_mgr_base_addr);
index e901b9879e7e70ce917af7bd740a41c74a651420..0230c96fa94dc483633d34accbfe2a0dc64df739 100644 (file)
@@ -499,6 +499,13 @@ config CHARGER_DETECTOR_MAX14656
          Revision 1.2 and can be found e.g. in Kindle 4/5th generation
          readers and certain LG devices.
 
+config CHARGER_MAX77650
+       tristate "Maxim MAX77650 battery charger driver"
+       depends on MFD_MAX77650
+       help
+         Say Y to enable support for the battery charger control of MAX77650
+         PMICs.
+
 config CHARGER_MAX77693
        tristate "Maxim MAX77693 battery charger driver"
        depends on MFD_MAX77693
index b731c2a9b695c59e62239bcb6b1f6b4f7cdd3002..b73eb8c5c1a900ce3387f15a6071b36f2bff43b7 100644 (file)
@@ -70,6 +70,7 @@ obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
 obj-$(CONFIG_CHARGER_LTC3651)  += ltc3651-charger.o
 obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
 obj-$(CONFIG_CHARGER_DETECTOR_MAX14656)        += max14656_charger_detector.o
+obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
 obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
diff --git a/drivers/power/supply/max77650-charger.c b/drivers/power/supply/max77650-charger.c
new file mode 100644 (file)
index 0000000..e34714c
--- /dev/null
@@ -0,0 +1,368 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Battery charger driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+#define MAX77650_CHARGER_ENABLED               BIT(0)
+#define MAX77650_CHARGER_DISABLED              0x00
+#define MAX77650_CHARGER_CHG_EN_MASK           BIT(0)
+
+#define MAX77650_CHG_DETAILS_MASK              GENMASK(7, 4)
+#define MAX77650_CHG_DETAILS_BITS(_reg) \
+               (((_reg) & MAX77650_CHG_DETAILS_MASK) >> 4)
+
+/* Charger is OFF. */
+#define MAX77650_CHG_OFF                       0x00
+/* Charger is in prequalification mode. */
+#define MAX77650_CHG_PREQ                      0x01
+/* Charger is in fast-charge constant current mode. */
+#define MAX77650_CHG_ON_CURR                   0x02
+/* Charger is in JEITA modified fast-charge constant-current mode. */
+#define MAX77650_CHG_ON_CURR_JEITA             0x03
+/* Charger is in fast-charge constant-voltage mode. */
+#define MAX77650_CHG_ON_VOLT                   0x04
+/* Charger is in JEITA modified fast-charge constant-voltage mode. */
+#define MAX77650_CHG_ON_VOLT_JEITA             0x05
+/* Charger is in top-off mode. */
+#define MAX77650_CHG_ON_TOPOFF                 0x06
+/* Charger is in JEITA modified top-off mode. */
+#define MAX77650_CHG_ON_TOPOFF_JEITA           0x07
+/* Charger is done. */
+#define MAX77650_CHG_DONE                      0x08
+/* Charger is JEITA modified done. */
+#define MAX77650_CHG_DONE_JEITA                        0x09
+/* Charger is suspended due to a prequalification timer fault. */
+#define MAX77650_CHG_SUSP_PREQ_TIM_FAULT       0x0a
+/* Charger is suspended due to a fast-charge timer fault. */
+#define MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT   0x0b
+/* Charger is suspended due to a battery temperature fault. */
+#define MAX77650_CHG_SUSP_BATT_TEMP_FAULT      0x0c
+
+#define MAX77650_CHGIN_DETAILS_MASK            GENMASK(3, 2)
+#define MAX77650_CHGIN_DETAILS_BITS(_reg) \
+               (((_reg) & MAX77650_CHGIN_DETAILS_MASK) >> 2)
+
+#define MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT    0x00
+#define MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT     0x01
+#define MAX77650_CHGIN_OKAY                    0x11
+
+#define MAX77650_CHARGER_CHG_MASK      BIT(1)
+#define MAX77650_CHARGER_CHG_CHARGING(_reg) \
+               (((_reg) & MAX77650_CHARGER_CHG_MASK) > 1)
+
+#define MAX77650_CHARGER_VCHGIN_MIN_MASK       0xc0
+#define MAX77650_CHARGER_VCHGIN_MIN_SHIFT(_val)        ((_val) << 5)
+
+#define MAX77650_CHARGER_ICHGIN_LIM_MASK       0x1c
+#define MAX77650_CHARGER_ICHGIN_LIM_SHIFT(_val)        ((_val) << 2)
+
+struct max77650_charger_data {
+       struct regmap *map;
+       struct device *dev;
+};
+
+static enum power_supply_property max77650_charger_properties[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_CHARGE_TYPE
+};
+
+static const unsigned int max77650_charger_vchgin_min_table[] = {
+       4000000, 4100000, 4200000, 4300000, 4400000, 4500000, 4600000, 4700000
+};
+
+static const unsigned int max77650_charger_ichgin_lim_table[] = {
+       95000, 190000, 285000, 380000, 475000
+};
+
+static int max77650_charger_set_vchgin_min(struct max77650_charger_data *chg,
+                                          unsigned int val)
+{
+       int i, rv;
+
+       for (i = 0; i < ARRAY_SIZE(max77650_charger_vchgin_min_table); i++) {
+               if (val == max77650_charger_vchgin_min_table[i]) {
+                       rv = regmap_update_bits(chg->map,
+                                       MAX77650_REG_CNFG_CHG_B,
+                                       MAX77650_CHARGER_VCHGIN_MIN_MASK,
+                                       MAX77650_CHARGER_VCHGIN_MIN_SHIFT(i));
+                       if (rv)
+                               return rv;
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int max77650_charger_set_ichgin_lim(struct max77650_charger_data *chg,
+                                          unsigned int val)
+{
+       int i, rv;
+
+       for (i = 0; i < ARRAY_SIZE(max77650_charger_ichgin_lim_table); i++) {
+               if (val == max77650_charger_ichgin_lim_table[i]) {
+                       rv = regmap_update_bits(chg->map,
+                                       MAX77650_REG_CNFG_CHG_B,
+                                       MAX77650_CHARGER_ICHGIN_LIM_MASK,
+                                       MAX77650_CHARGER_ICHGIN_LIM_SHIFT(i));
+                       if (rv)
+                               return rv;
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int max77650_charger_enable(struct max77650_charger_data *chg)
+{
+       int rv;
+
+       rv = regmap_update_bits(chg->map,
+                               MAX77650_REG_CNFG_CHG_B,
+                               MAX77650_CHARGER_CHG_EN_MASK,
+                               MAX77650_CHARGER_ENABLED);
+       if (rv)
+               dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
+
+       return rv;
+}
+
+static int max77650_charger_disable(struct max77650_charger_data *chg)
+{
+       int rv;
+
+       rv = regmap_update_bits(chg->map,
+                               MAX77650_REG_CNFG_CHG_B,
+                               MAX77650_CHARGER_CHG_EN_MASK,
+                               MAX77650_CHARGER_DISABLED);
+       if (rv)
+               dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
+
+       return rv;
+}
+
+static irqreturn_t max77650_charger_check_status(int irq, void *data)
+{
+       struct max77650_charger_data *chg = data;
+       int rv, reg;
+
+       rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+       if (rv) {
+               dev_err(chg->dev,
+                       "unable to read the charger status: %d\n", rv);
+               return IRQ_HANDLED;
+       }
+
+       switch (MAX77650_CHGIN_DETAILS_BITS(reg)) {
+       case MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT:
+               dev_err(chg->dev, "undervoltage lockout detected, disabling charger\n");
+               max77650_charger_disable(chg);
+               break;
+       case MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT:
+               dev_err(chg->dev, "overvoltage lockout detected, disabling charger\n");
+               max77650_charger_disable(chg);
+               break;
+       case MAX77650_CHGIN_OKAY:
+               max77650_charger_enable(chg);
+               break;
+       default:
+               /* May be 0x10 - debouncing */
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int max77650_charger_get_property(struct power_supply *psy,
+                                        enum power_supply_property psp,
+                                        union power_supply_propval *val)
+{
+       struct max77650_charger_data *chg = power_supply_get_drvdata(psy);
+       int rv, reg;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               if (MAX77650_CHARGER_CHG_CHARGING(reg)) {
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               }
+
+               switch (MAX77650_CHG_DETAILS_BITS(reg)) {
+               case MAX77650_CHG_OFF:
+               case MAX77650_CHG_SUSP_PREQ_TIM_FAULT:
+               case MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT:
+               case MAX77650_CHG_SUSP_BATT_TEMP_FAULT:
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       break;
+               case MAX77650_CHG_PREQ:
+               case MAX77650_CHG_ON_CURR:
+               case MAX77650_CHG_ON_CURR_JEITA:
+               case MAX77650_CHG_ON_VOLT:
+               case MAX77650_CHG_ON_VOLT_JEITA:
+               case MAX77650_CHG_ON_TOPOFF:
+               case MAX77650_CHG_ON_TOPOFF_JEITA:
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               case MAX77650_CHG_DONE:
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+                       break;
+               default:
+                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+               }
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               val->intval = MAX77650_CHARGER_CHG_CHARGING(reg);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               if (!MAX77650_CHARGER_CHG_CHARGING(reg)) {
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+                       break;
+               }
+
+               switch (MAX77650_CHG_DETAILS_BITS(reg)) {
+               case MAX77650_CHG_PREQ:
+               case MAX77650_CHG_ON_CURR:
+               case MAX77650_CHG_ON_CURR_JEITA:
+               case MAX77650_CHG_ON_VOLT:
+               case MAX77650_CHG_ON_VOLT_JEITA:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+                       break;
+               case MAX77650_CHG_ON_TOPOFF:
+               case MAX77650_CHG_ON_TOPOFF_JEITA:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+                       break;
+               default:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct power_supply_desc max77650_battery_desc = {
+       .name           = "max77650",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .get_property   = max77650_charger_get_property,
+       .properties     = max77650_charger_properties,
+       .num_properties = ARRAY_SIZE(max77650_charger_properties),
+};
+
+static int max77650_charger_probe(struct platform_device *pdev)
+{
+       struct power_supply_config pscfg = {};
+       struct max77650_charger_data *chg;
+       struct power_supply *battery;
+       struct device *dev, *parent;
+       int rv, chg_irq, chgin_irq;
+       unsigned int prop;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+
+       chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
+       if (!chg)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, chg);
+
+       chg->map = dev_get_regmap(parent, NULL);
+       if (!chg->map)
+               return -ENODEV;
+
+       chg->dev = dev;
+
+       pscfg.of_node = dev->of_node;
+       pscfg.drv_data = chg;
+
+       chg_irq = platform_get_irq_byname(pdev, "CHG");
+       if (chg_irq < 0)
+               return chg_irq;
+
+       chgin_irq = platform_get_irq_byname(pdev, "CHGIN");
+       if (chgin_irq < 0)
+               return chgin_irq;
+
+       rv = devm_request_any_context_irq(dev, chg_irq,
+                                         max77650_charger_check_status,
+                                         IRQF_ONESHOT, "chg", chg);
+       if (rv < 0)
+               return rv;
+
+       rv = devm_request_any_context_irq(dev, chgin_irq,
+                                         max77650_charger_check_status,
+                                         IRQF_ONESHOT, "chgin", chg);
+       if (rv < 0)
+               return rv;
+
+       battery = devm_power_supply_register(dev,
+                                            &max77650_battery_desc, &pscfg);
+       if (IS_ERR(battery))
+               return PTR_ERR(battery);
+
+       rv = of_property_read_u32(dev->of_node,
+                                 "input-voltage-min-microvolt", &prop);
+       if (rv == 0) {
+               rv = max77650_charger_set_vchgin_min(chg, prop);
+               if (rv)
+                       return rv;
+       }
+
+       rv = of_property_read_u32(dev->of_node,
+                                 "input-current-limit-microamp", &prop);
+       if (rv == 0) {
+               rv = max77650_charger_set_ichgin_lim(chg, prop);
+               if (rv)
+                       return rv;
+       }
+
+       return max77650_charger_enable(chg);
+}
+
+static int max77650_charger_remove(struct platform_device *pdev)
+{
+       struct max77650_charger_data *chg = platform_get_drvdata(pdev);
+
+       return max77650_charger_disable(chg);
+}
+
+static struct platform_driver max77650_charger_driver = {
+       .driver = {
+               .name = "max77650-charger",
+       },
+       .probe = max77650_charger_probe,
+       .remove = max77650_charger_remove,
+};
+module_platform_driver(max77650_charger_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 charger driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/altera-sysmgr.h b/include/linux/mfd/altera-sysmgr.h
new file mode 100644 (file)
index 0000000..b1ef11a
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 Intel Corporation
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ */
+
+#ifndef __LINUX_MFD_ALTERA_SYSMGR_H__
+#define __LINUX_MFD_ALTERA_SYSMGR_H__
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/firmware/intel/stratix10-smc.h>
+
+struct device_node;
+
+#ifdef CONFIG_MFD_ALTERA_SYSMGR
+struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                                   const char *property);
+#else
+static inline struct regmap *
+altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                    const char *property)
+{
+       return ERR_PTR(-ENOTSUPP);
+}
+#endif
+
+#endif /* __LINUX_MFD_ALTERA_SYSMGR_H__ */
index ad2a9a852aead143a69e7ada265e5b7832f3727f..82407fe85ca26144514a12327bcd695f0404ddd5 100644 (file)
 #define MAX77620_FPS_PERIOD_MIN_US             40
 #define MAX20024_FPS_PERIOD_MIN_US             20
 
-#define MAX77620_FPS_PERIOD_MAX_US             2560
-#define MAX20024_FPS_PERIOD_MAX_US             5120
+#define MAX20024_FPS_PERIOD_MAX_US             2560
+#define MAX77620_FPS_PERIOD_MAX_US             5120
 
 #define MAX77620_REG_FPS_GPIO1                 0x54
 #define MAX77620_REG_FPS_GPIO2                 0x55
@@ -324,6 +324,7 @@ enum max77620_fps_src {
 enum max77620_chip_id {
        MAX77620,
        MAX20024,
+       MAX77663,
 };
 
 struct max77620_chip {
diff --git a/include/linux/mfd/max77650.h b/include/linux/mfd/max77650.h
new file mode 100644 (file)
index 0000000..c809e21
--- /dev/null
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 BayLibre SAS
+ * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ *
+ * Common definitions for MAXIM 77650/77651 charger/power-supply.
+ */
+
+#ifndef MAX77650_H
+#define MAX77650_H
+
+#include <linux/bits.h>
+
+#define MAX77650_REG_INT_GLBL          0x00
+#define MAX77650_REG_INT_CHG           0x01
+#define MAX77650_REG_STAT_CHG_A                0x02
+#define MAX77650_REG_STAT_CHG_B                0x03
+#define MAX77650_REG_ERCFLAG           0x04
+#define MAX77650_REG_STAT_GLBL         0x05
+#define MAX77650_REG_INTM_GLBL         0x06
+#define MAX77650_REG_INTM_CHG          0x07
+#define MAX77650_REG_CNFG_GLBL         0x10
+#define MAX77650_REG_CID               0x11
+#define MAX77650_REG_CNFG_GPIO         0x12
+#define MAX77650_REG_CNFG_CHG_A                0x18
+#define MAX77650_REG_CNFG_CHG_B                0x19
+#define MAX77650_REG_CNFG_CHG_C                0x1a
+#define MAX77650_REG_CNFG_CHG_D                0x1b
+#define MAX77650_REG_CNFG_CHG_E                0x1c
+#define MAX77650_REG_CNFG_CHG_F                0x1d
+#define MAX77650_REG_CNFG_CHG_G                0x1e
+#define MAX77650_REG_CNFG_CHG_H                0x1f
+#define MAX77650_REG_CNFG_CHG_I                0x20
+#define MAX77650_REG_CNFG_SBB_TOP      0x28
+#define MAX77650_REG_CNFG_SBB0_A       0x29
+#define MAX77650_REG_CNFG_SBB0_B       0x2a
+#define MAX77650_REG_CNFG_SBB1_A       0x2b
+#define MAX77650_REG_CNFG_SBB1_B       0x2c
+#define MAX77650_REG_CNFG_SBB2_A       0x2d
+#define MAX77650_REG_CNFG_SBB2_B       0x2e
+#define MAX77650_REG_CNFG_LDO_A                0x38
+#define MAX77650_REG_CNFG_LDO_B                0x39
+#define MAX77650_REG_CNFG_LED0_A       0x40
+#define MAX77650_REG_CNFG_LED1_A       0x41
+#define MAX77650_REG_CNFG_LED2_A       0x42
+#define MAX77650_REG_CNFG_LED0_B       0x43
+#define MAX77650_REG_CNFG_LED1_B       0x44
+#define MAX77650_REG_CNFG_LED2_B       0x45
+#define MAX77650_REG_CNFG_LED_TOP      0x46
+
+#define MAX77650_CID_MASK              GENMASK(3, 0)
+#define MAX77650_CID_BITS(_reg)                (_reg & MAX77650_CID_MASK)
+
+#define MAX77650_CID_77650A            0x03
+#define MAX77650_CID_77650C            0x0a
+#define MAX77650_CID_77651A            0x06
+#define MAX77650_CID_77651B            0x08
+
+#endif /* MAX77650_H */
index 2125c7c02818b3c5c30eff67111e6e512ccfb065..f09510561a5555929c7b7e4e4f1d1b7bdb170e4a 100644 (file)
 
 #include <linux/bitops.h>
 
-/* LM3532 */
-#define LM3532_REG_OUTPUT_CFG                  0x10
-#define LM3532_ILED1_CFG_MASK                  0x03
-#define LM3532_ILED2_CFG_MASK                  0x0C
-#define LM3532_ILED3_CFG_MASK                  0x30
-#define LM3532_ILED1_CFG_SHIFT                 0
-#define LM3532_ILED2_CFG_SHIFT                 2
-#define LM3532_ILED3_CFG_SHIFT                 4
-
-#define LM3532_REG_RAMPUP                      0x12
-#define LM3532_REG_RAMPDN                      LM3532_REG_RAMPUP
-#define LM3532_RAMPUP_MASK                     0x07
-#define LM3532_RAMPUP_SHIFT                    0
-#define LM3532_RAMPDN_MASK                     0x38
-#define LM3532_RAMPDN_SHIFT                    3
-
-#define LM3532_REG_ENABLE                      0x1D
-
-#define LM3532_REG_PWM_A_CFG                   0x13
-#define LM3532_PWM_A_MASK                      0x05    /* zone 0 */
-#define LM3532_PWM_ZONE_0                      BIT(2)
-
-#define LM3532_REG_PWM_B_CFG                   0x14
-#define LM3532_PWM_B_MASK                      0x09    /* zone 1 */
-#define LM3532_PWM_ZONE_1                      BIT(3)
-
-#define LM3532_REG_PWM_C_CFG                   0x15
-#define LM3532_PWM_C_MASK                      0x11    /* zone 2 */
-#define LM3532_PWM_ZONE_2                      BIT(4)
-
-#define LM3532_REG_ZONE_CFG_A                  0x16
-#define LM3532_REG_ZONE_CFG_B                  0x18
-#define LM3532_REG_ZONE_CFG_C                  0x1A
-#define LM3532_ZONE_MASK                       (BIT(2) | BIT(3) | BIT(4))
-#define LM3532_ZONE_0                          0
-#define LM3532_ZONE_1                          BIT(2)
-#define LM3532_ZONE_2                          BIT(3)
-
-#define LM3532_REG_BRT_A                       0x70    /* zone 0 */
-#define LM3532_REG_BRT_B                       0x76    /* zone 1 */
-#define LM3532_REG_BRT_C                       0x7C    /* zone 2 */
-
-#define LM3532_MAX_REG                         0x7E
-
 /* LM3631 */
 #define LM3631_REG_DEVCTRL                     0x00
 #define LM3631_LCD_EN_MASK                     BIT(1)
index 1ef51ed36be56a82e20bfce286faa0c22244661c..7762c1bce55df9710e5abfd6da0d18add354b12e 100644 (file)
@@ -22,7 +22,6 @@
 #define LMU_EVENT_MONITOR_DONE         0x01
 
 enum ti_lmu_id {
-       LM3532,
        LM3631,
        LM3632,
        LM3633,