Commit 7f7a0208 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Merge tag 'ib-mfd-gpio-input-leds-power-v5.2' of...

Merge tag 'ib-mfd-gpio-input-leds-power-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd into next

Sync up with MFD tree to bring in MAX77650 PMIC driver.
parents 2a267e7c 796fad01
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;
};
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";
};
};
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";
};
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>;
};
......@@ -9408,6 +9408,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
......
......@@ -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
......
......@@ -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
......
// 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");
......@@ -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
......
......@@ -44,6 +44,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
......
// 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");
......@@ -608,6 +608,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
......
......@@ -61,6 +61,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
......
// 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");
......@@ -733,6 +733,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
......
......@@ -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
......
// 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");
......@@ -269,6 +269,19 @@ static int mfd_add_device(struct device *parent, int id,
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,
......
......@@ -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
......
......@@ -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
......
// 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");
/* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment