Merge branches 'ib-mfd-drm-5.6' and 'ib-mfd-clk-gpio-regulator-rtc-5.6' into ibs-for-mfd-merged
This commit is contained in:
commit
18490cdb9e
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/rohm,bd71828-leds.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD71828 Power Management Integrated Circuit LED driver
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
|
||||
description: |
|
||||
This module is part of the ROHM BD71828 MFD device. For more details
|
||||
see Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml.
|
||||
|
||||
The LED controller is represented as a sub-node of the PMIC node on the device
|
||||
tree.
|
||||
|
||||
The device has two LED outputs referred as GRNLED and AMBLED in data-sheet.
|
||||
|
||||
select: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd71828-leds
|
||||
|
||||
patternProperties:
|
||||
"^led-[1-2]$":
|
||||
type: object
|
||||
description:
|
||||
Properties for a single LED.
|
||||
properties:
|
||||
#allOf:
|
||||
#- $ref: "common.yaml#"
|
||||
rohm,led-compatible:
|
||||
description: LED identification string
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/string"
|
||||
- enum:
|
||||
- bd71828-ambled
|
||||
- bd71828-grnled
|
||||
function:
|
||||
description:
|
||||
Purpose of LED as defined in dt-bindings/leds/common.h
|
||||
$ref: "/schemas/types.yaml#/definitions/string"
|
||||
color:
|
||||
description:
|
||||
LED colour as defined in dt-bindings/leds/common.h
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
|
||||
required:
|
||||
- compatible
|
193
Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
Normal file
193
Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
Normal file
@ -0,0 +1,193 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/rohm,bd71828-pmic.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD71828 Power Management Integrated Circuit bindings
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
|
||||
|
||||
description: |
|
||||
BD71828GW is a single-chip power management IC for battery-powered portable
|
||||
devices. The IC integrates 7 buck converters, 7 LDOs, and a 1500 mA
|
||||
single-cell linear charger. Also included is a Coulomb counter, a real-time
|
||||
clock (RTC), and a 32.768 kHz clock gate.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd71828
|
||||
|
||||
reg:
|
||||
description:
|
||||
I2C slave address.
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the pin number and the second cell is used to specify
|
||||
flags. See ../gpio/gpio.txt for more information.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
rohm,charger-sense-resistor-ohms:
|
||||
minimum: 10000000
|
||||
maximum: 50000000
|
||||
description: |
|
||||
BD71827 and BD71828 have SAR ADC for measuring charging currents.
|
||||
External sense resistor (RSENSE in data sheet) should be used. If some
|
||||
other but 30MOhm resistor is used the resistance value should be given
|
||||
here in Ohms.
|
||||
|
||||
regulators:
|
||||
$ref: ../regulator/rohm,bd71828-regulator.yaml
|
||||
description:
|
||||
List of child nodes that specify the regulators.
|
||||
|
||||
leds:
|
||||
$ref: ../leds/rohm,bd71828-leds.yaml
|
||||
|
||||
gpio-reserved-ranges:
|
||||
description: |
|
||||
Usage of BD71828 GPIO pins can be changed via OTP. This property can be
|
||||
used to mark the pins which should not be configured for GPIO. Please see
|
||||
the ../gpio/gpio.txt for more information.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
- regulators
|
||||
- gpio-controller
|
||||
- "#gpio-cells"
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pmic: pmic@4b {
|
||||
compatible = "rohm,bd71828";
|
||||
reg = <0x4b>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
clocks = <&osc 0>;
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "bd71828-32k-out";
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-reserved-ranges = <0 1>, <2 1>;
|
||||
|
||||
rohm,charger-sense-resistor-ohms = <10000000>;
|
||||
|
||||
regulators {
|
||||
buck1: BUCK1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-ramp-delay = <2500>;
|
||||
};
|
||||
buck2: BUCK2 {
|
||||
regulator-name = "buck2";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-ramp-delay = <2500>;
|
||||
};
|
||||
buck3: BUCK3 {
|
||||
regulator-name = "buck3";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
};
|
||||
buck4: BUCK4 {
|
||||
regulator-name = "buck4";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
buck5: BUCK5 {
|
||||
regulator-name = "buck5";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
buck6: BUCK6 {
|
||||
regulator-name = "buck6";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-ramp-delay = <2500>;
|
||||
};
|
||||
buck7: BUCK7 {
|
||||
regulator-name = "buck7";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <2000000>;
|
||||
regulator-ramp-delay = <2500>;
|
||||
};
|
||||
ldo1: LDO1 {
|
||||
regulator-name = "ldo1";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
ldo2: LDO2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
ldo3: LDO3 {
|
||||
regulator-name = "ldo3";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
ldo4: LDO4 {
|
||||
regulator-name = "ldo4";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
ldo5: LDO5 {
|
||||
regulator-name = "ldo5";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
ldo6: LDO6 {
|
||||
regulator-name = "ldo6";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
ldo7_reg: LDO7 {
|
||||
regulator-name = "ldo7";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "rohm,bd71828-leds";
|
||||
|
||||
led-1 {
|
||||
rohm,led-compatible = "bd71828-grnled";
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
led-2 {
|
||||
rohm,led-compatible = "bd71828-ambled";
|
||||
function = LED_FUNCTION_CHARGING;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -305,10 +305,10 @@ config COMMON_CLK_MMP2
|
||||
Support for Marvell MMP2 and MMP3 SoC clocks
|
||||
|
||||
config COMMON_CLK_BD718XX
|
||||
tristate "Clock driver for ROHM BD718x7 PMIC"
|
||||
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528
|
||||
tristate "Clock driver for 32K clk gates on ROHM PMICs"
|
||||
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828
|
||||
help
|
||||
This driver supports ROHM BD71837, ROHM BD71847 and
|
||||
This driver supports ROHM BD71837, ROHM BD71847, ROHM BD71828 and
|
||||
ROHM BD70528 PMICs clock gates.
|
||||
|
||||
config COMMON_CLK_FIXED_MMIO
|
||||
|
@ -7,12 +7,25 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/rohm-bd718x7.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* clk control registers */
|
||||
/* BD70528 */
|
||||
#define BD70528_REG_OUT32K 0x2c
|
||||
/* BD71828 */
|
||||
#define BD71828_REG_OUT32K 0x4B
|
||||
/* BD71837 and BD71847 */
|
||||
#define BD718XX_REG_OUT32K 0x2E
|
||||
|
||||
/*
|
||||
* BD71837, BD71847, BD70528 and BD71828 all use bit [0] to clk output control
|
||||
*/
|
||||
#define CLK_OUT_EN_MASK BIT(0)
|
||||
|
||||
|
||||
struct bd718xx_clk {
|
||||
struct clk_hw hw;
|
||||
u8 reg;
|
||||
@ -21,10 +34,8 @@ struct bd718xx_clk {
|
||||
struct rohm_regmap_dev *mfd;
|
||||
};
|
||||
|
||||
static int bd71837_clk_set(struct clk_hw *hw, int status)
|
||||
static int bd71837_clk_set(struct bd718xx_clk *c, unsigned int status)
|
||||
{
|
||||
struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
|
||||
|
||||
return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status);
|
||||
}
|
||||
|
||||
@ -33,14 +44,16 @@ static void bd71837_clk_disable(struct clk_hw *hw)
|
||||
int rv;
|
||||
struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
|
||||
|
||||
rv = bd71837_clk_set(hw, 0);
|
||||
rv = bd71837_clk_set(c, 0);
|
||||
if (rv)
|
||||
dev_dbg(&c->pdev->dev, "Failed to disable 32K clk (%d)\n", rv);
|
||||
}
|
||||
|
||||
static int bd71837_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
return bd71837_clk_set(hw, 1);
|
||||
struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
|
||||
|
||||
return bd71837_clk_set(c, 0xffffffff);
|
||||
}
|
||||
|
||||
static int bd71837_clk_is_enabled(struct clk_hw *hw)
|
||||
@ -74,6 +87,7 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
.name = "bd718xx-32k-out",
|
||||
.ops = &bd71837_clk_ops,
|
||||
};
|
||||
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
c = devm_kzalloc(&pdev->dev, sizeof(*c), GFP_KERNEL);
|
||||
if (!c)
|
||||
@ -87,15 +101,19 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "No parent clk found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (mfd->chip_type) {
|
||||
switch (chip) {
|
||||
case ROHM_CHIP_TYPE_BD71837:
|
||||
case ROHM_CHIP_TYPE_BD71847:
|
||||
c->reg = BD718XX_REG_OUT32K;
|
||||
c->mask = BD718XX_OUT32K_EN;
|
||||
c->mask = CLK_OUT_EN_MASK;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD71828:
|
||||
c->reg = BD71828_REG_OUT32K;
|
||||
c->mask = CLK_OUT_EN_MASK;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD70528:
|
||||
c->reg = BD70528_REG_CLK_OUT;
|
||||
c->mask = BD70528_CLK_OUT_EN_MASK;
|
||||
c->reg = BD70528_REG_OUT32K;
|
||||
c->mask = CLK_OUT_EN_MASK;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown clk chip\n");
|
||||
@ -121,11 +139,21 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
return rval;
|
||||
}
|
||||
|
||||
static const struct platform_device_id bd718x7_clk_id[] = {
|
||||
{ "bd71837-clk", ROHM_CHIP_TYPE_BD71837 },
|
||||
{ "bd71847-clk", ROHM_CHIP_TYPE_BD71847 },
|
||||
{ "bd70528-clk", ROHM_CHIP_TYPE_BD70528 },
|
||||
{ "bd71828-clk", ROHM_CHIP_TYPE_BD71828 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
|
||||
|
||||
static struct platform_driver bd71837_clk = {
|
||||
.driver = {
|
||||
.name = "bd718xx-clk",
|
||||
},
|
||||
.probe = bd71837_clk_probe,
|
||||
.id_table = bd718x7_clk_id,
|
||||
};
|
||||
|
||||
module_platform_driver(bd71837_clk);
|
||||
|
@ -1021,6 +1021,18 @@ config GPIO_BD70528
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called gpio-bd70528.
|
||||
|
||||
config GPIO_BD71828
|
||||
tristate "ROHM BD71828 GPIO support"
|
||||
depends on MFD_ROHM_BD71828
|
||||
help
|
||||
Support for GPIOs on ROHM BD71828 PMIC. There are three GPIOs
|
||||
available on the ROHM PMIC in total. The GPIOs are limited to
|
||||
outputs only and pins must be configured to GPIO outputs by
|
||||
OTP. Enable this only if you want to use these pins as outputs.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called gpio-bd71828.
|
||||
|
||||
config GPIO_BD9571MWV
|
||||
tristate "ROHM BD9571 GPIO support"
|
||||
depends on MFD_BD9571MWV
|
||||
|
@ -37,6 +37,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
|
||||
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
|
||||
obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
|
||||
obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
|
||||
obj-$(CONFIG_GPIO_BD71828) += gpio-bd71828.o
|
||||
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
|
159
drivers/gpio/gpio-bd71828.c
Normal file
159
drivers/gpio/gpio-bd71828.c
Normal file
@ -0,0 +1,159 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (C) 2018 ROHM Semiconductors
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define GPIO_OUT_REG(off) (BD71828_REG_GPIO_CTRL1 + (off))
|
||||
#define HALL_GPIO_OFFSET 3
|
||||
|
||||
/*
|
||||
* These defines can be removed when
|
||||
* "gpio: Add definition for GPIO direction"
|
||||
* (9208b1e77d6e8e9776f34f46ef4079ecac9c3c25 in GPIO tree) gets merged,
|
||||
*/
|
||||
#ifndef GPIO_LINE_DIRECTION_IN
|
||||
#define GPIO_LINE_DIRECTION_IN 1
|
||||
#define GPIO_LINE_DIRECTION_OUT 0
|
||||
#endif
|
||||
|
||||
struct bd71828_gpio {
|
||||
struct rohm_regmap_dev chip;
|
||||
struct gpio_chip gpio;
|
||||
};
|
||||
|
||||
static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
int ret;
|
||||
struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
u8 val = (value) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO;
|
||||
|
||||
/*
|
||||
* The HALL input pin can only be used as input. If this is the pin
|
||||
* we are dealing with - then we are done
|
||||
*/
|
||||
if (offset == HALL_GPIO_OFFSET)
|
||||
return;
|
||||
|
||||
ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
|
||||
BD71828_GPIO_OUT_MASK, val);
|
||||
if (ret)
|
||||
dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value);
|
||||
}
|
||||
|
||||
static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
if (offset == HALL_GPIO_OFFSET)
|
||||
ret = regmap_read(bdgpio->chip.regmap, BD71828_REG_IO_STAT,
|
||||
&val);
|
||||
else
|
||||
ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
|
||||
&val);
|
||||
if (!ret)
|
||||
ret = (val & BD71828_GPIO_OUT_MASK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd71828_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
if (offset == HALL_GPIO_OFFSET)
|
||||
return -ENOTSUPP;
|
||||
|
||||
switch (pinconf_to_config_param(config)) {
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
return regmap_update_bits(bdgpio->chip.regmap,
|
||||
GPIO_OUT_REG(offset),
|
||||
BD71828_GPIO_DRIVE_MASK,
|
||||
BD71828_GPIO_OPEN_DRAIN);
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
return regmap_update_bits(bdgpio->chip.regmap,
|
||||
GPIO_OUT_REG(offset),
|
||||
BD71828_GPIO_DRIVE_MASK,
|
||||
BD71828_GPIO_PUSH_PULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int bd71828_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
/*
|
||||
* Pin usage is selected by OTP data. We can't read it runtime. Hence
|
||||
* we trust that if the pin is not excluded by "gpio-reserved-ranges"
|
||||
* the OTP configuration is set to OUT. (Other pins but HALL input pin
|
||||
* on BD71828 can't really be used for general purpose input - input
|
||||
* states are used for specific cases like regulator control or
|
||||
* PMIC_ON_REQ.
|
||||
*/
|
||||
if (offset == HALL_GPIO_OFFSET)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int bd71828_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd71828_gpio *bdgpio;
|
||||
struct rohm_regmap_dev *bd71828;
|
||||
|
||||
bd71828 = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!bd71828) {
|
||||
dev_err(&pdev->dev, "No MFD driver data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio),
|
||||
GFP_KERNEL);
|
||||
if (!bdgpio)
|
||||
return -ENOMEM;
|
||||
|
||||
bdgpio->chip.dev = &pdev->dev;
|
||||
bdgpio->gpio.parent = pdev->dev.parent;
|
||||
bdgpio->gpio.label = "bd71828-gpio";
|
||||
bdgpio->gpio.owner = THIS_MODULE;
|
||||
bdgpio->gpio.get_direction = bd71828_get_direction;
|
||||
bdgpio->gpio.set_config = bd71828_gpio_set_config;
|
||||
bdgpio->gpio.can_sleep = true;
|
||||
bdgpio->gpio.get = bd71828_gpio_get;
|
||||
bdgpio->gpio.set = bd71828_gpio_set;
|
||||
bdgpio->gpio.base = -1;
|
||||
|
||||
/*
|
||||
* See if we need some implementation to mark some PINs as
|
||||
* not controllable based on DT info or if core can handle
|
||||
* "gpio-reserved-ranges" and exclude them from control
|
||||
*/
|
||||
bdgpio->gpio.ngpio = 4;
|
||||
bdgpio->gpio.of_node = pdev->dev.parent->of_node;
|
||||
bdgpio->chip.regmap = bd71828->regmap;
|
||||
|
||||
return devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio,
|
||||
bdgpio);
|
||||
}
|
||||
|
||||
static struct platform_driver bd71828_gpio = {
|
||||
.driver = {
|
||||
.name = "bd71828-gpio"
|
||||
},
|
||||
.probe = bd71828_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(bd71828_gpio);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD71828 voltage regulator driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:bd71828-gpio");
|
@ -1906,6 +1906,21 @@ config MFD_ROHM_BD70528
|
||||
10 bits SAR ADC for battery temperature monitor and 1S battery
|
||||
charger.
|
||||
|
||||
config MFD_ROHM_BD71828
|
||||
tristate "ROHM BD71828 Power Management IC"
|
||||
depends on I2C=y
|
||||
depends on OF
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
help
|
||||
Select this option to get support for the ROHM BD71828 Power
|
||||
Management IC. BD71828GW is a single-chip power management IC for
|
||||
battery-powered portable devices. The IC integrates 7 buck
|
||||
converters, 7 LDOs, and a 1500 mA single-cell linear charger.
|
||||
Also included is a Coulomb counter, a real-time clock (RTC), and
|
||||
a 32.768 kHz clock gate.
|
||||
|
||||
config MFD_STM32_LPTIMER
|
||||
tristate "Support for STM32 Low-Power Timer"
|
||||
depends on (ARCH_STM32 && OF) || COMPILE_TEST
|
||||
|
@ -252,6 +252,7 @@ obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
|
||||
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
|
||||
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
|
||||
obj-$(CONFIG_MFD_STMFX) += stmfx.o
|
||||
|
||||
|
@ -48,7 +48,7 @@ static struct mfd_cell bd70528_mfd_cells[] = {
|
||||
* We use BD71837 driver to drive the clock block. Only differences to
|
||||
* BD70528 clock gate are the register address and mask.
|
||||
*/
|
||||
{ .name = "bd718xx-clk", },
|
||||
{ .name = "bd70528-clk", },
|
||||
{ .name = "bd70528-wdt", },
|
||||
{
|
||||
.name = "bd70528-power",
|
||||
@ -236,7 +236,6 @@ static int bd70528_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
dev_set_drvdata(&i2c->dev, &bd70528->chip);
|
||||
|
||||
bd70528->chip.chip_type = ROHM_CHIP_TYPE_BD70528;
|
||||
bd70528->chip.regmap = devm_regmap_init_i2c(i2c, &bd70528_regmap);
|
||||
if (IS_ERR(bd70528->chip.regmap)) {
|
||||
dev_err(&i2c->dev, "Failed to initialize Regmap\n");
|
||||
|
344
drivers/mfd/rohm-bd71828.c
Normal file
344
drivers/mfd/rohm-bd71828.c
Normal file
@ -0,0 +1,344 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Copyright (C) 2019 ROHM Semiconductors
|
||||
//
|
||||
// ROHM BD71828 PMIC driver
|
||||
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
static struct gpio_keys_button button = {
|
||||
.code = KEY_POWER,
|
||||
.gpio = -1,
|
||||
.type = EV_KEY,
|
||||
};
|
||||
|
||||
static struct gpio_keys_platform_data bd71828_powerkey_data = {
|
||||
.buttons = &button,
|
||||
.nbuttons = 1,
|
||||
.name = "bd71828-pwrkey",
|
||||
};
|
||||
|
||||
static const struct resource rtc_irqs[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"),
|
||||
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"),
|
||||
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"),
|
||||
};
|
||||
|
||||
static struct mfd_cell bd71828_mfd_cells[] = {
|
||||
{ .name = "bd71828-pmic", },
|
||||
{ .name = "bd71828-gpio", },
|
||||
{ .name = "bd71828-led", .of_compatible = "rohm,bd71828-leds" },
|
||||
/*
|
||||
* We use BD71837 driver to drive the clock block. Only differences to
|
||||
* BD70528 clock gate are the register address and mask.
|
||||
*/
|
||||
{ .name = "bd71828-clk", },
|
||||
{ .name = "bd71827-power", },
|
||||
{
|
||||
.name = "bd71828-rtc",
|
||||
.resources = rtc_irqs,
|
||||
.num_resources = ARRAY_SIZE(rtc_irqs),
|
||||
}, {
|
||||
.name = "gpio-keys",
|
||||
.platform_data = &bd71828_powerkey_data,
|
||||
.pdata_size = sizeof(bd71828_powerkey_data),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_range volatile_ranges[] = {
|
||||
{
|
||||
.range_min = BD71828_REG_PS_CTRL_1,
|
||||
.range_max = BD71828_REG_PS_CTRL_1,
|
||||
}, {
|
||||
.range_min = BD71828_REG_PS_CTRL_3,
|
||||
.range_max = BD71828_REG_PS_CTRL_3,
|
||||
}, {
|
||||
.range_min = BD71828_REG_RTC_SEC,
|
||||
.range_max = BD71828_REG_RTC_YEAR,
|
||||
}, {
|
||||
/*
|
||||
* For now make all charger registers volatile because many
|
||||
* needs to be and because the charger block is not that
|
||||
* performance critical.
|
||||
*/
|
||||
.range_min = BD71828_REG_CHG_STATE,
|
||||
.range_max = BD71828_REG_CHG_FULL,
|
||||
}, {
|
||||
.range_min = BD71828_REG_INT_MAIN,
|
||||
.range_max = BD71828_REG_IO_STAT,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_access_table volatile_regs = {
|
||||
.yes_ranges = &volatile_ranges[0],
|
||||
.n_yes_ranges = ARRAY_SIZE(volatile_ranges),
|
||||
};
|
||||
|
||||
static struct regmap_config bd71828_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_table = &volatile_regs,
|
||||
.max_register = BD71828_MAX_REGISTER,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
|
||||
* access corect sub-IRQ registers based on bits that are set in main IRQ
|
||||
* register.
|
||||
*/
|
||||
|
||||
static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */
|
||||
static unsigned int bit1_offsets[] = {10}; /* TEMP IRQ */
|
||||
static unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ */
|
||||
static unsigned int bit3_offsets[] = {5}; /* BAT IRQ */
|
||||
static unsigned int bit4_offsets[] = {4}; /* CHG IRQ */
|
||||
static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */
|
||||
static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */
|
||||
static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */
|
||||
|
||||
static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = {
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets),
|
||||
REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
|
||||
};
|
||||
|
||||
static struct regmap_irq bd71828_irqs[] = {
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK3_OCP, 0, BD71828_INT_BUCK3_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK4_OCP, 0, BD71828_INT_BUCK4_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK5_OCP, 0, BD71828_INT_BUCK5_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK6_OCP, 0, BD71828_INT_BUCK6_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BUCK7_OCP, 0, BD71828_INT_BUCK7_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_PGFAULT, 0, BD71828_INT_PGFAULT_MASK),
|
||||
/* DCIN1 interrupts */
|
||||
REGMAP_IRQ_REG(BD71828_INT_DCIN_DET, 1, BD71828_INT_DCIN_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_DCIN_RMV, 1, BD71828_INT_DCIN_RMV_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK),
|
||||
/* DCIN2 interrupts */
|
||||
REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2,
|
||||
BD71828_INT_DCIN_MON_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2,
|
||||
BD71828_INT_DCIN_MON_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_PUSH, 2, BD71828_INT_PUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK),
|
||||
/* Vsys */
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3,
|
||||
BD71828_INT_VSYS_UV_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3,
|
||||
BD71828_INT_VSYS_UV_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3,
|
||||
BD71828_INT_VSYS_LOW_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3,
|
||||
BD71828_INT_VSYS_LOW_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3,
|
||||
BD71828_INT_VSYS_HALL_IN_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3,
|
||||
BD71828_INT_VSYS_HALL_TOGGLE_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3,
|
||||
BD71828_INT_VSYS_MON_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3,
|
||||
BD71828_INT_VSYS_MON_DET_MASK),
|
||||
/* Charger */
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4,
|
||||
BD71828_INT_CHG_DCIN_ILIM_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4,
|
||||
BD71828_INT_CHG_TOPOFF_TO_DONE_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4,
|
||||
BD71828_INT_CHG_WDG_TEMP_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4,
|
||||
BD71828_INT_CHG_WDG_TIME_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4,
|
||||
BD71828_INT_CHG_RECHARGE_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4,
|
||||
BD71828_INT_CHG_RECHARGE_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4,
|
||||
BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4,
|
||||
BD71828_INT_CHG_STATE_TRANSITION_MASK),
|
||||
/* Battery */
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5,
|
||||
BD71828_INT_BAT_TEMP_NORMAL_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5,
|
||||
BD71828_INT_BAT_TEMP_ERANGE_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5,
|
||||
BD71828_INT_BAT_TEMP_WARN_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5,
|
||||
BD71828_INT_BAT_REMOVED_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5,
|
||||
BD71828_INT_BAT_DETECTED_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5,
|
||||
BD71828_INT_THERM_REMOVED_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5,
|
||||
BD71828_INT_THERM_DETECTED_MASK),
|
||||
/* Battery Mon 1 */
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6,
|
||||
BD71828_INT_BAT_SHORTC_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6,
|
||||
BD71828_INT_BAT_SHORTC_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6,
|
||||
BD71828_INT_BAT_LOW_VOLT_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6,
|
||||
BD71828_INT_BAT_LOW_VOLT_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6,
|
||||
BD71828_INT_BAT_OVER_VOLT_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6,
|
||||
BD71828_INT_BAT_OVER_VOLT_DET_MASK),
|
||||
/* Battery Mon 2 */
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7,
|
||||
BD71828_INT_BAT_MON_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7,
|
||||
BD71828_INT_BAT_MON_DET_MASK),
|
||||
/* Battery Mon 3 (Coulomb counter) */
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8,
|
||||
BD71828_INT_BAT_CC_MON1_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8,
|
||||
BD71828_INT_BAT_CC_MON2_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8,
|
||||
BD71828_INT_BAT_CC_MON3_MASK),
|
||||
/* Battery Mon 4 */
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_1_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_1_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_2_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_2_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_3_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9,
|
||||
BD71828_INT_BAT_OVER_CURR_3_DET_MASK),
|
||||
/* Temperature */
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10,
|
||||
BD71828_INT_TEMP_BAT_LOW_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10,
|
||||
BD71828_INT_TEMP_BAT_LOW_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10,
|
||||
BD71828_INT_TEMP_BAT_HI_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10,
|
||||
BD71828_INT_TEMP_BAT_HI_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10,
|
||||
BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10,
|
||||
BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_DET, 10,
|
||||
BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_RES, 10,
|
||||
BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK),
|
||||
/* RTC Alarm */
|
||||
REGMAP_IRQ_REG(BD71828_INT_RTC0, 11, BD71828_INT_RTC0_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_RTC1, 11, BD71828_INT_RTC1_MASK),
|
||||
REGMAP_IRQ_REG(BD71828_INT_RTC2, 11, BD71828_INT_RTC2_MASK),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip bd71828_irq_chip = {
|
||||
.name = "bd71828_irq",
|
||||
.main_status = BD71828_REG_INT_MAIN,
|
||||
.irqs = &bd71828_irqs[0],
|
||||
.num_irqs = ARRAY_SIZE(bd71828_irqs),
|
||||
.status_base = BD71828_REG_INT_BUCK,
|
||||
.mask_base = BD71828_REG_INT_MASK_BUCK,
|
||||
.ack_base = BD71828_REG_INT_BUCK,
|
||||
.mask_invert = true,
|
||||
.init_ack_masked = true,
|
||||
.num_regs = 12,
|
||||
.num_main_regs = 1,
|
||||
.sub_reg_offsets = &bd71828_sub_irq_offsets[0],
|
||||
.num_main_status_bits = 8,
|
||||
.irq_reg_stride = 1,
|
||||
};
|
||||
|
||||
static int bd71828_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct rohm_regmap_dev *chip;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
int ret;
|
||||
|
||||
if (!i2c->irq) {
|
||||
dev_err(&i2c->dev, "No IRQ configured\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&i2c->dev, chip);
|
||||
|
||||
chip->regmap = devm_regmap_init_i2c(i2c, &bd71828_regmap);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
dev_err(&i2c->dev, "Failed to initialize Regmap\n");
|
||||
return PTR_ERR(chip->regmap);
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&i2c->dev, chip->regmap,
|
||||
i2c->irq, IRQF_ONESHOT, 0,
|
||||
&bd71828_irq_chip, &irq_data);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to add IRQ chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n",
|
||||
bd71828_irq_chip.num_irqs);
|
||||
|
||||
ret = regmap_irq_get_virq(irq_data, BD71828_INT_SHORTPUSH);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "Failed to get the power-key IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
button.irq = ret;
|
||||
|
||||
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
|
||||
bd71828_mfd_cells,
|
||||
ARRAY_SIZE(bd71828_mfd_cells), NULL, 0,
|
||||
regmap_irq_get_domain(irq_data));
|
||||
if (ret)
|
||||
dev_err(&i2c->dev, "Failed to create subdevices\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id bd71828_of_match[] = {
|
||||
{ .compatible = "rohm,bd71828", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd71828_of_match);
|
||||
|
||||
static struct i2c_driver bd71828_drv = {
|
||||
.driver = {
|
||||
.name = "rohm-bd71828",
|
||||
.of_match_table = bd71828_of_match,
|
||||
},
|
||||
.probe_new = &bd71828_i2c_probe,
|
||||
};
|
||||
module_i2c_driver(bd71828_drv);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("ROHM BD71828 Power Management IC driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -30,14 +30,24 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = {
|
||||
.name = "bd718xx-pwrkey",
|
||||
};
|
||||
|
||||
static struct mfd_cell bd718xx_mfd_cells[] = {
|
||||
static struct mfd_cell bd71837_mfd_cells[] = {
|
||||
{
|
||||
.name = "gpio-keys",
|
||||
.platform_data = &bd718xx_powerkey_data,
|
||||
.pdata_size = sizeof(bd718xx_powerkey_data),
|
||||
},
|
||||
{ .name = "bd718xx-clk", },
|
||||
{ .name = "bd718xx-pmic", },
|
||||
{ .name = "bd71837-clk", },
|
||||
{ .name = "bd71837-pmic", },
|
||||
};
|
||||
|
||||
static struct mfd_cell bd71847_mfd_cells[] = {
|
||||
{
|
||||
.name = "gpio-keys",
|
||||
.platform_data = &bd718xx_powerkey_data,
|
||||
.pdata_size = sizeof(bd718xx_powerkey_data),
|
||||
},
|
||||
{ .name = "bd71847-clk", },
|
||||
{ .name = "bd71847-pmic", },
|
||||
};
|
||||
|
||||
static const struct regmap_irq bd718xx_irqs[] = {
|
||||
@ -124,6 +134,9 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
{
|
||||
struct bd718xx *bd718xx;
|
||||
int ret;
|
||||
unsigned int chip_type;
|
||||
struct mfd_cell *mfd;
|
||||
int cells;
|
||||
|
||||
if (!i2c->irq) {
|
||||
dev_err(&i2c->dev, "No IRQ configured\n");
|
||||
@ -136,8 +149,21 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
bd718xx->chip_irq = i2c->irq;
|
||||
bd718xx->chip.chip_type = (unsigned int)(uintptr_t)
|
||||
of_device_get_match_data(&i2c->dev);
|
||||
chip_type = (unsigned int)(uintptr_t)
|
||||
of_device_get_match_data(&i2c->dev);
|
||||
switch (chip_type) {
|
||||
case ROHM_CHIP_TYPE_BD71837:
|
||||
mfd = bd71837_mfd_cells;
|
||||
cells = ARRAY_SIZE(bd71837_mfd_cells);
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD71847:
|
||||
mfd = bd71847_mfd_cells;
|
||||
cells = ARRAY_SIZE(bd71847_mfd_cells);
|
||||
break;
|
||||
default:
|
||||
dev_err(&i2c->dev, "Unknown device type");
|
||||
return -EINVAL;
|
||||
}
|
||||
bd718xx->chip.dev = &i2c->dev;
|
||||
dev_set_drvdata(&i2c->dev, bd718xx);
|
||||
|
||||
@ -170,8 +196,7 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
button.irq = ret;
|
||||
|
||||
ret = devm_mfd_add_devices(bd718xx->chip.dev, PLATFORM_DEVID_AUTO,
|
||||
bd718xx_mfd_cells,
|
||||
ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0,
|
||||
mfd, cells, NULL, 0,
|
||||
regmap_irq_get_domain(bd718xx->irq_data));
|
||||
if (ret)
|
||||
dev_err(&i2c->dev, "Failed to create subdevices\n");
|
||||
@ -188,6 +213,10 @@ static const struct of_device_id bd718xx_of_match[] = {
|
||||
.compatible = "rohm,bd71847",
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD71847,
|
||||
},
|
||||
{
|
||||
.compatible = "rohm,bd71850",
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD71847,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd718xx_of_match);
|
||||
|
@ -197,6 +197,7 @@ config REGULATOR_BD70528
|
||||
config REGULATOR_BD718XX
|
||||
tristate "ROHM BD71837 Power Regulator"
|
||||
depends on MFD_ROHM_BD718XX
|
||||
select REGULATOR_ROHM
|
||||
help
|
||||
This driver supports voltage regulators on ROHM BD71837 PMIC.
|
||||
This will enable support for the software controllable buck
|
||||
@ -790,6 +791,9 @@ config REGULATOR_RN5T618
|
||||
Say y here to support the regulators found on Ricoh RN5T567,
|
||||
RN5T618 or RC5T619 PMIC.
|
||||
|
||||
config REGULATOR_ROHM
|
||||
tristate
|
||||
|
||||
config REGULATOR_RT5033
|
||||
tristate "Richtek RT5033 Regulators"
|
||||
depends on MFD_RT5033
|
||||
|
@ -99,6 +99,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
|
||||
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
|
||||
|
@ -318,6 +318,7 @@ struct reg_init {
|
||||
};
|
||||
struct bd718xx_regulator_data {
|
||||
struct regulator_desc desc;
|
||||
const struct rohm_dvs_config dvs;
|
||||
const struct reg_init init;
|
||||
const struct reg_init *additional_inits;
|
||||
int additional_init_amnt;
|
||||
@ -349,133 +350,15 @@ static const struct reg_init bd71837_ldo6_inits[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_DVS_BUCKS 4
|
||||
|
||||
struct of_dvs_setting {
|
||||
const char *prop;
|
||||
unsigned int reg;
|
||||
};
|
||||
|
||||
static int set_dvs_levels(const struct of_dvs_setting *dvs,
|
||||
struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned int uv;
|
||||
|
||||
ret = of_property_read_u32(np, dvs->prop, &uv);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < desc->n_voltages; i++) {
|
||||
ret = regulator_desc_list_voltage_linear_range(desc, i);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
if (ret == uv) {
|
||||
i <<= ffs(desc->vsel_mask) - 1;
|
||||
ret = regmap_update_bits(regmap, dvs->reg,
|
||||
DVS_BUCK_RUN_MASK, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int buck4_set_hw_dvs_levels(struct device_node *np,
|
||||
static int buck_set_hw_dvs_levels(struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
int ret, i;
|
||||
const struct of_dvs_setting dvs[] = {
|
||||
{
|
||||
.prop = "rohm,dvs-run-voltage",
|
||||
.reg = BD71837_REG_BUCK4_VOLT_RUN,
|
||||
},
|
||||
};
|
||||
struct bd718xx_regulator_data *data;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dvs); i++) {
|
||||
ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int buck3_set_hw_dvs_levels(struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
int ret, i;
|
||||
const struct of_dvs_setting dvs[] = {
|
||||
{
|
||||
.prop = "rohm,dvs-run-voltage",
|
||||
.reg = BD71837_REG_BUCK3_VOLT_RUN,
|
||||
},
|
||||
};
|
||||
data = container_of(desc, struct bd718xx_regulator_data, desc);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dvs); i++) {
|
||||
ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int buck2_set_hw_dvs_levels(struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
int ret, i;
|
||||
const struct of_dvs_setting dvs[] = {
|
||||
{
|
||||
.prop = "rohm,dvs-run-voltage",
|
||||
.reg = BD718XX_REG_BUCK2_VOLT_RUN,
|
||||
},
|
||||
{
|
||||
.prop = "rohm,dvs-idle-voltage",
|
||||
.reg = BD718XX_REG_BUCK2_VOLT_IDLE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dvs); i++) {
|
||||
ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int buck1_set_hw_dvs_levels(struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
int ret, i;
|
||||
const struct of_dvs_setting dvs[] = {
|
||||
{
|
||||
.prop = "rohm,dvs-run-voltage",
|
||||
.reg = BD718XX_REG_BUCK1_VOLT_RUN,
|
||||
},
|
||||
{
|
||||
.prop = "rohm,dvs-idle-voltage",
|
||||
.reg = BD718XX_REG_BUCK1_VOLT_IDLE,
|
||||
},
|
||||
{
|
||||
.prop = "rohm,dvs-suspend-voltage",
|
||||
.reg = BD718XX_REG_BUCK1_VOLT_SUSP,
|
||||
},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dvs); i++) {
|
||||
ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
|
||||
}
|
||||
|
||||
static const struct bd718xx_regulator_data bd71847_regulators[] = {
|
||||
@ -496,7 +379,17 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
|
||||
.enable_reg = BD718XX_REG_BUCK1_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck1_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
.idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
|
||||
.idle_mask = DVS_BUCK_RUN_MASK,
|
||||
.suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
|
||||
.suspend_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD718XX_REG_BUCK1_CTRL,
|
||||
@ -520,7 +413,14 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
|
||||
.enable_reg = BD718XX_REG_BUCK2_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck2_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
|
||||
.run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
.idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
|
||||
.idle_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD718XX_REG_BUCK2_CTRL,
|
||||
@ -792,7 +692,17 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
|
||||
.enable_reg = BD718XX_REG_BUCK1_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck1_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
.idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
|
||||
.idle_mask = DVS_BUCK_RUN_MASK,
|
||||
.suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
|
||||
.suspend_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD718XX_REG_BUCK1_CTRL,
|
||||
@ -816,7 +726,14 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
|
||||
.enable_reg = BD718XX_REG_BUCK2_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck2_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
|
||||
.run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
.idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
|
||||
.idle_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD718XX_REG_BUCK2_CTRL,
|
||||
@ -840,7 +757,12 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
|
||||
.enable_reg = BD71837_REG_BUCK3_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck3_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN,
|
||||
.run_reg = BD71837_REG_BUCK3_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD71837_REG_BUCK3_CTRL,
|
||||
@ -864,7 +786,12 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
|
||||
.enable_reg = BD71837_REG_BUCK4_CTRL,
|
||||
.enable_mask = BD718XX_BUCK_EN,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck4_set_hw_dvs_levels,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN,
|
||||
.run_reg = BD71837_REG_BUCK4_VOLT_RUN,
|
||||
.run_mask = DVS_BUCK_RUN_MASK,
|
||||
},
|
||||
.init = {
|
||||
.reg = BD71837_REG_BUCK4_CTRL,
|
||||
@ -1164,6 +1091,7 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
|
||||
int i, j, err;
|
||||
bool use_snvs;
|
||||
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
mfd = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!mfd) {
|
||||
@ -1172,8 +1100,8 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mfd->chip.chip_type >= ROHM_CHIP_TYPE_AMOUNT ||
|
||||
!pmic_regulators[mfd->chip.chip_type].r_datas) {
|
||||
if (chip >= ROHM_CHIP_TYPE_AMOUNT || chip < 0 ||
|
||||
!pmic_regulators[chip].r_datas) {
|
||||
dev_err(&pdev->dev, "Unsupported chip type\n");
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
@ -1215,13 +1143,13 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pmic_regulators[mfd->chip.chip_type].r_amount; i++) {
|
||||
for (i = 0; i < pmic_regulators[chip].r_amount; i++) {
|
||||
|
||||
const struct regulator_desc *desc;
|
||||
struct regulator_dev *rdev;
|
||||
const struct bd718xx_regulator_data *r;
|
||||
|
||||
r = &pmic_regulators[mfd->chip.chip_type].r_datas[i];
|
||||
r = &pmic_regulators[chip].r_datas[i];
|
||||
desc = &r->desc;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
@ -1281,11 +1209,19 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct platform_device_id bd718x7_pmic_id[] = {
|
||||
{ "bd71837-pmic", ROHM_CHIP_TYPE_BD71837 },
|
||||
{ "bd71847-pmic", ROHM_CHIP_TYPE_BD71847 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_pmic_id);
|
||||
|
||||
static struct platform_driver bd718xx_regulator = {
|
||||
.driver = {
|
||||
.name = "bd718xx-pmic",
|
||||
},
|
||||
.probe = bd718xx_probe,
|
||||
.id_table = bd718x7_pmic_id,
|
||||
};
|
||||
|
||||
module_platform_driver(bd718xx_regulator);
|
||||
|
95
drivers/regulator/rohm-regulator.c
Normal file
95
drivers/regulator/rohm-regulator.c
Normal file
@ -0,0 +1,95 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2020 ROHM Semiconductors
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
static int set_dvs_level(const struct regulator_desc *desc,
|
||||
struct device_node *np, struct regmap *regmap,
|
||||
char *prop, unsigned int reg, unsigned int mask,
|
||||
unsigned int omask, unsigned int oreg)
|
||||
{
|
||||
int ret, i;
|
||||
uint32_t uv;
|
||||
|
||||
ret = of_property_read_u32(np, prop, &uv);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uv == 0) {
|
||||
if (omask)
|
||||
return regmap_update_bits(regmap, oreg, omask, 0);
|
||||
}
|
||||
for (i = 0; i < desc->n_voltages; i++) {
|
||||
ret = regulator_desc_list_voltage_linear_range(desc, i);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
if (ret == uv) {
|
||||
i <<= ffs(desc->vsel_mask) - 1;
|
||||
ret = regmap_update_bits(regmap, reg, mask, i);
|
||||
if (omask && !ret)
|
||||
ret = regmap_update_bits(regmap, oreg, omask,
|
||||
omask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
|
||||
struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
int i, ret = 0;
|
||||
char *prop;
|
||||
unsigned int reg, mask, omask, oreg = desc->enable_reg;
|
||||
|
||||
for (i = 0; i < ROHM_DVS_LEVEL_MAX && !ret; i++) {
|
||||
if (dvs->level_map & (1 << i)) {
|
||||
switch (i + 1) {
|
||||
case ROHM_DVS_LEVEL_RUN:
|
||||
prop = "rohm,dvs-run-voltage";
|
||||
reg = dvs->run_reg;
|
||||
mask = dvs->run_mask;
|
||||
omask = dvs->run_on_mask;
|
||||
break;
|
||||
case ROHM_DVS_LEVEL_IDLE:
|
||||
prop = "rohm,dvs-idle-voltage";
|
||||
reg = dvs->idle_reg;
|
||||
mask = dvs->idle_mask;
|
||||
omask = dvs->idle_on_mask;
|
||||
break;
|
||||
case ROHM_DVS_LEVEL_SUSPEND:
|
||||
prop = "rohm,dvs-suspend-voltage";
|
||||
reg = dvs->suspend_reg;
|
||||
mask = dvs->suspend_mask;
|
||||
omask = dvs->suspend_on_mask;
|
||||
break;
|
||||
case ROHM_DVS_LEVEL_LPSR:
|
||||
prop = "rohm,dvs-lpsr-voltage";
|
||||
reg = dvs->lpsr_reg;
|
||||
mask = dvs->lpsr_mask;
|
||||
omask = dvs->lpsr_on_mask;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
|
||||
omask, oreg);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");
|
@ -498,12 +498,13 @@ config RTC_DRV_M41T80_WDT
|
||||
help
|
||||
If you say Y here you will get support for the
|
||||
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
|
||||
|
||||
config RTC_DRV_BD70528
|
||||
tristate "ROHM BD70528 PMIC RTC"
|
||||
depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
|
||||
help
|
||||
If you say Y here you will get support for the RTC
|
||||
on ROHM BD70528 Power Management IC.
|
||||
block on ROHM BD70528 and BD71828 Power Management IC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-bd70528.
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/mfd/rohm-bd71828.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -15,7 +16,7 @@
|
||||
/*
|
||||
* We read regs RTC_SEC => RTC_YEAR
|
||||
* this struct is ordered according to chip registers.
|
||||
* Keep it u8 only to avoid padding issues.
|
||||
* Keep it u8 only (or packed) to avoid padding issues.
|
||||
*/
|
||||
struct bd70528_rtc_day {
|
||||
u8 sec;
|
||||
@ -36,6 +37,13 @@ struct bd70528_rtc_wake {
|
||||
u8 ctrl;
|
||||
} __packed;
|
||||
|
||||
struct bd71828_rtc_alm {
|
||||
struct bd70528_rtc_data alm0;
|
||||
struct bd70528_rtc_data alm1;
|
||||
u8 alm_mask;
|
||||
u8 alm1_mask;
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc_alm {
|
||||
struct bd70528_rtc_data data;
|
||||
u8 alm_mask;
|
||||
@ -43,8 +51,10 @@ struct bd70528_rtc_alm {
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc {
|
||||
struct rohm_regmap_dev *mfd;
|
||||
struct rohm_regmap_dev *parent;
|
||||
struct device *dev;
|
||||
u8 reg_time_start;
|
||||
bool has_rtc_timers;
|
||||
};
|
||||
|
||||
static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
|
||||
@ -123,14 +133,14 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bd70528_wdt_set(r->mfd, new_state & BD70528_WDT_STATE_BIT,
|
||||
ret = bd70528_wdt_set(r->parent, new_state & BD70528_WDT_STATE_BIT,
|
||||
old_state);
|
||||
if (ret) {
|
||||
dev_err(r->dev,
|
||||
"Failed to disable WDG for RTC setting (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = bd70528_set_elapsed_tmr(r->mfd,
|
||||
ret = bd70528_set_elapsed_tmr(r->parent,
|
||||
new_state & BD70528_ELAPSED_STATE_BIT,
|
||||
old_state);
|
||||
if (ret) {
|
||||
@ -138,7 +148,7 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
|
||||
"Failed to disable 'elapsed timer' for RTC setting\n");
|
||||
return ret;
|
||||
}
|
||||
ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT,
|
||||
ret = bd70528_set_wake(r->parent, new_state & BD70528_WAKE_STATE_BIT,
|
||||
old_state);
|
||||
if (ret) {
|
||||
dev_err(r->dev,
|
||||
@ -152,12 +162,18 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
|
||||
static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
|
||||
int old_state)
|
||||
{
|
||||
if (!r->has_rtc_timers)
|
||||
return 0;
|
||||
|
||||
return bd70528_set_rtc_based_timers(r, old_state, NULL);
|
||||
}
|
||||
|
||||
static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
|
||||
int *old_state)
|
||||
{
|
||||
if (!r->has_rtc_timers)
|
||||
return 0;
|
||||
|
||||
return bd70528_set_rtc_based_timers(r, 0, old_state);
|
||||
}
|
||||
|
||||
@ -213,22 +229,52 @@ static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
|
||||
t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
|
||||
}
|
||||
|
||||
static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
{
|
||||
int ret;
|
||||
struct bd71828_rtc_alm alm;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
|
||||
ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm2rtc(&a->time, &alm.alm0);
|
||||
|
||||
if (!a->enabled)
|
||||
alm.alm_mask &= ~BD70528_MASK_ALM_EN;
|
||||
else
|
||||
alm.alm_mask |= BD70528_MASK_ALM_EN;
|
||||
|
||||
ret = regmap_bulk_write(parent->regmap, BD71828_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to set alarm time\n");
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
{
|
||||
struct bd70528_rtc_wake wake;
|
||||
struct bd70528_rtc_alm alm;
|
||||
int ret;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *bd70528 = r->mfd;
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
|
||||
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_WAKE_START,
|
||||
ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START,
|
||||
&wake, sizeof(wake));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read wake regs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
|
||||
ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
@ -246,14 +292,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
wake.ctrl &= ~BD70528_MASK_WAKE_EN;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_write(bd70528->regmap,
|
||||
ret = regmap_bulk_write(parent->regmap,
|
||||
BD70528_REG_RTC_WAKE_START, &wake,
|
||||
sizeof(wake));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set wake time\n");
|
||||
return ret;
|
||||
}
|
||||
ret = regmap_bulk_write(bd70528->regmap, BD70528_REG_RTC_ALM_START,
|
||||
ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to set alarm time\n");
|
||||
@ -261,14 +307,38 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
{
|
||||
int ret;
|
||||
struct bd71828_rtc_alm alm;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
|
||||
ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc2tm(&alm.alm0, &a->time);
|
||||
a->time.tm_mday = -1;
|
||||
a->time.tm_mon = -1;
|
||||
a->time.tm_year = -1;
|
||||
a->enabled = !!(alm.alm_mask & BD70528_MASK_ALM_EN);
|
||||
a->pending = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||
{
|
||||
struct bd70528_rtc_alm alm;
|
||||
int ret;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *bd70528 = r->mfd;
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
|
||||
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
|
||||
ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
@ -290,14 +360,14 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
|
||||
int ret, tmpret, old_states;
|
||||
struct bd70528_rtc_data rtc_data;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *bd70528 = r->mfd;
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
|
||||
ret = bd70528_disable_rtc_based_timers(r, &old_states);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmpret = regmap_bulk_read(bd70528->regmap,
|
||||
BD70528_REG_RTC_START, &rtc_data,
|
||||
tmpret = regmap_bulk_read(parent->regmap,
|
||||
r->reg_time_start, &rtc_data,
|
||||
sizeof(rtc_data));
|
||||
if (tmpret) {
|
||||
dev_err(dev, "Failed to read RTC time registers\n");
|
||||
@ -305,8 +375,8 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
|
||||
}
|
||||
tm2rtc(t, &rtc_data);
|
||||
|
||||
tmpret = regmap_bulk_write(bd70528->regmap,
|
||||
BD70528_REG_RTC_START, &rtc_data,
|
||||
tmpret = regmap_bulk_write(parent->regmap,
|
||||
r->reg_time_start, &rtc_data,
|
||||
sizeof(rtc_data));
|
||||
if (tmpret) {
|
||||
dev_err(dev, "Failed to set RTC time\n");
|
||||
@ -321,27 +391,32 @@ renable_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd71828_set_time(struct device *dev, struct rtc_time *t)
|
||||
{
|
||||
return bd70528_set_time_locked(dev, t);
|
||||
}
|
||||
|
||||
static int bd70528_set_time(struct device *dev, struct rtc_time *t)
|
||||
{
|
||||
int ret;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
|
||||
bd70528_wdt_lock(r->mfd);
|
||||
bd70528_wdt_lock(r->parent);
|
||||
ret = bd70528_set_time_locked(dev, t);
|
||||
bd70528_wdt_unlock(r->mfd);
|
||||
bd70528_wdt_unlock(r->parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_get_time(struct device *dev, struct rtc_time *t)
|
||||
{
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
struct rohm_regmap_dev *bd70528 = r->mfd;
|
||||
struct rohm_regmap_dev *parent = r->parent;
|
||||
struct bd70528_rtc_data rtc_data;
|
||||
int ret;
|
||||
|
||||
/* read the RTC date and time registers all at once */
|
||||
ret = regmap_bulk_read(bd70528->regmap,
|
||||
BD70528_REG_RTC_START, &rtc_data,
|
||||
ret = regmap_bulk_read(parent->regmap,
|
||||
r->reg_time_start, &rtc_data,
|
||||
sizeof(rtc_data));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
|
||||
@ -362,19 +437,36 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
|
||||
if (enabled)
|
||||
enableval = 0;
|
||||
|
||||
bd70528_wdt_lock(r->mfd);
|
||||
ret = bd70528_set_wake(r->mfd, enabled, NULL);
|
||||
bd70528_wdt_lock(r->parent);
|
||||
ret = bd70528_set_wake(r->parent, enabled, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to change wake state\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
ret = regmap_update_bits(r->mfd->regmap, BD70528_REG_RTC_ALM_MASK,
|
||||
ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK,
|
||||
BD70528_MASK_ALM_EN, enableval);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to change alarm state\n");
|
||||
|
||||
out_unlock:
|
||||
bd70528_wdt_unlock(r->mfd);
|
||||
bd70528_wdt_unlock(r->parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
int ret;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
unsigned int enableval = BD70528_MASK_ALM_EN;
|
||||
|
||||
if (!enabled)
|
||||
enableval = 0;
|
||||
|
||||
ret = regmap_update_bits(r->parent->regmap, BD71828_REG_RTC_ALM0_MASK,
|
||||
BD70528_MASK_ALM_EN, enableval);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to change alarm state\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -386,6 +478,14 @@ static const struct rtc_class_ops bd70528_rtc_ops = {
|
||||
.alarm_irq_enable = bd70528_alm_enable,
|
||||
};
|
||||
|
||||
static const struct rtc_class_ops bd71828_rtc_ops = {
|
||||
.read_time = bd70528_get_time,
|
||||
.set_time = bd71828_set_time,
|
||||
.read_alarm = bd71828_read_alarm,
|
||||
.set_alarm = bd71828_set_alarm,
|
||||
.alarm_irq_enable = bd71828_alm_enable,
|
||||
};
|
||||
|
||||
static irqreturn_t alm_hndlr(int irq, void *data)
|
||||
{
|
||||
struct rtc_device *rtc = data;
|
||||
@ -397,14 +497,19 @@ static irqreturn_t alm_hndlr(int irq, void *data)
|
||||
static int bd70528_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd70528_rtc *bd_rtc;
|
||||
struct rohm_regmap_dev *mfd;
|
||||
const struct rtc_class_ops *rtc_ops;
|
||||
struct rohm_regmap_dev *parent;
|
||||
const char *irq_name;
|
||||
int ret;
|
||||
struct rtc_device *rtc;
|
||||
int irq;
|
||||
unsigned int hr;
|
||||
bool enable_main_irq = false;
|
||||
u8 hour_reg;
|
||||
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
mfd = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!mfd) {
|
||||
parent = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!parent) {
|
||||
dev_err(&pdev->dev, "No MFD driver data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -412,16 +517,39 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||
if (!bd_rtc)
|
||||
return -ENOMEM;
|
||||
|
||||
bd_rtc->mfd = mfd;
|
||||
bd_rtc->parent = parent;
|
||||
bd_rtc->dev = &pdev->dev;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm");
|
||||
if (irq < 0)
|
||||
switch (chip) {
|
||||
case ROHM_CHIP_TYPE_BD70528:
|
||||
irq_name = "bd70528-rtc-alm";
|
||||
bd_rtc->has_rtc_timers = true;
|
||||
bd_rtc->reg_time_start = BD70528_REG_RTC_START;
|
||||
hour_reg = BD70528_REG_RTC_HOUR;
|
||||
enable_main_irq = true;
|
||||
rtc_ops = &bd70528_rtc_ops;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD71828:
|
||||
irq_name = "bd71828-rtc-alm-0";
|
||||
bd_rtc->reg_time_start = BD71828_REG_RTC_START;
|
||||
hour_reg = BD71828_REG_RTC_HOUR;
|
||||
rtc_ops = &bd71828_rtc_ops;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown chip\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
irq = platform_get_irq_byname(pdev, irq_name);
|
||||
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get irq\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, bd_rtc);
|
||||
|
||||
ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr);
|
||||
ret = regmap_read(parent->regmap, hour_reg, &hr);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to reag RTC clock\n");
|
||||
@ -431,10 +559,10 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||
if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
|
||||
struct rtc_time t;
|
||||
|
||||
ret = bd70528_get_time(&pdev->dev, &t);
|
||||
ret = rtc_ops->read_time(&pdev->dev, &t);
|
||||
|
||||
if (!ret)
|
||||
ret = bd70528_set_time(&pdev->dev, &t);
|
||||
ret = rtc_ops->set_time(&pdev->dev, &t);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
@ -454,7 +582,7 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||
|
||||
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
rtc->ops = &bd70528_rtc_ops;
|
||||
rtc->ops = rtc_ops;
|
||||
|
||||
/* Request alarm IRQ prior to registerig the RTC */
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
|
||||
@ -468,27 +596,37 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||
* leave them enabled as irq-controller should disable irqs
|
||||
* from sub-registers when IRQ is disabled or freed.
|
||||
*/
|
||||
ret = regmap_update_bits(mfd->regmap,
|
||||
if (enable_main_irq) {
|
||||
ret = regmap_update_bits(parent->regmap,
|
||||
BD70528_REG_INT_MAIN_MASK,
|
||||
BD70528_INT_RTC_MASK, 0);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
|
||||
return ret;
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return rtc_register_device(rtc);
|
||||
}
|
||||
|
||||
static const struct platform_device_id bd718x7_rtc_id[] = {
|
||||
{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },
|
||||
{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
|
||||
|
||||
static struct platform_driver bd70528_rtc = {
|
||||
.driver = {
|
||||
.name = "bd70528-rtc"
|
||||
},
|
||||
.probe = bd70528_probe,
|
||||
.id_table = bd718x7_rtc_id,
|
||||
};
|
||||
|
||||
module_platform_driver(bd70528_rtc);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD70528 RTC driver");
|
||||
MODULE_DESCRIPTION("ROHM BD70528 and BD71828 PMIC RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:bd70528-rtc");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/mfd/rohm-shared.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
@ -89,10 +90,6 @@ struct bd70528_data {
|
||||
#define BD70528_REG_GPIO3_OUT 0x52
|
||||
#define BD70528_REG_GPIO4_OUT 0x54
|
||||
|
||||
/* clk control */
|
||||
|
||||
#define BD70528_REG_CLK_OUT 0x2c
|
||||
|
||||
/* RTC */
|
||||
|
||||
#define BD70528_REG_RTC_COUNT_H 0x2d
|
||||
@ -309,21 +306,8 @@ enum {
|
||||
|
||||
#define BD70528_GPIO_IN_STATE_BASE 1
|
||||
|
||||
#define BD70528_CLK_OUT_EN_MASK 0x1
|
||||
|
||||
/* RTC masks to mask out reserved bits */
|
||||
|
||||
#define BD70528_MASK_RTC_SEC 0x7f
|
||||
#define BD70528_MASK_RTC_MINUTE 0x7f
|
||||
#define BD70528_MASK_RTC_HOUR_24H 0x80
|
||||
#define BD70528_MASK_RTC_HOUR_PM 0x20
|
||||
#define BD70528_MASK_RTC_HOUR 0x1f
|
||||
#define BD70528_MASK_RTC_DAY 0x3f
|
||||
#define BD70528_MASK_RTC_WEEK 0x07
|
||||
#define BD70528_MASK_RTC_MONTH 0x1f
|
||||
#define BD70528_MASK_RTC_YEAR 0xff
|
||||
#define BD70528_MASK_RTC_COUNT_L 0x7f
|
||||
|
||||
#define BD70528_MASK_ELAPSED_TIMER_EN 0x1
|
||||
/* Mask second, min and hour fields
|
||||
* HW would support ALM irq for over 24h
|
||||
@ -332,7 +316,6 @@ enum {
|
||||
* wake-up we limit ALM to 24H and only
|
||||
* unmask sec, min and hour
|
||||
*/
|
||||
#define BD70528_MASK_ALM_EN 0x7
|
||||
#define BD70528_MASK_WAKE_EN 0x1
|
||||
|
||||
/* WDT masks */
|
||||
|
423
include/linux/mfd/rohm-bd71828.h
Normal file
423
include/linux/mfd/rohm-bd71828.h
Normal file
@ -0,0 +1,423 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2019 ROHM Semiconductors */
|
||||
|
||||
#ifndef __LINUX_MFD_BD71828_H__
|
||||
#define __LINUX_MFD_BD71828_H__
|
||||
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/mfd/rohm-shared.h>
|
||||
|
||||
/* Regulator IDs */
|
||||
enum {
|
||||
BD71828_BUCK1,
|
||||
BD71828_BUCK2,
|
||||
BD71828_BUCK3,
|
||||
BD71828_BUCK4,
|
||||
BD71828_BUCK5,
|
||||
BD71828_BUCK6,
|
||||
BD71828_BUCK7,
|
||||
BD71828_LDO1,
|
||||
BD71828_LDO2,
|
||||
BD71828_LDO3,
|
||||
BD71828_LDO4,
|
||||
BD71828_LDO5,
|
||||
BD71828_LDO6,
|
||||
BD71828_LDO_SNVS,
|
||||
BD71828_REGULATOR_AMOUNT,
|
||||
};
|
||||
|
||||
#define BD71828_BUCK1267_VOLTS 0xEF
|
||||
#define BD71828_BUCK3_VOLTS 0x10
|
||||
#define BD71828_BUCK4_VOLTS 0x20
|
||||
#define BD71828_BUCK5_VOLTS 0x10
|
||||
#define BD71828_LDO_VOLTS 0x32
|
||||
/* LDO6 is fixed 1.8V voltage */
|
||||
#define BD71828_LDO_6_VOLTAGE 1800000
|
||||
|
||||
/* Registers and masks*/
|
||||
|
||||
/* MODE control */
|
||||
#define BD71828_REG_PS_CTRL_1 0x04
|
||||
#define BD71828_REG_PS_CTRL_2 0x05
|
||||
#define BD71828_REG_PS_CTRL_3 0x06
|
||||
|
||||
//#define BD71828_REG_SWRESET 0x06
|
||||
#define BD71828_MASK_RUN_LVL_CTRL 0x30
|
||||
|
||||
/* Regulator control masks */
|
||||
|
||||
#define BD71828_MASK_RAMP_DELAY 0x6
|
||||
|
||||
#define BD71828_MASK_RUN_EN 0x08
|
||||
#define BD71828_MASK_SUSP_EN 0x04
|
||||
#define BD71828_MASK_IDLE_EN 0x02
|
||||
#define BD71828_MASK_LPSR_EN 0x01
|
||||
|
||||
#define BD71828_MASK_RUN0_EN 0x01
|
||||
#define BD71828_MASK_RUN1_EN 0x02
|
||||
#define BD71828_MASK_RUN2_EN 0x04
|
||||
#define BD71828_MASK_RUN3_EN 0x08
|
||||
|
||||
#define BD71828_MASK_DVS_BUCK1_CTRL 0x10
|
||||
#define BD71828_DVS_BUCK1_CTRL_I2C 0
|
||||
#define BD71828_DVS_BUCK1_USE_RUNLVL 0x10
|
||||
|
||||
#define BD71828_MASK_DVS_BUCK2_CTRL 0x20
|
||||
#define BD71828_DVS_BUCK2_CTRL_I2C 0
|
||||
#define BD71828_DVS_BUCK2_USE_RUNLVL 0x20
|
||||
|
||||
#define BD71828_MASK_DVS_BUCK6_CTRL 0x40
|
||||
#define BD71828_DVS_BUCK6_CTRL_I2C 0
|
||||
#define BD71828_DVS_BUCK6_USE_RUNLVL 0x40
|
||||
|
||||
#define BD71828_MASK_DVS_BUCK7_CTRL 0x80
|
||||
#define BD71828_DVS_BUCK7_CTRL_I2C 0
|
||||
#define BD71828_DVS_BUCK7_USE_RUNLVL 0x80
|
||||
|
||||
#define BD71828_MASK_BUCK1267_VOLT 0xff
|
||||
#define BD71828_MASK_BUCK3_VOLT 0x1f
|
||||
#define BD71828_MASK_BUCK4_VOLT 0x3f
|
||||
#define BD71828_MASK_BUCK5_VOLT 0x1f
|
||||
#define BD71828_MASK_LDO_VOLT 0x3f
|
||||
|
||||
/* Regulator control regs */
|
||||
#define BD71828_REG_BUCK1_EN 0x08
|
||||
#define BD71828_REG_BUCK1_CTRL 0x09
|
||||
#define BD71828_REG_BUCK1_MODE 0x0a
|
||||
#define BD71828_REG_BUCK1_IDLE_VOLT 0x0b
|
||||
#define BD71828_REG_BUCK1_SUSP_VOLT 0x0c
|
||||
#define BD71828_REG_BUCK1_VOLT 0x0d
|
||||
|
||||
#define BD71828_REG_BUCK2_EN 0x12
|
||||
#define BD71828_REG_BUCK2_CTRL 0x13
|
||||
#define BD71828_REG_BUCK2_MODE 0x14
|
||||
#define BD71828_REG_BUCK2_IDLE_VOLT 0x15
|
||||
#define BD71828_REG_BUCK2_SUSP_VOLT 0x16
|
||||
#define BD71828_REG_BUCK2_VOLT 0x17
|
||||
|
||||
#define BD71828_REG_BUCK3_EN 0x1c
|
||||
#define BD71828_REG_BUCK3_MODE 0x1d
|
||||
#define BD71828_REG_BUCK3_VOLT 0x1e
|
||||
|
||||
#define BD71828_REG_BUCK4_EN 0x1f
|
||||
#define BD71828_REG_BUCK4_MODE 0x20
|
||||
#define BD71828_REG_BUCK4_VOLT 0x21
|
||||
|
||||
#define BD71828_REG_BUCK5_EN 0x22
|
||||
#define BD71828_REG_BUCK5_MODE 0x23
|
||||
#define BD71828_REG_BUCK5_VOLT 0x24
|
||||
|
||||
#define BD71828_REG_BUCK6_EN 0x25
|
||||
#define BD71828_REG_BUCK6_CTRL 0x26
|
||||
#define BD71828_REG_BUCK6_MODE 0x27
|
||||
#define BD71828_REG_BUCK6_IDLE_VOLT 0x28
|
||||
#define BD71828_REG_BUCK6_SUSP_VOLT 0x29
|
||||
#define BD71828_REG_BUCK6_VOLT 0x2a
|
||||
|
||||
#define BD71828_REG_BUCK7_EN 0x2f
|
||||
#define BD71828_REG_BUCK7_CTRL 0x30
|
||||
#define BD71828_REG_BUCK7_MODE 0x31
|
||||
#define BD71828_REG_BUCK7_IDLE_VOLT 0x32
|
||||
#define BD71828_REG_BUCK7_SUSP_VOLT 0x33
|
||||
#define BD71828_REG_BUCK7_VOLT 0x34
|
||||
|
||||
#define BD71828_REG_LDO1_EN 0x39
|
||||
#define BD71828_REG_LDO1_VOLT 0x3a
|
||||
#define BD71828_REG_LDO2_EN 0x3b
|
||||
#define BD71828_REG_LDO2_VOLT 0x3c
|
||||
#define BD71828_REG_LDO3_EN 0x3d
|
||||
#define BD71828_REG_LDO3_VOLT 0x3e
|
||||
#define BD71828_REG_LDO4_EN 0x3f
|
||||
#define BD71828_REG_LDO4_VOLT 0x40
|
||||
#define BD71828_REG_LDO5_EN 0x41
|
||||
#define BD71828_REG_LDO5_VOLT 0x43
|
||||
#define BD71828_REG_LDO5_VOLT_OPT 0x42
|
||||
#define BD71828_REG_LDO6_EN 0x44
|
||||
//#define BD71828_REG_LDO6_VOLT 0x4
|
||||
#define BD71828_REG_LDO7_EN 0x45
|
||||
#define BD71828_REG_LDO7_VOLT 0x46
|
||||
|
||||
/* GPIO */
|
||||
|
||||
#define BD71828_GPIO_DRIVE_MASK 0x2
|
||||
#define BD71828_GPIO_OPEN_DRAIN 0x0
|
||||
#define BD71828_GPIO_PUSH_PULL 0x2
|
||||
#define BD71828_GPIO_OUT_HI 0x1
|
||||
#define BD71828_GPIO_OUT_LO 0x0
|
||||
#define BD71828_GPIO_OUT_MASK 0x1
|
||||
|
||||
#define BD71828_REG_GPIO_CTRL1 0x47
|
||||
#define BD71828_REG_GPIO_CTRL2 0x48
|
||||
#define BD71828_REG_GPIO_CTRL3 0x49
|
||||
#define BD71828_REG_IO_STAT 0xed
|
||||
|
||||
/* RTC */
|
||||
#define BD71828_REG_RTC_SEC 0x4c
|
||||
#define BD71828_REG_RTC_MINUTE 0x4d
|
||||
#define BD71828_REG_RTC_HOUR 0x4e
|
||||
#define BD71828_REG_RTC_WEEK 0x4f
|
||||
#define BD71828_REG_RTC_DAY 0x50
|
||||
#define BD71828_REG_RTC_MONTH 0x51
|
||||
#define BD71828_REG_RTC_YEAR 0x52
|
||||
|
||||
#define BD71828_REG_RTC_ALM0_SEC 0x53
|
||||
#define BD71828_REG_RTC_ALM_START BD71828_REG_RTC_ALM0_SEC
|
||||
#define BD71828_REG_RTC_ALM0_MINUTE 0x54
|
||||
#define BD71828_REG_RTC_ALM0_HOUR 0x55
|
||||
#define BD71828_REG_RTC_ALM0_WEEK 0x56
|
||||
#define BD71828_REG_RTC_ALM0_DAY 0x57
|
||||
#define BD71828_REG_RTC_ALM0_MONTH 0x58
|
||||
#define BD71828_REG_RTC_ALM0_YEAR 0x59
|
||||
#define BD71828_REG_RTC_ALM0_MASK 0x61
|
||||
|
||||
#define BD71828_REG_RTC_ALM1_SEC 0x5a
|
||||
#define BD71828_REG_RTC_ALM1_MINUTE 0x5b
|
||||
#define BD71828_REG_RTC_ALM1_HOUR 0x5c
|
||||
#define BD71828_REG_RTC_ALM1_WEEK 0x5d
|
||||
#define BD71828_REG_RTC_ALM1_DAY 0x5e
|
||||
#define BD71828_REG_RTC_ALM1_MONTH 0x5f
|
||||
#define BD71828_REG_RTC_ALM1_YEAR 0x60
|
||||
#define BD71828_REG_RTC_ALM1_MASK 0x62
|
||||
|
||||
#define BD71828_REG_RTC_ALM2 0x63
|
||||
#define BD71828_REG_RTC_START BD71828_REG_RTC_SEC
|
||||
|
||||
/* Charger/Battey */
|
||||
#define BD71828_REG_CHG_STATE 0x65
|
||||
#define BD71828_REG_CHG_FULL 0xd2
|
||||
|
||||
/* LEDs */
|
||||
#define BD71828_REG_LED_CTRL 0x4A
|
||||
#define BD71828_MASK_LED_AMBER 0x80
|
||||
#define BD71828_MASK_LED_GREEN 0x40
|
||||
#define BD71828_LED_ON 0xff
|
||||
#define BD71828_LED_OFF 0x0
|
||||
|
||||
/* IRQ registers */
|
||||
#define BD71828_REG_INT_MASK_BUCK 0xd3
|
||||
#define BD71828_REG_INT_MASK_DCIN1 0xd4
|
||||
#define BD71828_REG_INT_MASK_DCIN2 0xd5
|
||||
#define BD71828_REG_INT_MASK_VSYS 0xd6
|
||||
#define BD71828_REG_INT_MASK_CHG 0xd7
|
||||
#define BD71828_REG_INT_MASK_BAT 0xd8
|
||||
#define BD71828_REG_INT_MASK_BAT_MON1 0xd9
|
||||
#define BD71828_REG_INT_MASK_BAT_MON2 0xda
|
||||
#define BD71828_REG_INT_MASK_BAT_MON3 0xdb
|
||||
#define BD71828_REG_INT_MASK_BAT_MON4 0xdc
|
||||
#define BD71828_REG_INT_MASK_TEMP 0xdd
|
||||
#define BD71828_REG_INT_MASK_RTC 0xde
|
||||
|
||||
#define BD71828_REG_INT_MAIN 0xdf
|
||||
#define BD71828_REG_INT_BUCK 0xe0
|
||||
#define BD71828_REG_INT_DCIN1 0xe1
|
||||
#define BD71828_REG_INT_DCIN2 0xe2
|
||||
#define BD71828_REG_INT_VSYS 0xe3
|
||||
#define BD71828_REG_INT_CHG 0xe4
|
||||
#define BD71828_REG_INT_BAT 0xe5
|
||||
#define BD71828_REG_INT_BAT_MON1 0xe6
|
||||
#define BD71828_REG_INT_BAT_MON2 0xe7
|
||||
#define BD71828_REG_INT_BAT_MON3 0xe8
|
||||
#define BD71828_REG_INT_BAT_MON4 0xe9
|
||||
#define BD71828_REG_INT_TEMP 0xea
|
||||
#define BD71828_REG_INT_RTC 0xeb
|
||||
#define BD71828_REG_INT_UPDATE 0xec
|
||||
|
||||
#define BD71828_MAX_REGISTER BD71828_REG_IO_STAT
|
||||
|
||||
/* Masks for main IRQ register bits */
|
||||
enum {
|
||||
BD71828_INT_BUCK,
|
||||
#define BD71828_INT_BUCK_MASK BIT(BD71828_INT_BUCK)
|
||||
BD71828_INT_DCIN,
|
||||
#define BD71828_INT_DCIN_MASK BIT(BD71828_INT_DCIN)
|
||||
BD71828_INT_VSYS,
|
||||
#define BD71828_INT_VSYS_MASK BIT(BD71828_INT_VSYS)
|
||||
BD71828_INT_CHG,
|
||||
#define BD71828_INT_CHG_MASK BIT(BD71828_INT_CHG)
|
||||
BD71828_INT_BAT,
|
||||
#define BD71828_INT_BAT_MASK BIT(BD71828_INT_BAT)
|
||||
BD71828_INT_BAT_MON,
|
||||
#define BD71828_INT_BAT_MON_MASK BIT(BD71828_INT_BAT_MON)
|
||||
BD71828_INT_TEMP,
|
||||
#define BD71828_INT_TEMP_MASK BIT(BD71828_INT_TEMP)
|
||||
BD71828_INT_RTC,
|
||||
#define BD71828_INT_RTC_MASK BIT(BD71828_INT_RTC)
|
||||
};
|
||||
|
||||
/* Interrupts */
|
||||
enum {
|
||||
/* BUCK reg interrupts */
|
||||
BD71828_INT_BUCK1_OCP,
|
||||
BD71828_INT_BUCK2_OCP,
|
||||
BD71828_INT_BUCK3_OCP,
|
||||
BD71828_INT_BUCK4_OCP,
|
||||
BD71828_INT_BUCK5_OCP,
|
||||
BD71828_INT_BUCK6_OCP,
|
||||
BD71828_INT_BUCK7_OCP,
|
||||
BD71828_INT_PGFAULT,
|
||||
/* DCIN1 interrupts */
|
||||
BD71828_INT_DCIN_DET,
|
||||
BD71828_INT_DCIN_RMV,
|
||||
BD71828_INT_CLPS_OUT,
|
||||
BD71828_INT_CLPS_IN,
|
||||
/* DCIN2 interrupts */
|
||||
BD71828_INT_DCIN_MON_RES,
|
||||
BD71828_INT_DCIN_MON_DET,
|
||||
BD71828_INT_LONGPUSH,
|
||||
BD71828_INT_MIDPUSH,
|
||||
BD71828_INT_SHORTPUSH,
|
||||
BD71828_INT_PUSH,
|
||||
BD71828_INT_WDOG,
|
||||
BD71828_INT_SWRESET,
|
||||
/* Vsys */
|
||||
BD71828_INT_VSYS_UV_RES,
|
||||
BD71828_INT_VSYS_UV_DET,
|
||||
BD71828_INT_VSYS_LOW_RES,
|
||||
BD71828_INT_VSYS_LOW_DET,
|
||||
BD71828_INT_VSYS_HALL_IN,
|
||||
BD71828_INT_VSYS_HALL_TOGGLE,
|
||||
BD71828_INT_VSYS_MON_RES,
|
||||
BD71828_INT_VSYS_MON_DET,
|
||||
/* Charger */
|
||||
BD71828_INT_CHG_DCIN_ILIM,
|
||||
BD71828_INT_CHG_TOPOFF_TO_DONE,
|
||||
BD71828_INT_CHG_WDG_TEMP,
|
||||
BD71828_INT_CHG_WDG_TIME,
|
||||
BD71828_INT_CHG_RECHARGE_RES,
|
||||
BD71828_INT_CHG_RECHARGE_DET,
|
||||
BD71828_INT_CHG_RANGED_TEMP_TRANSITION,
|
||||
BD71828_INT_CHG_STATE_TRANSITION,
|
||||
/* Battery */
|
||||
BD71828_INT_BAT_TEMP_NORMAL,
|
||||
BD71828_INT_BAT_TEMP_ERANGE,
|
||||
BD71828_INT_BAT_TEMP_WARN,
|
||||
BD71828_INT_BAT_REMOVED,
|
||||
BD71828_INT_BAT_DETECTED,
|
||||
BD71828_INT_THERM_REMOVED,
|
||||
BD71828_INT_THERM_DETECTED,
|
||||
/* Battery Mon 1 */
|
||||
BD71828_INT_BAT_DEAD,
|
||||
BD71828_INT_BAT_SHORTC_RES,
|
||||
BD71828_INT_BAT_SHORTC_DET,
|
||||
BD71828_INT_BAT_LOW_VOLT_RES,
|
||||
BD71828_INT_BAT_LOW_VOLT_DET,
|
||||
BD71828_INT_BAT_OVER_VOLT_RES,
|
||||
BD71828_INT_BAT_OVER_VOLT_DET,
|
||||
/* Battery Mon 2 */
|
||||
BD71828_INT_BAT_MON_RES,
|
||||
BD71828_INT_BAT_MON_DET,
|
||||
/* Battery Mon 3 (Coulomb counter) */
|
||||
BD71828_INT_BAT_CC_MON1,
|
||||
BD71828_INT_BAT_CC_MON2,
|
||||
BD71828_INT_BAT_CC_MON3,
|
||||
/* Battery Mon 4 */
|
||||
BD71828_INT_BAT_OVER_CURR_1_RES,
|
||||
BD71828_INT_BAT_OVER_CURR_1_DET,
|
||||
BD71828_INT_BAT_OVER_CURR_2_RES,
|
||||
BD71828_INT_BAT_OVER_CURR_2_DET,
|
||||
BD71828_INT_BAT_OVER_CURR_3_RES,
|
||||
BD71828_INT_BAT_OVER_CURR_3_DET,
|
||||
/* Temperature */
|
||||
BD71828_INT_TEMP_BAT_LOW_RES,
|
||||
BD71828_INT_TEMP_BAT_LOW_DET,
|
||||
BD71828_INT_TEMP_BAT_HI_RES,
|
||||
BD71828_INT_TEMP_BAT_HI_DET,
|
||||
BD71828_INT_TEMP_CHIP_OVER_125_RES,
|
||||
BD71828_INT_TEMP_CHIP_OVER_125_DET,
|
||||
BD71828_INT_TEMP_CHIP_OVER_VF_DET,
|
||||
BD71828_INT_TEMP_CHIP_OVER_VF_RES,
|
||||
/* RTC Alarm */
|
||||
BD71828_INT_RTC0,
|
||||
BD71828_INT_RTC1,
|
||||
BD71828_INT_RTC2,
|
||||
};
|
||||
|
||||
#define BD71828_INT_BUCK1_OCP_MASK 0x1
|
||||
#define BD71828_INT_BUCK2_OCP_MASK 0x2
|
||||
#define BD71828_INT_BUCK3_OCP_MASK 0x4
|
||||
#define BD71828_INT_BUCK4_OCP_MASK 0x8
|
||||
#define BD71828_INT_BUCK5_OCP_MASK 0x10
|
||||
#define BD71828_INT_BUCK6_OCP_MASK 0x20
|
||||
#define BD71828_INT_BUCK7_OCP_MASK 0x40
|
||||
#define BD71828_INT_PGFAULT_MASK 0x80
|
||||
|
||||
#define BD71828_INT_DCIN_DET_MASK 0x1
|
||||
#define BD71828_INT_DCIN_RMV_MASK 0x2
|
||||
#define BD71828_INT_CLPS_OUT_MASK 0x4
|
||||
#define BD71828_INT_CLPS_IN_MASK 0x8
|
||||
/* DCIN2 interrupts */
|
||||
#define BD71828_INT_DCIN_MON_RES_MASK 0x1
|
||||
#define BD71828_INT_DCIN_MON_DET_MASK 0x2
|
||||
#define BD71828_INT_LONGPUSH_MASK 0x4
|
||||
#define BD71828_INT_MIDPUSH_MASK 0x8
|
||||
#define BD71828_INT_SHORTPUSH_MASK 0x10
|
||||
#define BD71828_INT_PUSH_MASK 0x20
|
||||
#define BD71828_INT_WDOG_MASK 0x40
|
||||
#define BD71828_INT_SWRESET_MASK 0x80
|
||||
/* Vsys */
|
||||
#define BD71828_INT_VSYS_UV_RES_MASK 0x1
|
||||
#define BD71828_INT_VSYS_UV_DET_MASK 0x2
|
||||
#define BD71828_INT_VSYS_LOW_RES_MASK 0x4
|
||||
#define BD71828_INT_VSYS_LOW_DET_MASK 0x8
|
||||
#define BD71828_INT_VSYS_HALL_IN_MASK 0x10
|
||||
#define BD71828_INT_VSYS_HALL_TOGGLE_MASK 0x20
|
||||
#define BD71828_INT_VSYS_MON_RES_MASK 0x40
|
||||
#define BD71828_INT_VSYS_MON_DET_MASK 0x80
|
||||
/* Charger */
|
||||
#define BD71828_INT_CHG_DCIN_ILIM_MASK 0x1
|
||||
#define BD71828_INT_CHG_TOPOFF_TO_DONE_MASK 0x2
|
||||
#define BD71828_INT_CHG_WDG_TEMP_MASK 0x4
|
||||
#define BD71828_INT_CHG_WDG_TIME_MASK 0x8
|
||||
#define BD71828_INT_CHG_RECHARGE_RES_MASK 0x10
|
||||
#define BD71828_INT_CHG_RECHARGE_DET_MASK 0x20
|
||||
#define BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK 0x40
|
||||
#define BD71828_INT_CHG_STATE_TRANSITION_MASK 0x80
|
||||
/* Battery */
|
||||
#define BD71828_INT_BAT_TEMP_NORMAL_MASK 0x1
|
||||
#define BD71828_INT_BAT_TEMP_ERANGE_MASK 0x2
|
||||
#define BD71828_INT_BAT_TEMP_WARN_MASK 0x4
|
||||
#define BD71828_INT_BAT_REMOVED_MASK 0x10
|
||||
#define BD71828_INT_BAT_DETECTED_MASK 0x20
|
||||
#define BD71828_INT_THERM_REMOVED_MASK 0x40
|
||||
#define BD71828_INT_THERM_DETECTED_MASK 0x80
|
||||
/* Battery Mon 1 */
|
||||
#define BD71828_INT_BAT_DEAD_MASK 0x2
|
||||
#define BD71828_INT_BAT_SHORTC_RES_MASK 0x4
|
||||
#define BD71828_INT_BAT_SHORTC_DET_MASK 0x8
|
||||
#define BD71828_INT_BAT_LOW_VOLT_RES_MASK 0x10
|
||||
#define BD71828_INT_BAT_LOW_VOLT_DET_MASK 0x20
|
||||
#define BD71828_INT_BAT_OVER_VOLT_RES_MASK 0x40
|
||||
#define BD71828_INT_BAT_OVER_VOLT_DET_MASK 0x80
|
||||
/* Battery Mon 2 */
|
||||
#define BD71828_INT_BAT_MON_RES_MASK 0x1
|
||||
#define BD71828_INT_BAT_MON_DET_MASK 0x2
|
||||
/* Battery Mon 3 (Coulomb counter) */
|
||||
#define BD71828_INT_BAT_CC_MON1_MASK 0x1
|
||||
#define BD71828_INT_BAT_CC_MON2_MASK 0x2
|
||||
#define BD71828_INT_BAT_CC_MON3_MASK 0x4
|
||||
/* Battery Mon 4 */
|
||||
#define BD71828_INT_BAT_OVER_CURR_1_RES_MASK 0x1
|
||||
#define BD71828_INT_BAT_OVER_CURR_1_DET_MASK 0x2
|
||||
#define BD71828_INT_BAT_OVER_CURR_2_RES_MASK 0x4
|
||||
#define BD71828_INT_BAT_OVER_CURR_2_DET_MASK 0x8
|
||||
#define BD71828_INT_BAT_OVER_CURR_3_RES_MASK 0x10
|
||||
#define BD71828_INT_BAT_OVER_CURR_3_DET_MASK 0x20
|
||||
/* Temperature */
|
||||
#define BD71828_INT_TEMP_BAT_LOW_RES_MASK 0x1
|
||||
#define BD71828_INT_TEMP_BAT_LOW_DET_MASK 0x2
|
||||
#define BD71828_INT_TEMP_BAT_HI_RES_MASK 0x4
|
||||
#define BD71828_INT_TEMP_BAT_HI_DET_MASK 0x8
|
||||
#define BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK 0x10
|
||||
#define BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK 0x20
|
||||
#define BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK 0x40
|
||||
#define BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK 0x80
|
||||
/* RTC Alarm */
|
||||
#define BD71828_INT_RTC0_MASK 0x1
|
||||
#define BD71828_INT_RTC1_MASK 0x2
|
||||
#define BD71828_INT_RTC2_MASK 0x4
|
||||
|
||||
#define BD71828_OUT_TYPE_MASK 0x2
|
||||
#define BD71828_OUT_TYPE_OPEN_DRAIN 0x0
|
||||
#define BD71828_OUT_TYPE_CMOS 0x2
|
||||
|
||||
#endif /* __LINUX_MFD_BD71828_H__ */
|
@ -191,12 +191,6 @@ enum {
|
||||
#define IRQ_ON_REQ 0x02
|
||||
#define IRQ_STBY_REQ 0x01
|
||||
|
||||
/* BD718XX_REG_OUT32K bits */
|
||||
#define BD718XX_OUT32K_EN 0x01
|
||||
|
||||
/* BD7183XX gated clock rate */
|
||||
#define BD718XX_CLK_RATE 32768
|
||||
|
||||
/* ROHM BD718XX irqs */
|
||||
enum {
|
||||
BD718XX_INT_STBY_REQ,
|
||||
|
@ -4,17 +4,83 @@
|
||||
#ifndef __LINUX_MFD_ROHM_H__
|
||||
#define __LINUX_MFD_ROHM_H__
|
||||
|
||||
enum {
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
enum rohm_chip_type {
|
||||
ROHM_CHIP_TYPE_BD71837 = 0,
|
||||
ROHM_CHIP_TYPE_BD71847,
|
||||
ROHM_CHIP_TYPE_BD70528,
|
||||
ROHM_CHIP_TYPE_BD71828,
|
||||
ROHM_CHIP_TYPE_AMOUNT
|
||||
};
|
||||
|
||||
struct rohm_regmap_dev {
|
||||
unsigned int chip_type;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
enum {
|
||||
ROHM_DVS_LEVEL_UNKNOWN,
|
||||
ROHM_DVS_LEVEL_RUN,
|
||||
ROHM_DVS_LEVEL_IDLE,
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
ROHM_DVS_LEVEL_LPSR,
|
||||
ROHM_DVS_LEVEL_MAX = ROHM_DVS_LEVEL_LPSR,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rohm_dvs_config - dynamic voltage scaling register descriptions
|
||||
*
|
||||
* @level_map: bitmap representing supported run-levels for this
|
||||
* regulator
|
||||
* @run_reg: register address for regulator config at 'run' state
|
||||
* @run_mask: value mask for regulator voltages at 'run' state
|
||||
* @run_on_mask: enable mask for regulator at 'run' state
|
||||
* @idle_reg: register address for regulator config at 'idle' state
|
||||
* @idle_mask: value mask for regulator voltages at 'idle' state
|
||||
* @idle_on_mask: enable mask for regulator at 'idle' state
|
||||
* @suspend_reg: register address for regulator config at 'suspend' state
|
||||
* @suspend_mask: value mask for regulator voltages at 'suspend' state
|
||||
* @suspend_on_mask: enable mask for regulator at 'suspend' state
|
||||
* @lpsr_reg: register address for regulator config at 'lpsr' state
|
||||
* @lpsr_mask: value mask for regulator voltages at 'lpsr' state
|
||||
* @lpsr_on_mask: enable mask for regulator at 'lpsr' state
|
||||
*
|
||||
* Description of ROHM PMICs voltage configuration registers for different
|
||||
* system states. This is used to correctly configure the PMIC at startup
|
||||
* based on values read from DT.
|
||||
*/
|
||||
struct rohm_dvs_config {
|
||||
uint64_t level_map;
|
||||
unsigned int run_reg;
|
||||
unsigned int run_mask;
|
||||
unsigned int run_on_mask;
|
||||
unsigned int idle_reg;
|
||||
unsigned int idle_mask;
|
||||
unsigned int idle_on_mask;
|
||||
unsigned int suspend_reg;
|
||||
unsigned int suspend_mask;
|
||||
unsigned int suspend_on_mask;
|
||||
unsigned int lpsr_reg;
|
||||
unsigned int lpsr_mask;
|
||||
unsigned int lpsr_on_mask;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_REGULATOR_ROHM)
|
||||
int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
|
||||
struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regmap *regmap);
|
||||
|
||||
#else
|
||||
static inline int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
|
||||
struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
21
include/linux/mfd/rohm-shared.h
Normal file
21
include/linux/mfd/rohm-shared.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2020 ROHM Semiconductors */
|
||||
|
||||
|
||||
#ifndef __LINUX_MFD_ROHM_SHARED_H__
|
||||
#define __LINUX_MFD_ROHM_SHARED_H__
|
||||
|
||||
/* RTC definitions shared between BD70528 and BD71828 */
|
||||
|
||||
#define BD70528_MASK_RTC_SEC 0x7f
|
||||
#define BD70528_MASK_RTC_MINUTE 0x7f
|
||||
#define BD70528_MASK_RTC_HOUR_24H 0x80
|
||||
#define BD70528_MASK_RTC_HOUR_PM 0x20
|
||||
#define BD70528_MASK_RTC_HOUR 0x3f
|
||||
#define BD70528_MASK_RTC_DAY 0x3f
|
||||
#define BD70528_MASK_RTC_WEEK 0x07
|
||||
#define BD70528_MASK_RTC_MONTH 0x1f
|
||||
#define BD70528_MASK_RTC_YEAR 0xff
|
||||
#define BD70528_MASK_ALM_EN 0x7
|
||||
|
||||
#endif /* __LINUX_MFD_ROHM_SHARED_H__ */
|
Loading…
Reference in New Issue
Block a user