forked from Minki/linux
- Core Frameworks
- Set 'struct device' fwnode when registering a new device - New Drivers - Add support for ROHM BD70528 PMIC - New Device Support - Add support for LP87561 4-Phase Regulator to TI LP87565 PMIC - Add support for RK809 and RK817 to Rockchip RK808 - Add support for Lid Angle to ChromeOS core - Add support for CS47L15 CODEC to Madera core - Add support for CS47L92 CODEC to Madera core - Add support for ChromeOS (legacy) Accelerometers in ChromeOS core - Add support for Add Intel Elkhart Lake PCH to Intel LPSS - New Functionality - Provide regulator supply information when registering; madera-core - Additional Device Tree support; lp87565, madera, cros-ec, rohm,bd71837-pmic - Allow over-riding power button press via Device Tree; rohm-bd718x7 - Differentiate between running processors; cros_ec_dev - Fix-ups - Big header file update; cros_ec_commands.h - Split header per-subsystem; rohm-bd718x7 - Remove superfluous code; menelaus, cs5535-mfd, cs47lXX-tables - Trivial; sorting, coding style; intel-lpss-pci - Only remove Power Off functionality if set locally; rk808 - Make use for Power Off Prepare(); rk808 - Fix spelling mistake in header guards; stmfx - Properly free IDA resources - SPDX fixups; cs47lXX-tables, madera - Error path fixups; hi655x-pmic - Bug Fixes - Add missing break in case() statement - Repair undefined behaviour when not initialising variables; arizona-core, madera-core - Fix reference to Device Tree documentation; madera -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAl0sLxgACgkQUa+KL4f8 d2E25Q/9HmDJIdfyDQg0xv5IM5HS1WsP9BcJCEgoRIsad4mMDRYt+ZeLbslwMhue E9tsFH359gGvyqR+7d6hPpEUET1UEcJy4eRD1zAc0+epllQTDHSy8oHt1dtH+8xB 2AU5rvAKOqBk83D+V2Hkx2KcroWEQQNYIoR9/12Pi3xmEB1uaCO0/Ajd3B28bIBM Tzi3cVQ3U7jY9EIM44GVTsjDAbMSkQR0iab6cQF0vJAWaUmGKlsO7iRrU1XkN69V qXyBauI8WGiGssihrE8r+jYvHvmg7hA9OKZIckUaMXD/k7kpHbwIaFRh7gukq4Re Q6Cy30NfVJ1tY66/5oqN6gj5znfeuEudMCCzYAkzlROSp5eApe2Ke5ajYn3kOCZd ZKcsrw9Fiox1lKmuWXDbyf0nqf4zwdDPAnShRWaaF5aipwgywyGcwSigVtK4F0P5 Hjc5RLv7GjTAJq+ZzwgKyAdtx8L0mhdLd1ZTQpEXk/g/E9dW4GF72hWj9TQ/9BnA ZflKv8aP3lDGRHgO3Huwi4lMzskB8BVCQMCFwLwGs5cY1oZQhAjTdJzBZjTGexhC evuuA8OUsCrOWMvnZf3saSdHJ1iMHtfPnqEGHRJQtNj4fFaXv80LasIomvvfJc1/ 9JlRyAgm2pF7YDrgTh65ZzBb324eKSZZoAj9XZbnTyzxUAcF69A= =A3jw -----END PGP SIGNATURE----- Merge tag 'mfd-next-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd Pull MFD updates from Lee Jones: "Core Frameworks: - Set 'struct device' fwnode when registering a new device New Drivers: - Add support for ROHM BD70528 PMIC New Device Support: - Add support for LP87561 4-Phase Regulator to TI LP87565 PMIC - Add support for RK809 and RK817 to Rockchip RK808 - Add support for Lid Angle to ChromeOS core - Add support for CS47L15 CODEC to Madera core - Add support for CS47L92 CODEC to Madera core - Add support for ChromeOS (legacy) Accelerometers in ChromeOS core - Add support for Add Intel Elkhart Lake PCH to Intel LPSS New Functionality: - Provide regulator supply information when registering; madera-core - Additional Device Tree support; lp87565, madera, cros-ec, rohm,bd71837-pmic - Allow over-riding power button press via Device Tree; rohm-bd718x7 - Differentiate between running processors; cros_ec_dev Fix-ups: - Big header file update; cros_ec_commands.h - Split header per-subsystem; rohm-bd718x7 - Remove superfluous code; menelaus, cs5535-mfd, cs47lXX-tables - Trivial; sorting, coding style; intel-lpss-pci - Only remove Power Off functionality if set locally; rk808 - Make use for Power Off Prepare(); rk808 - Fix spelling mistake in header guards; stmfx - Properly free IDA resources - SPDX fixups; cs47lXX-tables, madera - Error path fixups; hi655x-pmic Bug Fixes: - Add missing break in case() statement - Repair undefined behaviour when not initialising variables; arizona-core, madera-core - Fix reference to Device Tree documentation; madera" * tag 'mfd-next-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (45 commits) mfd: hi655x-pmic: Fix missing return value check for devm_regmap_init_mmio_clk mfd: madera: Fixup SPDX headers mfd: madera: Remove some unused registers and fix some defaults mfd: intel-lpss: Release IDA resources mfd: intel-lpss: Add Intel Elkhart Lake PCH PCI IDs mfd: cs5535-mfd: Remove ifdef OLPC noise mfd: stmfx: Fix macro definition spelling dt-bindings: mfd: Add link to ROHM BD71847 Datasheet MAINAINERS: Swap words in INTEL PMIC MULTIFUNCTION DEVICE DRIVERS mfd: cros_ec_dev: Register cros_ec_accel_legacy driver as a subdevice mfd: rk808: Prepare rk805 for poweroff mfd: rk808: Check pm_power_off pointer mfd: cros_ec: differentiate SCP from EC by feature bit dt-bindings: Add binding for cros-ec-rpmsg mfd: madera: Add Madera core support for CS47L92 mfd: madera: Add Madera core support for CS47L15 mfd: madera: Update DT bindings to add additional CODECs mfd: madera: Add supply mapping for MICVDD mfd: madera: Fix potential uninitialised use of variable mfd: madera: Fix bad reference to pinctrl.txt file ...
This commit is contained in:
commit
8de262531f
@ -3,7 +3,7 @@ ChromeOS Embedded Controller
|
||||
Google's ChromeOS EC is a Cortex-M device which talks to the AP and
|
||||
implements various function such as keyboard and battery charging.
|
||||
|
||||
The EC can be connect through various means (I2C, SPI, LPC) and the
|
||||
The EC can be connect through various means (I2C, SPI, LPC, RPMSG) and the
|
||||
compatible string used depends on the interface. Each connection method has
|
||||
its own driver which connects to the top level interface-agnostic EC driver.
|
||||
Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
|
||||
@ -17,6 +17,9 @@ Required properties (SPI):
|
||||
- compatible: "google,cros-ec-spi"
|
||||
- reg: SPI chip select
|
||||
|
||||
Required properties (RPMSG):
|
||||
- compatible: "google,cros-ec-rpmsg"
|
||||
|
||||
Optional properties (SPI):
|
||||
- google,cros-ec-spi-pre-delay: Some implementations of the EC need a little
|
||||
time to wake up from sleep before they can receive SPI transfers at a high
|
||||
|
@ -41,3 +41,39 @@ lp87565_pmic: pmic@60 {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
TI LP87561 PMIC:
|
||||
|
||||
This is a single output 4-phase regulator configuration
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,lp87561-q1"
|
||||
- reg: I2C slave address.
|
||||
- gpio-controller: Marks the device node as a GPIO Controller.
|
||||
- #gpio-cells: Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify flags.
|
||||
See ../gpio/gpio.txt for more information.
|
||||
- xxx-in-supply: Phandle to parent supply node of each regulator
|
||||
populated under regulators node. xxx should match
|
||||
the supply_name populated in driver.
|
||||
Example:
|
||||
|
||||
lp87561_pmic: pmic@62 {
|
||||
compatible = "ti,lp87561-q1";
|
||||
reg = <0x62>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
buck3210-in-supply = <&vsys_3v3>;
|
||||
|
||||
regulators: regulators {
|
||||
buck3210_reg: buck3210 {
|
||||
/* VDD_CORE */
|
||||
regulator-name = "buck3210";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -11,10 +11,14 @@ bindings/sound/madera.txt
|
||||
Required properties:
|
||||
|
||||
- compatible : One of the following chip-specific strings:
|
||||
"cirrus,cs47l15"
|
||||
"cirrus,cs47l35"
|
||||
"cirrus,cs47l85"
|
||||
"cirrus,cs47l90"
|
||||
"cirrus,cs47l91"
|
||||
"cirrus,cs42l92"
|
||||
"cirrus,cs47l92"
|
||||
"cirrus,cs47l93"
|
||||
"cirrus,wm1840"
|
||||
|
||||
- reg : I2C slave address when connected using I2C, chip select number when
|
||||
@ -22,7 +26,7 @@ Required properties:
|
||||
|
||||
- DCVDD-supply : Power supply for the device as defined in
|
||||
bindings/regulator/regulator.txt
|
||||
Mandatory on CS47L35, CS47L90, CS47L91
|
||||
Mandatory on CS47L15, CS47L35, CS47L90, CS47L91, CS42L92, CS47L92, CS47L93
|
||||
Optional on CS47L85, WM1840
|
||||
|
||||
- AVDD-supply, DBVDD1-supply, DBVDD2-supply, CPVDD1-supply, CPVDD2-supply :
|
||||
@ -35,7 +39,7 @@ Required properties:
|
||||
(CS47L85, WM1840)
|
||||
|
||||
- SPKVDD-supply : Power supply for the device
|
||||
(CS47L35)
|
||||
(CS47L15, CS47L35)
|
||||
|
||||
- interrupt-controller : Indicates that this device is an interrupt controller
|
||||
|
||||
|
@ -3,11 +3,15 @@ RK8XX Power Management Integrated Circuit
|
||||
The rk8xx family current members:
|
||||
rk805
|
||||
rk808
|
||||
rk809
|
||||
rk817
|
||||
rk818
|
||||
|
||||
Required properties:
|
||||
- compatible: "rockchip,rk805"
|
||||
- compatible: "rockchip,rk808"
|
||||
- compatible: "rockchip,rk809"
|
||||
- compatible: "rockchip,rk817"
|
||||
- compatible: "rockchip,rk818"
|
||||
- reg: I2C slave address
|
||||
- interrupts: the interrupt outputs of the controller.
|
||||
@ -45,6 +49,23 @@ Optional RK808 properties:
|
||||
the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
|
||||
very quickly with no slow ramp time.
|
||||
|
||||
Optional shared RK809 and RK817 properties:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
- vcc2-supply: The input supply for DCDC_REG2
|
||||
- vcc3-supply: The input supply for DCDC_REG3
|
||||
- vcc4-supply: The input supply for DCDC_REG4
|
||||
- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3
|
||||
- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6
|
||||
- vcc7-supply: The input supply for LDO_REG7, LDO_REG8, LDO_REG9
|
||||
|
||||
Optional RK809 properties:
|
||||
- vcc8-supply: The input supply for SWITCH_REG1
|
||||
- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2
|
||||
|
||||
Optional RK817 properties:
|
||||
- vcc8-supply: The input supply for BOOST
|
||||
- vcc9-supply: The input supply for OTG_SWITCH
|
||||
|
||||
Optional RK818 properties:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
- vcc2-supply: The input supply for DCDC_REG2
|
||||
@ -86,6 +107,21 @@ number as described in RK808 datasheet.
|
||||
- SWITCH_REGn
|
||||
- valid values for n are 1 to 2
|
||||
|
||||
Following regulators of the RK809 and RK817 PMIC blocks are supported. Note that
|
||||
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
|
||||
number as described in RK809 and RK817 datasheets.
|
||||
|
||||
- DCDC_REGn
|
||||
- valid values for n are 1 to 5 for RK809.
|
||||
- valid values for n are 1 to 4 for RK817.
|
||||
- LDO_REGn
|
||||
- valid values for n are 1 to 9 for RK809.
|
||||
- valid values for n are 1 to 9 for RK817.
|
||||
- SWITCH_REGn
|
||||
- valid values for n are 1 to 2 for RK809.
|
||||
- BOOST for RK817
|
||||
- OTG_SWITCH for RK817
|
||||
|
||||
Following regulators of the RK818 PMIC block are supported. Note that
|
||||
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
|
||||
number as described in RK818 datasheet.
|
||||
@ -98,6 +134,14 @@ number as described in RK818 datasheet.
|
||||
- HDMI_SWITCH
|
||||
- OTG_SWITCH
|
||||
|
||||
It is necessary to configure three pins for both the RK809 and RK817, the three
|
||||
pins are "gpio_ts" "gpio_gt" "gpio_slp".
|
||||
The gpio_gt and gpio_ts pins support the gpio function.
|
||||
The gpio_slp pin is for controlling the pmic states, as below:
|
||||
- reset
|
||||
- power down
|
||||
- sleep
|
||||
|
||||
Standard regulator bindings are used inside regulator subnodes. Check
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
for more details
|
||||
|
102
Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
Normal file
102
Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
Normal file
@ -0,0 +1,102 @@
|
||||
* ROHM BD70528 Power Management Integrated Circuit bindings
|
||||
|
||||
BD70528MWV is an ultra-low quiescent current general purpose, single-chip,
|
||||
power management IC for battery-powered portable devices. The IC
|
||||
integrates 3 ultra-low current consumption buck converters, 3 LDOs and 2
|
||||
LED Drivers. Also included are 4 GPIOs, a real-time clock (RTC), a 32kHz
|
||||
clock gate, high-accuracy VREF for use with an external ADC, flexible
|
||||
dual-input power path, 10 bit SAR ADC for battery temperature monitor and
|
||||
1S battery charger with scalable charge currents.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "rohm,bd70528"
|
||||
- reg : I2C slave address.
|
||||
- interrupts : The interrupt line the device is connected to.
|
||||
- interrupt-controller : To indicate BD70528 acts as an interrupt controller.
|
||||
- #interrupt-cells : Should be 2. Usage is compliant to the 2 cells
|
||||
variant of ../interrupt-controller/interrupts.txt
|
||||
- gpio-controller : To indicate BD70528 acts as a GPIO controller.
|
||||
- #gpio-cells : Should be 2. The first cell is the pin number and
|
||||
the second cell is used to specify flags. See
|
||||
../gpio/gpio.txt for more information.
|
||||
- #clock-cells : Should be 0.
|
||||
- regulators: : List of child nodes that specify the regulators.
|
||||
Please see ../regulator/rohm,bd70528-regulator.txt
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names : Should contain name for output clock.
|
||||
|
||||
Example:
|
||||
/* External oscillator */
|
||||
osc: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <1>;
|
||||
clock-frequency = <32768>;
|
||||
clock-output-names = "osc";
|
||||
};
|
||||
|
||||
pmic: pmic@4b {
|
||||
compatible = "rohm,bd70528";
|
||||
reg = <0x4b>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 GPIO_ACTIVE_LOW>;
|
||||
clocks = <&osc 0>;
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "bd70528-32k-out";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
regulators {
|
||||
buck1: BUCK1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3400000>;
|
||||
regulator-boot-on;
|
||||
regulator-ramp-delay = <125>;
|
||||
};
|
||||
buck2: BUCK2 {
|
||||
regulator-name = "buck2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-ramp-delay = <125>;
|
||||
};
|
||||
buck3: BUCK3 {
|
||||
regulator-name = "buck3";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-ramp-delay = <250>;
|
||||
};
|
||||
ldo1: LDO1 {
|
||||
regulator-name = "ldo1";
|
||||
regulator-min-microvolt = <1650000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
ldo2: LDO2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = <1650000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
ldo3: LDO3 {
|
||||
regulator-name = "ldo3";
|
||||
regulator-min-microvolt = <1650000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
led_ldo1: LED_LDO1 {
|
||||
regulator-name = "led_ldo1";
|
||||
regulator-min-microvolt = <200000>;
|
||||
regulator-max-microvolt = <300000>;
|
||||
};
|
||||
led_ldo2: LED_LDO2 {
|
||||
regulator-name = "led_ldo2";
|
||||
regulator-min-microvolt = <200000>;
|
||||
regulator-max-microvolt = <300000>;
|
||||
};
|
||||
};
|
||||
};
|
@ -8,6 +8,8 @@ and 6 LDOs.
|
||||
|
||||
Datasheet for BD71837 is available at:
|
||||
https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
|
||||
Datasheet for BD71847 is available at:
|
||||
https://www.rohm.com/datasheet/BD71847AMWV/bd71847amwv-e
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "rohm,bd71837" for bd71837
|
||||
@ -38,6 +40,14 @@ target state is set to READY by default. If SNVS state is used the boot
|
||||
crucial regulators must have the regulator-always-on and regulator-boot-on
|
||||
properties set in regulator node.
|
||||
|
||||
- rohm,short-press-ms : Short press duration in milliseconds
|
||||
- rohm,long-press-ms : Long press duration in milliseconds
|
||||
|
||||
Configure the "short press" and "long press" timers for the power button.
|
||||
Values are rounded to what hardware supports (500ms multiple for short and
|
||||
1000ms multiple for long). If these properties are not present the existing
|
||||
configuration (from bootloader or OTP) is not touched.
|
||||
|
||||
Example:
|
||||
|
||||
/* external oscillator node */
|
||||
|
@ -8222,7 +8222,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
|
||||
F: drivers/gpio/gpio-*cove.c
|
||||
F: drivers/gpio/gpio-msic.c
|
||||
|
||||
INTEL MULTIFUNCTION PMIC DEVICE DRIVERS
|
||||
INTEL PMIC MULTIFUNCTION DEVICE DRIVERS
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
S: Maintained
|
||||
F: drivers/mfd/intel_msic.c
|
||||
|
@ -53,13 +53,12 @@ config COMMON_CLK_MAX9485
|
||||
This driver supports Maxim 9485 Programmable Audio Clock Generator
|
||||
|
||||
config COMMON_CLK_RK808
|
||||
tristate "Clock driver for RK805/RK808/RK818"
|
||||
tristate "Clock driver for RK805/RK808/RK809/RK817/RK818"
|
||||
depends on MFD_RK808
|
||||
---help---
|
||||
This driver supports RK805, RK808 and RK818 crystal oscillator clock. These
|
||||
multi-function devices have two fixed-rate oscillators,
|
||||
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
|
||||
by control register.
|
||||
This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock.
|
||||
These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
|
||||
Clkout1 is always on, Clkout2 can off by control register.
|
||||
|
||||
config COMMON_CLK_HI655X
|
||||
tristate "Clock driver for Hi655x" if EXPERT
|
||||
@ -293,10 +292,10 @@ config COMMON_CLK_STM32H7
|
||||
|
||||
config COMMON_CLK_BD718XX
|
||||
tristate "Clock driver for ROHM BD718x7 PMIC"
|
||||
depends on MFD_ROHM_BD718XX
|
||||
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528
|
||||
help
|
||||
This driver supports ROHM BD71837 and ROHM BD71847
|
||||
PMICs clock gates.
|
||||
This driver supports ROHM BD71837, ROHM BD71847 and
|
||||
ROHM BD70528 PMICs clock gates.
|
||||
|
||||
config COMMON_CLK_FIXED_MMIO
|
||||
bool "Clock driver for Memory Mapped Fixed values"
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/rohm-bd718x7.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -17,7 +18,7 @@ struct bd718xx_clk {
|
||||
u8 reg;
|
||||
u8 mask;
|
||||
struct platform_device *pdev;
|
||||
struct bd718xx *mfd;
|
||||
struct rohm_regmap_dev *mfd;
|
||||
};
|
||||
|
||||
static int bd71837_clk_set(struct clk_hw *hw, int status)
|
||||
@ -68,7 +69,7 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
int rval = -ENOMEM;
|
||||
const char *parent_clk;
|
||||
struct device *parent = pdev->dev.parent;
|
||||
struct bd718xx *mfd = dev_get_drvdata(parent);
|
||||
struct rohm_regmap_dev *mfd = dev_get_drvdata(parent);
|
||||
struct clk_init_data init = {
|
||||
.name = "bd718xx-32k-out",
|
||||
.ops = &bd71837_clk_ops,
|
||||
@ -86,9 +87,20 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "No parent clk found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
c->reg = BD718XX_REG_OUT32K;
|
||||
c->mask = BD718XX_OUT32K_EN;
|
||||
switch (mfd->chip_type) {
|
||||
case ROHM_CHIP_TYPE_BD71837:
|
||||
case ROHM_CHIP_TYPE_BD71847:
|
||||
c->reg = BD718XX_REG_OUT32K;
|
||||
c->mask = BD718XX_OUT32K_EN;
|
||||
break;
|
||||
case ROHM_CHIP_TYPE_BD70528:
|
||||
c->reg = BD70528_REG_CLK_OUT;
|
||||
c->mask = BD70528_CLK_OUT_EN_MASK;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown clk chip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
c->mfd = mfd;
|
||||
c->pdev = pdev;
|
||||
c->hw.init = &init;
|
||||
@ -119,5 +131,5 @@ static struct platform_driver bd71837_clk = {
|
||||
module_platform_driver(bd71837_clk);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD71837 chip clk driver");
|
||||
MODULE_DESCRIPTION("BD71837/BD71847/BD70528 chip clk driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -88,6 +88,68 @@ of_clk_rk808_get(struct of_phandle_args *clkspec, void *data)
|
||||
return idx ? &rk808_clkout->clkout2_hw : &rk808_clkout->clkout1_hw;
|
||||
}
|
||||
|
||||
static int rk817_clkout2_enable(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct rk808_clkout *rk808_clkout = container_of(hw,
|
||||
struct rk808_clkout,
|
||||
clkout2_hw);
|
||||
struct rk808 *rk808 = rk808_clkout->rk808;
|
||||
|
||||
return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1),
|
||||
RK817_CLK32KOUT2_EN,
|
||||
enable ? RK817_CLK32KOUT2_EN : 0);
|
||||
}
|
||||
|
||||
static int rk817_clkout2_prepare(struct clk_hw *hw)
|
||||
{
|
||||
return rk817_clkout2_enable(hw, true);
|
||||
}
|
||||
|
||||
static void rk817_clkout2_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
rk817_clkout2_enable(hw, false);
|
||||
}
|
||||
|
||||
static int rk817_clkout2_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct rk808_clkout *rk808_clkout = container_of(hw,
|
||||
struct rk808_clkout,
|
||||
clkout2_hw);
|
||||
struct rk808 *rk808 = rk808_clkout->rk808;
|
||||
unsigned int val;
|
||||
|
||||
int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val);
|
||||
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
return (val & RK817_CLK32KOUT2_EN) ? 1 : 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops rk817_clkout2_ops = {
|
||||
.prepare = rk817_clkout2_prepare,
|
||||
.unprepare = rk817_clkout2_unprepare,
|
||||
.is_prepared = rk817_clkout2_is_prepared,
|
||||
.recalc_rate = rk808_clkout_recalc_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops *rkpmic_get_ops(long variant)
|
||||
{
|
||||
switch (variant) {
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
return &rk817_clkout2_ops;
|
||||
/*
|
||||
* For the default case, it match the following PMIC type.
|
||||
* RK805_ID
|
||||
* RK808_ID
|
||||
* RK818_ID
|
||||
*/
|
||||
default:
|
||||
return &rk808_clkout2_ops;
|
||||
}
|
||||
}
|
||||
|
||||
static int rk808_clkout_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -119,7 +181,7 @@ static int rk808_clkout_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
init.name = "rk808-clkout2";
|
||||
init.ops = &rk808_clkout2_ops;
|
||||
init.ops = rkpmic_get_ops(rk808->variant);
|
||||
rk808_clkout->clkout2_hw.init = &init;
|
||||
|
||||
/* optional override of the clockname */
|
||||
|
@ -975,6 +975,17 @@ config GPIO_ARIZONA
|
||||
help
|
||||
Support for GPIOs on Wolfson Arizona class devices.
|
||||
|
||||
config GPIO_BD70528
|
||||
tristate "ROHM BD70528 GPIO support"
|
||||
depends on MFD_ROHM_BD70528
|
||||
help
|
||||
Support for GPIOs on ROHM BD70528 PMIC. There are four GPIOs
|
||||
available on the ROHM PMIC in total. The GPIOs can also
|
||||
generate interrupts.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called gpio-bd70528.
|
||||
|
||||
config GPIO_BD9571MWV
|
||||
tristate "ROHM BD9571 GPIO support"
|
||||
depends on MFD_BD9571MWV
|
||||
|
@ -34,6 +34,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
|
||||
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
|
||||
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
|
||||
obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
|
||||
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
|
232
drivers/gpio/gpio-bd70528.c
Normal file
232
drivers/gpio/gpio-bd70528.c
Normal file
@ -0,0 +1,232 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2018 ROHM Semiconductors
|
||||
// gpio-bd70528.c ROHM BD70528MWV gpio driver
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + (offset) * 2)
|
||||
#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + (offset) * 2)
|
||||
|
||||
struct bd70528_gpio {
|
||||
struct rohm_regmap_dev chip;
|
||||
struct gpio_chip gpio;
|
||||
};
|
||||
|
||||
static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
|
||||
unsigned int offset, unsigned int debounce)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (debounce) {
|
||||
case 0:
|
||||
val = BD70528_DEBOUNCE_DISABLE;
|
||||
break;
|
||||
case 1 ... 15:
|
||||
val = BD70528_DEBOUNCE_15MS;
|
||||
break;
|
||||
case 16 ... 30:
|
||||
val = BD70528_DEBOUNCE_30MS;
|
||||
break;
|
||||
case 31 ... 50:
|
||||
val = BD70528_DEBOUNCE_50MS;
|
||||
break;
|
||||
default:
|
||||
dev_err(bdgpio->chip.dev,
|
||||
"Invalid debouce value %u\n", debounce);
|
||||
return -EINVAL;
|
||||
}
|
||||
return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
|
||||
BD70528_DEBOUNCE_MASK, val);
|
||||
}
|
||||
|
||||
static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
int val, ret;
|
||||
|
||||
/* Do we need to do something to IRQs here? */
|
||||
ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
|
||||
if (ret) {
|
||||
dev_err(bdgpio->chip.dev, "Could not read gpio direction\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !(val & BD70528_GPIO_OUT_EN_MASK);
|
||||
}
|
||||
|
||||
static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
switch (pinconf_to_config_param(config)) {
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
return regmap_update_bits(bdgpio->chip.regmap,
|
||||
GPIO_OUT_REG(offset),
|
||||
BD70528_GPIO_DRIVE_MASK,
|
||||
BD70528_GPIO_OPEN_DRAIN);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
return regmap_update_bits(bdgpio->chip.regmap,
|
||||
GPIO_OUT_REG(offset),
|
||||
BD70528_GPIO_DRIVE_MASK,
|
||||
BD70528_GPIO_PUSH_PULL);
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
return bd70528_set_debounce(bdgpio, offset,
|
||||
pinconf_to_config_argument(config));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
/* Do we need to do something to IRQs here? */
|
||||
return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
|
||||
BD70528_GPIO_OUT_EN_MASK,
|
||||
BD70528_GPIO_OUT_DISABLE);
|
||||
}
|
||||
|
||||
static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
int ret;
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO;
|
||||
|
||||
ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
|
||||
BD70528_GPIO_OUT_MASK, val);
|
||||
if (ret)
|
||||
dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value);
|
||||
}
|
||||
|
||||
static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
bd70528_gpio_set(chip, offset, value);
|
||||
return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
|
||||
BD70528_GPIO_OUT_EN_MASK,
|
||||
BD70528_GPIO_OUT_ENABLE);
|
||||
}
|
||||
|
||||
#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << (offset))
|
||||
|
||||
static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
|
||||
if (!ret)
|
||||
ret = !!(val & BD70528_GPIO_OUT_MASK);
|
||||
else
|
||||
dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val);
|
||||
|
||||
if (!ret)
|
||||
ret = !(val & GPIO_IN_STATE_MASK(offset));
|
||||
else
|
||||
dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
|
||||
|
||||
/*
|
||||
* There is a race condition where someone might be changing the
|
||||
* GPIO direction after we get it but before we read the value. But
|
||||
* application design where GPIO direction may be changed just when
|
||||
* we read GPIO value would be pointless as reader could not know
|
||||
* whether the returned high/low state is caused by input or output.
|
||||
* Or then there must be other ways to mitigate the issue. Thus
|
||||
* locking would make no sense.
|
||||
*/
|
||||
ret = bd70528_get_direction(chip, offset);
|
||||
if (ret == 0)
|
||||
ret = bd70528_gpio_get_o(bdgpio, offset);
|
||||
else if (ret == 1)
|
||||
ret = bd70528_gpio_get_i(bdgpio, offset);
|
||||
else
|
||||
dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd70528_gpio *bdgpio;
|
||||
struct rohm_regmap_dev *bd70528;
|
||||
int ret;
|
||||
|
||||
bd70528 = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!bd70528) {
|
||||
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 = "bd70528-gpio";
|
||||
bdgpio->gpio.owner = THIS_MODULE;
|
||||
bdgpio->gpio.get_direction = bd70528_get_direction;
|
||||
bdgpio->gpio.direction_input = bd70528_direction_input;
|
||||
bdgpio->gpio.direction_output = bd70528_direction_output;
|
||||
bdgpio->gpio.set_config = bd70528_gpio_set_config;
|
||||
bdgpio->gpio.can_sleep = true;
|
||||
bdgpio->gpio.get = bd70528_gpio_get;
|
||||
bdgpio->gpio.set = bd70528_gpio_set;
|
||||
bdgpio->gpio.ngpio = 4;
|
||||
bdgpio->gpio.base = -1;
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
bdgpio->gpio.of_node = pdev->dev.parent->of_node;
|
||||
#endif
|
||||
bdgpio->chip.regmap = bd70528->regmap;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio,
|
||||
bdgpio);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver bd70528_gpio = {
|
||||
.driver = {
|
||||
.name = "bd70528-gpio"
|
||||
},
|
||||
.probe = bd70528_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(bd70528_gpio);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD70528 voltage regulator driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -261,6 +261,13 @@ config MFD_MADERA_SPI
|
||||
Support for the Cirrus Logic Madera platform audio SoC
|
||||
core functionality controlled via SPI.
|
||||
|
||||
config MFD_CS47L15
|
||||
bool "Cirrus Logic CS47L15"
|
||||
select PINCTRL_CS47L15
|
||||
depends on MFD_MADERA
|
||||
help
|
||||
Support for Cirrus Logic CS47L15 Smart Codec
|
||||
|
||||
config MFD_CS47L35
|
||||
bool "Cirrus Logic CS47L35"
|
||||
select PINCTRL_CS47L35
|
||||
@ -282,6 +289,13 @@ config MFD_CS47L90
|
||||
help
|
||||
Support for Cirrus Logic CS47L90 and CS47L91 Smart Codecs
|
||||
|
||||
config MFD_CS47L92
|
||||
bool "Cirrus Logic CS47L92/93"
|
||||
select PINCTRL_CS47L92
|
||||
depends on MFD_MADERA
|
||||
help
|
||||
Support for Cirrus Logic CS42L92, CS47L92 and CS47L93 Smart Codecs
|
||||
|
||||
config MFD_ASIC3
|
||||
bool "Compaq ASIC3"
|
||||
depends on GPIOLIB && ARM
|
||||
@ -1031,14 +1045,14 @@ config MFD_RC5T583
|
||||
different functionality of the device.
|
||||
|
||||
config MFD_RK808
|
||||
tristate "Rockchip RK805/RK808/RK818 Power Management Chip"
|
||||
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
|
||||
depends on I2C && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
If you say yes here you get support for the RK805, RK808 and RK818
|
||||
Power Management chips.
|
||||
If you say yes here you get support for the RK805, RK808, RK809,
|
||||
RK817 and RK818 Power Management chips.
|
||||
This driver provides common support for accessing the device
|
||||
through I2C interface. The device supports multiple sub-devices
|
||||
including interrupts, RTC, LDO & DCDC regulators, and onkey.
|
||||
@ -1890,6 +1904,23 @@ config MFD_ROHM_BD718XX
|
||||
NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
|
||||
and emergency shut down as well as 32,768KHz clock output.
|
||||
|
||||
config MFD_ROHM_BD70528
|
||||
tristate "ROHM BD70528 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 BD70528 Power
|
||||
Management IC. BD71837 is general purpose single-chip power
|
||||
management IC for battery-powered portable devices. It contains
|
||||
3 ultra-low current consumption buck converters, 3 LDOs and 2 LED
|
||||
drivers. Also included are 4 GPIOs, a real-time clock (RTC), a 32kHz
|
||||
crystal oscillator, high-accuracy VREF for use with an external ADC,
|
||||
10 bits SAR ADC for battery temperature monitor and 1S battery
|
||||
charger.
|
||||
|
||||
config MFD_STM32_LPTIMER
|
||||
tristate "Support for STM32 Low-Power Timer"
|
||||
depends on (ARCH_STM32 && OF) || COMPILE_TEST
|
||||
|
@ -75,6 +75,9 @@ obj-$(CONFIG_MFD_WM8994) += wm8994.o
|
||||
obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o
|
||||
|
||||
madera-objs := madera-core.o
|
||||
ifeq ($(CONFIG_MFD_CS47L15),y)
|
||||
madera-objs += cs47l15-tables.o
|
||||
endif
|
||||
ifeq ($(CONFIG_MFD_CS47L35),y)
|
||||
madera-objs += cs47l35-tables.o
|
||||
endif
|
||||
@ -84,6 +87,9 @@ endif
|
||||
ifeq ($(CONFIG_MFD_CS47L90),y)
|
||||
madera-objs += cs47l90-tables.o
|
||||
endif
|
||||
ifeq ($(CONFIG_MFD_CS47L92),y)
|
||||
madera-objs += cs47l92-tables.o
|
||||
endif
|
||||
obj-$(CONFIG_MFD_MADERA) += madera.o
|
||||
obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o
|
||||
obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o
|
||||
@ -247,5 +253,7 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
|
||||
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_BD718XX) += rohm-bd718x7.o
|
||||
obj-$(CONFIG_MFD_STMFX) += stmfx.o
|
||||
|
||||
|
@ -993,7 +993,7 @@ int arizona_dev_init(struct arizona *arizona)
|
||||
unsigned int reg, val;
|
||||
int (*apply_patch)(struct arizona *) = NULL;
|
||||
const struct mfd_cell *subdevs = NULL;
|
||||
int n_subdevs, ret, i;
|
||||
int n_subdevs = 0, ret, i;
|
||||
|
||||
dev_set_drvdata(arizona->dev, arizona);
|
||||
mutex_init(&arizona->clk_lock);
|
||||
|
@ -285,13 +285,15 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
||||
|
||||
resp = (struct ec_response_motion_sense *)msg->data;
|
||||
sensor_num = resp->dump.sensor_count;
|
||||
/* Allocate 1 extra sensors in FIFO are needed */
|
||||
sensor_cells = kcalloc(sensor_num + 1, sizeof(struct mfd_cell),
|
||||
/*
|
||||
* Allocate 2 extra sensors if lid angle sensor and/or FIFO are needed.
|
||||
*/
|
||||
sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell),
|
||||
GFP_KERNEL);
|
||||
if (sensor_cells == NULL)
|
||||
goto error;
|
||||
|
||||
sensor_platforms = kcalloc(sensor_num + 1,
|
||||
sensor_platforms = kcalloc(sensor_num,
|
||||
sizeof(struct cros_ec_sensor_platform),
|
||||
GFP_KERNEL);
|
||||
if (sensor_platforms == NULL)
|
||||
@ -351,6 +353,11 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
||||
sensor_cells[id].name = "cros-ec-ring";
|
||||
id++;
|
||||
}
|
||||
if (cros_ec_check_features(ec,
|
||||
EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
|
||||
sensor_cells[id].name = "cros-ec-lid-angle";
|
||||
id++;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
|
||||
NULL, 0, NULL);
|
||||
@ -364,6 +371,72 @@ error:
|
||||
kfree(msg);
|
||||
}
|
||||
|
||||
static struct cros_ec_sensor_platform sensor_platforms[] = {
|
||||
{ .sensor_num = 0 },
|
||||
{ .sensor_num = 1 }
|
||||
};
|
||||
|
||||
static const struct mfd_cell cros_ec_accel_legacy_cells[] = {
|
||||
{
|
||||
.name = "cros-ec-accel-legacy",
|
||||
.platform_data = &sensor_platforms[0],
|
||||
.pdata_size = sizeof(struct cros_ec_sensor_platform),
|
||||
},
|
||||
{
|
||||
.name = "cros-ec-accel-legacy",
|
||||
.platform_data = &sensor_platforms[1],
|
||||
.pdata_size = sizeof(struct cros_ec_sensor_platform),
|
||||
}
|
||||
};
|
||||
|
||||
static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = ec->ec_dev;
|
||||
u8 status;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* ECs that need legacy support are the main EC, directly connected to
|
||||
* the AP.
|
||||
*/
|
||||
if (ec->cmd_offset != 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check if EC supports direct memory reads and if EC has
|
||||
* accelerometers.
|
||||
*/
|
||||
if (ec_dev->cmd_readmem) {
|
||||
ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 1,
|
||||
&status);
|
||||
if (ret < 0) {
|
||||
dev_warn(ec->dev, "EC direct read error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if EC has accelerometers. */
|
||||
if (!(status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
|
||||
dev_info(ec->dev, "EC does not have accelerometers.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The device may still support accelerometers:
|
||||
* it would be an older ARM based device that do not suppor the
|
||||
* EC_CMD_GET_FEATURES command.
|
||||
*
|
||||
* Register 2 accelerometers, we will fail in the IIO driver if there
|
||||
* are no sensors.
|
||||
*/
|
||||
ret = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_accel_legacy_cells,
|
||||
ARRAY_SIZE(cros_ec_accel_legacy_cells),
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
dev_err(ec_dev->dev, "failed to add EC sensors\n");
|
||||
}
|
||||
|
||||
static const struct mfd_cell cros_ec_cec_cells[] = {
|
||||
{ .name = "cros-ec-cec" }
|
||||
};
|
||||
@ -440,6 +513,16 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
ec_platform->ec_name = CROS_EC_DEV_TP_NAME;
|
||||
}
|
||||
|
||||
/* Check whether this is actually a SCP rather than an EC. */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
|
||||
dev_info(dev, "CrOS SCP MCU detected.\n");
|
||||
/*
|
||||
* Help userspace differentiating ECs from SCP,
|
||||
* regardless of the probing order.
|
||||
*/
|
||||
ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the class device
|
||||
* Link to the character device for creating the /dev entry
|
||||
@ -459,6 +542,9 @@ static int ec_device_probe(struct platform_device *pdev)
|
||||
/* check whether this EC is a sensor hub. */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
||||
cros_ec_sensors_register(ec);
|
||||
else
|
||||
/* Workaroud for older EC firmware */
|
||||
cros_ec_accel_legacy_register(ec);
|
||||
|
||||
/* Check whether this EC instance has CEC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
|
||||
|
1299
drivers/mfd/cs47l15-tables.c
Normal file
1299
drivers/mfd/cs47l15-tables.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Regmap tables for CS47L35 codec
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -109,9 +105,8 @@ static const struct reg_default cs47l35_reg_default[] = {
|
||||
{ 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
|
||||
{ 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
|
||||
{ 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
|
||||
{ 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
|
||||
{ 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
|
||||
{ 0x0000017a, 0x0b06 }, /* R378 (0x17a) - FLL1 EFS2 */
|
||||
{ 0x0000017a, 0x2906 }, /* R378 (0x17a) - FLL1 EFS2 */
|
||||
{ 0x0000017f, 0x0000 }, /* R383 (0x17f) - FLL1 Synchroniser 1 */
|
||||
{ 0x00000180, 0x0000 }, /* R384 (0x180) - FLL1 Synchroniser 2 */
|
||||
{ 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 3 */
|
||||
@ -174,9 +169,6 @@ static const struct reg_default cs47l35_reg_default[] = {
|
||||
{ 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
|
||||
{ 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
|
||||
{ 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
|
||||
{ 0x00000440, 0x0003 }, /* R1088 (0x440) - DRE Enable */
|
||||
{ 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */
|
||||
{ 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */
|
||||
{ 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
|
||||
{ 0x00000451, 0x0000 }, /* R1105 (0x451) - DAC AEC Control 2 */
|
||||
{ 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
|
||||
@ -720,28 +712,6 @@ static const struct reg_default cs47l35_reg_default[] = {
|
||||
{ 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
|
||||
{ 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
|
||||
{ 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
|
||||
{ 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
|
||||
{ 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
|
||||
{ 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
|
||||
{ 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
|
||||
{ 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
|
||||
{ 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
|
||||
{ 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
|
||||
{ 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
|
||||
{ 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
|
||||
{ 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
|
||||
{ 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 4L 1 */
|
||||
{ 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 4L 2 */
|
||||
{ 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 4L 3 */
|
||||
{ 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 4L 4 */
|
||||
{ 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 5L 1 */
|
||||
{ 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 5L 2 */
|
||||
{ 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 5L 3 */
|
||||
{ 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 5L 4 */
|
||||
{ 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 5R 1 */
|
||||
{ 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 5R 2 */
|
||||
{ 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 5R 3 */
|
||||
{ 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 5R 4 */
|
||||
{ 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
|
||||
{ 0x00001701, 0xf000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
|
||||
{ 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
|
||||
@ -892,7 +862,6 @@ static bool cs47l35_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL1_CONTROL_6:
|
||||
case MADERA_FLL1_CONTROL_7:
|
||||
case MADERA_FLL1_EFS_2:
|
||||
case MADERA_FLL1_LOOP_FILTER_TEST_1:
|
||||
case CS47L35_FLL1_SYNCHRONISER_1:
|
||||
case CS47L35_FLL1_SYNCHRONISER_2:
|
||||
case CS47L35_FLL1_SYNCHRONISER_3:
|
||||
@ -967,9 +936,6 @@ static bool cs47l35_16bit_readable_register(struct device *dev,
|
||||
case MADERA_OUTPUT_PATH_CONFIG_5R:
|
||||
case MADERA_DAC_DIGITAL_VOLUME_5R:
|
||||
case MADERA_NOISE_GATE_SELECT_5R:
|
||||
case MADERA_DRE_ENABLE:
|
||||
case MADERA_EDRE_ENABLE:
|
||||
case MADERA_EDRE_MANUAL:
|
||||
case MADERA_DAC_AEC_CONTROL_1:
|
||||
case MADERA_DAC_AEC_CONTROL_2:
|
||||
case MADERA_NOISE_GATE_CONTROL:
|
||||
@ -1439,28 +1405,6 @@ static bool cs47l35_16bit_readable_register(struct device *dev,
|
||||
case MADERA_ISRC_2_CTRL_1:
|
||||
case MADERA_ISRC_2_CTRL_2:
|
||||
case MADERA_ISRC_2_CTRL_3:
|
||||
case MADERA_DAC_COMP_1:
|
||||
case MADERA_DAC_COMP_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_1:
|
||||
case MADERA_FRF_COEFFICIENT_1L_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_3:
|
||||
case MADERA_FRF_COEFFICIENT_1L_4:
|
||||
case MADERA_FRF_COEFFICIENT_1R_1:
|
||||
case MADERA_FRF_COEFFICIENT_1R_2:
|
||||
case MADERA_FRF_COEFFICIENT_1R_3:
|
||||
case MADERA_FRF_COEFFICIENT_1R_4:
|
||||
case CS47L35_FRF_COEFFICIENT_4L_1:
|
||||
case CS47L35_FRF_COEFFICIENT_4L_2:
|
||||
case CS47L35_FRF_COEFFICIENT_4L_3:
|
||||
case CS47L35_FRF_COEFFICIENT_4L_4:
|
||||
case CS47L35_FRF_COEFFICIENT_5L_1:
|
||||
case CS47L35_FRF_COEFFICIENT_5L_2:
|
||||
case CS47L35_FRF_COEFFICIENT_5L_3:
|
||||
case CS47L35_FRF_COEFFICIENT_5L_4:
|
||||
case CS47L35_FRF_COEFFICIENT_5R_1:
|
||||
case CS47L35_FRF_COEFFICIENT_5R_2:
|
||||
case CS47L35_FRF_COEFFICIENT_5R_3:
|
||||
case CS47L35_FRF_COEFFICIENT_5R_4:
|
||||
case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO16_CTRL_2:
|
||||
case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
|
||||
case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Regmap tables for CS47L85 codec
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -402,7 +398,6 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
|
||||
{ 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
|
||||
{ 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
|
||||
{ 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
|
||||
{ 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
|
||||
{ 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
|
||||
{ 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 2 */
|
||||
@ -419,7 +414,6 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
|
||||
{ 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
|
||||
{ 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
|
||||
{ 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
|
||||
{ 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
|
||||
{ 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
|
||||
{ 0x000001a2, 0x0000 }, /* R418 (0x1a2) - FLL2 Synchroniser 2 */
|
||||
@ -436,7 +430,6 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x000001b4, 0x007d }, /* R436 (0x1b4) - FLL3 Control 4 */
|
||||
{ 0x000001b5, 0x0000 }, /* R437 (0x1b5) - FLL3 Control 5 */
|
||||
{ 0x000001b6, 0x0000 }, /* R438 (0x1b6) - FLL3 Control 6 */
|
||||
{ 0x000001b7, 0x0281 }, /* R439 (0x1b7) - FLL3 Loop Filter Test 1 */
|
||||
{ 0x000001b9, 0x0000 }, /* R441 (0x1b9) - FLL3 Control 7 */
|
||||
{ 0x000001c1, 0x0000 }, /* R449 (0x1c1) - FLL3 Synchroniser 1 */
|
||||
{ 0x000001c2, 0x0000 }, /* R450 (0x1c2) - FLL3 Synchroniser 2 */
|
||||
@ -546,9 +539,6 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x0000043c, 0x0000 }, /* R1084 (0x43c) - Output Path Config 6R */
|
||||
{ 0x0000043d, 0x0180 }, /* R1085 (0x43d) - DAC Digital Volume 6R */
|
||||
{ 0x0000043f, 0x0800 }, /* R1087 (0x43f) - Noise Gate Select 6R */
|
||||
{ 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
|
||||
{ 0x00000448, 0x003f }, /* R1096 (0x448) - EDRE Enable */
|
||||
{ 0x0000044a, 0x0000 }, /* R1098 (0x44a) - EDRE Manual */
|
||||
{ 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
|
||||
{ 0x00000451, 0x0000 }, /* R1105 (0x451) - DAC AEC Control 2 */
|
||||
{ 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
|
||||
@ -556,7 +546,7 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
|
||||
{ 0x00000492, 0x0069 }, /* R1170 (0x492) - PDM SPK2 CTRL 1 */
|
||||
{ 0x00000493, 0x0000 }, /* R1171 (0x493) - PDM SPK2 CTRL 2 */
|
||||
{ 0x000004a0, 0x3210 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
|
||||
{ 0x000004a0, 0x3280 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
|
||||
{ 0x000004a1, 0x3200 }, /* R1185 (0x4a1) - HP2 Short Circuit Ctrl */
|
||||
{ 0x000004a2, 0x3200 }, /* R1186 (0x4a2) - HP3 Short Circuit Ctrl */
|
||||
{ 0x000004a8, 0x7020 }, /* R1192 (0x4a8) - HP Test Ctrl 5 */
|
||||
@ -1365,11 +1355,11 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
|
||||
{ 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
|
||||
{ 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
|
||||
{ 0x00000e88, 0x0933 }, /* R3720 (0xe88) - DRC2 ctrl1 */
|
||||
{ 0x00000e89, 0x0018 }, /* R3721 (0xe89) - DRC2 ctrl2 */
|
||||
{ 0x00000e8a, 0x0000 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
|
||||
{ 0x00000e88, 0x0018 }, /* R3720 (0xe88) - DRC2 ctrl1 */
|
||||
{ 0x00000e89, 0x0933 }, /* R3721 (0xe89) - DRC2 ctrl2 */
|
||||
{ 0x00000e8a, 0x0018 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
|
||||
{ 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
|
||||
{ 0x00000e8c, 0x0040 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
|
||||
{ 0x00000e8c, 0x0000 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
|
||||
{ 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
|
||||
{ 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
|
||||
{ 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
|
||||
@ -1577,56 +1567,6 @@ static const struct reg_default cs47l85_reg_default[] = {
|
||||
{ 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
|
||||
{ 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
|
||||
{ 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
|
||||
{ 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
|
||||
{ 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
|
||||
{ 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
|
||||
{ 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
|
||||
{ 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
|
||||
{ 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
|
||||
{ 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
|
||||
{ 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
|
||||
{ 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
|
||||
{ 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
|
||||
{ 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
|
||||
{ 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
|
||||
{ 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
|
||||
{ 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
|
||||
{ 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
|
||||
{ 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
|
||||
{ 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
|
||||
{ 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
|
||||
{ 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
|
||||
{ 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
|
||||
{ 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
|
||||
{ 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
|
||||
{ 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
|
||||
{ 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
|
||||
{ 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
|
||||
{ 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
|
||||
{ 0x000013e0, 0x0000 }, /* R5088 (0x13e0) - FRF Coefficient 4L 1 */
|
||||
{ 0x000013e1, 0x0000 }, /* R5089 (0x13e1) - FRF Coefficient 4L 2 */
|
||||
{ 0x000013e2, 0x0000 }, /* R5090 (0x13e2) - FRF Coefficient 4L 3 */
|
||||
{ 0x000013e3, 0x0000 }, /* R5091 (0x13e3) - FRF Coefficient 4L 4 */
|
||||
{ 0x000013f0, 0x0000 }, /* R5104 (0x13f0) - FRF Coefficient 4R 1 */
|
||||
{ 0x000013f1, 0x0000 }, /* R5105 (0x13f1) - FRF Coefficient 4R 2 */
|
||||
{ 0x000013f2, 0x0000 }, /* R5106 (0x13f2) - FRF Coefficient 4R 3 */
|
||||
{ 0x000013f3, 0x0000 }, /* R5107 (0x13f3) - FRF Coefficient 4R 4 */
|
||||
{ 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
|
||||
{ 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
|
||||
{ 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
|
||||
{ 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
|
||||
{ 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
|
||||
{ 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
|
||||
{ 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
|
||||
{ 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
|
||||
{ 0x00001420, 0x0000 }, /* R5152 (0x1420) - FRF Coefficient 6L 1 */
|
||||
{ 0x00001421, 0x0000 }, /* R5153 (0x1421) - FRF Coefficient 6L 2 */
|
||||
{ 0x00001422, 0x0000 }, /* R5154 (0x1422) - FRF Coefficient 6L 3 */
|
||||
{ 0x00001423, 0x0000 }, /* R5155 (0x1423) - FRF Coefficient 6L 4 */
|
||||
{ 0x00001430, 0x0000 }, /* R5168 (0x1430) - FRF Coefficient 6R 1 */
|
||||
{ 0x00001431, 0x0000 }, /* R5169 (0x1431) - FRF Coefficient 6R 2 */
|
||||
{ 0x00001432, 0x0000 }, /* R5170 (0x1432) - FRF Coefficient 6R 3 */
|
||||
{ 0x00001433, 0x0000 }, /* R5171 (0x1433) - FRF Coefficient 6R 4 */
|
||||
{ 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
|
||||
{ 0x00001701, 0xe000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
|
||||
{ 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
|
||||
@ -1845,7 +1785,6 @@ static bool cs47l85_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL1_CONTROL_5:
|
||||
case MADERA_FLL1_CONTROL_6:
|
||||
case MADERA_FLL1_CONTROL_7:
|
||||
case MADERA_FLL1_LOOP_FILTER_TEST_1:
|
||||
case MADERA_FLL1_SYNCHRONISER_1:
|
||||
case MADERA_FLL1_SYNCHRONISER_2:
|
||||
case MADERA_FLL1_SYNCHRONISER_3:
|
||||
@ -1862,7 +1801,6 @@ static bool cs47l85_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL2_CONTROL_5:
|
||||
case MADERA_FLL2_CONTROL_6:
|
||||
case MADERA_FLL2_CONTROL_7:
|
||||
case MADERA_FLL2_LOOP_FILTER_TEST_1:
|
||||
case MADERA_FLL2_SYNCHRONISER_1:
|
||||
case MADERA_FLL2_SYNCHRONISER_2:
|
||||
case MADERA_FLL2_SYNCHRONISER_3:
|
||||
@ -1879,7 +1817,6 @@ static bool cs47l85_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL3_CONTROL_5:
|
||||
case MADERA_FLL3_CONTROL_6:
|
||||
case MADERA_FLL3_CONTROL_7:
|
||||
case MADERA_FLL3_LOOP_FILTER_TEST_1:
|
||||
case MADERA_FLL3_SYNCHRONISER_1:
|
||||
case MADERA_FLL3_SYNCHRONISER_2:
|
||||
case MADERA_FLL3_SYNCHRONISER_3:
|
||||
@ -2004,9 +1941,6 @@ static bool cs47l85_16bit_readable_register(struct device *dev,
|
||||
case MADERA_OUTPUT_PATH_CONFIG_6R:
|
||||
case MADERA_DAC_DIGITAL_VOLUME_6R:
|
||||
case MADERA_NOISE_GATE_SELECT_6R:
|
||||
case MADERA_DRE_ENABLE:
|
||||
case MADERA_EDRE_ENABLE:
|
||||
case MADERA_EDRE_MANUAL:
|
||||
case MADERA_DAC_AEC_CONTROL_1:
|
||||
case MADERA_DAC_AEC_CONTROL_2:
|
||||
case MADERA_NOISE_GATE_CONTROL:
|
||||
@ -2792,56 +2726,6 @@ static bool cs47l85_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FCR_FILTER_CONTROL:
|
||||
case MADERA_FCR_ADC_REFORMATTER_CONTROL:
|
||||
case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
|
||||
case MADERA_DAC_COMP_1:
|
||||
case MADERA_DAC_COMP_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_1:
|
||||
case MADERA_FRF_COEFFICIENT_1L_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_3:
|
||||
case MADERA_FRF_COEFFICIENT_1L_4:
|
||||
case MADERA_FRF_COEFFICIENT_1R_1:
|
||||
case MADERA_FRF_COEFFICIENT_1R_2:
|
||||
case MADERA_FRF_COEFFICIENT_1R_3:
|
||||
case MADERA_FRF_COEFFICIENT_1R_4:
|
||||
case MADERA_FRF_COEFFICIENT_2L_1:
|
||||
case MADERA_FRF_COEFFICIENT_2L_2:
|
||||
case MADERA_FRF_COEFFICIENT_2L_3:
|
||||
case MADERA_FRF_COEFFICIENT_2L_4:
|
||||
case MADERA_FRF_COEFFICIENT_2R_1:
|
||||
case MADERA_FRF_COEFFICIENT_2R_2:
|
||||
case MADERA_FRF_COEFFICIENT_2R_3:
|
||||
case MADERA_FRF_COEFFICIENT_2R_4:
|
||||
case MADERA_FRF_COEFFICIENT_3L_1:
|
||||
case MADERA_FRF_COEFFICIENT_3L_2:
|
||||
case MADERA_FRF_COEFFICIENT_3L_3:
|
||||
case MADERA_FRF_COEFFICIENT_3L_4:
|
||||
case MADERA_FRF_COEFFICIENT_3R_1:
|
||||
case MADERA_FRF_COEFFICIENT_3R_2:
|
||||
case MADERA_FRF_COEFFICIENT_3R_3:
|
||||
case MADERA_FRF_COEFFICIENT_3R_4:
|
||||
case MADERA_FRF_COEFFICIENT_4L_1:
|
||||
case MADERA_FRF_COEFFICIENT_4L_2:
|
||||
case MADERA_FRF_COEFFICIENT_4L_3:
|
||||
case MADERA_FRF_COEFFICIENT_4L_4:
|
||||
case MADERA_FRF_COEFFICIENT_4R_1:
|
||||
case MADERA_FRF_COEFFICIENT_4R_2:
|
||||
case MADERA_FRF_COEFFICIENT_4R_3:
|
||||
case MADERA_FRF_COEFFICIENT_4R_4:
|
||||
case MADERA_FRF_COEFFICIENT_5L_1:
|
||||
case MADERA_FRF_COEFFICIENT_5L_2:
|
||||
case MADERA_FRF_COEFFICIENT_5L_3:
|
||||
case MADERA_FRF_COEFFICIENT_5L_4:
|
||||
case MADERA_FRF_COEFFICIENT_5R_1:
|
||||
case MADERA_FRF_COEFFICIENT_5R_2:
|
||||
case MADERA_FRF_COEFFICIENT_5R_3:
|
||||
case MADERA_FRF_COEFFICIENT_5R_4:
|
||||
case MADERA_FRF_COEFFICIENT_6L_1:
|
||||
case MADERA_FRF_COEFFICIENT_6L_2:
|
||||
case MADERA_FRF_COEFFICIENT_6L_3:
|
||||
case MADERA_FRF_COEFFICIENT_6L_4:
|
||||
case MADERA_FRF_COEFFICIENT_6R_1:
|
||||
case MADERA_FRF_COEFFICIENT_6R_2:
|
||||
case MADERA_FRF_COEFFICIENT_6R_3:
|
||||
case MADERA_FRF_COEFFICIENT_6R_4:
|
||||
case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO40_CTRL_2:
|
||||
case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
|
||||
case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Regmap tables for CS47L90 codec
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -119,7 +115,6 @@ static const struct reg_default cs47l90_reg_default[] = {
|
||||
{ 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
|
||||
{ 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
|
||||
{ 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
|
||||
{ 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
|
||||
{ 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
|
||||
{ 0x0000017a, 0x2906 }, /* R377 (0x17a) - FLL1 Efs 2 */
|
||||
{ 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
|
||||
@ -137,7 +132,6 @@ static const struct reg_default cs47l90_reg_default[] = {
|
||||
{ 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
|
||||
{ 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
|
||||
{ 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
|
||||
{ 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
|
||||
{ 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
|
||||
{ 0x0000019a, 0x2906 }, /* R410 (0x19a) - FLL2 Efs 2 */
|
||||
{ 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
|
||||
@ -260,8 +254,6 @@ static const struct reg_default cs47l90_reg_default[] = {
|
||||
{ 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
|
||||
{ 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
|
||||
{ 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
|
||||
{ 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
|
||||
{ 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */
|
||||
{ 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
|
||||
{ 0x00000451, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 2 */
|
||||
{ 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
|
||||
@ -1262,40 +1254,6 @@ static const struct reg_default cs47l90_reg_default[] = {
|
||||
{ 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
|
||||
{ 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
|
||||
{ 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
|
||||
{ 0x00001300, 0x050E }, /* R4864 (0x1300) - DAC Comp 1 */
|
||||
{ 0x00001302, 0x0101 }, /* R4866 (0x1302) - DAC Comp 2 */
|
||||
{ 0x00001380, 0x0425 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
|
||||
{ 0x00001381, 0xF6D8 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
|
||||
{ 0x00001382, 0x0632 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
|
||||
{ 0x00001383, 0xFEC8 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
|
||||
{ 0x00001390, 0x042F }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
|
||||
{ 0x00001391, 0xF6CA }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
|
||||
{ 0x00001392, 0x0637 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
|
||||
{ 0x00001393, 0xFEC8 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
|
||||
{ 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
|
||||
{ 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
|
||||
{ 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
|
||||
{ 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
|
||||
{ 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
|
||||
{ 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
|
||||
{ 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
|
||||
{ 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
|
||||
{ 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
|
||||
{ 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
|
||||
{ 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
|
||||
{ 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
|
||||
{ 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
|
||||
{ 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
|
||||
{ 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
|
||||
{ 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
|
||||
{ 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
|
||||
{ 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
|
||||
{ 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
|
||||
{ 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
|
||||
{ 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
|
||||
{ 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
|
||||
{ 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
|
||||
{ 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
|
||||
{ 0x00001480, 0x0000 }, /* R5248 (0x1480) - DFC1_CTRL */
|
||||
{ 0x00001482, 0x1f00 }, /* R5250 (0x1482) - DFC1_RX */
|
||||
{ 0x00001484, 0x1f00 }, /* R5252 (0x1486) - DFC1_TX */
|
||||
@ -1535,7 +1493,6 @@ static bool cs47l90_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL1_CONTROL_6:
|
||||
case MADERA_FLL1_CONTROL_7:
|
||||
case MADERA_FLL1_EFS_2:
|
||||
case MADERA_FLL1_LOOP_FILTER_TEST_1:
|
||||
case MADERA_FLL1_SYNCHRONISER_1:
|
||||
case MADERA_FLL1_SYNCHRONISER_2:
|
||||
case MADERA_FLL1_SYNCHRONISER_3:
|
||||
@ -1553,7 +1510,6 @@ static bool cs47l90_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FLL2_CONTROL_6:
|
||||
case MADERA_FLL2_CONTROL_7:
|
||||
case MADERA_FLL2_EFS_2:
|
||||
case MADERA_FLL2_LOOP_FILTER_TEST_1:
|
||||
case MADERA_FLL2_SYNCHRONISER_1:
|
||||
case MADERA_FLL2_SYNCHRONISER_2:
|
||||
case MADERA_FLL2_SYNCHRONISER_3:
|
||||
@ -1690,8 +1646,6 @@ static bool cs47l90_16bit_readable_register(struct device *dev,
|
||||
case MADERA_OUTPUT_PATH_CONFIG_5R:
|
||||
case MADERA_DAC_DIGITAL_VOLUME_5R:
|
||||
case MADERA_NOISE_GATE_SELECT_5R:
|
||||
case MADERA_DRE_ENABLE:
|
||||
case MADERA_EDRE_ENABLE:
|
||||
case MADERA_DAC_AEC_CONTROL_1:
|
||||
case MADERA_DAC_AEC_CONTROL_2:
|
||||
case MADERA_NOISE_GATE_CONTROL:
|
||||
@ -2449,40 +2403,6 @@ static bool cs47l90_16bit_readable_register(struct device *dev,
|
||||
case MADERA_FCR_FILTER_CONTROL:
|
||||
case MADERA_FCR_ADC_REFORMATTER_CONTROL:
|
||||
case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
|
||||
case MADERA_DAC_COMP_1:
|
||||
case MADERA_DAC_COMP_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_1:
|
||||
case MADERA_FRF_COEFFICIENT_1L_2:
|
||||
case MADERA_FRF_COEFFICIENT_1L_3:
|
||||
case MADERA_FRF_COEFFICIENT_1L_4:
|
||||
case MADERA_FRF_COEFFICIENT_1R_1:
|
||||
case MADERA_FRF_COEFFICIENT_1R_2:
|
||||
case MADERA_FRF_COEFFICIENT_1R_3:
|
||||
case MADERA_FRF_COEFFICIENT_1R_4:
|
||||
case MADERA_FRF_COEFFICIENT_2L_1:
|
||||
case MADERA_FRF_COEFFICIENT_2L_2:
|
||||
case MADERA_FRF_COEFFICIENT_2L_3:
|
||||
case MADERA_FRF_COEFFICIENT_2L_4:
|
||||
case MADERA_FRF_COEFFICIENT_2R_1:
|
||||
case MADERA_FRF_COEFFICIENT_2R_2:
|
||||
case MADERA_FRF_COEFFICIENT_2R_3:
|
||||
case MADERA_FRF_COEFFICIENT_2R_4:
|
||||
case MADERA_FRF_COEFFICIENT_3L_1:
|
||||
case MADERA_FRF_COEFFICIENT_3L_2:
|
||||
case MADERA_FRF_COEFFICIENT_3L_3:
|
||||
case MADERA_FRF_COEFFICIENT_3L_4:
|
||||
case MADERA_FRF_COEFFICIENT_3R_1:
|
||||
case MADERA_FRF_COEFFICIENT_3R_2:
|
||||
case MADERA_FRF_COEFFICIENT_3R_3:
|
||||
case MADERA_FRF_COEFFICIENT_3R_4:
|
||||
case MADERA_FRF_COEFFICIENT_5L_1:
|
||||
case MADERA_FRF_COEFFICIENT_5L_2:
|
||||
case MADERA_FRF_COEFFICIENT_5L_3:
|
||||
case MADERA_FRF_COEFFICIENT_5L_4:
|
||||
case MADERA_FRF_COEFFICIENT_5R_1:
|
||||
case MADERA_FRF_COEFFICIENT_5R_2:
|
||||
case MADERA_FRF_COEFFICIENT_5R_3:
|
||||
case MADERA_FRF_COEFFICIENT_5R_4:
|
||||
case MADERA_DFC1_CTRL:
|
||||
case MADERA_DFC1_RX:
|
||||
case MADERA_DFC1_TX:
|
||||
|
1947
drivers/mfd/cs47l92-tables.c
Normal file
1947
drivers/mfd/cs47l92-tables.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -100,22 +100,10 @@ static struct mfd_cell cs5535_mfd_cells[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OLPC
|
||||
static void cs5535_clone_olpc_cells(void)
|
||||
{
|
||||
static const char *acpi_clones[] = {
|
||||
"olpc-xo1-pm-acpi",
|
||||
"olpc-xo1-sci-acpi"
|
||||
};
|
||||
|
||||
if (!machine_is_olpc())
|
||||
return;
|
||||
|
||||
mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones));
|
||||
}
|
||||
#else
|
||||
static void cs5535_clone_olpc_cells(void) { }
|
||||
#endif
|
||||
static const char *olpc_acpi_clones[] = {
|
||||
"olpc-xo1-pm-acpi",
|
||||
"olpc-xo1-sci-acpi"
|
||||
};
|
||||
|
||||
static int cs5535_mfd_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
@ -145,7 +133,9 @@ static int cs5535_mfd_probe(struct pci_dev *pdev,
|
||||
dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
|
||||
goto err_disable;
|
||||
}
|
||||
cs5535_clone_olpc_cells();
|
||||
|
||||
if (machine_is_olpc())
|
||||
mfd_clone_cell("cs5535-acpi", olpc_acpi_clones, ARRAY_SIZE(olpc_acpi_clones));
|
||||
|
||||
dev_info(&pdev->dev, "%zu devices registered.\n",
|
||||
ARRAY_SIZE(cs5535_mfd_cells));
|
||||
|
@ -109,6 +109,8 @@ static int hi655x_pmic_probe(struct platform_device *pdev)
|
||||
|
||||
pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,
|
||||
&hi655x_regmap_config);
|
||||
if (IS_ERR(pmic->regmap))
|
||||
return PTR_ERR(pmic->regmap);
|
||||
|
||||
regmap_read(pmic->regmap, HI655X_BUS_ADDR(HI655X_VER_REG), &pmic->ver);
|
||||
if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) {
|
||||
|
@ -183,10 +183,10 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31ee), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x31ee), (kernel_ulong_t)&bxt_uart_info },
|
||||
/* ICL-LP */
|
||||
{ PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
|
||||
@ -200,6 +200,21 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
|
||||
/* EHL */
|
||||
{ PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b2a), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b2b), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b37), (kernel_ulong_t)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b44), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b45), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b4b), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b4c), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b4d), (kernel_ulong_t)&bxt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b78), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b79), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b7a), (kernel_ulong_t)&bxt_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b7b), (kernel_ulong_t)&bxt_i2c_info },
|
||||
/* APL */
|
||||
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
|
||||
@ -233,7 +248,6 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x9da9), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
|
||||
@ -241,6 +255,7 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
|
||||
/* SPT-H */
|
||||
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
|
||||
@ -265,12 +280,12 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0xa329), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa32a), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info },
|
||||
{ PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
|
||||
|
@ -543,6 +543,7 @@ module_init(intel_lpss_init);
|
||||
|
||||
static void __exit intel_lpss_exit(void)
|
||||
{
|
||||
ida_destroy(&intel_lpss_devid_ida);
|
||||
debugfs_remove(intel_lpss_debugfs);
|
||||
}
|
||||
module_exit(intel_lpss_exit);
|
||||
|
@ -30,6 +30,10 @@ static const struct of_device_id of_lp87565_match_table[] = {
|
||||
.compatible = "ti,lp87565-q1",
|
||||
.data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,lp87561-q1",
|
||||
.data = (void *)LP87565_DEVICE_TYPE_LP87561_Q1,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_lp87565_match_table);
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Core MFD support for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -31,9 +27,11 @@
|
||||
|
||||
#include "madera.h"
|
||||
|
||||
#define CS47L15_SILICON_ID 0x6370
|
||||
#define CS47L35_SILICON_ID 0x6360
|
||||
#define CS47L85_SILICON_ID 0x6338
|
||||
#define CS47L90_SILICON_ID 0x6364
|
||||
#define CS47L92_SILICON_ID 0x6371
|
||||
|
||||
#define MADERA_32KZ_MCLK2 1
|
||||
|
||||
@ -46,6 +44,28 @@ static const struct mfd_cell madera_ldo1_devs[] = {
|
||||
{ .name = "madera-ldo1" },
|
||||
};
|
||||
|
||||
static const char * const cs47l15_supplies[] = {
|
||||
"MICVDD",
|
||||
"CPVDD1",
|
||||
"SPKVDD",
|
||||
};
|
||||
|
||||
static const struct mfd_cell cs47l15_devs[] = {
|
||||
{ .name = "madera-pinctrl", },
|
||||
{ .name = "madera-irq" },
|
||||
{ .name = "madera-gpio" },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l15_supplies,
|
||||
.num_parent_supplies = 1, /* We only need MICVDD */
|
||||
},
|
||||
{
|
||||
.name = "cs47l15-codec",
|
||||
.parent_supplies = cs47l15_supplies,
|
||||
.num_parent_supplies = ARRAY_SIZE(cs47l15_supplies),
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cs47l35_supplies[] = {
|
||||
"MICVDD",
|
||||
"DBVDD2",
|
||||
@ -59,7 +79,11 @@ static const struct mfd_cell cs47l35_devs[] = {
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l35_supplies,
|
||||
.num_parent_supplies = 1, /* We only need MICVDD */
|
||||
},
|
||||
{
|
||||
.name = "cs47l35-codec",
|
||||
.parent_supplies = cs47l35_supplies,
|
||||
@ -83,7 +107,11 @@ static const struct mfd_cell cs47l85_devs[] = {
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp" },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l85_supplies,
|
||||
.num_parent_supplies = 1, /* We only need MICVDD */
|
||||
},
|
||||
{
|
||||
.name = "cs47l85-codec",
|
||||
.parent_supplies = cs47l85_supplies,
|
||||
@ -105,7 +133,11 @@ static const struct mfd_cell cs47l90_devs[] = {
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio", },
|
||||
{ .name = "madera-extcon", },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l90_supplies,
|
||||
.num_parent_supplies = 1, /* We only need MICVDD */
|
||||
},
|
||||
{
|
||||
.name = "cs47l90-codec",
|
||||
.parent_supplies = cs47l90_supplies,
|
||||
@ -113,10 +145,35 @@ static const struct mfd_cell cs47l90_devs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const char * const cs47l92_supplies[] = {
|
||||
"MICVDD",
|
||||
"CPVDD1",
|
||||
"CPVDD2",
|
||||
};
|
||||
|
||||
static const struct mfd_cell cs47l92_devs[] = {
|
||||
{ .name = "madera-pinctrl" },
|
||||
{ .name = "madera-irq", },
|
||||
{ .name = "madera-micsupp", },
|
||||
{ .name = "madera-gpio" },
|
||||
{
|
||||
.name = "madera-extcon",
|
||||
.parent_supplies = cs47l92_supplies,
|
||||
.num_parent_supplies = 1, /* We only need MICVDD */
|
||||
},
|
||||
{
|
||||
.name = "cs47l92-codec",
|
||||
.parent_supplies = cs47l92_supplies,
|
||||
.num_parent_supplies = ARRAY_SIZE(cs47l92_supplies),
|
||||
},
|
||||
};
|
||||
|
||||
/* Used by madera-i2c and madera-spi drivers */
|
||||
const char *madera_name_from_type(enum madera_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case CS47L15:
|
||||
return "CS47L15";
|
||||
case CS47L35:
|
||||
return "CS47L35";
|
||||
case CS47L85:
|
||||
@ -125,6 +182,12 @@ const char *madera_name_from_type(enum madera_type type)
|
||||
return "CS47L90";
|
||||
case CS47L91:
|
||||
return "CS47L91";
|
||||
case CS42L92:
|
||||
return "CS42L92";
|
||||
case CS47L92:
|
||||
return "CS47L92";
|
||||
case CS47L93:
|
||||
return "CS47L93";
|
||||
case WM1840:
|
||||
return "WM1840";
|
||||
default:
|
||||
@ -139,7 +202,7 @@ EXPORT_SYMBOL_GPL(madera_name_from_type);
|
||||
static int madera_wait_for_boot(struct madera *madera)
|
||||
{
|
||||
ktime_t timeout;
|
||||
unsigned int val;
|
||||
unsigned int val = 0;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
@ -279,13 +342,18 @@ const struct dev_pm_ops madera_pm_ops = {
|
||||
EXPORT_SYMBOL_GPL(madera_pm_ops);
|
||||
|
||||
const struct of_device_id madera_of_match[] = {
|
||||
{ .compatible = "cirrus,cs47l15", .data = (void *)CS47L15 },
|
||||
{ .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
|
||||
{ .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
|
||||
{ .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
|
||||
{ .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
|
||||
{ .compatible = "cirrus,cs42l92", .data = (void *)CS42L92 },
|
||||
{ .compatible = "cirrus,cs47l92", .data = (void *)CS47L92 },
|
||||
{ .compatible = "cirrus,cs47l93", .data = (void *)CS47L93 },
|
||||
{ .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, madera_of_match);
|
||||
EXPORT_SYMBOL_GPL(madera_of_match);
|
||||
|
||||
static int madera_get_reset_gpio(struct madera *madera)
|
||||
@ -326,6 +394,10 @@ static void madera_set_micbias_info(struct madera *madera)
|
||||
* childbiases for each micbias. Unspecified values default to 0.
|
||||
*/
|
||||
switch (madera->type) {
|
||||
case CS47L15:
|
||||
madera->num_micbias = 1;
|
||||
madera->num_childbias[0] = 3;
|
||||
return;
|
||||
case CS47L35:
|
||||
madera->num_micbias = 2;
|
||||
madera->num_childbias[0] = 2;
|
||||
@ -342,6 +414,13 @@ static void madera_set_micbias_info(struct madera *madera)
|
||||
madera->num_childbias[0] = 4;
|
||||
madera->num_childbias[1] = 4;
|
||||
return;
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
madera->num_micbias = 2;
|
||||
madera->num_childbias[0] = 4;
|
||||
madera->num_childbias[1] = 2;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -389,9 +468,13 @@ int madera_dev_init(struct madera *madera)
|
||||
* No devm_ because we need to control shutdown order of children.
|
||||
*/
|
||||
switch (madera->type) {
|
||||
case CS47L15:
|
||||
case CS47L35:
|
||||
case CS47L90:
|
||||
case CS47L91:
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
break;
|
||||
case CS47L85:
|
||||
case WM1840:
|
||||
@ -458,6 +541,19 @@ int madera_dev_init(struct madera *madera)
|
||||
}
|
||||
|
||||
switch (hwid) {
|
||||
case CS47L15_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
|
||||
switch (madera->type) {
|
||||
case CS47L15:
|
||||
patch_fn = &cs47l15_patch;
|
||||
mfd_devs = cs47l15_devs;
|
||||
n_devs = ARRAY_SIZE(cs47l15_devs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CS47L35_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
switch (madera->type) {
|
||||
@ -499,6 +595,21 @@ int madera_dev_init(struct madera *madera)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CS47L92_SILICON_ID:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
|
||||
switch (madera->type) {
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
patch_fn = cs47l92_patch;
|
||||
mfd_devs = cs47l92_devs;
|
||||
n_devs = ARRAY_SIZE(cs47l92_devs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
|
||||
ret = -EINVAL;
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* I2C bus interface to Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -39,6 +35,12 @@ static int madera_i2c_probe(struct i2c_client *i2c,
|
||||
type = id->driver_data;
|
||||
|
||||
switch (type) {
|
||||
case CS47L15:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
|
||||
regmap_16bit_config = &cs47l15_16bit_i2c_regmap;
|
||||
regmap_32bit_config = &cs47l15_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L35:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
regmap_16bit_config = &cs47l35_16bit_i2c_regmap;
|
||||
@ -59,6 +61,14 @@ static int madera_i2c_probe(struct i2c_client *i2c,
|
||||
regmap_32bit_config = &cs47l90_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
|
||||
regmap_16bit_config = &cs47l92_16bit_i2c_regmap;
|
||||
regmap_32bit_config = &cs47l92_32bit_i2c_regmap;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(&i2c->dev,
|
||||
"Unknown Madera I2C device type %ld\n", type);
|
||||
@ -113,10 +123,14 @@ static int madera_i2c_remove(struct i2c_client *i2c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id madera_i2c_id[] = {
|
||||
{ "cs47l15", CS47L15 },
|
||||
{ "cs47l35", CS47L35 },
|
||||
{ "cs47l85", CS47L85 },
|
||||
{ "cs47l90", CS47L90 },
|
||||
{ "cs47l91", CS47L91 },
|
||||
{ "cs42l92", CS42L92 },
|
||||
{ "cs47l92", CS47L92 },
|
||||
{ "cs47l93", CS47L93 },
|
||||
{ "wm1840", WM1840 },
|
||||
{ }
|
||||
};
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* SPI bus interface to Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@ -39,6 +35,12 @@ static int madera_spi_probe(struct spi_device *spi)
|
||||
type = id->driver_data;
|
||||
|
||||
switch (type) {
|
||||
case CS47L15:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L15)) {
|
||||
regmap_16bit_config = &cs47l15_16bit_spi_regmap;
|
||||
regmap_32bit_config = &cs47l15_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
case CS47L35:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
|
||||
regmap_16bit_config = &cs47l35_16bit_spi_regmap;
|
||||
@ -59,6 +61,14 @@ static int madera_spi_probe(struct spi_device *spi)
|
||||
regmap_32bit_config = &cs47l90_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
case CS42L92:
|
||||
case CS47L92:
|
||||
case CS47L93:
|
||||
if (IS_ENABLED(CONFIG_MFD_CS47L92)) {
|
||||
regmap_16bit_config = &cs47l92_16bit_spi_regmap;
|
||||
regmap_32bit_config = &cs47l92_32bit_spi_regmap;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(&spi->dev,
|
||||
"Unknown Madera SPI device type %ld\n", type);
|
||||
@ -112,10 +122,14 @@ static int madera_spi_remove(struct spi_device *spi)
|
||||
}
|
||||
|
||||
static const struct spi_device_id madera_spi_ids[] = {
|
||||
{ "cs47l15", CS47L15 },
|
||||
{ "cs47l35", CS47L35 },
|
||||
{ "cs47l85", CS47L85 },
|
||||
{ "cs47l90", CS47L90 },
|
||||
{ "cs47l91", CS47L91 },
|
||||
{ "cs42l92", CS42L92 },
|
||||
{ "cs47l92", CS47L92 },
|
||||
{ "cs47l93", CS47L93 },
|
||||
{ "wm1840", WM1840 },
|
||||
{ }
|
||||
};
|
||||
|
@ -21,6 +21,12 @@ int madera_dev_exit(struct madera *madera);
|
||||
|
||||
const char *madera_name_from_type(enum madera_type type);
|
||||
|
||||
extern const struct regmap_config cs47l15_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l15_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l15_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l15_32bit_i2c_regmap;
|
||||
int cs47l15_patch(struct madera *madera);
|
||||
|
||||
extern const struct regmap_config cs47l35_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l35_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l35_16bit_i2c_regmap;
|
||||
@ -38,4 +44,11 @@ extern const struct regmap_config cs47l90_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l90_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l90_32bit_i2c_regmap;
|
||||
int cs47l90_patch(struct madera *madera);
|
||||
|
||||
extern const struct regmap_config cs47l92_16bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l92_32bit_spi_regmap;
|
||||
extern const struct regmap_config cs47l92_16bit_i2c_regmap;
|
||||
extern const struct regmap_config cs47l92_32bit_i2c_regmap;
|
||||
int cs47l92_patch(struct madera *madera);
|
||||
|
||||
#endif
|
||||
|
@ -1125,8 +1125,6 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
|
||||
menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
|
||||
device_init_wakeup(&m->client->dev, 0);
|
||||
}
|
||||
dev_err(&m->client->dev, "can't register RTC: %d\n",
|
||||
(int) PTR_ERR(m->rtc));
|
||||
the_menelaus->rtc = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +175,7 @@ static int mfd_add_device(struct device *parent, int id,
|
||||
for_each_child_of_node(parent->of_node, np) {
|
||||
if (of_device_is_compatible(np, cell->of_compatible)) {
|
||||
pdev->dev.of_node = np;
|
||||
pdev->dev.fwnode = &np->fwnode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
struct rk808_reg_data {
|
||||
int addr;
|
||||
@ -54,6 +55,27 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
/*
|
||||
* Notes:
|
||||
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
|
||||
* we don't use that feature. It's better to cache.
|
||||
*/
|
||||
|
||||
switch (reg) {
|
||||
case RK817_SECONDS_REG ... RK817_WEEKS_REG:
|
||||
case RK817_RTC_STATUS_REG:
|
||||
case RK817_INT_STS_REG0:
|
||||
case RK817_INT_STS_REG1:
|
||||
case RK817_INT_STS_REG2:
|
||||
case RK817_SYS_STS:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct regmap_config rk818_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
@ -78,6 +100,14 @@ static const struct regmap_config rk808_regmap_config = {
|
||||
.volatile_reg = rk808_is_volatile_reg,
|
||||
};
|
||||
|
||||
static const struct regmap_config rk817_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = RK817_GPIO_INT_CFG,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.volatile_reg = rk817_is_volatile_reg,
|
||||
};
|
||||
|
||||
static struct resource rtc_resources[] = {
|
||||
{
|
||||
.start = RK808_IRQ_RTC_ALARM,
|
||||
@ -86,6 +116,10 @@ static struct resource rtc_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource rk817_rtc_resources[] = {
|
||||
DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM),
|
||||
};
|
||||
|
||||
static struct resource rk805_key_resources[] = {
|
||||
{
|
||||
.start = RK805_IRQ_PWRON_FALL,
|
||||
@ -99,6 +133,11 @@ static struct resource rk805_key_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource rk817_pwrkey_resources[] = {
|
||||
DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE),
|
||||
DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL),
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk805s[] = {
|
||||
{ .name = "rk808-clkout", },
|
||||
{ .name = "rk808-regulator", },
|
||||
@ -124,6 +163,21 @@ static const struct mfd_cell rk808s[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk817s[] = {
|
||||
{ .name = "rk808-clkout",},
|
||||
{ .name = "rk808-regulator",},
|
||||
{
|
||||
.name = "rk8xx-pwrkey",
|
||||
.num_resources = ARRAY_SIZE(rk817_pwrkey_resources),
|
||||
.resources = &rk817_pwrkey_resources[0],
|
||||
},
|
||||
{
|
||||
.name = "rk808-rtc",
|
||||
.num_resources = ARRAY_SIZE(rk817_rtc_resources),
|
||||
.resources = &rk817_rtc_resources[0],
|
||||
},
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk818s[] = {
|
||||
{ .name = "rk808-clkout", },
|
||||
{ .name = "rk808-regulator", },
|
||||
@ -159,6 +213,13 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
|
||||
VB_LO_SEL_3500MV },
|
||||
};
|
||||
|
||||
static const struct rk808_reg_data rk817_pre_init_reg[] = {
|
||||
{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
|
||||
{RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_H},
|
||||
{RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
|
||||
RK817_HOTDIE_105 | RK817_TSD_140},
|
||||
};
|
||||
|
||||
static const struct rk808_reg_data rk818_pre_init_reg[] = {
|
||||
/* improve efficiency */
|
||||
{ RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
|
||||
@ -324,6 +385,33 @@ static const struct regmap_irq rk818_irqs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = {
|
||||
REGMAP_IRQ_REG_LINE(0, 8),
|
||||
REGMAP_IRQ_REG_LINE(1, 8),
|
||||
REGMAP_IRQ_REG_LINE(2, 8),
|
||||
REGMAP_IRQ_REG_LINE(3, 8),
|
||||
REGMAP_IRQ_REG_LINE(4, 8),
|
||||
REGMAP_IRQ_REG_LINE(5, 8),
|
||||
REGMAP_IRQ_REG_LINE(6, 8),
|
||||
REGMAP_IRQ_REG_LINE(7, 8),
|
||||
REGMAP_IRQ_REG_LINE(8, 8),
|
||||
REGMAP_IRQ_REG_LINE(9, 8),
|
||||
REGMAP_IRQ_REG_LINE(10, 8),
|
||||
REGMAP_IRQ_REG_LINE(11, 8),
|
||||
REGMAP_IRQ_REG_LINE(12, 8),
|
||||
REGMAP_IRQ_REG_LINE(13, 8),
|
||||
REGMAP_IRQ_REG_LINE(14, 8),
|
||||
REGMAP_IRQ_REG_LINE(15, 8),
|
||||
REGMAP_IRQ_REG_LINE(16, 8),
|
||||
REGMAP_IRQ_REG_LINE(17, 8),
|
||||
REGMAP_IRQ_REG_LINE(18, 8),
|
||||
REGMAP_IRQ_REG_LINE(19, 8),
|
||||
REGMAP_IRQ_REG_LINE(20, 8),
|
||||
REGMAP_IRQ_REG_LINE(21, 8),
|
||||
REGMAP_IRQ_REG_LINE(22, 8),
|
||||
REGMAP_IRQ_REG_LINE(23, 8)
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip rk805_irq_chip = {
|
||||
.name = "rk805",
|
||||
.irqs = rk805_irqs,
|
||||
@ -347,6 +435,18 @@ static const struct regmap_irq_chip rk808_irq_chip = {
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip rk817_irq_chip = {
|
||||
.name = "rk817",
|
||||
.irqs = rk817_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rk817_irqs),
|
||||
.num_regs = 3,
|
||||
.irq_reg_stride = 2,
|
||||
.status_base = RK817_INT_STS_REG0,
|
||||
.mask_base = RK817_INT_STS_MSK_REG0,
|
||||
.ack_base = RK817_INT_STS_REG0,
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip rk818_irq_chip = {
|
||||
.name = "rk818",
|
||||
.irqs = rk818_irqs,
|
||||
@ -366,17 +466,29 @@ static void rk805_device_shutdown(void)
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
if (!rk808) {
|
||||
dev_warn(&rk808_i2c_client->dev,
|
||||
"have no rk805, so do nothing here\n");
|
||||
if (!rk808)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK805_DEV_CTRL_REG,
|
||||
DEV_OFF, DEV_OFF);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "power off error!\n");
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
}
|
||||
|
||||
static void rk805_device_shutdown_prepare(void)
|
||||
{
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
if (!rk808)
|
||||
return;
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK805_GPIO_IO_POL_REG,
|
||||
SLP_SD_MSK, SHUTDOWN_FUN);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
}
|
||||
|
||||
static void rk808_device_shutdown(void)
|
||||
@ -384,17 +496,14 @@ static void rk808_device_shutdown(void)
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
if (!rk808) {
|
||||
dev_warn(&rk808_i2c_client->dev,
|
||||
"have no rk808, so do nothing here\n");
|
||||
if (!rk808)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK808_DEVCTRL_REG,
|
||||
DEV_OFF_RST, DEV_OFF_RST);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "power off error!\n");
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
}
|
||||
|
||||
static void rk818_device_shutdown(void)
|
||||
@ -402,22 +511,43 @@ static void rk818_device_shutdown(void)
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
if (!rk808) {
|
||||
dev_warn(&rk808_i2c_client->dev,
|
||||
"have no rk818, so do nothing here\n");
|
||||
if (!rk808)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK818_DEVCTRL_REG,
|
||||
DEV_OFF, DEV_OFF);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "power off error!\n");
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
}
|
||||
|
||||
static void rk8xx_syscore_shutdown(void)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
int ret;
|
||||
|
||||
if (system_state == SYSTEM_POWER_OFF &&
|
||||
(rk808->variant == RK809_ID || rk808->variant == RK817_ID)) {
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_DN_FUN);
|
||||
if (ret) {
|
||||
dev_warn(&rk808_i2c_client->dev,
|
||||
"Cannot switch to power down function\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct syscore_ops rk808_syscore_ops = {
|
||||
.shutdown = rk8xx_syscore_shutdown,
|
||||
};
|
||||
|
||||
static const struct of_device_id rk808_of_match[] = {
|
||||
{ .compatible = "rockchip,rk805" },
|
||||
{ .compatible = "rockchip,rk808" },
|
||||
{ .compatible = "rockchip,rk809" },
|
||||
{ .compatible = "rockchip,rk817" },
|
||||
{ .compatible = "rockchip,rk818" },
|
||||
{ },
|
||||
};
|
||||
@ -430,10 +560,10 @@ static int rk808_probe(struct i2c_client *client,
|
||||
struct rk808 *rk808;
|
||||
const struct rk808_reg_data *pre_init_reg;
|
||||
const struct mfd_cell *cells;
|
||||
void (*pm_pwroff_fn)(void);
|
||||
int nr_pre_init_regs;
|
||||
int nr_cells;
|
||||
int pm_off = 0, msb, lsb;
|
||||
unsigned char pmic_id_msb, pmic_id_lsb;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@ -441,15 +571,24 @@ static int rk808_probe(struct i2c_client *client,
|
||||
if (!rk808)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_device_is_compatible(np, "rockchip,rk817") ||
|
||||
of_device_is_compatible(np, "rockchip,rk809")) {
|
||||
pmic_id_msb = RK817_ID_MSB;
|
||||
pmic_id_lsb = RK817_ID_LSB;
|
||||
} else {
|
||||
pmic_id_msb = RK808_ID_MSB;
|
||||
pmic_id_lsb = RK808_ID_LSB;
|
||||
}
|
||||
|
||||
/* Read chip variant */
|
||||
msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB);
|
||||
msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
|
||||
if (msb < 0) {
|
||||
dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
|
||||
RK808_ID_MSB);
|
||||
return msb;
|
||||
}
|
||||
|
||||
lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB);
|
||||
lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
|
||||
if (lsb < 0) {
|
||||
dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
|
||||
RK808_ID_LSB);
|
||||
@ -467,7 +606,8 @@ static int rk808_probe(struct i2c_client *client,
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
|
||||
cells = rk805s;
|
||||
nr_cells = ARRAY_SIZE(rk805s);
|
||||
pm_pwroff_fn = rk805_device_shutdown;
|
||||
rk808->pm_pwroff_fn = rk805_device_shutdown;
|
||||
rk808->pm_pwroff_prep_fn = rk805_device_shutdown_prepare;
|
||||
break;
|
||||
case RK808_ID:
|
||||
rk808->regmap_cfg = &rk808_regmap_config;
|
||||
@ -476,7 +616,7 @@ static int rk808_probe(struct i2c_client *client,
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
|
||||
cells = rk808s;
|
||||
nr_cells = ARRAY_SIZE(rk808s);
|
||||
pm_pwroff_fn = rk808_device_shutdown;
|
||||
rk808->pm_pwroff_fn = rk808_device_shutdown;
|
||||
break;
|
||||
case RK818_ID:
|
||||
rk808->regmap_cfg = &rk818_regmap_config;
|
||||
@ -485,7 +625,17 @@ static int rk808_probe(struct i2c_client *client,
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
|
||||
cells = rk818s;
|
||||
nr_cells = ARRAY_SIZE(rk818s);
|
||||
pm_pwroff_fn = rk818_device_shutdown;
|
||||
rk808->pm_pwroff_fn = rk818_device_shutdown;
|
||||
break;
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
rk808->regmap_cfg = &rk817_regmap_config;
|
||||
rk808->regmap_irq_chip = &rk817_irq_chip;
|
||||
pre_init_reg = rk817_pre_init_reg;
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
|
||||
cells = rk817s;
|
||||
nr_cells = ARRAY_SIZE(rk817s);
|
||||
register_syscore_ops(&rk808_syscore_ops);
|
||||
break;
|
||||
default:
|
||||
dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
|
||||
@ -540,7 +690,13 @@ static int rk808_probe(struct i2c_client *client,
|
||||
"rockchip,system-power-controller");
|
||||
if (pm_off && !pm_power_off) {
|
||||
rk808_i2c_client = client;
|
||||
pm_power_off = pm_pwroff_fn;
|
||||
pm_power_off = rk808->pm_pwroff_fn;
|
||||
}
|
||||
|
||||
if (pm_off && !pm_power_off_prepare) {
|
||||
if (!rk808_i2c_client)
|
||||
rk808_i2c_client = client;
|
||||
pm_power_off_prepare = rk808->pm_pwroff_prep_fn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -555,15 +711,70 @@ static int rk808_remove(struct i2c_client *client)
|
||||
struct rk808 *rk808 = i2c_get_clientdata(client);
|
||||
|
||||
regmap_del_irq_chip(client->irq, rk808->irq_data);
|
||||
pm_power_off = NULL;
|
||||
|
||||
/**
|
||||
* pm_power_off may points to a function from another module.
|
||||
* Check if the pointer is set by us and only then overwrite it.
|
||||
*/
|
||||
if (rk808->pm_pwroff_fn && pm_power_off == rk808->pm_pwroff_fn)
|
||||
pm_power_off = NULL;
|
||||
|
||||
/**
|
||||
* As above, check if the pointer is set by us before overwrite.
|
||||
*/
|
||||
if (rk808->pm_pwroff_prep_fn &&
|
||||
pm_power_off_prepare == rk808->pm_pwroff_prep_fn)
|
||||
pm_power_off_prepare = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk8xx_suspend(struct device *dev)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
int ret = 0;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_SLP_FUN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk8xx_resume(struct device *dev)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
int ret = 0;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_NULL_FUN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
|
||||
|
||||
static struct i2c_driver rk808_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rk808",
|
||||
.of_match_table = rk808_of_match,
|
||||
.pm = &rk8xx_pm_ops,
|
||||
},
|
||||
.probe = rk808_probe,
|
||||
.remove = rk808_remove,
|
||||
|
316
drivers/mfd/rohm-bd70528.c
Normal file
316
drivers/mfd/rohm-bd70528.c
Normal file
@ -0,0 +1,316 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Copyright (C) 2019 ROHM Semiconductors
|
||||
//
|
||||
// ROHM BD70528 PMIC driver
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BD70528_NUM_OF_GPIOS 4
|
||||
|
||||
static const struct resource rtc_irqs[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_RTC_ALARM, "bd70528-rtc-alm"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_ELPS_TIM, "bd70528-elapsed-timer"),
|
||||
};
|
||||
|
||||
static const struct resource charger_irqs[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BAT_OV_RES, "bd70528-bat-ov-res"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BAT_OV_DET, "bd70528-bat-ov-det"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DBAT_DET, "bd70528-bat-dead"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BATTSD_COLD_RES, "bd70528-bat-warmed"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BATTSD_COLD_DET, "bd70528-bat-cold"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BATTSD_HOT_RES, "bd70528-bat-cooled"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BATTSD_HOT_DET, "bd70528-bat-hot"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_CHG_TSD, "bd70528-chg-tshd"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BAT_RMV, "bd70528-bat-removed"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_BAT_DET, "bd70528-bat-detected"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN2_OV_RES, "bd70528-dcin2-ov-res"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN2_OV_DET, "bd70528-dcin2-ov-det"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN2_RMV, "bd70528-dcin2-removed"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN2_DET, "bd70528-dcin2-detected"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN1_RMV, "bd70528-dcin1-removed"),
|
||||
DEFINE_RES_IRQ_NAMED(BD70528_INT_DCIN1_DET, "bd70528-dcin1-detected"),
|
||||
};
|
||||
|
||||
static struct mfd_cell bd70528_mfd_cells[] = {
|
||||
{ .name = "bd70528-pmic", },
|
||||
{ .name = "bd70528-gpio", },
|
||||
/*
|
||||
* 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-wdt", },
|
||||
{
|
||||
.name = "bd70528-power",
|
||||
.resources = charger_irqs,
|
||||
.num_resources = ARRAY_SIZE(charger_irqs),
|
||||
}, {
|
||||
.name = "bd70528-rtc",
|
||||
.resources = rtc_irqs,
|
||||
.num_resources = ARRAY_SIZE(rtc_irqs),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_range volatile_ranges[] = {
|
||||
{
|
||||
.range_min = BD70528_REG_INT_MAIN,
|
||||
.range_max = BD70528_REG_INT_OP_FAIL,
|
||||
}, {
|
||||
.range_min = BD70528_REG_RTC_COUNT_H,
|
||||
.range_max = BD70528_REG_RTC_ALM_REPEAT,
|
||||
}, {
|
||||
/*
|
||||
* WDT control reg is special. Magic values must be written to
|
||||
* it in order to change the control. Should not be cached.
|
||||
*/
|
||||
.range_min = BD70528_REG_WDT_CTRL,
|
||||
.range_max = BD70528_REG_WDT_CTRL,
|
||||
}, {
|
||||
/*
|
||||
* BD70528 also contains a few other registers which require
|
||||
* magic sequences to be written in order to update the value.
|
||||
* At least SHIPMODE, HWRESET, WARMRESET,and STANDBY
|
||||
*/
|
||||
.range_min = BD70528_REG_SHIPMODE,
|
||||
.range_max = BD70528_REG_STANDBY,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_access_table volatile_regs = {
|
||||
.yes_ranges = &volatile_ranges[0],
|
||||
.n_yes_ranges = ARRAY_SIZE(volatile_ranges),
|
||||
};
|
||||
|
||||
static struct regmap_config bd70528_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_table = &volatile_regs,
|
||||
.max_register = BD70528_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.
|
||||
*/
|
||||
|
||||
/* bit [0] - Shutdown register */
|
||||
unsigned int bit0_offsets[] = {0}; /* Shutdown register */
|
||||
unsigned int bit1_offsets[] = {1}; /* Power failure register */
|
||||
unsigned int bit2_offsets[] = {2}; /* VR FAULT register */
|
||||
unsigned int bit3_offsets[] = {3}; /* PMU register interrupts */
|
||||
unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 registers */
|
||||
unsigned int bit5_offsets[] = {6}; /* RTC register */
|
||||
unsigned int bit6_offsets[] = {7}; /* GPIO register */
|
||||
unsigned int bit7_offsets[] = {8}; /* Invalid operation register */
|
||||
|
||||
static struct regmap_irq_sub_irq_map bd70528_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 bd70528_irqs[] = {
|
||||
REGMAP_IRQ_REG(BD70528_INT_LONGPUSH, 0, BD70528_INT_LONGPUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_WDT, 0, BD70528_INT_WDT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_HWRESET, 0, BD70528_INT_HWRESET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_RSTB_FAULT, 0, BD70528_INT_RSTB_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_VBAT_UVLO, 0, BD70528_INT_VBAT_UVLO_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_TSD, 0, BD70528_INT_TSD_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_RSTIN, 0, BD70528_INT_RSTIN_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK1_FAULT, 1,
|
||||
BD70528_INT_BUCK1_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK2_FAULT, 1,
|
||||
BD70528_INT_BUCK2_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK3_FAULT, 1,
|
||||
BD70528_INT_BUCK3_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LDO1_FAULT, 1, BD70528_INT_LDO1_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LDO2_FAULT, 1, BD70528_INT_LDO2_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LDO3_FAULT, 1, BD70528_INT_LDO3_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED1_FAULT, 1, BD70528_INT_LED1_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED2_FAULT, 1, BD70528_INT_LED2_FAULT_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK1_OCP, 2, BD70528_INT_BUCK1_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK2_OCP, 2, BD70528_INT_BUCK2_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK3_OCP, 2, BD70528_INT_BUCK3_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED1_OCP, 2, BD70528_INT_LED1_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED2_OCP, 2, BD70528_INT_LED2_OCP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK1_FULLON, 2,
|
||||
BD70528_INT_BUCK1_FULLON_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK2_FULLON, 2,
|
||||
BD70528_INT_BUCK2_FULLON_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_SHORTPUSH, 3, BD70528_INT_SHORTPUSH_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_AUTO_WAKEUP, 3,
|
||||
BD70528_INT_AUTO_WAKEUP_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_STATE_CHANGE, 3,
|
||||
BD70528_INT_STATE_CHANGE_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BAT_OV_RES, 4, BD70528_INT_BAT_OV_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BAT_OV_DET, 4, BD70528_INT_BAT_OV_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DBAT_DET, 4, BD70528_INT_DBAT_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BATTSD_COLD_RES, 4,
|
||||
BD70528_INT_BATTSD_COLD_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BATTSD_COLD_DET, 4,
|
||||
BD70528_INT_BATTSD_COLD_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BATTSD_HOT_RES, 4,
|
||||
BD70528_INT_BATTSD_HOT_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BATTSD_HOT_DET, 4,
|
||||
BD70528_INT_BATTSD_HOT_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_CHG_TSD, 4, BD70528_INT_CHG_TSD_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BAT_RMV, 5, BD70528_INT_BAT_RMV_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BAT_DET, 5, BD70528_INT_BAT_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN2_OV_RES, 5,
|
||||
BD70528_INT_DCIN2_OV_RES_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN2_OV_DET, 5,
|
||||
BD70528_INT_DCIN2_OV_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN2_RMV, 5, BD70528_INT_DCIN2_RMV_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN2_DET, 5, BD70528_INT_DCIN2_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN1_RMV, 5, BD70528_INT_DCIN1_RMV_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_DCIN1_DET, 5, BD70528_INT_DCIN1_DET_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_RTC_ALARM, 6, BD70528_INT_RTC_ALARM_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_ELPS_TIM, 6, BD70528_INT_ELPS_TIM_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_GPIO0, 7, BD70528_INT_GPIO0_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_GPIO1, 7, BD70528_INT_GPIO1_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_GPIO2, 7, BD70528_INT_GPIO2_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_GPIO3, 7, BD70528_INT_GPIO3_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK1_DVS_OPFAIL, 8,
|
||||
BD70528_INT_BUCK1_DVS_OPFAIL_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK2_DVS_OPFAIL, 8,
|
||||
BD70528_INT_BUCK2_DVS_OPFAIL_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_BUCK3_DVS_OPFAIL, 8,
|
||||
BD70528_INT_BUCK3_DVS_OPFAIL_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED1_VOLT_OPFAIL, 8,
|
||||
BD70528_INT_LED1_VOLT_OPFAIL_MASK),
|
||||
REGMAP_IRQ_REG(BD70528_INT_LED2_VOLT_OPFAIL, 8,
|
||||
BD70528_INT_LED2_VOLT_OPFAIL_MASK),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip bd70528_irq_chip = {
|
||||
.name = "bd70528_irq",
|
||||
.main_status = BD70528_REG_INT_MAIN,
|
||||
.irqs = &bd70528_irqs[0],
|
||||
.num_irqs = ARRAY_SIZE(bd70528_irqs),
|
||||
.status_base = BD70528_REG_INT_SHDN,
|
||||
.mask_base = BD70528_REG_INT_SHDN_MASK,
|
||||
.ack_base = BD70528_REG_INT_SHDN,
|
||||
.type_base = BD70528_REG_GPIO1_IN,
|
||||
.init_ack_masked = true,
|
||||
.num_regs = 9,
|
||||
.num_main_regs = 1,
|
||||
.num_type_reg = 4,
|
||||
.sub_reg_offsets = &bd70528_sub_irq_offsets[0],
|
||||
.num_main_status_bits = 8,
|
||||
.irq_reg_stride = 1,
|
||||
};
|
||||
|
||||
static int bd70528_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct bd70528_data *bd70528;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
int ret, i;
|
||||
|
||||
if (!i2c->irq) {
|
||||
dev_err(&i2c->dev, "No IRQ configured\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bd70528 = devm_kzalloc(&i2c->dev, sizeof(*bd70528), GFP_KERNEL);
|
||||
if (!bd70528)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&bd70528->rtc_timer_lock);
|
||||
|
||||
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");
|
||||
return PTR_ERR(bd70528->chip.regmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow type setting for all IRQs by default as most of them do not
|
||||
* support setting type.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(bd70528_irqs); i++)
|
||||
bd70528_irqs[i].type.types_supported = 0;
|
||||
|
||||
/* Set IRQ typesetting information for GPIO pins 0 - 3 */
|
||||
for (i = 0; i < BD70528_NUM_OF_GPIOS; i++) {
|
||||
struct regmap_irq_type *type;
|
||||
|
||||
type = &bd70528_irqs[BD70528_INT_GPIO0 + i].type;
|
||||
type->type_reg_offset = 2 * i;
|
||||
type->type_rising_val = 0x20;
|
||||
type->type_falling_val = 0x10;
|
||||
type->type_level_high_val = 0x40;
|
||||
type->type_level_low_val = 0x50;
|
||||
type->types_supported = (IRQ_TYPE_EDGE_BOTH |
|
||||
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW);
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&i2c->dev, bd70528->chip.regmap,
|
||||
i2c->irq, IRQF_ONESHOT, 0,
|
||||
&bd70528_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",
|
||||
bd70528_irq_chip.num_irqs);
|
||||
|
||||
/*
|
||||
* BD70528 IRQ controller is not touching the main mask register.
|
||||
* So enable the GPIO block interrupts at main level. We can just leave
|
||||
* them enabled as the IRQ controller should disable IRQs from
|
||||
* sub-registers when IRQ is disabled or freed.
|
||||
*/
|
||||
ret = regmap_update_bits(bd70528->chip.regmap,
|
||||
BD70528_REG_INT_MAIN_MASK,
|
||||
BD70528_INT_GPIO_MASK, 0);
|
||||
|
||||
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
|
||||
bd70528_mfd_cells,
|
||||
ARRAY_SIZE(bd70528_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 bd70528_of_match[] = {
|
||||
{ .compatible = "rohm,bd70528", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd70528_of_match);
|
||||
|
||||
static struct i2c_driver bd70528_drv = {
|
||||
.driver = {
|
||||
.name = "rohm-bd70528",
|
||||
.of_match_table = bd70528_of_match,
|
||||
},
|
||||
.probe = &bd70528_i2c_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(bd70528_drv);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("ROHM BD70528 Power Management IC driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -81,6 +81,44 @@ static const struct regmap_config bd718xx_regmap_config = {
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int bd718xx_init_press_duration(struct bd718xx *bd718xx)
|
||||
{
|
||||
struct device* dev = bd718xx->chip.dev;
|
||||
u32 short_press_ms, long_press_ms;
|
||||
u32 short_press_value, long_press_value;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "rohm,short-press-ms",
|
||||
&short_press_ms);
|
||||
if (!ret) {
|
||||
short_press_value = min(15u, (short_press_ms + 250) / 500);
|
||||
ret = regmap_update_bits(bd718xx->chip.regmap,
|
||||
BD718XX_REG_PWRONCONFIG0,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
short_press_value);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init pwron short press\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "rohm,long-press-ms",
|
||||
&long_press_ms);
|
||||
if (!ret) {
|
||||
long_press_value = min(15u, (long_press_ms + 500) / 1000);
|
||||
ret = regmap_update_bits(bd718xx->chip.regmap,
|
||||
BD718XX_REG_PWRONCONFIG1,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
long_press_value);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init pwron long press\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -98,18 +136,19 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
return -ENOMEM;
|
||||
|
||||
bd718xx->chip_irq = i2c->irq;
|
||||
bd718xx->chip_type = (unsigned int)(uintptr_t)
|
||||
bd718xx->chip.chip_type = (unsigned int)(uintptr_t)
|
||||
of_device_get_match_data(&i2c->dev);
|
||||
bd718xx->dev = &i2c->dev;
|
||||
bd718xx->chip.dev = &i2c->dev;
|
||||
dev_set_drvdata(&i2c->dev, bd718xx);
|
||||
|
||||
bd718xx->regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config);
|
||||
if (IS_ERR(bd718xx->regmap)) {
|
||||
bd718xx->chip.regmap = devm_regmap_init_i2c(i2c,
|
||||
&bd718xx_regmap_config);
|
||||
if (IS_ERR(bd718xx->chip.regmap)) {
|
||||
dev_err(&i2c->dev, "regmap initialization failed\n");
|
||||
return PTR_ERR(bd718xx->regmap);
|
||||
return PTR_ERR(bd718xx->chip.regmap);
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->regmap,
|
||||
ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->chip.regmap,
|
||||
bd718xx->chip_irq, IRQF_ONESHOT, 0,
|
||||
&bd718xx_irq_chip, &bd718xx->irq_data);
|
||||
if (ret) {
|
||||
@ -117,28 +156,9 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure short press to 10 milliseconds */
|
||||
ret = regmap_update_bits(bd718xx->regmap,
|
||||
BD718XX_REG_PWRONCONFIG0,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
BD718XX_PWRBTN_SHORT_PRESS_10MS);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to configure button short press timeout\n");
|
||||
ret = bd718xx_init_press_duration(bd718xx);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure long press to 10 seconds */
|
||||
ret = regmap_update_bits(bd718xx->regmap,
|
||||
BD718XX_REG_PWRONCONFIG1,
|
||||
BD718XX_PWRBTN_PRESS_DURATION_MASK,
|
||||
BD718XX_PWRBTN_LONG_PRESS_10S);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev,
|
||||
"Failed to configure button long press timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S);
|
||||
|
||||
@ -149,7 +169,7 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
button.irq = ret;
|
||||
|
||||
ret = devm_mfd_add_devices(bd718xx->dev, PLATFORM_DEVID_AUTO,
|
||||
ret = devm_mfd_add_devices(bd718xx->chip.dev, PLATFORM_DEVID_AUTO,
|
||||
bd718xx_mfd_cells,
|
||||
ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0,
|
||||
regmap_irq_get_domain(bd718xx->irq_data));
|
||||
@ -162,11 +182,11 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
|
||||
static const struct of_device_id bd718xx_of_match[] = {
|
||||
{
|
||||
.compatible = "rohm,bd71837",
|
||||
.data = (void *)BD718XX_TYPE_BD71837,
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD71837,
|
||||
},
|
||||
{
|
||||
.compatible = "rohm,bd71847",
|
||||
.data = (void *)BD718XX_TYPE_BD71847,
|
||||
.data = (void *)ROHM_CHIP_TYPE_BD71847,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
@ -689,4 +689,13 @@ config CHARGER_UCS1002
|
||||
Say Y to enable support for Microchip UCS1002 Programmable
|
||||
USB Port Power Controller with Charger Emulation.
|
||||
|
||||
config CHARGER_BD70528
|
||||
tristate "ROHM bd70528 charger driver"
|
||||
depends on MFD_ROHM_BD70528
|
||||
default n
|
||||
help
|
||||
Say Y here to enable support for getting battery status
|
||||
information and altering charger configurations from charger
|
||||
block of the ROHM BD70528 Power Management IC.
|
||||
|
||||
endif # POWER_SUPPLY
|
||||
|
@ -90,3 +90,4 @@ obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o
|
||||
obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o
|
||||
obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o
|
||||
obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o
|
||||
obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o
|
||||
|
743
drivers/power/supply/bd70528-charger.c
Normal file
743
drivers/power/supply/bd70528-charger.c
Normal file
@ -0,0 +1,743 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Copyright (C) 2018 ROHM Semiconductors
|
||||
//
|
||||
// power-supply driver for ROHM BD70528 PMIC
|
||||
|
||||
/*
|
||||
* BD70528 charger HW state machine.
|
||||
*
|
||||
* The thermal shutdown state is not drawn. From any other state but
|
||||
* battery error and suspend it is possible to go to TSD/TMP states
|
||||
* if temperature is out of bounds.
|
||||
*
|
||||
* CHG_RST = H
|
||||
* or CHG_EN=L
|
||||
* or (DCIN2_UVLO=L && DCIN1_UVLO=L)
|
||||
* or (DCIN2_OVLO=H & DCIN1_UVKLO=L)
|
||||
*
|
||||
* +--------------+ +--------------+
|
||||
* | | | |
|
||||
* | Any state +-------> | Suspend |
|
||||
* | | | |
|
||||
* +--------------+ +------+-------+
|
||||
* |
|
||||
* CHG_EN = H && BAT_DET = H && |
|
||||
* No errors (temp, bat_ov, UVLO, |
|
||||
* OVLO...) |
|
||||
* |
|
||||
* BAT_OV or +---------v----------+
|
||||
* (DBAT && TTRI) | |
|
||||
* +-----------------+ Trickle Charge | <---------------+
|
||||
* | | | |
|
||||
* | +-------+------------+ |
|
||||
* | | |
|
||||
* | | ^ |
|
||||
* | V_BAT > VTRI_TH | | VBAT < VTRI_TH - 50mV |
|
||||
* | | | |
|
||||
* | v | |
|
||||
* | | |
|
||||
* | BAT_OV or +----------+----+ |
|
||||
* | (DBAT && TFST) | | |
|
||||
* | +----------------+ Fast Charge | |
|
||||
* | | | | |
|
||||
* v v +----+----------+ |
|
||||
* | |
|
||||
*+----------------+ ILIM_DET=L | ^ ILIM_DET |
|
||||
*| | & CV_DET=H | | or CV_DET=L |
|
||||
*| Battery Error | & VBAT > | | or VBAT < VRECHG_TH |
|
||||
*| | VRECHG_TH | | or IBAT > IFST/x |
|
||||
*+----------------+ & IBAT < | | |
|
||||
* IFST/x v | |
|
||||
* ^ | |
|
||||
* | +---------+-+ |
|
||||
* | | | |
|
||||
* +-------------------+ Top OFF | |
|
||||
* BAT_OV = H or | | |
|
||||
* (DBAT && TFST) +-----+-----+ |
|
||||
* | |
|
||||
* Stay top-off for 15s | |
|
||||
* v |
|
||||
* |
|
||||
* +--------+ |
|
||||
* | | |
|
||||
* | Done +-------------------------+
|
||||
* | |
|
||||
* +--------+ VBAT < VRECHG_TH
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#define CHG_STAT_SUSPEND 0x0
|
||||
#define CHG_STAT_TRICKLE 0x1
|
||||
#define CHG_STAT_FAST 0x3
|
||||
#define CHG_STAT_TOPOFF 0xe
|
||||
#define CHG_STAT_DONE 0xf
|
||||
#define CHG_STAT_OTP_TRICKLE 0x10
|
||||
#define CHG_STAT_OTP_FAST 0x11
|
||||
#define CHG_STAT_OTP_DONE 0x12
|
||||
#define CHG_STAT_TSD_TRICKLE 0x20
|
||||
#define CHG_STAT_TSD_FAST 0x21
|
||||
#define CHG_STAT_TSD_TOPOFF 0x22
|
||||
#define CHG_STAT_BAT_ERR 0x7f
|
||||
|
||||
static const char *bd70528_charger_model = "BD70528";
|
||||
static const char *bd70528_charger_manufacturer = "ROHM Semiconductors";
|
||||
|
||||
#define BD_ERR_IRQ_HND(_name_, _wrn_) \
|
||||
static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \
|
||||
{ \
|
||||
struct power_supply *psy = (struct power_supply *)arg; \
|
||||
\
|
||||
power_supply_changed(psy); \
|
||||
dev_err(&psy->dev, (_wrn_)); \
|
||||
\
|
||||
return IRQ_HANDLED; \
|
||||
}
|
||||
|
||||
#define BD_INFO_IRQ_HND(_name_, _wrn_) \
|
||||
static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \
|
||||
{ \
|
||||
struct power_supply *psy = (struct power_supply *)arg; \
|
||||
\
|
||||
power_supply_changed(psy); \
|
||||
dev_dbg(&psy->dev, (_wrn_)); \
|
||||
\
|
||||
return IRQ_HANDLED; \
|
||||
}
|
||||
|
||||
#define BD_IRQ_HND(_name_) bd0528_##_name_##_interrupt
|
||||
|
||||
struct bd70528_psy {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
struct power_supply *psy;
|
||||
};
|
||||
|
||||
BD_ERR_IRQ_HND(BAT_OV_DET, "Battery overvoltage detected\n");
|
||||
BD_ERR_IRQ_HND(DBAT_DET, "Dead battery detected\n");
|
||||
BD_ERR_IRQ_HND(COLD_DET, "Battery cold\n");
|
||||
BD_ERR_IRQ_HND(HOT_DET, "Battery hot\n");
|
||||
BD_ERR_IRQ_HND(CHG_TSD, "Charger thermal shutdown\n");
|
||||
BD_ERR_IRQ_HND(DCIN2_OV_DET, "DCIN2 overvoltage detected\n");
|
||||
|
||||
BD_INFO_IRQ_HND(BAT_OV_RES, "Battery voltage back to normal\n");
|
||||
BD_INFO_IRQ_HND(COLD_RES, "Battery temperature back to normal\n");
|
||||
BD_INFO_IRQ_HND(HOT_RES, "Battery temperature back to normal\n");
|
||||
BD_INFO_IRQ_HND(BAT_RMV, "Battery removed\n");
|
||||
BD_INFO_IRQ_HND(BAT_DET, "Battery detected\n");
|
||||
BD_INFO_IRQ_HND(DCIN2_OV_RES, "DCIN2 voltage back to normal\n");
|
||||
BD_INFO_IRQ_HND(DCIN2_RMV, "DCIN2 removed\n");
|
||||
BD_INFO_IRQ_HND(DCIN2_DET, "DCIN2 detected\n");
|
||||
BD_INFO_IRQ_HND(DCIN1_RMV, "DCIN1 removed\n");
|
||||
BD_INFO_IRQ_HND(DCIN1_DET, "DCIN1 detected\n");
|
||||
|
||||
struct irq_name_pair {
|
||||
const char *n;
|
||||
irqreturn_t (*h)(int irq, void *arg);
|
||||
};
|
||||
|
||||
static int bd70528_get_irqs(struct platform_device *pdev,
|
||||
struct bd70528_psy *bdpsy)
|
||||
{
|
||||
int irq, i, ret;
|
||||
unsigned int mask;
|
||||
static const struct irq_name_pair bd70528_chg_irqs[] = {
|
||||
{ .n = "bd70528-bat-ov-res", .h = BD_IRQ_HND(BAT_OV_RES) },
|
||||
{ .n = "bd70528-bat-ov-det", .h = BD_IRQ_HND(BAT_OV_DET) },
|
||||
{ .n = "bd70528-bat-dead", .h = BD_IRQ_HND(DBAT_DET) },
|
||||
{ .n = "bd70528-bat-warmed", .h = BD_IRQ_HND(COLD_RES) },
|
||||
{ .n = "bd70528-bat-cold", .h = BD_IRQ_HND(COLD_DET) },
|
||||
{ .n = "bd70528-bat-cooled", .h = BD_IRQ_HND(HOT_RES) },
|
||||
{ .n = "bd70528-bat-hot", .h = BD_IRQ_HND(HOT_DET) },
|
||||
{ .n = "bd70528-chg-tshd", .h = BD_IRQ_HND(CHG_TSD) },
|
||||
{ .n = "bd70528-bat-removed", .h = BD_IRQ_HND(BAT_RMV) },
|
||||
{ .n = "bd70528-bat-detected", .h = BD_IRQ_HND(BAT_DET) },
|
||||
{ .n = "bd70528-dcin2-ov-res", .h = BD_IRQ_HND(DCIN2_OV_RES) },
|
||||
{ .n = "bd70528-dcin2-ov-det", .h = BD_IRQ_HND(DCIN2_OV_DET) },
|
||||
{ .n = "bd70528-dcin2-removed", .h = BD_IRQ_HND(DCIN2_RMV) },
|
||||
{ .n = "bd70528-dcin2-detected", .h = BD_IRQ_HND(DCIN2_DET) },
|
||||
{ .n = "bd70528-dcin1-removed", .h = BD_IRQ_HND(DCIN1_RMV) },
|
||||
{ .n = "bd70528-dcin1-detected", .h = BD_IRQ_HND(DCIN1_DET) },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bd70528_chg_irqs); i++) {
|
||||
irq = platform_get_irq_byname(pdev, bd70528_chg_irqs[i].n);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Bad IRQ information for %s (%d)\n",
|
||||
bd70528_chg_irqs[i].n, irq);
|
||||
return irq;
|
||||
}
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
bd70528_chg_irqs[i].h,
|
||||
IRQF_ONESHOT,
|
||||
bd70528_chg_irqs[i].n,
|
||||
bdpsy->psy);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* BD70528 irq controller is not touching the main mask register.
|
||||
* So enable the charger block interrupts at main level. We can just
|
||||
* leave them enabled as irq-controller should disable irqs
|
||||
* from sub-registers when IRQ is disabled or freed.
|
||||
*/
|
||||
mask = BD70528_REG_INT_BAT1_MASK | BD70528_REG_INT_BAT2_MASK;
|
||||
ret = regmap_update_bits(bdpsy->regmap,
|
||||
BD70528_REG_INT_MAIN_MASK, mask, 0);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to enable charger IRQs\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_get_charger_status(struct bd70528_psy *bdpsy, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int v;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev, "Charger state read failure %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (v & BD70528_MASK_CHG_STAT) {
|
||||
case CHG_STAT_SUSPEND:
|
||||
/* Maybe we should check the CHG_TTRI_EN? */
|
||||
case CHG_STAT_OTP_TRICKLE:
|
||||
case CHG_STAT_OTP_FAST:
|
||||
case CHG_STAT_OTP_DONE:
|
||||
case CHG_STAT_TSD_TRICKLE:
|
||||
case CHG_STAT_TSD_FAST:
|
||||
case CHG_STAT_TSD_TOPOFF:
|
||||
case CHG_STAT_BAT_ERR:
|
||||
*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
break;
|
||||
case CHG_STAT_DONE:
|
||||
*val = POWER_SUPPLY_STATUS_FULL;
|
||||
break;
|
||||
case CHG_STAT_TRICKLE:
|
||||
case CHG_STAT_FAST:
|
||||
case CHG_STAT_TOPOFF:
|
||||
*val = POWER_SUPPLY_STATUS_CHARGING;
|
||||
break;
|
||||
default:
|
||||
*val = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_get_charge_type(struct bd70528_psy *bdpsy, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int v;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev, "Charger state read failure %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (v & BD70528_MASK_CHG_STAT) {
|
||||
case CHG_STAT_TRICKLE:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
|
||||
break;
|
||||
case CHG_STAT_FAST:
|
||||
case CHG_STAT_TOPOFF:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||
break;
|
||||
case CHG_STAT_DONE:
|
||||
case CHG_STAT_SUSPEND:
|
||||
/* Maybe we should check the CHG_TTRI_EN? */
|
||||
case CHG_STAT_OTP_TRICKLE:
|
||||
case CHG_STAT_OTP_FAST:
|
||||
case CHG_STAT_OTP_DONE:
|
||||
case CHG_STAT_TSD_TRICKLE:
|
||||
case CHG_STAT_TSD_FAST:
|
||||
case CHG_STAT_TSD_TOPOFF:
|
||||
case CHG_STAT_BAT_ERR:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
|
||||
break;
|
||||
default:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_get_battery_health(struct bd70528_psy *bdpsy, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int v;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev, "Battery state read failure %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
/* No battery? */
|
||||
if (!(v & BD70528_MASK_CHG_BAT_DETECT))
|
||||
*val = POWER_SUPPLY_HEALTH_DEAD;
|
||||
else if (v & BD70528_MASK_CHG_BAT_OVERVOLT)
|
||||
*val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
else if (v & BD70528_MASK_CHG_BAT_TIMER)
|
||||
*val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
|
||||
else
|
||||
*val = POWER_SUPPLY_HEALTH_GOOD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_get_online(struct bd70528_psy *bdpsy, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int v;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_IN_STAT, &v);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev, "DC1 IN state read failure %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = (v & BD70528_MASK_CHG_DCIN1_UVLO) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int v;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev, "Battery state read failure %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = (v & BD70528_MASK_CHG_BAT_DETECT) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct linear_range {
|
||||
int min;
|
||||
int step;
|
||||
int vals;
|
||||
int low_sel;
|
||||
};
|
||||
|
||||
static const struct linear_range current_limit_ranges[] = {
|
||||
{
|
||||
.min = 5,
|
||||
.step = 1,
|
||||
.vals = 36,
|
||||
.low_sel = 0,
|
||||
},
|
||||
{
|
||||
.min = 40,
|
||||
.step = 5,
|
||||
.vals = 5,
|
||||
.low_sel = 0x23,
|
||||
},
|
||||
{
|
||||
.min = 60,
|
||||
.step = 20,
|
||||
.vals = 8,
|
||||
.low_sel = 0x27,
|
||||
},
|
||||
{
|
||||
.min = 200,
|
||||
.step = 50,
|
||||
.vals = 7,
|
||||
.low_sel = 0x2e,
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* BD70528 would support setting and getting own charge current/
|
||||
* voltage for low temperatures. The driver currently only reads
|
||||
* the charge current at room temperature. We do set both though.
|
||||
*/
|
||||
static const struct linear_range warm_charge_curr[] = {
|
||||
{
|
||||
.min = 10,
|
||||
.step = 10,
|
||||
.vals = 20,
|
||||
.low_sel = 0,
|
||||
},
|
||||
{
|
||||
.min = 200,
|
||||
.step = 25,
|
||||
.vals = 13,
|
||||
.low_sel = 0x13,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Cold charge current selectors are identical to warm charge current
|
||||
* selectors. The difference is that only smaller currents are available
|
||||
* at cold charge range.
|
||||
*/
|
||||
#define MAX_COLD_CHG_CURR_SEL 0x15
|
||||
#define MAX_WARM_CHG_CURR_SEL 0x1f
|
||||
#define MIN_CHG_CURR_SEL 0x0
|
||||
|
||||
static int find_value_for_selector_low(const struct linear_range *r,
|
||||
int selectors, unsigned int sel,
|
||||
unsigned int *val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < selectors; i++) {
|
||||
if (r[i].low_sel <= sel && r[i].low_sel + r[i].vals >= sel) {
|
||||
*val = r[i].min + (sel - r[i].low_sel) * r[i].step;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For BD70528 voltage/current limits we happily accept any value which
|
||||
* belongs the range. We could check if value matching the selector is
|
||||
* desired by computing the range min + (sel - sel_low) * range step - but
|
||||
* I guess it is enough if we use voltage/current which is closest (below)
|
||||
* the requested?
|
||||
*/
|
||||
static int find_selector_for_value_low(const struct linear_range *r,
|
||||
int selectors, unsigned int val,
|
||||
unsigned int *sel, bool *found)
|
||||
{
|
||||
int i;
|
||||
int ret = -EINVAL;
|
||||
|
||||
*found = false;
|
||||
for (i = 0; i < selectors; i++) {
|
||||
if (r[i].min <= val) {
|
||||
if (r[i].min + r[i].step * r[i].vals >= val) {
|
||||
*found = true;
|
||||
*sel = r[i].low_sel + (val - r[i].min) /
|
||||
r[i].step;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If the range max is smaller than requested
|
||||
* we can set the max supported value from range
|
||||
*/
|
||||
*sel = r[i].low_sel + r[i].vals;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
|
||||
{
|
||||
unsigned int sel;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CHG_CURR_WARM,
|
||||
&sel);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev,
|
||||
"Charge current reading failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sel &= BD70528_MASK_CHG_CHG_CURR;
|
||||
|
||||
ret = find_value_for_selector_low(&warm_charge_curr[0],
|
||||
ARRAY_SIZE(warm_charge_curr), sel,
|
||||
ma);
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev,
|
||||
"Unknown charge current value 0x%x\n",
|
||||
sel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_current_limit(struct bd70528_psy *bdpsy, int *ma)
|
||||
{
|
||||
unsigned int sel;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_DCIN_ILIM,
|
||||
&sel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(bdpsy->dev,
|
||||
"Input current limit reading failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sel &= BD70528_MASK_CHG_DCIN_ILIM;
|
||||
|
||||
ret = find_value_for_selector_low(¤t_limit_ranges[0],
|
||||
ARRAY_SIZE(current_limit_ranges), sel,
|
||||
ma);
|
||||
|
||||
if (ret) {
|
||||
/* Unspecified values mean 500 mA */
|
||||
*ma = 500;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum power_supply_property bd70528_charger_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
|
||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
};
|
||||
|
||||
static int bd70528_charger_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
return bd70528_get_charger_status(bdpsy, &val->intval);
|
||||
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||
return bd70528_get_charge_type(bdpsy, &val->intval);
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
return bd70528_get_battery_health(bdpsy, &val->intval);
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
return bd70528_get_present(bdpsy, &val->intval);
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
ret = get_current_limit(bdpsy, &val->intval);
|
||||
val->intval *= 1000;
|
||||
return ret;
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
ret = get_charge_current(bdpsy, &val->intval);
|
||||
val->intval *= 1000;
|
||||
return ret;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
return bd70528_get_online(bdpsy, &val->intval);
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
val->strval = bd70528_charger_model;
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_MANUFACTURER:
|
||||
val->strval = bd70528_charger_manufacturer;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int bd70528_prop_is_writable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_charge_current(struct bd70528_psy *bdpsy, int ma)
|
||||
{
|
||||
unsigned int reg;
|
||||
int ret = 0, tmpret;
|
||||
bool found;
|
||||
|
||||
if (ma > 500) {
|
||||
dev_warn(bdpsy->dev,
|
||||
"Requested charge current %u exceed maximum (500mA)\n",
|
||||
ma);
|
||||
reg = MAX_WARM_CHG_CURR_SEL;
|
||||
goto set;
|
||||
}
|
||||
if (ma < 10) {
|
||||
dev_err(bdpsy->dev,
|
||||
"Requested charge current %u smaller than min (10mA)\n",
|
||||
ma);
|
||||
reg = MIN_CHG_CURR_SEL;
|
||||
ret = -EINVAL;
|
||||
goto set;
|
||||
}
|
||||
|
||||
ret = find_selector_for_value_low(&warm_charge_curr[0],
|
||||
ARRAY_SIZE(warm_charge_curr), ma,
|
||||
®, &found);
|
||||
if (ret) {
|
||||
reg = MIN_CHG_CURR_SEL;
|
||||
goto set;
|
||||
}
|
||||
if (!found) {
|
||||
/* There was a gap in supported values and we hit it */
|
||||
dev_warn(bdpsy->dev,
|
||||
"Unsupported charge current %u mA\n", ma);
|
||||
}
|
||||
set:
|
||||
|
||||
tmpret = regmap_update_bits(bdpsy->regmap,
|
||||
BD70528_REG_CHG_CHG_CURR_WARM,
|
||||
BD70528_MASK_CHG_CHG_CURR, reg);
|
||||
if (tmpret)
|
||||
dev_err(bdpsy->dev,
|
||||
"Charge current write failure (%d)\n", tmpret);
|
||||
|
||||
if (reg > MAX_COLD_CHG_CURR_SEL)
|
||||
reg = MAX_COLD_CHG_CURR_SEL;
|
||||
|
||||
if (!tmpret)
|
||||
tmpret = regmap_update_bits(bdpsy->regmap,
|
||||
BD70528_REG_CHG_CHG_CURR_COLD,
|
||||
BD70528_MASK_CHG_CHG_CURR, reg);
|
||||
|
||||
if (!ret)
|
||||
ret = tmpret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_CURR_LIMIT_SEL 0x34
|
||||
#define MIN_CURR_LIMIT_SEL 0x0
|
||||
|
||||
static int set_current_limit(struct bd70528_psy *bdpsy, int ma)
|
||||
{
|
||||
unsigned int reg;
|
||||
int ret = 0, tmpret;
|
||||
bool found;
|
||||
|
||||
if (ma > 500) {
|
||||
dev_warn(bdpsy->dev,
|
||||
"Requested current limit %u exceed maximum (500mA)\n",
|
||||
ma);
|
||||
reg = MAX_CURR_LIMIT_SEL;
|
||||
goto set;
|
||||
}
|
||||
if (ma < 5) {
|
||||
dev_err(bdpsy->dev,
|
||||
"Requested current limit %u smaller than min (5mA)\n",
|
||||
ma);
|
||||
reg = MIN_CURR_LIMIT_SEL;
|
||||
ret = -EINVAL;
|
||||
goto set;
|
||||
}
|
||||
|
||||
ret = find_selector_for_value_low(¤t_limit_ranges[0],
|
||||
ARRAY_SIZE(current_limit_ranges), ma,
|
||||
®, &found);
|
||||
if (ret) {
|
||||
reg = MIN_CURR_LIMIT_SEL;
|
||||
goto set;
|
||||
}
|
||||
if (!found) {
|
||||
/* There was a gap in supported values and we hit it ?*/
|
||||
dev_warn(bdpsy->dev, "Unsupported current limit %umA\n",
|
||||
ma);
|
||||
}
|
||||
|
||||
set:
|
||||
tmpret = regmap_update_bits(bdpsy->regmap,
|
||||
BD70528_REG_CHG_DCIN_ILIM,
|
||||
BD70528_MASK_CHG_DCIN_ILIM, reg);
|
||||
|
||||
if (!ret)
|
||||
ret = tmpret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_charger_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return set_current_limit(bdpsy, val->intval / 1000);
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
return set_charge_current(bdpsy, val->intval / 1000);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc bd70528_charger_desc = {
|
||||
.name = "bd70528-charger",
|
||||
.type = POWER_SUPPLY_TYPE_MAINS,
|
||||
.properties = bd70528_charger_props,
|
||||
.num_properties = ARRAY_SIZE(bd70528_charger_props),
|
||||
.get_property = bd70528_charger_get_property,
|
||||
.set_property = bd70528_charger_set_property,
|
||||
.property_is_writeable = bd70528_prop_is_writable,
|
||||
};
|
||||
|
||||
static int bd70528_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd70528_psy *bdpsy;
|
||||
struct power_supply_config cfg = {};
|
||||
|
||||
bdpsy = devm_kzalloc(&pdev->dev, sizeof(*bdpsy), GFP_KERNEL);
|
||||
if (!bdpsy)
|
||||
return -ENOMEM;
|
||||
|
||||
bdpsy->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!bdpsy->regmap) {
|
||||
dev_err(&pdev->dev, "No regmap found for chip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
bdpsy->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, bdpsy);
|
||||
cfg.drv_data = bdpsy;
|
||||
cfg.of_node = pdev->dev.parent->of_node;
|
||||
|
||||
bdpsy->psy = devm_power_supply_register(&pdev->dev,
|
||||
&bd70528_charger_desc, &cfg);
|
||||
if (IS_ERR(bdpsy->psy)) {
|
||||
dev_err(&pdev->dev, "failed: power supply register\n");
|
||||
return PTR_ERR(bdpsy->psy);
|
||||
}
|
||||
|
||||
return bd70528_get_irqs(pdev, bdpsy);
|
||||
}
|
||||
|
||||
static struct platform_driver bd70528_power = {
|
||||
.driver = {
|
||||
.name = "bd70528-power"
|
||||
},
|
||||
.probe = bd70528_power_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(bd70528_power);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD70528 power-supply driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -764,11 +764,11 @@ config REGULATOR_RC5T583
|
||||
outputs which can be controlled by i2c communication.
|
||||
|
||||
config REGULATOR_RK808
|
||||
tristate "Rockchip RK805/RK808/RK818 Power regulators"
|
||||
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators"
|
||||
depends on MFD_RK808
|
||||
help
|
||||
Select this option to enable the power regulator of ROCKCHIP
|
||||
PMIC RK805,RK808 and RK818.
|
||||
PMIC RK805,RK809&RK817,RK808 and RK818.
|
||||
This driver supports the control of different power rails of device
|
||||
through regulator interface. The device supports multiple DCDC/LDO
|
||||
outputs which can be controlled by i2c communication.
|
||||
|
@ -1151,12 +1151,12 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd718xx *mfd;
|
||||
struct regulator_config config = { 0 };
|
||||
struct bd718xx_pmic_inits pmic_regulators[] = {
|
||||
[BD718XX_TYPE_BD71837] = {
|
||||
struct bd718xx_pmic_inits pmic_regulators[ROHM_CHIP_TYPE_AMOUNT] = {
|
||||
[ROHM_CHIP_TYPE_BD71837] = {
|
||||
.r_datas = bd71837_regulators,
|
||||
.r_amount = ARRAY_SIZE(bd71837_regulators),
|
||||
},
|
||||
[BD718XX_TYPE_BD71847] = {
|
||||
[ROHM_CHIP_TYPE_BD71847] = {
|
||||
.r_datas = bd71847_regulators,
|
||||
.r_amount = ARRAY_SIZE(bd71847_regulators),
|
||||
},
|
||||
@ -1172,15 +1172,15 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mfd->chip_type >= BD718XX_TYPE_AMOUNT ||
|
||||
!pmic_regulators[mfd->chip_type].r_datas) {
|
||||
if (mfd->chip.chip_type >= ROHM_CHIP_TYPE_AMOUNT ||
|
||||
!pmic_regulators[mfd->chip.chip_type].r_datas) {
|
||||
dev_err(&pdev->dev, "Unsupported chip type\n");
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Register LOCK release */
|
||||
err = regmap_update_bits(mfd->regmap, BD718XX_REG_REGLOCK,
|
||||
err = regmap_update_bits(mfd->chip.regmap, BD718XX_REG_REGLOCK,
|
||||
(REGLOCK_PWRSEQ | REGLOCK_VREG), 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to unlock PMIC (%d)\n", err);
|
||||
@ -1199,7 +1199,8 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
* bit allowing HW defaults for power rails to be used
|
||||
*/
|
||||
if (!use_snvs) {
|
||||
err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1,
|
||||
err = regmap_update_bits(mfd->chip.regmap,
|
||||
BD718XX_REG_TRANS_COND1,
|
||||
BD718XX_ON_REQ_POWEROFF_MASK |
|
||||
BD718XX_SWRESET_POWEROFF_MASK |
|
||||
BD718XX_WDOG_POWEROFF_MASK |
|
||||
@ -1214,17 +1215,17 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) {
|
||||
for (i = 0; i < pmic_regulators[mfd->chip.chip_type].r_amount; i++) {
|
||||
|
||||
const struct regulator_desc *desc;
|
||||
struct regulator_dev *rdev;
|
||||
const struct bd718xx_regulator_data *r;
|
||||
|
||||
r = &pmic_regulators[mfd->chip_type].r_datas[i];
|
||||
r = &pmic_regulators[mfd->chip.chip_type].r_datas[i];
|
||||
desc = &r->desc;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
config.regmap = mfd->regmap;
|
||||
config.regmap = mfd->chip.regmap;
|
||||
|
||||
rdev = devm_regulator_register(&pdev->dev, desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
@ -1253,7 +1254,7 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (!use_snvs || !rdev->constraints->always_on ||
|
||||
!rdev->constraints->boot_on) {
|
||||
err = regmap_update_bits(mfd->regmap, r->init.reg,
|
||||
err = regmap_update_bits(mfd->chip.regmap, r->init.reg,
|
||||
r->init.mask, r->init.val);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
@ -1263,7 +1264,7 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
for (j = 0; j < r->additional_init_amnt; j++) {
|
||||
err = regmap_update_bits(mfd->regmap,
|
||||
err = regmap_update_bits(mfd->chip.regmap,
|
||||
r->additional_inits[j].reg,
|
||||
r->additional_inits[j].mask,
|
||||
r->additional_inits[j].val);
|
||||
|
@ -150,6 +150,12 @@ static const struct lp87565_regulator regulators[] = {
|
||||
LP87565_REG_BUCK2_CTRL_1,
|
||||
LP87565_BUCK_CTRL_1_EN, 3230,
|
||||
buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
|
||||
LP87565_REGULATOR("BUCK3210", LP87565_BUCK_3210, "buck3210",
|
||||
lp87565_buck_ops, 256, LP87565_REG_BUCK0_VOUT,
|
||||
LP87565_BUCK_VSET, LP87565_REG_BUCK0_CTRL_1,
|
||||
LP87565_BUCK_CTRL_1_EN |
|
||||
LP87565_BUCK_CTRL_1_FPWM_MP_0_2, 3230,
|
||||
buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
|
||||
};
|
||||
|
||||
static int lp87565_regulator_probe(struct platform_device *pdev)
|
||||
@ -166,9 +172,19 @@ static int lp87565_regulator_probe(struct platform_device *pdev)
|
||||
config.driver_data = lp87565;
|
||||
config.regmap = lp87565->regmap;
|
||||
|
||||
if (lp87565->dev_type == LP87565_DEVICE_TYPE_LP87565_Q1) {
|
||||
switch (lp87565->dev_type) {
|
||||
case LP87565_DEVICE_TYPE_LP87565_Q1:
|
||||
min_idx = LP87565_BUCK_10;
|
||||
max_idx = LP87565_BUCK_23;
|
||||
break;
|
||||
case LP87565_DEVICE_TYPE_LP87561_Q1:
|
||||
min_idx = LP87565_BUCK_3210;
|
||||
max_idx = LP87565_BUCK_3210;
|
||||
break;
|
||||
default:
|
||||
dev_err(lp87565->dev, "Invalid lp config %d\n",
|
||||
lp87565->dev_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = min_idx; i <= max_idx; i++) {
|
||||
|
@ -28,6 +28,12 @@
|
||||
#define RK808_BUCK4_VSEL_MASK 0xf
|
||||
#define RK808_LDO_VSEL_MASK 0x1f
|
||||
|
||||
#define RK809_BUCK5_VSEL_MASK 0x7
|
||||
|
||||
#define RK817_LDO_VSEL_MASK 0x7f
|
||||
#define RK817_BOOST_VSEL_MASK 0x7
|
||||
#define RK817_BUCK_VSEL_MASK 0x7f
|
||||
|
||||
#define RK818_BUCK_VSEL_MASK 0x3f
|
||||
#define RK818_BUCK4_VSEL_MASK 0x1f
|
||||
#define RK818_LDO_VSEL_MASK 0x1f
|
||||
@ -57,30 +63,12 @@
|
||||
/* max steps for increase voltage of Buck1/2, equal 100mv*/
|
||||
#define MAX_STEPS_ONE_TIME 8
|
||||
|
||||
#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _etime) \
|
||||
[_id] = { \
|
||||
.name = (_match), \
|
||||
.supply_name = (_supply), \
|
||||
.of_match = of_match_ptr(_match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = (_id), \
|
||||
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = (_min) * 1000, \
|
||||
.uV_step = (_step) * 1000, \
|
||||
.vsel_reg = (_vreg), \
|
||||
.vsel_mask = (_vmask), \
|
||||
.enable_reg = (_ereg), \
|
||||
.enable_mask = (_emask), \
|
||||
.enable_time = (_etime), \
|
||||
.ops = &rk805_reg_ops, \
|
||||
}
|
||||
#define ENABLE_MASK(id) (BIT(id) | BIT(4 + (id)))
|
||||
#define DISABLE_VAL(id) (BIT(4 + (id)))
|
||||
|
||||
#define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _etime) \
|
||||
[_id] = { \
|
||||
#define RK817_BOOST_DESC(_id, _match, _supply, _min, _max, _step, _vreg,\
|
||||
_vmask, _ereg, _emask, _enval, _disval, _etime, m_drop) \
|
||||
{ \
|
||||
.name = (_match), \
|
||||
.supply_name = (_supply), \
|
||||
.of_match = of_match_ptr(_match), \
|
||||
@ -95,12 +83,54 @@
|
||||
.vsel_mask = (_vmask), \
|
||||
.enable_reg = (_ereg), \
|
||||
.enable_mask = (_emask), \
|
||||
.enable_val = (_enval), \
|
||||
.disable_val = (_disval), \
|
||||
.enable_time = (_etime), \
|
||||
.ops = &rk808_reg_ops, \
|
||||
.min_dropout_uV = (m_drop) * 1000, \
|
||||
.ops = &rk817_boost_ops, \
|
||||
}
|
||||
|
||||
#define RK8XX_DESC_SWITCH(_id, _match, _supply, _ereg, _emask) \
|
||||
[_id] = { \
|
||||
#define RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _enval, _disval, _etime, _ops) \
|
||||
{ \
|
||||
.name = (_match), \
|
||||
.supply_name = (_supply), \
|
||||
.of_match = of_match_ptr(_match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = (_id), \
|
||||
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = (_min) * 1000, \
|
||||
.uV_step = (_step) * 1000, \
|
||||
.vsel_reg = (_vreg), \
|
||||
.vsel_mask = (_vmask), \
|
||||
.enable_reg = (_ereg), \
|
||||
.enable_mask = (_emask), \
|
||||
.enable_val = (_enval), \
|
||||
.disable_val = (_disval), \
|
||||
.enable_time = (_etime), \
|
||||
.ops = _ops, \
|
||||
}
|
||||
|
||||
#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _etime) \
|
||||
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, 0, 0, _etime, &rk805_reg_ops)
|
||||
|
||||
#define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _etime) \
|
||||
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops)
|
||||
|
||||
#define RK817_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _disval, _etime) \
|
||||
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
|
||||
_vmask, _ereg, _emask, _emask, _disval, _etime, &rk817_reg_ops)
|
||||
|
||||
#define RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
|
||||
_enval, _disval, _ops) \
|
||||
{ \
|
||||
.name = (_match), \
|
||||
.supply_name = (_supply), \
|
||||
.of_match = of_match_ptr(_match), \
|
||||
@ -109,10 +139,20 @@
|
||||
.id = (_id), \
|
||||
.enable_reg = (_ereg), \
|
||||
.enable_mask = (_emask), \
|
||||
.enable_val = (_enval), \
|
||||
.disable_val = (_disval), \
|
||||
.owner = THIS_MODULE, \
|
||||
.ops = &rk808_switch_ops \
|
||||
.ops = _ops \
|
||||
}
|
||||
|
||||
#define RK817_DESC_SWITCH(_id, _match, _supply, _ereg, _emask, \
|
||||
_disval) \
|
||||
RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
|
||||
_emask, _disval, &rk817_switch_ops)
|
||||
|
||||
#define RK8XX_DESC_SWITCH(_id, _match, _supply, _ereg, _emask) \
|
||||
RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
|
||||
0, 0, &rk808_switch_ops)
|
||||
|
||||
struct rk808_regulator_data {
|
||||
struct gpio_desc *dvs_gpio[2];
|
||||
@ -130,6 +170,51 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
|
||||
};
|
||||
|
||||
#define RK809_BUCK5_SEL_CNT (8)
|
||||
|
||||
static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(1500000, 0, 0, 0),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 1, 3, 200000),
|
||||
REGULATOR_LINEAR_RANGE(2800000, 4, 5, 200000),
|
||||
REGULATOR_LINEAR_RANGE(3300000, 6, 7, 300000),
|
||||
};
|
||||
|
||||
#define RK817_BUCK1_MIN0 500000
|
||||
#define RK817_BUCK1_MAX0 1500000
|
||||
|
||||
#define RK817_BUCK1_MIN1 1600000
|
||||
#define RK817_BUCK1_MAX1 2400000
|
||||
|
||||
#define RK817_BUCK3_MAX1 3400000
|
||||
|
||||
#define RK817_BUCK1_STP0 12500
|
||||
#define RK817_BUCK1_STP1 100000
|
||||
|
||||
#define RK817_BUCK1_SEL0 ((RK817_BUCK1_MAX0 - RK817_BUCK1_MIN0) /\
|
||||
RK817_BUCK1_STP0)
|
||||
#define RK817_BUCK1_SEL1 ((RK817_BUCK1_MAX1 - RK817_BUCK1_MIN1) /\
|
||||
RK817_BUCK1_STP1)
|
||||
|
||||
#define RK817_BUCK3_SEL1 ((RK817_BUCK3_MAX1 - RK817_BUCK1_MIN1) /\
|
||||
RK817_BUCK1_STP1)
|
||||
|
||||
#define RK817_BUCK1_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK1_SEL1 + 1)
|
||||
#define RK817_BUCK3_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK3_SEL1 + 1)
|
||||
|
||||
static const struct regulator_linear_range rk817_buck1_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
|
||||
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
|
||||
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
|
||||
RK817_BUCK1_SEL_CNT, RK817_BUCK1_STP1),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range rk817_buck3_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
|
||||
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
|
||||
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
|
||||
RK817_BUCK3_SEL_CNT, RK817_BUCK1_STP1),
|
||||
};
|
||||
|
||||
static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
|
||||
@ -281,6 +366,36 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
||||
RK808_RAMP_RATE_MASK, ramp_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* RK817 RK809
|
||||
*/
|
||||
static int rk817_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
||||
{
|
||||
unsigned int ramp_value = RK817_RAMP_RATE_25MV_PER_US;
|
||||
unsigned int reg = RK817_BUCK_CONFIG_REG(rdev_get_id(rdev));
|
||||
|
||||
switch (ramp_delay) {
|
||||
case 0 ... 3000:
|
||||
ramp_value = RK817_RAMP_RATE_3MV_PER_US;
|
||||
break;
|
||||
case 3001 ... 6300:
|
||||
ramp_value = RK817_RAMP_RATE_6_3MV_PER_US;
|
||||
break;
|
||||
case 6301 ... 12500:
|
||||
ramp_value = RK817_RAMP_RATE_12_5MV_PER_US;
|
||||
break;
|
||||
case 12501 ... 25000:
|
||||
break;
|
||||
default:
|
||||
dev_warn(&rdev->dev,
|
||||
"%s ramp_delay: %d not supported, setting 10000\n",
|
||||
rdev->desc->name, ramp_delay);
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, reg,
|
||||
RK817_RAMP_RATE_MASK, ramp_value);
|
||||
}
|
||||
|
||||
static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
|
||||
{
|
||||
unsigned int reg;
|
||||
@ -296,6 +411,21 @@ static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
|
||||
sel);
|
||||
}
|
||||
|
||||
static int rk817_set_suspend_voltage(struct regulator_dev *rdev, int uv)
|
||||
{
|
||||
unsigned int reg;
|
||||
int sel = regulator_map_voltage_linear(rdev, uv, uv);
|
||||
/* only ldo1~ldo9 */
|
||||
if (sel < 0)
|
||||
return -EINVAL;
|
||||
|
||||
reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
|
||||
|
||||
return regmap_update_bits(rdev->regmap, reg,
|
||||
rdev->desc->vsel_mask,
|
||||
sel);
|
||||
}
|
||||
|
||||
static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv)
|
||||
{
|
||||
unsigned int reg;
|
||||
@ -355,6 +485,131 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
|
||||
rdev->desc->enable_mask);
|
||||
}
|
||||
|
||||
static int rk817_set_suspend_enable_ctrl(struct regulator_dev *rdev,
|
||||
unsigned int en)
|
||||
{
|
||||
unsigned int reg;
|
||||
int id = rdev_get_id(rdev);
|
||||
unsigned int id_slp, msk, val;
|
||||
|
||||
if (id >= RK817_ID_DCDC1 && id <= RK817_ID_DCDC4)
|
||||
id_slp = id;
|
||||
else if (id >= RK817_ID_LDO1 && id <= RK817_ID_LDO8)
|
||||
id_slp = 8 + (id - RK817_ID_LDO1);
|
||||
else if (id >= RK817_ID_LDO9 && id <= RK809_ID_SW2)
|
||||
id_slp = 4 + (id - RK817_ID_LDO9);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
reg = RK817_POWER_SLP_EN_REG(id_slp / 8);
|
||||
|
||||
msk = BIT(id_slp % 8);
|
||||
if (en)
|
||||
val = msk;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return regmap_update_bits(rdev->regmap, reg, msk, val);
|
||||
}
|
||||
|
||||
static int rk817_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
return rk817_set_suspend_enable_ctrl(rdev, 1);
|
||||
}
|
||||
|
||||
static int rk817_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
return rk817_set_suspend_enable_ctrl(rdev, 0);
|
||||
}
|
||||
|
||||
static int rk8xx_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
return regmap_update_bits(rdev->regmap, reg,
|
||||
PWM_MODE_MSK, FPWM_MODE);
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
return regmap_update_bits(rdev->regmap, reg,
|
||||
PWM_MODE_MSK, AUTO_PWM_MODE);
|
||||
default:
|
||||
dev_err(&rdev->dev, "do not support this mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk8xx_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
|
||||
PWM_MODE_MSK, FPWM_MODE);
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
|
||||
PWM_MODE_MSK, AUTO_PWM_MODE);
|
||||
default:
|
||||
dev_err(&rdev->dev, "do not support this mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int rk8xx_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
int err;
|
||||
|
||||
err = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val & FPWM_MODE)
|
||||
return REGULATOR_MODE_FAST;
|
||||
else
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int rk8xx_is_enabled_wmsk_regmap(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* add write mask bit */
|
||||
val |= (rdev->desc->enable_mask & 0xf0);
|
||||
val &= rdev->desc->enable_mask;
|
||||
|
||||
if (rdev->desc->enable_is_inverted) {
|
||||
if (rdev->desc->enable_val)
|
||||
return val != rdev->desc->enable_val;
|
||||
return (val == 0);
|
||||
}
|
||||
if (rdev->desc->enable_val)
|
||||
return val == rdev->desc->enable_val;
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 1:
|
||||
return REGULATOR_MODE_FAST;
|
||||
case 2:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regulator_ops rk805_reg_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
@ -431,6 +686,71 @@ static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
|
||||
};
|
||||
|
||||
static struct regulator_ops rk809_buck5_ops_range = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
|
||||
.set_suspend_voltage = rk808_set_suspend_voltage_range,
|
||||
.set_suspend_enable = rk817_set_suspend_enable,
|
||||
.set_suspend_disable = rk817_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops rk817_reg_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
|
||||
.set_suspend_voltage = rk817_set_suspend_voltage,
|
||||
.set_suspend_enable = rk817_set_suspend_enable,
|
||||
.set_suspend_disable = rk817_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops rk817_boost_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
|
||||
.set_suspend_enable = rk817_set_suspend_enable,
|
||||
.set_suspend_disable = rk817_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops rk817_buck_ops_range = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
|
||||
.set_mode = rk8xx_set_mode,
|
||||
.get_mode = rk8xx_get_mode,
|
||||
.set_suspend_mode = rk8xx_set_suspend_mode,
|
||||
.set_ramp_delay = rk817_set_ramp_delay,
|
||||
.set_suspend_voltage = rk808_set_suspend_voltage_range,
|
||||
.set_suspend_enable = rk817_set_suspend_enable,
|
||||
.set_suspend_disable = rk817_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops rk817_switch_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
|
||||
.set_suspend_enable = rk817_set_suspend_enable,
|
||||
.set_suspend_disable = rk817_set_suspend_disable,
|
||||
};
|
||||
|
||||
static const struct regulator_desc rk805_reg[] = {
|
||||
{
|
||||
.name = "DCDC_REG1",
|
||||
@ -587,6 +907,271 @@ static const struct regulator_desc rk808_reg[] = {
|
||||
RK808_DCDC_EN_REG, BIT(6)),
|
||||
};
|
||||
|
||||
static const struct regulator_desc rk809_reg[] = {
|
||||
{
|
||||
.name = "DCDC_REG1",
|
||||
.supply_name = "vcc1",
|
||||
.of_match = of_match_ptr("DCDC_REG1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC1,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK1_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC1),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC1),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC1),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG2",
|
||||
.supply_name = "vcc2",
|
||||
.of_match = of_match_ptr("DCDC_REG2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC2,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK2_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC2),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC2),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC2),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG3",
|
||||
.supply_name = "vcc3",
|
||||
.of_match = of_match_ptr("DCDC_REG3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC3,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK3_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC3),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC3),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG4",
|
||||
.supply_name = "vcc4",
|
||||
.of_match = of_match_ptr("DCDC_REG4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC4,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK3_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck3_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK4_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC4),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC4),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC4),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "DCDC_REG5",
|
||||
.supply_name = "vcc9",
|
||||
.of_match = of_match_ptr("DCDC_REG5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK809_ID_DCDC5,
|
||||
.ops = &rk809_buck5_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK809_BUCK5_SEL_CNT,
|
||||
.linear_ranges = rk809_buck5_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk809_buck5_voltage_ranges),
|
||||
.vsel_reg = RK809_BUCK5_CONFIG(0),
|
||||
.vsel_mask = RK809_BUCK5_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(3),
|
||||
.enable_mask = ENABLE_MASK(1),
|
||||
.enable_val = ENABLE_MASK(1),
|
||||
.disable_val = DISABLE_VAL(1),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
RK817_DESC(RK817_ID_LDO1, "LDO_REG1", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_DESC(RK817_ID_LDO2, "LDO_REG2", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(1),
|
||||
DISABLE_VAL(1), 400),
|
||||
RK817_DESC(RK817_ID_LDO3, "LDO_REG3", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2), 400),
|
||||
RK817_DESC(RK817_ID_LDO4, "LDO_REG4", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(3),
|
||||
DISABLE_VAL(3), 400),
|
||||
RK817_DESC(RK817_ID_LDO5, "LDO_REG5", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_DESC(RK817_ID_LDO6, "LDO_REG6", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(1),
|
||||
DISABLE_VAL(1), 400),
|
||||
RK817_DESC(RK817_ID_LDO7, "LDO_REG7", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2), 400),
|
||||
RK817_DESC(RK817_ID_LDO8, "LDO_REG8", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(3),
|
||||
DISABLE_VAL(3), 400),
|
||||
RK817_DESC(RK817_ID_LDO9, "LDO_REG9", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_DESC_SWITCH(RK809_ID_SW1, "SWITCH_REG1", "vcc9",
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2)),
|
||||
RK817_DESC_SWITCH(RK809_ID_SW2, "SWITCH_REG2", "vcc8",
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(3),
|
||||
DISABLE_VAL(3)),
|
||||
};
|
||||
|
||||
static const struct regulator_desc rk817_reg[] = {
|
||||
{
|
||||
.name = "DCDC_REG1",
|
||||
.supply_name = "vcc1",
|
||||
.of_match = of_match_ptr("DCDC_REG1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC1,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK1_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC1),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC1),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC1),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG2",
|
||||
.supply_name = "vcc2",
|
||||
.of_match = of_match_ptr("DCDC_REG2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC2,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK2_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC2),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC2),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC2),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG3",
|
||||
.supply_name = "vcc3",
|
||||
.of_match = of_match_ptr("DCDC_REG3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC3,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK1_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck1_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK3_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC3),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC3),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
}, {
|
||||
.name = "DCDC_REG4",
|
||||
.supply_name = "vcc4",
|
||||
.of_match = of_match_ptr("DCDC_REG4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = RK817_ID_DCDC4,
|
||||
.ops = &rk817_buck_ops_range,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = RK817_BUCK3_SEL_CNT + 1,
|
||||
.linear_ranges = rk817_buck3_voltage_ranges,
|
||||
.n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges),
|
||||
.vsel_reg = RK817_BUCK4_ON_VSEL_REG,
|
||||
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
||||
.enable_reg = RK817_POWER_EN_REG(0),
|
||||
.enable_mask = ENABLE_MASK(RK817_ID_DCDC4),
|
||||
.enable_val = ENABLE_MASK(RK817_ID_DCDC4),
|
||||
.disable_val = DISABLE_VAL(RK817_ID_DCDC4),
|
||||
.of_map_mode = rk8xx_regulator_of_map_mode,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
RK817_DESC(RK817_ID_LDO1, "LDO_REG1", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_DESC(RK817_ID_LDO2, "LDO_REG2", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(1),
|
||||
DISABLE_VAL(1), 400),
|
||||
RK817_DESC(RK817_ID_LDO3, "LDO_REG3", "vcc5", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2), 400),
|
||||
RK817_DESC(RK817_ID_LDO4, "LDO_REG4", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(1), ENABLE_MASK(3),
|
||||
DISABLE_VAL(3), 400),
|
||||
RK817_DESC(RK817_ID_LDO5, "LDO_REG5", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_DESC(RK817_ID_LDO6, "LDO_REG6", "vcc6", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(1),
|
||||
DISABLE_VAL(1), 400),
|
||||
RK817_DESC(RK817_ID_LDO7, "LDO_REG7", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2), 400),
|
||||
RK817_DESC(RK817_ID_LDO8, "LDO_REG8", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(2), ENABLE_MASK(3),
|
||||
DISABLE_VAL(3), 400),
|
||||
RK817_DESC(RK817_ID_LDO9, "LDO_REG9", "vcc7", 600, 3400, 25,
|
||||
RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(0),
|
||||
DISABLE_VAL(0), 400),
|
||||
RK817_BOOST_DESC(RK817_ID_BOOST, "BOOST", "vcc8", 4700, 5400, 100,
|
||||
RK817_BOOST_OTG_CFG, RK817_BOOST_VSEL_MASK,
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(1), ENABLE_MASK(1),
|
||||
DISABLE_VAL(1), 400, 3500 - 5400),
|
||||
RK817_DESC_SWITCH(RK817_ID_BOOST_OTG_SW, "OTG_SWITCH", "vcc9",
|
||||
RK817_POWER_EN_REG(3), ENABLE_MASK(2),
|
||||
DISABLE_VAL(2)),
|
||||
};
|
||||
|
||||
static const struct regulator_desc rk818_reg[] = {
|
||||
{
|
||||
.name = "DCDC_REG1",
|
||||
@ -757,6 +1342,14 @@ static int rk808_regulator_probe(struct platform_device *pdev)
|
||||
regulators = rk808_reg;
|
||||
nregulators = RK808_NUM_REGULATORS;
|
||||
break;
|
||||
case RK809_ID:
|
||||
regulators = rk809_reg;
|
||||
nregulators = RK809_NUM_REGULATORS;
|
||||
break;
|
||||
case RK817_ID:
|
||||
regulators = rk817_reg;
|
||||
nregulators = RK817_NUM_REGULATORS;
|
||||
break;
|
||||
case RK818_ID:
|
||||
regulators = rk818_reg;
|
||||
nregulators = RK818_NUM_REGULATORS;
|
||||
@ -795,6 +1388,7 @@ static struct platform_driver rk808_regulator_driver = {
|
||||
module_platform_driver(rk808_regulator_driver);
|
||||
|
||||
MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
|
||||
MODULE_AUTHOR("Tony xie <tony.xie@rock-chips.com>");
|
||||
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
|
||||
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
|
||||
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
|
||||
|
@ -374,11 +374,11 @@ config RTC_DRV_MAX77686
|
||||
will be called rtc-max77686.
|
||||
|
||||
config RTC_DRV_RK808
|
||||
tristate "Rockchip RK805/RK808/RK818 RTC"
|
||||
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
|
||||
depends on MFD_RK808
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
RTC of RK805, RK808 and RK818 PMIC.
|
||||
RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rk808-rtc.
|
||||
@ -498,6 +498,14 @@ 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"
|
||||
help
|
||||
If you say Y here you will get support for the RTC
|
||||
on ROHM BD70528 Power Management IC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-bd70528.
|
||||
|
||||
config RTC_DRV_BQ32K
|
||||
tristate "TI BQ32000"
|
||||
|
@ -38,6 +38,7 @@ obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o
|
||||
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
|
||||
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
|
||||
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
|
||||
obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
|
||||
obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o
|
||||
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
|
||||
obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o
|
||||
|
500
drivers/rtc/rtc-bd70528.c
Normal file
500
drivers/rtc/rtc-bd70528.c
Normal file
@ -0,0 +1,500 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Copyright (C) 2018 ROHM Semiconductors
|
||||
//
|
||||
// RTC driver for ROHM BD70528 PMIC
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/mfd/rohm-bd70528.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
/*
|
||||
* We read regs RTC_SEC => RTC_YEAR
|
||||
* this struct is ordered according to chip registers.
|
||||
* Keep it u8 only to avoid padding issues.
|
||||
*/
|
||||
struct bd70528_rtc_day {
|
||||
u8 sec;
|
||||
u8 min;
|
||||
u8 hour;
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc_data {
|
||||
struct bd70528_rtc_day time;
|
||||
u8 week;
|
||||
u8 day;
|
||||
u8 month;
|
||||
u8 year;
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc_wake {
|
||||
struct bd70528_rtc_day time;
|
||||
u8 ctrl;
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc_alm {
|
||||
struct bd70528_rtc_data data;
|
||||
u8 alm_mask;
|
||||
u8 alm_repeat;
|
||||
} __packed;
|
||||
|
||||
struct bd70528_rtc {
|
||||
struct rohm_regmap_dev *mfd;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
|
||||
int enable, int *old_state)
|
||||
{
|
||||
int ret;
|
||||
unsigned int ctrl_reg;
|
||||
|
||||
ret = regmap_read(bd70528->regmap, BD70528_REG_WAKE_EN, &ctrl_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (old_state) {
|
||||
if (ctrl_reg & BD70528_MASK_WAKE_EN)
|
||||
*old_state |= BD70528_WAKE_STATE_BIT;
|
||||
else
|
||||
*old_state &= ~BD70528_WAKE_STATE_BIT;
|
||||
|
||||
if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
ctrl_reg |= BD70528_MASK_WAKE_EN;
|
||||
else
|
||||
ctrl_reg &= ~BD70528_MASK_WAKE_EN;
|
||||
|
||||
return regmap_write(bd70528->regmap, BD70528_REG_WAKE_EN,
|
||||
ctrl_reg);
|
||||
}
|
||||
|
||||
static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528,
|
||||
int enable, int *old_state)
|
||||
{
|
||||
int ret;
|
||||
unsigned int ctrl_reg;
|
||||
|
||||
/*
|
||||
* TBD
|
||||
* What is the purpose of elapsed timer ?
|
||||
* Is the timeout registers counting down, or is the disable - re-enable
|
||||
* going to restart the elapsed-time counting? If counting is restarted
|
||||
* the timeout should be decreased by the amount of time that has
|
||||
* elapsed since starting the timer. Maybe we should store the monotonic
|
||||
* clock value when timer is started so that if RTC is set while timer
|
||||
* is armed we could do the compensation. This is a hack if RTC/system
|
||||
* clk are drifting. OTOH, RTC controlled via I2C is in any case
|
||||
* inaccurate...
|
||||
*/
|
||||
ret = regmap_read(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
|
||||
&ctrl_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (old_state) {
|
||||
if (ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN)
|
||||
*old_state |= BD70528_ELAPSED_STATE_BIT;
|
||||
else
|
||||
*old_state &= ~BD70528_ELAPSED_STATE_BIT;
|
||||
|
||||
if ((!enable) == (!(*old_state & BD70528_ELAPSED_STATE_BIT)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
ctrl_reg |= BD70528_MASK_ELAPSED_TIMER_EN;
|
||||
else
|
||||
ctrl_reg &= ~BD70528_MASK_ELAPSED_TIMER_EN;
|
||||
|
||||
return regmap_write(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
|
||||
ctrl_reg);
|
||||
}
|
||||
|
||||
static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
|
||||
int *old_state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bd70528_wdt_set(r->mfd, 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,
|
||||
new_state & BD70528_ELAPSED_STATE_BIT,
|
||||
old_state);
|
||||
if (ret) {
|
||||
dev_err(r->dev,
|
||||
"Failed to disable 'elapsed timer' for RTC setting\n");
|
||||
return ret;
|
||||
}
|
||||
ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT,
|
||||
old_state);
|
||||
if (ret) {
|
||||
dev_err(r->dev,
|
||||
"Failed to disable 'wake timer' for RTC setting\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
|
||||
int old_state)
|
||||
{
|
||||
return bd70528_set_rtc_based_timers(r, old_state, NULL);
|
||||
}
|
||||
|
||||
static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
|
||||
int *old_state)
|
||||
{
|
||||
return bd70528_set_rtc_based_timers(r, 0, old_state);
|
||||
}
|
||||
|
||||
static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
|
||||
{
|
||||
d->sec &= ~BD70528_MASK_RTC_SEC;
|
||||
d->min &= ~BD70528_MASK_RTC_MINUTE;
|
||||
d->hour &= ~BD70528_MASK_RTC_HOUR;
|
||||
d->sec |= bin2bcd(t->tm_sec);
|
||||
d->min |= bin2bcd(t->tm_min);
|
||||
d->hour |= bin2bcd(t->tm_hour);
|
||||
}
|
||||
|
||||
static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r)
|
||||
{
|
||||
r->day &= ~BD70528_MASK_RTC_DAY;
|
||||
r->week &= ~BD70528_MASK_RTC_WEEK;
|
||||
r->month &= ~BD70528_MASK_RTC_MONTH;
|
||||
/*
|
||||
* PM and 24H bits are not used by Wake - thus we clear them
|
||||
* here and not in tmday2rtc() which is also used by wake.
|
||||
*/
|
||||
r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H);
|
||||
|
||||
tmday2rtc(t, &r->time);
|
||||
/*
|
||||
* We do always set time in 24H mode.
|
||||
*/
|
||||
r->time.hour |= BD70528_MASK_RTC_HOUR_24H;
|
||||
r->day |= bin2bcd(t->tm_mday);
|
||||
r->week |= bin2bcd(t->tm_wday);
|
||||
r->month |= bin2bcd(t->tm_mon + 1);
|
||||
r->year = bin2bcd(t->tm_year - 100);
|
||||
}
|
||||
|
||||
static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
|
||||
{
|
||||
t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC);
|
||||
t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE);
|
||||
t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR);
|
||||
/*
|
||||
* If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM
|
||||
* is not BCD value but tells whether it is AM or PM
|
||||
*/
|
||||
if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) {
|
||||
t->tm_hour %= 12;
|
||||
if (r->time.hour & BD70528_MASK_RTC_HOUR_PM)
|
||||
t->tm_hour += 12;
|
||||
}
|
||||
t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY);
|
||||
t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1;
|
||||
t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR);
|
||||
t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ret = regmap_bulk_read(bd70528->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,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm2rtc(&a->time, &alm.data);
|
||||
tmday2rtc(&a->time, &wake.time);
|
||||
|
||||
if (a->enabled) {
|
||||
alm.alm_mask &= ~BD70528_MASK_ALM_EN;
|
||||
wake.ctrl |= BD70528_MASK_WAKE_EN;
|
||||
} else {
|
||||
alm.alm_mask |= BD70528_MASK_ALM_EN;
|
||||
wake.ctrl &= ~BD70528_MASK_WAKE_EN;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_write(bd70528->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,
|
||||
&alm, sizeof(alm));
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to set alarm time\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START,
|
||||
&alm, sizeof(alm));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read alarm regs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc2tm(&alm.data, &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_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;
|
||||
|
||||
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,
|
||||
sizeof(rtc_data));
|
||||
if (tmpret) {
|
||||
dev_err(dev, "Failed to read RTC time registers\n");
|
||||
goto renable_out;
|
||||
}
|
||||
tm2rtc(t, &rtc_data);
|
||||
|
||||
tmpret = regmap_bulk_write(bd70528->regmap,
|
||||
BD70528_REG_RTC_START, &rtc_data,
|
||||
sizeof(rtc_data));
|
||||
if (tmpret) {
|
||||
dev_err(dev, "Failed to set RTC time\n");
|
||||
goto renable_out;
|
||||
}
|
||||
|
||||
renable_out:
|
||||
ret = bd70528_re_enable_rtc_based_timers(r, old_states);
|
||||
if (tmpret)
|
||||
ret = tmpret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
ret = bd70528_set_time_locked(dev, t);
|
||||
bd70528_wdt_unlock(r->mfd);
|
||||
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 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,
|
||||
sizeof(rtc_data));
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc2tm(&rtc_data, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
int ret;
|
||||
unsigned int enableval = BD70528_MASK_ALM_EN;
|
||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||
|
||||
if (enabled)
|
||||
enableval = 0;
|
||||
|
||||
bd70528_wdt_lock(r->mfd);
|
||||
ret = bd70528_set_wake(r->mfd, 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,
|
||||
BD70528_MASK_ALM_EN, enableval);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to change alarm state\n");
|
||||
|
||||
out_unlock:
|
||||
bd70528_wdt_unlock(r->mfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops bd70528_rtc_ops = {
|
||||
.read_time = bd70528_get_time,
|
||||
.set_time = bd70528_set_time,
|
||||
.read_alarm = bd70528_read_alarm,
|
||||
.set_alarm = bd70528_set_alarm,
|
||||
.alarm_irq_enable = bd70528_alm_enable,
|
||||
};
|
||||
|
||||
static irqreturn_t alm_hndlr(int irq, void *data)
|
||||
{
|
||||
struct rtc_device *rtc = data;
|
||||
|
||||
rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int bd70528_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bd70528_rtc *bd_rtc;
|
||||
struct rohm_regmap_dev *mfd;
|
||||
int ret;
|
||||
struct rtc_device *rtc;
|
||||
int irq;
|
||||
unsigned int hr;
|
||||
|
||||
mfd = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!mfd) {
|
||||
dev_err(&pdev->dev, "No MFD driver data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);
|
||||
if (!bd_rtc)
|
||||
return -ENOMEM;
|
||||
|
||||
bd_rtc->mfd = mfd;
|
||||
bd_rtc->dev = &pdev->dev;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm");
|
||||
|
||||
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);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to reag RTC clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
|
||||
struct rtc_time t;
|
||||
|
||||
ret = bd70528_get_time(&pdev->dev, &t);
|
||||
|
||||
if (!ret)
|
||||
ret = bd70528_set_time(&pdev->dev, &t);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Setting 24H clock for RTC failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
device_set_wakeup_capable(&pdev->dev, true);
|
||||
device_wakeup_enable(&pdev->dev);
|
||||
|
||||
rtc = devm_rtc_allocate_device(&pdev->dev);
|
||||
if (IS_ERR(rtc)) {
|
||||
dev_err(&pdev->dev, "RTC device creation failed\n");
|
||||
return PTR_ERR(rtc);
|
||||
}
|
||||
|
||||
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
rtc->ops = &bd70528_rtc_ops;
|
||||
|
||||
/* Request alarm IRQ prior to registerig the RTC */
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
|
||||
IRQF_ONESHOT, "bd70528-rtc", rtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* BD70528 irq controller is not touching the main mask register.
|
||||
* So enable the RTC block interrupts at main level. We can just
|
||||
* leave them enabled as irq-controller should disable irqs
|
||||
* from sub-registers when IRQ is disabled or freed.
|
||||
*/
|
||||
ret = regmap_update_bits(mfd->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;
|
||||
}
|
||||
|
||||
ret = rtc_register_device(rtc);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Registering RTC failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver bd70528_rtc = {
|
||||
.driver = {
|
||||
.name = "bd70528-rtc"
|
||||
},
|
||||
.probe = bd70528_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(bd70528_rtc);
|
||||
|
||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||
MODULE_DESCRIPTION("BD70528 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -42,9 +42,18 @@
|
||||
#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
|
||||
#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
|
||||
|
||||
struct rk_rtc_compat_reg {
|
||||
unsigned int ctrl_reg;
|
||||
unsigned int status_reg;
|
||||
unsigned int alarm_seconds_reg;
|
||||
unsigned int int_reg;
|
||||
unsigned int seconds_reg;
|
||||
};
|
||||
|
||||
struct rk808_rtc {
|
||||
struct rk808 *rk808;
|
||||
struct rtc_device *rtc;
|
||||
struct rk_rtc_compat_reg *creg;
|
||||
int irq;
|
||||
};
|
||||
|
||||
@ -93,7 +102,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
|
||||
int ret;
|
||||
|
||||
/* Force an update of the shadowed registers right now */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME);
|
||||
if (ret) {
|
||||
@ -107,7 +116,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
|
||||
* 32khz. If we clear the GET_TIME bit here, the time of i2c transfer
|
||||
* certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency.
|
||||
*/
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
|
||||
BIT_RTC_CTRL_REG_RTC_GET_TIME,
|
||||
0);
|
||||
if (ret) {
|
||||
@ -115,7 +124,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
|
||||
ret = regmap_bulk_read(rk808->regmap, rk808_rtc->creg->seconds_reg,
|
||||
rtc_data, NUM_TIME_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
|
||||
@ -154,7 +163,7 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
rtc_data[6] = bin2bcd(tm->tm_wday);
|
||||
|
||||
/* Stop RTC while updating the RTC registers */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M);
|
||||
if (ret) {
|
||||
@ -162,14 +171,14 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
|
||||
ret = regmap_bulk_write(rk808->regmap, rk808_rtc->creg->seconds_reg,
|
||||
rtc_data, NUM_TIME_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/* Start RTC again */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to update RTC control: %d\n", ret);
|
||||
@ -187,8 +196,13 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
uint32_t int_reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
|
||||
ret = regmap_bulk_read(rk808->regmap,
|
||||
rk808_rtc->creg->alarm_seconds_reg,
|
||||
alrm_data, NUM_ALARM_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read RTC alarm date REG: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
|
||||
alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
|
||||
@ -198,7 +212,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
|
||||
rockchip_to_gregorian(&alrm->time);
|
||||
|
||||
ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
|
||||
ret = regmap_read(rk808->regmap, rk808_rtc->creg->int_reg, &int_reg);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
|
||||
return ret;
|
||||
@ -217,7 +231,7 @@ static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
|
||||
|
||||
return ret;
|
||||
@ -228,7 +242,7 @@ static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
|
||||
struct rk808 *rk808 = rk808_rtc->rk808;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
|
||||
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
|
||||
|
||||
@ -258,7 +272,8 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
|
||||
alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
|
||||
|
||||
ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
|
||||
ret = regmap_bulk_write(rk808->regmap,
|
||||
rk808_rtc->creg->alarm_seconds_reg,
|
||||
alrm_data, NUM_ALARM_REGS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to bulk write: %d\n", ret);
|
||||
@ -302,7 +317,7 @@ static irqreturn_t rk808_alarm_irq(int irq, void *data)
|
||||
struct i2c_client *client = rk808->i2c;
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
|
||||
ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg,
|
||||
RTC_STATUS_MASK);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
@ -353,6 +368,22 @@ static int rk808_rtc_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
|
||||
rk808_rtc_suspend, rk808_rtc_resume);
|
||||
|
||||
static struct rk_rtc_compat_reg rk808_creg = {
|
||||
.ctrl_reg = RK808_RTC_CTRL_REG,
|
||||
.status_reg = RK808_RTC_STATUS_REG,
|
||||
.alarm_seconds_reg = RK808_ALARM_SECONDS_REG,
|
||||
.int_reg = RK808_RTC_INT_REG,
|
||||
.seconds_reg = RK808_SECONDS_REG,
|
||||
};
|
||||
|
||||
static struct rk_rtc_compat_reg rk817_creg = {
|
||||
.ctrl_reg = RK817_RTC_CTRL_REG,
|
||||
.status_reg = RK817_RTC_STATUS_REG,
|
||||
.alarm_seconds_reg = RK817_ALARM_SECONDS_REG,
|
||||
.int_reg = RK817_RTC_INT_REG,
|
||||
.seconds_reg = RK817_SECONDS_REG,
|
||||
};
|
||||
|
||||
static int rk808_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -363,11 +394,20 @@ static int rk808_rtc_probe(struct platform_device *pdev)
|
||||
if (rk808_rtc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
rk808_rtc->creg = &rk817_creg;
|
||||
break;
|
||||
default:
|
||||
rk808_rtc->creg = &rk808_creg;
|
||||
break;
|
||||
}
|
||||
platform_set_drvdata(pdev, rk808_rtc);
|
||||
rk808_rtc->rk808 = rk808;
|
||||
|
||||
/* start rtc running by default, and use shadowed timer. */
|
||||
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
|
||||
ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg,
|
||||
BIT_RTC_CTRL_REG_STOP_RTC_M |
|
||||
BIT_RTC_CTRL_REG_RTC_READSEL_M,
|
||||
BIT_RTC_CTRL_REG_RTC_READSEL_M);
|
||||
@ -377,7 +417,7 @@ static int rk808_rtc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
|
||||
ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg,
|
||||
RTC_STATUS_MASK);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define CROS_EC_DEV_PD_NAME "cros_pd"
|
||||
#define CROS_EC_DEV_TP_NAME "cros_tp"
|
||||
#define CROS_EC_DEV_ISH_NAME "cros_ish"
|
||||
#define CROS_EC_DEV_SCP_NAME "cros_scp"
|
||||
|
||||
/*
|
||||
* The EC is unresponsive for a time after a reboot command. Add a
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
enum lp87565_device_type {
|
||||
LP87565_DEVICE_TYPE_UNKNOWN = 0,
|
||||
LP87565_DEVICE_TYPE_LP87561_Q1,
|
||||
LP87565_DEVICE_TYPE_LP87565_Q1,
|
||||
};
|
||||
|
||||
@ -246,6 +247,7 @@ enum LP87565_regulator_id {
|
||||
LP87565_BUCK_3,
|
||||
LP87565_BUCK_10,
|
||||
LP87565_BUCK_23,
|
||||
LP87565_BUCK_3210,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* MFD internals for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_CORE_H
|
||||
@ -26,15 +22,21 @@ enum madera_type {
|
||||
CS47L85 = 2,
|
||||
CS47L90 = 3,
|
||||
CS47L91 = 4,
|
||||
CS47L92 = 5,
|
||||
CS47L93 = 6,
|
||||
WM1840 = 7,
|
||||
CS47L15 = 8,
|
||||
CS42L92 = 9,
|
||||
};
|
||||
|
||||
#define MADERA_MAX_CORE_SUPPLIES 2
|
||||
#define MADERA_MAX_GPIOS 40
|
||||
|
||||
#define CS47L15_NUM_GPIOS 15
|
||||
#define CS47L35_NUM_GPIOS 16
|
||||
#define CS47L85_NUM_GPIOS 40
|
||||
#define CS47L90_NUM_GPIOS 38
|
||||
#define CS47L92_NUM_GPIOS 16
|
||||
|
||||
#define MADERA_MAX_MICBIAS 4
|
||||
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Platform data for Cirrus Logic Madera codecs
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_PDATA_H
|
||||
@ -35,7 +31,8 @@ struct madera_codec_pdata;
|
||||
* @micvdd: Substruct of pdata for the MICVDD regulator
|
||||
* @irq_flags: Mode for primary IRQ (defaults to active low)
|
||||
* @gpio_base: Base GPIO number
|
||||
* @gpio_configs: Array of GPIO configurations (See Documentation/pinctrl.txt)
|
||||
* @gpio_configs: Array of GPIO configurations (See
|
||||
* Documentation/driver-api/pinctl.rst)
|
||||
* @n_gpio_configs: Number of entries in gpio_configs
|
||||
* @gpsw: General purpose switch mode setting. Depends on the external
|
||||
* hardware connected to the switch. (See the SW1_MODE field
|
||||
|
@ -1,12 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Madera register definitions
|
||||
*
|
||||
* Copyright (C) 2015-2018 Cirrus Logic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2.
|
||||
*/
|
||||
|
||||
#ifndef MADERA_REGISTERS_H
|
||||
@ -76,10 +72,14 @@
|
||||
#define MADERA_FLL1_CONTROL_4 0x174
|
||||
#define MADERA_FLL1_CONTROL_5 0x175
|
||||
#define MADERA_FLL1_CONTROL_6 0x176
|
||||
#define MADERA_FLL1_LOOP_FILTER_TEST_1 0x177
|
||||
#define MADERA_FLL1_NCO_TEST_0 0x178
|
||||
#define CS47L92_FLL1_CONTROL_7 0x177
|
||||
#define CS47L92_FLL1_CONTROL_8 0x178
|
||||
#define MADERA_FLL1_CONTROL_7 0x179
|
||||
#define CS47L92_FLL1_CONTROL_9 0x179
|
||||
#define MADERA_FLL1_EFS_2 0x17A
|
||||
#define CS47L92_FLL1_CONTROL_10 0x17A
|
||||
#define MADERA_FLL1_CONTROL_11 0x17B
|
||||
#define MADERA_FLL1_DIGITAL_TEST_1 0x17D
|
||||
#define CS47L35_FLL1_SYNCHRONISER_1 0x17F
|
||||
#define CS47L35_FLL1_SYNCHRONISER_2 0x180
|
||||
#define CS47L35_FLL1_SYNCHRONISER_3 0x181
|
||||
@ -98,16 +98,21 @@
|
||||
#define MADERA_FLL1_SYNCHRONISER_7 0x187
|
||||
#define MADERA_FLL1_SPREAD_SPECTRUM 0x189
|
||||
#define MADERA_FLL1_GPIO_CLOCK 0x18A
|
||||
#define CS47L92_FLL1_GPIO_CLOCK 0x18E
|
||||
#define MADERA_FLL2_CONTROL_1 0x191
|
||||
#define MADERA_FLL2_CONTROL_2 0x192
|
||||
#define MADERA_FLL2_CONTROL_3 0x193
|
||||
#define MADERA_FLL2_CONTROL_4 0x194
|
||||
#define MADERA_FLL2_CONTROL_5 0x195
|
||||
#define MADERA_FLL2_CONTROL_6 0x196
|
||||
#define MADERA_FLL2_LOOP_FILTER_TEST_1 0x197
|
||||
#define MADERA_FLL2_NCO_TEST_0 0x198
|
||||
#define CS47L92_FLL2_CONTROL_7 0x197
|
||||
#define CS47L92_FLL2_CONTROL_8 0x198
|
||||
#define MADERA_FLL2_CONTROL_7 0x199
|
||||
#define CS47L92_FLL2_CONTROL_9 0x199
|
||||
#define MADERA_FLL2_EFS_2 0x19A
|
||||
#define CS47L92_FLL2_CONTROL_10 0x19A
|
||||
#define MADERA_FLL2_CONTROL_11 0x19B
|
||||
#define MADERA_FLL2_DIGITAL_TEST_1 0x19D
|
||||
#define MADERA_FLL2_SYNCHRONISER_1 0x1A1
|
||||
#define MADERA_FLL2_SYNCHRONISER_2 0x1A2
|
||||
#define MADERA_FLL2_SYNCHRONISER_3 0x1A3
|
||||
@ -117,14 +122,13 @@
|
||||
#define MADERA_FLL2_SYNCHRONISER_7 0x1A7
|
||||
#define MADERA_FLL2_SPREAD_SPECTRUM 0x1A9
|
||||
#define MADERA_FLL2_GPIO_CLOCK 0x1AA
|
||||
#define CS47L92_FLL2_GPIO_CLOCK 0x1AE
|
||||
#define MADERA_FLL3_CONTROL_1 0x1B1
|
||||
#define MADERA_FLL3_CONTROL_2 0x1B2
|
||||
#define MADERA_FLL3_CONTROL_3 0x1B3
|
||||
#define MADERA_FLL3_CONTROL_4 0x1B4
|
||||
#define MADERA_FLL3_CONTROL_5 0x1B5
|
||||
#define MADERA_FLL3_CONTROL_6 0x1B6
|
||||
#define MADERA_FLL3_LOOP_FILTER_TEST_1 0x1B7
|
||||
#define MADERA_FLL3_NCO_TEST_0 0x1B8
|
||||
#define MADERA_FLL3_CONTROL_7 0x1B9
|
||||
#define MADERA_FLL3_SYNCHRONISER_1 0x1C1
|
||||
#define MADERA_FLL3_SYNCHRONISER_2 0x1C2
|
||||
@ -244,6 +248,8 @@
|
||||
#define MADERA_IN6R_CONTROL 0x33C
|
||||
#define MADERA_ADC_DIGITAL_VOLUME_6R 0x33D
|
||||
#define MADERA_DMIC6R_CONTROL 0x33E
|
||||
#define CS47L15_ADC_INT_BIAS 0x3A8
|
||||
#define CS47L15_PGA_BIAS_SEL 0x3C4
|
||||
#define MADERA_OUTPUT_ENABLES_1 0x400
|
||||
#define MADERA_OUTPUT_STATUS_1 0x401
|
||||
#define MADERA_RAW_OUTPUT_STATUS_1 0x406
|
||||
@ -265,6 +271,7 @@
|
||||
#define MADERA_NOISE_GATE_SELECT_2R 0x41F
|
||||
#define MADERA_OUTPUT_PATH_CONFIG_3L 0x420
|
||||
#define MADERA_DAC_DIGITAL_VOLUME_3L 0x421
|
||||
#define MADERA_OUTPUT_PATH_CONFIG_3 0x422
|
||||
#define MADERA_NOISE_GATE_SELECT_3L 0x423
|
||||
#define MADERA_OUTPUT_PATH_CONFIG_3R 0x424
|
||||
#define MADERA_DAC_DIGITAL_VOLUME_3R 0x425
|
||||
@ -287,9 +294,6 @@
|
||||
#define MADERA_OUTPUT_PATH_CONFIG_6R 0x43C
|
||||
#define MADERA_DAC_DIGITAL_VOLUME_6R 0x43D
|
||||
#define MADERA_NOISE_GATE_SELECT_6R 0x43F
|
||||
#define MADERA_DRE_ENABLE 0x440
|
||||
#define MADERA_EDRE_ENABLE 0x448
|
||||
#define MADERA_EDRE_MANUAL 0x44A
|
||||
#define MADERA_DAC_AEC_CONTROL_1 0x450
|
||||
#define MADERA_DAC_AEC_CONTROL_2 0x451
|
||||
#define MADERA_NOISE_GATE_CONTROL 0x458
|
||||
@ -367,8 +371,20 @@
|
||||
#define MADERA_AIF3_FRAME_CTRL_2 0x588
|
||||
#define MADERA_AIF3_FRAME_CTRL_3 0x589
|
||||
#define MADERA_AIF3_FRAME_CTRL_4 0x58A
|
||||
#define MADERA_AIF3_FRAME_CTRL_5 0x58B
|
||||
#define MADERA_AIF3_FRAME_CTRL_6 0x58C
|
||||
#define MADERA_AIF3_FRAME_CTRL_7 0x58D
|
||||
#define MADERA_AIF3_FRAME_CTRL_8 0x58E
|
||||
#define MADERA_AIF3_FRAME_CTRL_9 0x58F
|
||||
#define MADERA_AIF3_FRAME_CTRL_10 0x590
|
||||
#define MADERA_AIF3_FRAME_CTRL_11 0x591
|
||||
#define MADERA_AIF3_FRAME_CTRL_12 0x592
|
||||
#define MADERA_AIF3_FRAME_CTRL_13 0x593
|
||||
#define MADERA_AIF3_FRAME_CTRL_14 0x594
|
||||
#define MADERA_AIF3_FRAME_CTRL_15 0x595
|
||||
#define MADERA_AIF3_FRAME_CTRL_16 0x596
|
||||
#define MADERA_AIF3_FRAME_CTRL_17 0x597
|
||||
#define MADERA_AIF3_FRAME_CTRL_18 0x598
|
||||
#define MADERA_AIF3_TX_ENABLES 0x599
|
||||
#define MADERA_AIF3_RX_ENABLES 0x59A
|
||||
#define MADERA_AIF3_FORCE_WRITE 0x59B
|
||||
@ -660,6 +676,54 @@
|
||||
#define MADERA_AIF3TX2MIX_INPUT_3_VOLUME 0x78D
|
||||
#define MADERA_AIF3TX2MIX_INPUT_4_SOURCE 0x78E
|
||||
#define MADERA_AIF3TX2MIX_INPUT_4_VOLUME 0x78F
|
||||
#define MADERA_AIF3TX3MIX_INPUT_1_SOURCE 0x790
|
||||
#define MADERA_AIF3TX3MIX_INPUT_1_VOLUME 0x791
|
||||
#define MADERA_AIF3TX3MIX_INPUT_2_SOURCE 0x792
|
||||
#define MADERA_AIF3TX3MIX_INPUT_2_VOLUME 0x793
|
||||
#define MADERA_AIF3TX3MIX_INPUT_3_SOURCE 0x794
|
||||
#define MADERA_AIF3TX3MIX_INPUT_3_VOLUME 0x795
|
||||
#define MADERA_AIF3TX3MIX_INPUT_4_SOURCE 0x796
|
||||
#define MADERA_AIF3TX3MIX_INPUT_4_VOLUME 0x797
|
||||
#define MADERA_AIF3TX4MIX_INPUT_1_SOURCE 0x798
|
||||
#define MADERA_AIF3TX4MIX_INPUT_1_VOLUME 0x799
|
||||
#define MADERA_AIF3TX4MIX_INPUT_2_SOURCE 0x79A
|
||||
#define MADERA_AIF3TX4MIX_INPUT_2_VOLUME 0x79B
|
||||
#define MADERA_AIF3TX4MIX_INPUT_3_SOURCE 0x79C
|
||||
#define MADERA_AIF3TX4MIX_INPUT_3_VOLUME 0x79D
|
||||
#define MADERA_AIF3TX4MIX_INPUT_4_SOURCE 0x79E
|
||||
#define MADERA_AIF3TX4MIX_INPUT_4_VOLUME 0x79F
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_1_SOURCE 0x7A0
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_1_VOLUME 0x7A1
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_2_SOURCE 0x7A2
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_2_VOLUME 0x7A3
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_3_SOURCE 0x7A4
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_3_VOLUME 0x7A5
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_4_SOURCE 0x7A6
|
||||
#define CS47L92_AIF3TX5MIX_INPUT_4_VOLUME 0x7A7
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_1_SOURCE 0x7A8
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_1_VOLUME 0x7A9
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_2_SOURCE 0x7AA
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_2_VOLUME 0x7AB
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_3_SOURCE 0x7AC
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_3_VOLUME 0x7AD
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_4_SOURCE 0x7AE
|
||||
#define CS47L92_AIF3TX6MIX_INPUT_4_VOLUME 0x7AF
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_1_SOURCE 0x7B0
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_1_VOLUME 0x7B1
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_2_SOURCE 0x7B2
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_2_VOLUME 0x7B3
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_3_SOURCE 0x7B4
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_3_VOLUME 0x7B5
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_4_SOURCE 0x7B6
|
||||
#define CS47L92_AIF3TX7MIX_INPUT_4_VOLUME 0x7B7
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_1_SOURCE 0x7B8
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_1_VOLUME 0x7B9
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_2_SOURCE 0x7BA
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_2_VOLUME 0x7BB
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_3_SOURCE 0x7BC
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_3_VOLUME 0x7BD
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_4_SOURCE 0x7BE
|
||||
#define CS47L92_AIF3TX8MIX_INPUT_4_VOLUME 0x7BF
|
||||
#define MADERA_AIF4TX1MIX_INPUT_1_SOURCE 0x7A0
|
||||
#define MADERA_AIF4TX1MIX_INPUT_1_VOLUME 0x7A1
|
||||
#define MADERA_AIF4TX1MIX_INPUT_2_SOURCE 0x7A2
|
||||
@ -1103,68 +1167,8 @@
|
||||
#define MADERA_FCR_ADC_REFORMATTER_CONTROL 0xF73
|
||||
#define MADERA_FCR_COEFF_START 0xF74
|
||||
#define MADERA_FCR_COEFF_END 0xFC5
|
||||
#define MADERA_DAC_COMP_1 0x1300
|
||||
#define MADERA_DAC_COMP_2 0x1302
|
||||
#define MADERA_FRF_COEFFICIENT_1L_1 0x1380
|
||||
#define MADERA_FRF_COEFFICIENT_1L_2 0x1381
|
||||
#define MADERA_FRF_COEFFICIENT_1L_3 0x1382
|
||||
#define MADERA_FRF_COEFFICIENT_1L_4 0x1383
|
||||
#define MADERA_FRF_COEFFICIENT_1R_1 0x1390
|
||||
#define MADERA_FRF_COEFFICIENT_1R_2 0x1391
|
||||
#define MADERA_FRF_COEFFICIENT_1R_3 0x1392
|
||||
#define MADERA_FRF_COEFFICIENT_1R_4 0x1393
|
||||
#define MADERA_FRF_COEFFICIENT_2L_1 0x13A0
|
||||
#define MADERA_FRF_COEFFICIENT_2L_2 0x13A1
|
||||
#define MADERA_FRF_COEFFICIENT_2L_3 0x13A2
|
||||
#define MADERA_FRF_COEFFICIENT_2L_4 0x13A3
|
||||
#define MADERA_FRF_COEFFICIENT_2R_1 0x13B0
|
||||
#define MADERA_FRF_COEFFICIENT_2R_2 0x13B1
|
||||
#define MADERA_FRF_COEFFICIENT_2R_3 0x13B2
|
||||
#define MADERA_FRF_COEFFICIENT_2R_4 0x13B3
|
||||
#define MADERA_FRF_COEFFICIENT_3L_1 0x13C0
|
||||
#define MADERA_FRF_COEFFICIENT_3L_2 0x13C1
|
||||
#define MADERA_FRF_COEFFICIENT_3L_3 0x13C2
|
||||
#define MADERA_FRF_COEFFICIENT_3L_4 0x13C3
|
||||
#define MADERA_FRF_COEFFICIENT_3R_1 0x13D0
|
||||
#define MADERA_FRF_COEFFICIENT_3R_2 0x13D1
|
||||
#define MADERA_FRF_COEFFICIENT_3R_3 0x13D2
|
||||
#define MADERA_FRF_COEFFICIENT_3R_4 0x13D3
|
||||
#define MADERA_FRF_COEFFICIENT_4L_1 0x13E0
|
||||
#define MADERA_FRF_COEFFICIENT_4L_2 0x13E1
|
||||
#define MADERA_FRF_COEFFICIENT_4L_3 0x13E2
|
||||
#define MADERA_FRF_COEFFICIENT_4L_4 0x13E3
|
||||
#define MADERA_FRF_COEFFICIENT_4R_1 0x13F0
|
||||
#define MADERA_FRF_COEFFICIENT_4R_2 0x13F1
|
||||
#define MADERA_FRF_COEFFICIENT_4R_3 0x13F2
|
||||
#define MADERA_FRF_COEFFICIENT_4R_4 0x13F3
|
||||
#define CS47L35_FRF_COEFFICIENT_4L_1 0x13A0
|
||||
#define CS47L35_FRF_COEFFICIENT_4L_2 0x13A1
|
||||
#define CS47L35_FRF_COEFFICIENT_4L_3 0x13A2
|
||||
#define CS47L35_FRF_COEFFICIENT_4L_4 0x13A3
|
||||
#define CS47L35_FRF_COEFFICIENT_5L_1 0x13B0
|
||||
#define CS47L35_FRF_COEFFICIENT_5L_2 0x13B1
|
||||
#define CS47L35_FRF_COEFFICIENT_5L_3 0x13B2
|
||||
#define CS47L35_FRF_COEFFICIENT_5L_4 0x13B3
|
||||
#define CS47L35_FRF_COEFFICIENT_5R_1 0x13C0
|
||||
#define CS47L35_FRF_COEFFICIENT_5R_2 0x13C1
|
||||
#define CS47L35_FRF_COEFFICIENT_5R_3 0x13C2
|
||||
#define CS47L35_FRF_COEFFICIENT_5R_4 0x13C3
|
||||
#define MADERA_FRF_COEFFICIENT_5L_1 0x1400
|
||||
#define MADERA_FRF_COEFFICIENT_5L_2 0x1401
|
||||
#define MADERA_FRF_COEFFICIENT_5L_3 0x1402
|
||||
#define MADERA_FRF_COEFFICIENT_5L_4 0x1403
|
||||
#define MADERA_FRF_COEFFICIENT_5R_1 0x1410
|
||||
#define MADERA_FRF_COEFFICIENT_5R_2 0x1411
|
||||
#define MADERA_FRF_COEFFICIENT_5R_3 0x1412
|
||||
#define MADERA_FRF_COEFFICIENT_5R_4 0x1413
|
||||
#define MADERA_FRF_COEFFICIENT_6L_1 0x1420
|
||||
#define MADERA_FRF_COEFFICIENT_6L_2 0x1421
|
||||
#define MADERA_FRF_COEFFICIENT_6L_3 0x1422
|
||||
#define MADERA_FRF_COEFFICIENT_6L_4 0x1423
|
||||
#define MADERA_FRF_COEFFICIENT_6R_1 0x1430
|
||||
#define MADERA_FRF_COEFFICIENT_6R_2 0x1431
|
||||
#define MADERA_FRF_COEFFICIENT_6R_3 0x1432
|
||||
#define MADERA_FRF_COEFFICIENT_6R_4 0x1433
|
||||
#define MADERA_AUXPDM1_CTRL_0 0x10C0
|
||||
#define MADERA_AUXPDM1_CTRL_1 0x10C1
|
||||
#define MADERA_DFC1_CTRL 0x1480
|
||||
#define MADERA_DFC1_RX 0x1482
|
||||
#define MADERA_DFC1_TX 0x1484
|
||||
@ -1202,6 +1206,8 @@
|
||||
#define MADERA_GPIO1_CTRL_2 0x1701
|
||||
#define MADERA_GPIO2_CTRL_1 0x1702
|
||||
#define MADERA_GPIO2_CTRL_2 0x1703
|
||||
#define MADERA_GPIO15_CTRL_1 0x171C
|
||||
#define MADERA_GPIO15_CTRL_2 0x171D
|
||||
#define MADERA_GPIO16_CTRL_1 0x171E
|
||||
#define MADERA_GPIO16_CTRL_2 0x171F
|
||||
#define MADERA_GPIO38_CTRL_1 0x174A
|
||||
@ -1232,6 +1238,7 @@
|
||||
#define MADERA_IRQ2_CTRL 0x1A82
|
||||
#define MADERA_INTERRUPT_RAW_STATUS_1 0x1AA0
|
||||
#define MADERA_WSEQ_SEQUENCE_1 0x3000
|
||||
#define MADERA_WSEQ_SEQUENCE_225 0x31C0
|
||||
#define MADERA_WSEQ_SEQUENCE_252 0x31F6
|
||||
#define CS47L35_OTP_HPDET_CAL_1 0x31F8
|
||||
#define CS47L35_OTP_HPDET_CAL_2 0x31FA
|
||||
@ -1441,6 +1448,12 @@
|
||||
#define MADERA_OPCLK_ASYNC_SEL_WIDTH 3
|
||||
|
||||
/* (0x0171) FLL1_Control_1 */
|
||||
#define CS47L92_FLL1_REFCLK_SRC_MASK 0xF000
|
||||
#define CS47L92_FLL1_REFCLK_SRC_SHIFT 12
|
||||
#define CS47L92_FLL1_REFCLK_SRC_WIDTH 4
|
||||
#define MADERA_FLL1_HOLD_MASK 0x0004
|
||||
#define MADERA_FLL1_HOLD_SHIFT 2
|
||||
#define MADERA_FLL1_HOLD_WIDTH 1
|
||||
#define MADERA_FLL1_FREERUN 0x0002
|
||||
#define MADERA_FLL1_FREERUN_MASK 0x0002
|
||||
#define MADERA_FLL1_FREERUN_SHIFT 1
|
||||
@ -1473,6 +1486,9 @@
|
||||
#define MADERA_FLL1_FRATIO_MASK 0x0F00
|
||||
#define MADERA_FLL1_FRATIO_SHIFT 8
|
||||
#define MADERA_FLL1_FRATIO_WIDTH 4
|
||||
#define MADERA_FLL1_FB_DIV_MASK 0x03FF
|
||||
#define MADERA_FLL1_FB_DIV_SHIFT 0
|
||||
#define MADERA_FLL1_FB_DIV_WIDTH 10
|
||||
|
||||
/* (0x0176) FLL1_Control_6 */
|
||||
#define MADERA_FLL1_REFCLK_DIV_MASK 0x00C0
|
||||
@ -1482,15 +1498,6 @@
|
||||
#define MADERA_FLL1_REFCLK_SRC_SHIFT 0
|
||||
#define MADERA_FLL1_REFCLK_SRC_WIDTH 4
|
||||
|
||||
/* (0x0177) FLL1_Loop_Filter_Test_1 */
|
||||
#define MADERA_FLL1_FRC_INTEG_UPD 0x8000
|
||||
#define MADERA_FLL1_FRC_INTEG_UPD_MASK 0x8000
|
||||
#define MADERA_FLL1_FRC_INTEG_UPD_SHIFT 15
|
||||
#define MADERA_FLL1_FRC_INTEG_UPD_WIDTH 1
|
||||
#define MADERA_FLL1_FRC_INTEG_VAL_MASK 0x0FFF
|
||||
#define MADERA_FLL1_FRC_INTEG_VAL_SHIFT 0
|
||||
#define MADERA_FLL1_FRC_INTEG_VAL_WIDTH 12
|
||||
|
||||
/* (0x0179) FLL1_Control_7 */
|
||||
#define MADERA_FLL1_GAIN_MASK 0x003c
|
||||
#define MADERA_FLL1_GAIN_SHIFT 2
|
||||
@ -1504,6 +1511,30 @@
|
||||
#define MADERA_FLL1_PHASE_ENA_SHIFT 11
|
||||
#define MADERA_FLL1_PHASE_ENA_WIDTH 1
|
||||
|
||||
/* (0x017A) FLL1_Control_10 */
|
||||
#define MADERA_FLL1_HP_MASK 0xC000
|
||||
#define MADERA_FLL1_HP_SHIFT 14
|
||||
#define MADERA_FLL1_HP_WIDTH 2
|
||||
#define MADERA_FLL1_PHASEDET_ENA_MASK 0x1000
|
||||
#define MADERA_FLL1_PHASEDET_ENA_SHIFT 12
|
||||
#define MADERA_FLL1_PHASEDET_ENA_WIDTH 1
|
||||
|
||||
/* (0x017B) FLL1_Control_11 */
|
||||
#define MADERA_FLL1_LOCKDET_THR_MASK 0x001E
|
||||
#define MADERA_FLL1_LOCKDET_THR_SHIFT 1
|
||||
#define MADERA_FLL1_LOCKDET_THR_WIDTH 4
|
||||
#define MADERA_FLL1_LOCKDET_MASK 0x0001
|
||||
#define MADERA_FLL1_LOCKDET_SHIFT 0
|
||||
#define MADERA_FLL1_LOCKDET_WIDTH 1
|
||||
|
||||
/* (0x017D) FLL1_Digital_Test_1 */
|
||||
#define MADERA_FLL1_SYNC_EFS_ENA_MASK 0x0100
|
||||
#define MADERA_FLL1_SYNC_EFS_ENA_SHIFT 8
|
||||
#define MADERA_FLL1_SYNC_EFS_ENA_WIDTH 1
|
||||
#define MADERA_FLL1_CLK_VCO_FAST_SRC_MASK 0x0003
|
||||
#define MADERA_FLL1_CLK_VCO_FAST_SRC_SHIFT 0
|
||||
#define MADERA_FLL1_CLK_VCO_FAST_SRC_WIDTH 2
|
||||
|
||||
/* (0x0181) FLL1_Synchroniser_1 */
|
||||
#define MADERA_FLL1_SYNC_ENA 0x0001
|
||||
#define MADERA_FLL1_SYNC_ENA_MASK 0x0001
|
||||
@ -1625,6 +1656,13 @@
|
||||
#define MADERA_LDO2_ENA_WIDTH 1
|
||||
|
||||
/* (0x0218) Mic_Bias_Ctrl_1 */
|
||||
#define MADERA_MICB1_EXT_CAP 0x8000
|
||||
#define MADERA_MICB1_EXT_CAP_MASK 0x8000
|
||||
#define MADERA_MICB1_EXT_CAP_SHIFT 15
|
||||
#define MADERA_MICB1_EXT_CAP_WIDTH 1
|
||||
#define MADERA_MICB1_LVL_MASK 0x01E0
|
||||
#define MADERA_MICB1_LVL_SHIFT 5
|
||||
#define MADERA_MICB1_LVL_WIDTH 4
|
||||
#define MADERA_MICB1_ENA 0x0001
|
||||
#define MADERA_MICB1_ENA_MASK 0x0001
|
||||
#define MADERA_MICB1_ENA_SHIFT 0
|
||||
@ -2308,6 +2346,17 @@
|
||||
#define MADERA_OUT1R_ENA_SHIFT 0
|
||||
#define MADERA_OUT1R_ENA_WIDTH 1
|
||||
|
||||
/* (0x0408) Output_Rate_1 */
|
||||
#define MADERA_CP_DAC_MODE_MASK 0x0040
|
||||
#define MADERA_CP_DAC_MODE_SHIFT 6
|
||||
#define MADERA_CP_DAC_MODE_WIDTH 1
|
||||
#define MADERA_OUT_EXT_CLK_DIV_MASK 0x0030
|
||||
#define MADERA_OUT_EXT_CLK_DIV_SHIFT 4
|
||||
#define MADERA_OUT_EXT_CLK_DIV_WIDTH 2
|
||||
#define MADERA_OUT_CLK_SRC_MASK 0x0007
|
||||
#define MADERA_OUT_CLK_SRC_SHIFT 0
|
||||
#define MADERA_OUT_CLK_SRC_WIDTH 3
|
||||
|
||||
/* (0x0409) Output_Volume_Ramp */
|
||||
#define MADERA_OUT_VD_RAMP_MASK 0x0070
|
||||
#define MADERA_OUT_VD_RAMP_SHIFT 4
|
||||
@ -2829,6 +2878,30 @@
|
||||
#define MADERA_AIF2RX1_ENA_WIDTH 1
|
||||
|
||||
/* (0x0599) AIF3_Tx_Enables */
|
||||
#define MADERA_AIF3TX8_ENA 0x0080
|
||||
#define MADERA_AIF3TX8_ENA_MASK 0x0080
|
||||
#define MADERA_AIF3TX8_ENA_SHIFT 7
|
||||
#define MADERA_AIF3TX8_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX7_ENA 0x0040
|
||||
#define MADERA_AIF3TX7_ENA_MASK 0x0040
|
||||
#define MADERA_AIF3TX7_ENA_SHIFT 6
|
||||
#define MADERA_AIF3TX7_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX6_ENA 0x0020
|
||||
#define MADERA_AIF3TX6_ENA_MASK 0x0020
|
||||
#define MADERA_AIF3TX6_ENA_SHIFT 5
|
||||
#define MADERA_AIF3TX6_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX5_ENA 0x0010
|
||||
#define MADERA_AIF3TX5_ENA_MASK 0x0010
|
||||
#define MADERA_AIF3TX5_ENA_SHIFT 4
|
||||
#define MADERA_AIF3TX5_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX4_ENA 0x0008
|
||||
#define MADERA_AIF3TX4_ENA_MASK 0x0008
|
||||
#define MADERA_AIF3TX4_ENA_SHIFT 3
|
||||
#define MADERA_AIF3TX4_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX3_ENA 0x0004
|
||||
#define MADERA_AIF3TX3_ENA_MASK 0x0004
|
||||
#define MADERA_AIF3TX3_ENA_SHIFT 2
|
||||
#define MADERA_AIF3TX3_ENA_WIDTH 1
|
||||
#define MADERA_AIF3TX2_ENA 0x0002
|
||||
#define MADERA_AIF3TX2_ENA_MASK 0x0002
|
||||
#define MADERA_AIF3TX2_ENA_SHIFT 1
|
||||
@ -2839,6 +2912,30 @@
|
||||
#define MADERA_AIF3TX1_ENA_WIDTH 1
|
||||
|
||||
/* (0x059A) AIF3_Rx_Enables */
|
||||
#define MADERA_AIF3RX8_ENA 0x0080
|
||||
#define MADERA_AIF3RX8_ENA_MASK 0x0080
|
||||
#define MADERA_AIF3RX8_ENA_SHIFT 7
|
||||
#define MADERA_AIF3RX8_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX7_ENA 0x0040
|
||||
#define MADERA_AIF3RX7_ENA_MASK 0x0040
|
||||
#define MADERA_AIF3RX7_ENA_SHIFT 6
|
||||
#define MADERA_AIF3RX7_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX6_ENA 0x0020
|
||||
#define MADERA_AIF3RX6_ENA_MASK 0x0020
|
||||
#define MADERA_AIF3RX6_ENA_SHIFT 5
|
||||
#define MADERA_AIF3RX6_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX5_ENA 0x0010
|
||||
#define MADERA_AIF3RX5_ENA_MASK 0x0010
|
||||
#define MADERA_AIF3RX5_ENA_SHIFT 4
|
||||
#define MADERA_AIF3RX5_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX4_ENA 0x0008
|
||||
#define MADERA_AIF3RX4_ENA_MASK 0x0008
|
||||
#define MADERA_AIF3RX4_ENA_SHIFT 3
|
||||
#define MADERA_AIF3RX4_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX3_ENA 0x0004
|
||||
#define MADERA_AIF3RX3_ENA_MASK 0x0004
|
||||
#define MADERA_AIF3RX3_ENA_SHIFT 2
|
||||
#define MADERA_AIF3RX3_ENA_WIDTH 1
|
||||
#define MADERA_AIF3RX2_ENA 0x0002
|
||||
#define MADERA_AIF3RX2_ENA_MASK 0x0002
|
||||
#define MADERA_AIF3RX2_ENA_SHIFT 1
|
||||
@ -3453,6 +3550,25 @@
|
||||
#define MADERA_FCR_MIC_MODE_SEL_SHIFT 2
|
||||
#define MADERA_FCR_MIC_MODE_SEL_WIDTH 2
|
||||
|
||||
/* (0x10C0) AUXPDM1_CTRL_0 */
|
||||
#define MADERA_AUXPDM1_SRC_MASK 0x0F00
|
||||
#define MADERA_AUXPDM1_SRC_SHIFT 8
|
||||
#define MADERA_AUXPDM1_SRC_WIDTH 4
|
||||
#define MADERA_AUXPDM1_TXEDGE_MASK 0x0010
|
||||
#define MADERA_AUXPDM1_TXEDGE_SHIFT 4
|
||||
#define MADERA_AUXPDM1_TXEDGE_WIDTH 1
|
||||
#define MADERA_AUXPDM1_MSTR_MASK 0x0008
|
||||
#define MADERA_AUXPDM1_MSTR_SHIFT 3
|
||||
#define MADERA_AUXPDM1_MSTR_WIDTH 1
|
||||
#define MADERA_AUXPDM1_ENABLE_MASK 0x0001
|
||||
#define MADERA_AUXPDM1_ENABLE_SHIFT 0
|
||||
#define MADERA_AUXPDM1_ENABLE_WIDTH 1
|
||||
|
||||
/* (0x10C1) AUXPDM1_CTRL_1 */
|
||||
#define MADERA_AUXPDM1_CLK_FREQ_MASK 0xC000
|
||||
#define MADERA_AUXPDM1_CLK_FREQ_SHIFT 14
|
||||
#define MADERA_AUXPDM1_CLK_FREQ_WIDTH 2
|
||||
|
||||
/* (0x1480) DFC1_CTRL_W0 */
|
||||
#define MADERA_DFC1_RATE_MASK 0x007C
|
||||
#define MADERA_DFC1_RATE_SHIFT 2
|
||||
|
@ -374,6 +374,7 @@ enum rk805_reg {
|
||||
#define SWITCH1_EN BIT(5)
|
||||
#define DEV_OFF_RST BIT(3)
|
||||
#define DEV_OFF BIT(0)
|
||||
#define RTC_STOP BIT(0)
|
||||
|
||||
#define VB_LO_ACT BIT(4)
|
||||
#define VB_LO_SEL_3500MV (7 << 0)
|
||||
@ -387,7 +388,179 @@ enum rk805_reg {
|
||||
#define SHUTDOWN_FUN (0x2 << 2)
|
||||
#define SLEEP_FUN (0x1 << 2)
|
||||
#define RK8XX_ID_MSK 0xfff0
|
||||
#define PWM_MODE_MSK BIT(7)
|
||||
#define FPWM_MODE BIT(7)
|
||||
#define AUTO_PWM_MODE 0
|
||||
|
||||
enum rk817_reg_id {
|
||||
RK817_ID_DCDC1 = 0,
|
||||
RK817_ID_DCDC2,
|
||||
RK817_ID_DCDC3,
|
||||
RK817_ID_DCDC4,
|
||||
RK817_ID_LDO1,
|
||||
RK817_ID_LDO2,
|
||||
RK817_ID_LDO3,
|
||||
RK817_ID_LDO4,
|
||||
RK817_ID_LDO5,
|
||||
RK817_ID_LDO6,
|
||||
RK817_ID_LDO7,
|
||||
RK817_ID_LDO8,
|
||||
RK817_ID_LDO9,
|
||||
RK817_ID_BOOST,
|
||||
RK817_ID_BOOST_OTG_SW,
|
||||
RK817_NUM_REGULATORS
|
||||
};
|
||||
|
||||
enum rk809_reg_id {
|
||||
RK809_ID_DCDC5 = RK817_ID_BOOST,
|
||||
RK809_ID_SW1,
|
||||
RK809_ID_SW2,
|
||||
RK809_NUM_REGULATORS
|
||||
};
|
||||
|
||||
#define RK817_SECONDS_REG 0x00
|
||||
#define RK817_MINUTES_REG 0x01
|
||||
#define RK817_HOURS_REG 0x02
|
||||
#define RK817_DAYS_REG 0x03
|
||||
#define RK817_MONTHS_REG 0x04
|
||||
#define RK817_YEARS_REG 0x05
|
||||
#define RK817_WEEKS_REG 0x06
|
||||
#define RK817_ALARM_SECONDS_REG 0x07
|
||||
#define RK817_ALARM_MINUTES_REG 0x08
|
||||
#define RK817_ALARM_HOURS_REG 0x09
|
||||
#define RK817_ALARM_DAYS_REG 0x0a
|
||||
#define RK817_ALARM_MONTHS_REG 0x0b
|
||||
#define RK817_ALARM_YEARS_REG 0x0c
|
||||
#define RK817_RTC_CTRL_REG 0xd
|
||||
#define RK817_RTC_STATUS_REG 0xe
|
||||
#define RK817_RTC_INT_REG 0xf
|
||||
#define RK817_RTC_COMP_LSB_REG 0x10
|
||||
#define RK817_RTC_COMP_MSB_REG 0x11
|
||||
|
||||
#define RK817_POWER_EN_REG(i) (0xb1 + (i))
|
||||
#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i))
|
||||
|
||||
#define RK817_POWER_CONFIG (0xb9)
|
||||
|
||||
#define RK817_BUCK_CONFIG_REG(i) (0xba + (i) * 3)
|
||||
|
||||
#define RK817_BUCK1_ON_VSEL_REG 0xBB
|
||||
#define RK817_BUCK1_SLP_VSEL_REG 0xBC
|
||||
|
||||
#define RK817_BUCK2_CONFIG_REG 0xBD
|
||||
#define RK817_BUCK2_ON_VSEL_REG 0xBE
|
||||
#define RK817_BUCK2_SLP_VSEL_REG 0xBF
|
||||
|
||||
#define RK817_BUCK3_CONFIG_REG 0xC0
|
||||
#define RK817_BUCK3_ON_VSEL_REG 0xC1
|
||||
#define RK817_BUCK3_SLP_VSEL_REG 0xC2
|
||||
|
||||
#define RK817_BUCK4_CONFIG_REG 0xC3
|
||||
#define RK817_BUCK4_ON_VSEL_REG 0xC4
|
||||
#define RK817_BUCK4_SLP_VSEL_REG 0xC5
|
||||
|
||||
#define RK817_LDO_ON_VSEL_REG(idx) (0xcc + (idx) * 2)
|
||||
#define RK817_BOOST_OTG_CFG (0xde)
|
||||
|
||||
#define RK817_ID_MSB 0xed
|
||||
#define RK817_ID_LSB 0xee
|
||||
|
||||
#define RK817_SYS_STS 0xf0
|
||||
#define RK817_SYS_CFG(i) (0xf1 + (i))
|
||||
|
||||
#define RK817_ON_SOURCE_REG 0xf5
|
||||
#define RK817_OFF_SOURCE_REG 0xf6
|
||||
|
||||
/* INTERRUPT REGISTER */
|
||||
#define RK817_INT_STS_REG0 0xf8
|
||||
#define RK817_INT_STS_MSK_REG0 0xf9
|
||||
#define RK817_INT_STS_REG1 0xfa
|
||||
#define RK817_INT_STS_MSK_REG1 0xfb
|
||||
#define RK817_INT_STS_REG2 0xfc
|
||||
#define RK817_INT_STS_MSK_REG2 0xfd
|
||||
#define RK817_GPIO_INT_CFG 0xfe
|
||||
|
||||
/* IRQ Definitions */
|
||||
#define RK817_IRQ_PWRON_FALL 0
|
||||
#define RK817_IRQ_PWRON_RISE 1
|
||||
#define RK817_IRQ_PWRON 2
|
||||
#define RK817_IRQ_PWMON_LP 3
|
||||
#define RK817_IRQ_HOTDIE 4
|
||||
#define RK817_IRQ_RTC_ALARM 5
|
||||
#define RK817_IRQ_RTC_PERIOD 6
|
||||
#define RK817_IRQ_VB_LO 7
|
||||
#define RK817_IRQ_PLUG_IN 8
|
||||
#define RK817_IRQ_PLUG_OUT 9
|
||||
#define RK817_IRQ_CHRG_TERM 10
|
||||
#define RK817_IRQ_CHRG_TIME 11
|
||||
#define RK817_IRQ_CHRG_TS 12
|
||||
#define RK817_IRQ_USB_OV 13
|
||||
#define RK817_IRQ_CHRG_IN_CLMP 14
|
||||
#define RK817_IRQ_BAT_DIS_ILIM 15
|
||||
#define RK817_IRQ_GATE_GPIO 16
|
||||
#define RK817_IRQ_TS_GPIO 17
|
||||
#define RK817_IRQ_CODEC_PD 18
|
||||
#define RK817_IRQ_CODEC_PO 19
|
||||
#define RK817_IRQ_CLASSD_MUTE_DONE 20
|
||||
#define RK817_IRQ_CLASSD_OCP 21
|
||||
#define RK817_IRQ_BAT_OVP 22
|
||||
#define RK817_IRQ_CHRG_BAT_HI 23
|
||||
#define RK817_IRQ_END (RK817_IRQ_CHRG_BAT_HI + 1)
|
||||
|
||||
/*
|
||||
* rtc_ctrl 0xd
|
||||
* same as 808, except bit4
|
||||
*/
|
||||
#define RK817_RTC_CTRL_RSV4 BIT(4)
|
||||
|
||||
/* power config 0xb9 */
|
||||
#define RK817_BUCK3_FB_RES_MSK BIT(6)
|
||||
#define RK817_BUCK3_FB_RES_INTER BIT(6)
|
||||
#define RK817_BUCK3_FB_RES_EXT 0
|
||||
|
||||
/* buck config 0xba */
|
||||
#define RK817_RAMP_RATE_OFFSET 6
|
||||
#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET)
|
||||
#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET)
|
||||
#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET)
|
||||
#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET)
|
||||
#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET)
|
||||
|
||||
/* sys_cfg1 0xf2 */
|
||||
#define RK817_HOTDIE_TEMP_MSK (0x3 << 4)
|
||||
#define RK817_HOTDIE_85 (0x0 << 4)
|
||||
#define RK817_HOTDIE_95 (0x1 << 4)
|
||||
#define RK817_HOTDIE_105 (0x2 << 4)
|
||||
#define RK817_HOTDIE_115 (0x3 << 4)
|
||||
|
||||
#define RK817_TSD_TEMP_MSK BIT(6)
|
||||
#define RK817_TSD_140 0
|
||||
#define RK817_TSD_160 BIT(6)
|
||||
|
||||
#define RK817_CLK32KOUT2_EN BIT(7)
|
||||
|
||||
/* sys_cfg3 0xf4 */
|
||||
#define RK817_SLPPIN_FUNC_MSK (0x3 << 3)
|
||||
#define SLPPIN_NULL_FUN (0x0 << 3)
|
||||
#define SLPPIN_SLP_FUN (0x1 << 3)
|
||||
#define SLPPIN_DN_FUN (0x2 << 3)
|
||||
#define SLPPIN_RST_FUN (0x3 << 3)
|
||||
|
||||
#define RK817_RST_FUNC_MSK (0x3 << 6)
|
||||
#define RK817_RST_FUNC_SFT (6)
|
||||
#define RK817_RST_FUNC_CNT (3)
|
||||
#define RK817_RST_FUNC_DEV (0) /* reset the dev */
|
||||
#define RK817_RST_FUNC_REG (0x1 << 6) /* reset the reg only */
|
||||
|
||||
#define RK817_SLPPOL_MSK BIT(5)
|
||||
#define RK817_SLPPOL_H BIT(5)
|
||||
#define RK817_SLPPOL_L (0)
|
||||
|
||||
/* gpio&int 0xfe */
|
||||
#define RK817_INT_POL_MSK BIT(1)
|
||||
#define RK817_INT_POL_H BIT(1)
|
||||
#define RK817_INT_POL_L 0
|
||||
#define RK809_BUCK5_CONFIG(i) (RK817_BOOST_OTG_CFG + (i) * 1)
|
||||
|
||||
enum {
|
||||
BUCK_ILMIN_50MA,
|
||||
@ -435,6 +608,8 @@ enum {
|
||||
enum {
|
||||
RK805_ID = 0x8050,
|
||||
RK808_ID = 0x0000,
|
||||
RK809_ID = 0x8090,
|
||||
RK817_ID = 0x8170,
|
||||
RK818_ID = 0x8181,
|
||||
};
|
||||
|
||||
@ -445,5 +620,7 @@ struct rk808 {
|
||||
long variant;
|
||||
const struct regmap_config *regmap_cfg;
|
||||
const struct regmap_irq_chip *regmap_irq_chip;
|
||||
void (*pm_pwroff_fn)(void);
|
||||
void (*pm_pwroff_prep_fn)(void);
|
||||
};
|
||||
#endif /* __LINUX_REGULATOR_RK808_H */
|
||||
|
408
include/linux/mfd/rohm-bd70528.h
Normal file
408
include/linux/mfd/rohm-bd70528.h
Normal file
@ -0,0 +1,408 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2018 ROHM Semiconductors */
|
||||
|
||||
#ifndef __LINUX_MFD_BD70528_H__
|
||||
#define __LINUX_MFD_BD70528_H__
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
BD70528_BUCK1,
|
||||
BD70528_BUCK2,
|
||||
BD70528_BUCK3,
|
||||
BD70528_LDO1,
|
||||
BD70528_LDO2,
|
||||
BD70528_LDO3,
|
||||
BD70528_LED1,
|
||||
BD70528_LED2,
|
||||
};
|
||||
|
||||
struct bd70528_data {
|
||||
struct rohm_regmap_dev chip;
|
||||
struct mutex rtc_timer_lock;
|
||||
};
|
||||
|
||||
#define BD70528_BUCK_VOLTS 17
|
||||
#define BD70528_BUCK_VOLTS 17
|
||||
#define BD70528_BUCK_VOLTS 17
|
||||
#define BD70528_LDO_VOLTS 0x20
|
||||
|
||||
#define BD70528_REG_BUCK1_EN 0x0F
|
||||
#define BD70528_REG_BUCK1_VOLT 0x15
|
||||
#define BD70528_REG_BUCK2_EN 0x10
|
||||
#define BD70528_REG_BUCK2_VOLT 0x16
|
||||
#define BD70528_REG_BUCK3_EN 0x11
|
||||
#define BD70528_REG_BUCK3_VOLT 0x17
|
||||
#define BD70528_REG_LDO1_EN 0x1b
|
||||
#define BD70528_REG_LDO1_VOLT 0x1e
|
||||
#define BD70528_REG_LDO2_EN 0x1c
|
||||
#define BD70528_REG_LDO2_VOLT 0x1f
|
||||
#define BD70528_REG_LDO3_EN 0x1d
|
||||
#define BD70528_REG_LDO3_VOLT 0x20
|
||||
#define BD70528_REG_LED_CTRL 0x2b
|
||||
#define BD70528_REG_LED_VOLT 0x29
|
||||
#define BD70528_REG_LED_EN 0x2a
|
||||
|
||||
/* main irq registers */
|
||||
#define BD70528_REG_INT_MAIN 0x7E
|
||||
#define BD70528_REG_INT_MAIN_MASK 0x74
|
||||
|
||||
/* 'sub irq' registers */
|
||||
#define BD70528_REG_INT_SHDN 0x7F
|
||||
#define BD70528_REG_INT_PWR_FLT 0x80
|
||||
#define BD70528_REG_INT_VR_FLT 0x81
|
||||
#define BD70528_REG_INT_MISC 0x82
|
||||
#define BD70528_REG_INT_BAT1 0x83
|
||||
#define BD70528_REG_INT_BAT2 0x84
|
||||
#define BD70528_REG_INT_RTC 0x85
|
||||
#define BD70528_REG_INT_GPIO 0x86
|
||||
#define BD70528_REG_INT_OP_FAIL 0x87
|
||||
|
||||
#define BD70528_REG_INT_SHDN_MASK 0x75
|
||||
#define BD70528_REG_INT_PWR_FLT_MASK 0x76
|
||||
#define BD70528_REG_INT_VR_FLT_MASK 0x77
|
||||
#define BD70528_REG_INT_MISC_MASK 0x78
|
||||
#define BD70528_REG_INT_BAT1_MASK 0x79
|
||||
#define BD70528_REG_INT_BAT2_MASK 0x7a
|
||||
#define BD70528_REG_INT_RTC_MASK 0x7b
|
||||
#define BD70528_REG_INT_GPIO_MASK 0x7c
|
||||
#define BD70528_REG_INT_OP_FAIL_MASK 0x7d
|
||||
|
||||
/* Reset related 'magic' registers */
|
||||
#define BD70528_REG_SHIPMODE 0x03
|
||||
#define BD70528_REG_HWRESET 0x04
|
||||
#define BD70528_REG_WARMRESET 0x05
|
||||
#define BD70528_REG_STANDBY 0x06
|
||||
|
||||
/* GPIO registers */
|
||||
#define BD70528_REG_GPIO_STATE 0x8F
|
||||
|
||||
#define BD70528_REG_GPIO1_IN 0x4d
|
||||
#define BD70528_REG_GPIO2_IN 0x4f
|
||||
#define BD70528_REG_GPIO3_IN 0x51
|
||||
#define BD70528_REG_GPIO4_IN 0x53
|
||||
#define BD70528_REG_GPIO1_OUT 0x4e
|
||||
#define BD70528_REG_GPIO2_OUT 0x50
|
||||
#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
|
||||
#define BD70528_REG_RTC_COUNT_L 0x2e
|
||||
#define BD70528_REG_RTC_SEC 0x2f
|
||||
#define BD70528_REG_RTC_MINUTE 0x30
|
||||
#define BD70528_REG_RTC_HOUR 0x31
|
||||
#define BD70528_REG_RTC_WEEK 0x32
|
||||
#define BD70528_REG_RTC_DAY 0x33
|
||||
#define BD70528_REG_RTC_MONTH 0x34
|
||||
#define BD70528_REG_RTC_YEAR 0x35
|
||||
|
||||
#define BD70528_REG_RTC_ALM_SEC 0x36
|
||||
#define BD70528_REG_RTC_ALM_START BD70528_REG_RTC_ALM_SEC
|
||||
#define BD70528_REG_RTC_ALM_MINUTE 0x37
|
||||
#define BD70528_REG_RTC_ALM_HOUR 0x38
|
||||
#define BD70528_REG_RTC_ALM_WEEK 0x39
|
||||
#define BD70528_REG_RTC_ALM_DAY 0x3a
|
||||
#define BD70528_REG_RTC_ALM_MONTH 0x3b
|
||||
#define BD70528_REG_RTC_ALM_YEAR 0x3c
|
||||
#define BD70528_REG_RTC_ALM_MASK 0x3d
|
||||
#define BD70528_REG_RTC_ALM_REPEAT 0x3e
|
||||
#define BD70528_REG_RTC_START BD70528_REG_RTC_SEC
|
||||
|
||||
#define BD70528_REG_RTC_WAKE_SEC 0x43
|
||||
#define BD70528_REG_RTC_WAKE_START BD70528_REG_RTC_WAKE_SEC
|
||||
#define BD70528_REG_RTC_WAKE_MIN 0x44
|
||||
#define BD70528_REG_RTC_WAKE_HOUR 0x45
|
||||
#define BD70528_REG_RTC_WAKE_CTRL 0x46
|
||||
|
||||
#define BD70528_REG_ELAPSED_TIMER_EN 0x42
|
||||
#define BD70528_REG_WAKE_EN 0x46
|
||||
|
||||
/* WDT registers */
|
||||
#define BD70528_REG_WDT_CTRL 0x4A
|
||||
#define BD70528_REG_WDT_HOUR 0x49
|
||||
#define BD70528_REG_WDT_MINUTE 0x48
|
||||
#define BD70528_REG_WDT_SEC 0x47
|
||||
|
||||
/* Charger / Battery */
|
||||
#define BD70528_REG_CHG_CURR_STAT 0x59
|
||||
#define BD70528_REG_CHG_BAT_STAT 0x57
|
||||
#define BD70528_REG_CHG_BAT_TEMP 0x58
|
||||
#define BD70528_REG_CHG_IN_STAT 0x56
|
||||
#define BD70528_REG_CHG_DCIN_ILIM 0x5d
|
||||
#define BD70528_REG_CHG_CHG_CURR_WARM 0x61
|
||||
#define BD70528_REG_CHG_CHG_CURR_COLD 0x62
|
||||
|
||||
/* Masks for main IRQ register bits */
|
||||
enum {
|
||||
BD70528_INT_SHDN,
|
||||
#define BD70528_INT_SHDN_MASK BIT(BD70528_INT_SHDN)
|
||||
BD70528_INT_PWR_FLT,
|
||||
#define BD70528_INT_PWR_FLT_MASK BIT(BD70528_INT_PWR_FLT)
|
||||
BD70528_INT_VR_FLT,
|
||||
#define BD70528_INT_VR_FLT_MASK BIT(BD70528_INT_VR_FLT)
|
||||
BD70528_INT_MISC,
|
||||
#define BD70528_INT_MISC_MASK BIT(BD70528_INT_MISC)
|
||||
BD70528_INT_BAT1,
|
||||
#define BD70528_INT_BAT1_MASK BIT(BD70528_INT_BAT1)
|
||||
BD70528_INT_RTC,
|
||||
#define BD70528_INT_RTC_MASK BIT(BD70528_INT_RTC)
|
||||
BD70528_INT_GPIO,
|
||||
#define BD70528_INT_GPIO_MASK BIT(BD70528_INT_GPIO)
|
||||
BD70528_INT_OP_FAIL,
|
||||
#define BD70528_INT_OP_FAIL_MASK BIT(BD70528_INT_OP_FAIL)
|
||||
};
|
||||
|
||||
/* IRQs */
|
||||
enum {
|
||||
/* Shutdown register IRQs */
|
||||
BD70528_INT_LONGPUSH,
|
||||
BD70528_INT_WDT,
|
||||
BD70528_INT_HWRESET,
|
||||
BD70528_INT_RSTB_FAULT,
|
||||
BD70528_INT_VBAT_UVLO,
|
||||
BD70528_INT_TSD,
|
||||
BD70528_INT_RSTIN,
|
||||
/* Power failure register IRQs */
|
||||
BD70528_INT_BUCK1_FAULT,
|
||||
BD70528_INT_BUCK2_FAULT,
|
||||
BD70528_INT_BUCK3_FAULT,
|
||||
BD70528_INT_LDO1_FAULT,
|
||||
BD70528_INT_LDO2_FAULT,
|
||||
BD70528_INT_LDO3_FAULT,
|
||||
BD70528_INT_LED1_FAULT,
|
||||
BD70528_INT_LED2_FAULT,
|
||||
/* VR FAULT register IRQs */
|
||||
BD70528_INT_BUCK1_OCP,
|
||||
BD70528_INT_BUCK2_OCP,
|
||||
BD70528_INT_BUCK3_OCP,
|
||||
BD70528_INT_LED1_OCP,
|
||||
BD70528_INT_LED2_OCP,
|
||||
BD70528_INT_BUCK1_FULLON,
|
||||
BD70528_INT_BUCK2_FULLON,
|
||||
/* PMU register interrupts */
|
||||
BD70528_INT_SHORTPUSH,
|
||||
BD70528_INT_AUTO_WAKEUP,
|
||||
BD70528_INT_STATE_CHANGE,
|
||||
/* Charger 1 register IRQs */
|
||||
BD70528_INT_BAT_OV_RES,
|
||||
BD70528_INT_BAT_OV_DET,
|
||||
BD70528_INT_DBAT_DET,
|
||||
BD70528_INT_BATTSD_COLD_RES,
|
||||
BD70528_INT_BATTSD_COLD_DET,
|
||||
BD70528_INT_BATTSD_HOT_RES,
|
||||
BD70528_INT_BATTSD_HOT_DET,
|
||||
BD70528_INT_CHG_TSD,
|
||||
/* Charger 2 register IRQs */
|
||||
BD70528_INT_BAT_RMV,
|
||||
BD70528_INT_BAT_DET,
|
||||
BD70528_INT_DCIN2_OV_RES,
|
||||
BD70528_INT_DCIN2_OV_DET,
|
||||
BD70528_INT_DCIN2_RMV,
|
||||
BD70528_INT_DCIN2_DET,
|
||||
BD70528_INT_DCIN1_RMV,
|
||||
BD70528_INT_DCIN1_DET,
|
||||
/* RTC register IRQs */
|
||||
BD70528_INT_RTC_ALARM,
|
||||
BD70528_INT_ELPS_TIM,
|
||||
/* GPIO register IRQs */
|
||||
BD70528_INT_GPIO0,
|
||||
BD70528_INT_GPIO1,
|
||||
BD70528_INT_GPIO2,
|
||||
BD70528_INT_GPIO3,
|
||||
/* Invalid operation register IRQs */
|
||||
BD70528_INT_BUCK1_DVS_OPFAIL,
|
||||
BD70528_INT_BUCK2_DVS_OPFAIL,
|
||||
BD70528_INT_BUCK3_DVS_OPFAIL,
|
||||
BD70528_INT_LED1_VOLT_OPFAIL,
|
||||
BD70528_INT_LED2_VOLT_OPFAIL,
|
||||
};
|
||||
|
||||
/* Masks */
|
||||
#define BD70528_INT_LONGPUSH_MASK 0x1
|
||||
#define BD70528_INT_WDT_MASK 0x2
|
||||
#define BD70528_INT_HWRESET_MASK 0x4
|
||||
#define BD70528_INT_RSTB_FAULT_MASK 0x8
|
||||
#define BD70528_INT_VBAT_UVLO_MASK 0x10
|
||||
#define BD70528_INT_TSD_MASK 0x20
|
||||
#define BD70528_INT_RSTIN_MASK 0x40
|
||||
|
||||
#define BD70528_INT_BUCK1_FAULT_MASK 0x1
|
||||
#define BD70528_INT_BUCK2_FAULT_MASK 0x2
|
||||
#define BD70528_INT_BUCK3_FAULT_MASK 0x4
|
||||
#define BD70528_INT_LDO1_FAULT_MASK 0x8
|
||||
#define BD70528_INT_LDO2_FAULT_MASK 0x10
|
||||
#define BD70528_INT_LDO3_FAULT_MASK 0x20
|
||||
#define BD70528_INT_LED1_FAULT_MASK 0x40
|
||||
#define BD70528_INT_LED2_FAULT_MASK 0x80
|
||||
|
||||
#define BD70528_INT_BUCK1_OCP_MASK 0x1
|
||||
#define BD70528_INT_BUCK2_OCP_MASK 0x2
|
||||
#define BD70528_INT_BUCK3_OCP_MASK 0x4
|
||||
#define BD70528_INT_LED1_OCP_MASK 0x8
|
||||
#define BD70528_INT_LED2_OCP_MASK 0x10
|
||||
#define BD70528_INT_BUCK1_FULLON_MASK 0x20
|
||||
#define BD70528_INT_BUCK2_FULLON_MASK 0x40
|
||||
|
||||
#define BD70528_INT_SHORTPUSH_MASK 0x1
|
||||
#define BD70528_INT_AUTO_WAKEUP_MASK 0x2
|
||||
#define BD70528_INT_STATE_CHANGE_MASK 0x10
|
||||
|
||||
#define BD70528_INT_BAT_OV_RES_MASK 0x1
|
||||
#define BD70528_INT_BAT_OV_DET_MASK 0x2
|
||||
#define BD70528_INT_DBAT_DET_MASK 0x4
|
||||
#define BD70528_INT_BATTSD_COLD_RES_MASK 0x8
|
||||
#define BD70528_INT_BATTSD_COLD_DET_MASK 0x10
|
||||
#define BD70528_INT_BATTSD_HOT_RES_MASK 0x20
|
||||
#define BD70528_INT_BATTSD_HOT_DET_MASK 0x40
|
||||
#define BD70528_INT_CHG_TSD_MASK 0x80
|
||||
|
||||
#define BD70528_INT_BAT_RMV_MASK 0x1
|
||||
#define BD70528_INT_BAT_DET_MASK 0x2
|
||||
#define BD70528_INT_DCIN2_OV_RES_MASK 0x4
|
||||
#define BD70528_INT_DCIN2_OV_DET_MASK 0x8
|
||||
#define BD70528_INT_DCIN2_RMV_MASK 0x10
|
||||
#define BD70528_INT_DCIN2_DET_MASK 0x20
|
||||
#define BD70528_INT_DCIN1_RMV_MASK 0x40
|
||||
#define BD70528_INT_DCIN1_DET_MASK 0x80
|
||||
|
||||
#define BD70528_INT_RTC_ALARM_MASK 0x1
|
||||
#define BD70528_INT_ELPS_TIM_MASK 0x2
|
||||
|
||||
#define BD70528_INT_GPIO0_MASK 0x1
|
||||
#define BD70528_INT_GPIO1_MASK 0x2
|
||||
#define BD70528_INT_GPIO2_MASK 0x4
|
||||
#define BD70528_INT_GPIO3_MASK 0x8
|
||||
|
||||
#define BD70528_INT_BUCK1_DVS_OPFAIL_MASK 0x1
|
||||
#define BD70528_INT_BUCK2_DVS_OPFAIL_MASK 0x2
|
||||
#define BD70528_INT_BUCK3_DVS_OPFAIL_MASK 0x4
|
||||
#define BD70528_INT_LED1_VOLT_OPFAIL_MASK 0x10
|
||||
#define BD70528_INT_LED2_VOLT_OPFAIL_MASK 0x20
|
||||
|
||||
#define BD70528_DEBOUNCE_MASK 0x3
|
||||
|
||||
#define BD70528_DEBOUNCE_DISABLE 0
|
||||
#define BD70528_DEBOUNCE_15MS 1
|
||||
#define BD70528_DEBOUNCE_30MS 2
|
||||
#define BD70528_DEBOUNCE_50MS 3
|
||||
|
||||
#define BD70528_GPIO_DRIVE_MASK 0x2
|
||||
#define BD70528_GPIO_PUSH_PULL 0x0
|
||||
#define BD70528_GPIO_OPEN_DRAIN 0x2
|
||||
|
||||
#define BD70528_GPIO_OUT_EN_MASK 0x80
|
||||
#define BD70528_GPIO_OUT_ENABLE 0x80
|
||||
#define BD70528_GPIO_OUT_DISABLE 0x0
|
||||
|
||||
#define BD70528_GPIO_OUT_HI 0x1
|
||||
#define BD70528_GPIO_OUT_LO 0x0
|
||||
#define BD70528_GPIO_OUT_MASK 0x1
|
||||
|
||||
#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
|
||||
* (by setting day, month and year too)
|
||||
* but as we wish to keep this same as for
|
||||
* 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 */
|
||||
#define BD70528_MASK_WDT_EN 0x1
|
||||
#define BD70528_MASK_WDT_HOUR 0x1
|
||||
#define BD70528_MASK_WDT_MINUTE 0x7f
|
||||
#define BD70528_MASK_WDT_SEC 0x7f
|
||||
|
||||
#define BD70528_WDT_STATE_BIT 0x1
|
||||
#define BD70528_ELAPSED_STATE_BIT 0x2
|
||||
#define BD70528_WAKE_STATE_BIT 0x4
|
||||
|
||||
/* Charger masks */
|
||||
#define BD70528_MASK_CHG_STAT 0x7f
|
||||
#define BD70528_MASK_CHG_BAT_TIMER 0x20
|
||||
#define BD70528_MASK_CHG_BAT_OVERVOLT 0x10
|
||||
#define BD70528_MASK_CHG_BAT_DETECT 0x1
|
||||
#define BD70528_MASK_CHG_DCIN1_UVLO 0x1
|
||||
#define BD70528_MASK_CHG_DCIN_ILIM 0x3f
|
||||
#define BD70528_MASK_CHG_CHG_CURR 0x1f
|
||||
#define BD70528_MASK_CHG_TRICKLE_CURR 0x10
|
||||
|
||||
/*
|
||||
* Note, external battery register is the lonely rider at
|
||||
* address 0xc5. See how to stuff that in the regmap
|
||||
*/
|
||||
#define BD70528_MAX_REGISTER 0x94
|
||||
|
||||
/* Buck control masks */
|
||||
#define BD70528_MASK_RUN_EN 0x4
|
||||
#define BD70528_MASK_STBY_EN 0x2
|
||||
#define BD70528_MASK_IDLE_EN 0x1
|
||||
#define BD70528_MASK_LED1_EN 0x1
|
||||
#define BD70528_MASK_LED2_EN 0x10
|
||||
|
||||
#define BD70528_MASK_BUCK_VOLT 0xf
|
||||
#define BD70528_MASK_LDO_VOLT 0x1f
|
||||
#define BD70528_MASK_LED1_VOLT 0x1
|
||||
#define BD70528_MASK_LED2_VOLT 0x10
|
||||
|
||||
/* Misc irq masks */
|
||||
#define BD70528_INT_MASK_SHORT_PUSH 1
|
||||
#define BD70528_INT_MASK_AUTO_WAKE 2
|
||||
#define BD70528_INT_MASK_POWER_STATE 4
|
||||
|
||||
#define BD70528_MASK_BUCK_RAMP 0x10
|
||||
#define BD70528_SIFT_BUCK_RAMP 4
|
||||
|
||||
#if IS_ENABLED(CONFIG_BD70528_WATCHDOG)
|
||||
|
||||
int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, int *old_state);
|
||||
void bd70528_wdt_lock(struct rohm_regmap_dev *data);
|
||||
void bd70528_wdt_unlock(struct rohm_regmap_dev *data);
|
||||
|
||||
#else /* CONFIG_BD70528_WATCHDOG */
|
||||
|
||||
static inline int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable,
|
||||
int *old_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void bd70528_wdt_lock(struct rohm_regmap_dev *data)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void bd70528_wdt_unlock(struct rohm_regmap_dev *data)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BD70528_WATCHDOG */
|
||||
|
||||
#endif /* __LINUX_MFD_BD70528_H__ */
|
@ -4,14 +4,9 @@
|
||||
#ifndef __LINUX_MFD_BD718XX_H__
|
||||
#define __LINUX_MFD_BD718XX_H__
|
||||
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
BD718XX_TYPE_BD71837 = 0,
|
||||
BD718XX_TYPE_BD71847,
|
||||
BD718XX_TYPE_AMOUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
BD718XX_BUCK1 = 0,
|
||||
BD718XX_BUCK2,
|
||||
@ -321,18 +316,17 @@ enum {
|
||||
BD718XX_PWRBTN_LONG_PRESS_15S
|
||||
};
|
||||
|
||||
struct bd718xx_clk;
|
||||
|
||||
struct bd718xx {
|
||||
unsigned int chip_type;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
unsigned long int id;
|
||||
/*
|
||||
* Please keep this as the first member here as some
|
||||
* drivers (clk) supporting more than one chip may only know this
|
||||
* generic struct 'struct rohm_regmap_dev' and assume it is
|
||||
* the first chunk of parent device's private data.
|
||||
*/
|
||||
struct rohm_regmap_dev chip;
|
||||
|
||||
int chip_irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
|
||||
struct bd718xx_clk *clk;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_BD718XX_H__ */
|
||||
|
20
include/linux/mfd/rohm-generic.h
Normal file
20
include/linux/mfd/rohm-generic.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* Copyright (C) 2018 ROHM Semiconductors */
|
||||
|
||||
#ifndef __LINUX_MFD_ROHM_H__
|
||||
#define __LINUX_MFD_ROHM_H__
|
||||
|
||||
enum {
|
||||
ROHM_CHIP_TYPE_BD71837 = 0,
|
||||
ROHM_CHIP_TYPE_BD71847,
|
||||
ROHM_CHIP_TYPE_BD70528,
|
||||
ROHM_CHIP_TYPE_AMOUNT
|
||||
};
|
||||
|
||||
struct rohm_regmap_dev {
|
||||
unsigned int chip_type;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#ifndef MFD_STMFX_H
|
||||
#define MFX_STMFX_H
|
||||
#define MFD_STMFX_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user