mfd: rk806: Add RK806 support
The RK806 are a Power Management IC (PMIC) for multimedia and handheld devices. They contains the following components: - Regulators - Pinctrl - PowerKey Signed-off-by: shengfei Xu <xsf@rock-chips.com> Change-Id: Iee9c521d52c53752286238c93b39afb5eb32e9b2
This commit is contained in:
parent
52b779b7f4
commit
94a2726fb4
|
|
@ -1138,6 +1138,25 @@ config MFD_RK630_SPI
|
|||
if you say yes here you get support for the RK630 when controlled
|
||||
using SPI.
|
||||
|
||||
config MFD_RK806
|
||||
tristate "Rockchip RK806 Power Management Chip"
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
If you say yes here you get support for the RK806 Power Management chips.
|
||||
This driver provides common support for accessing the device
|
||||
through SPI interface. The device supports multiple sub-devices
|
||||
including interrupts, LDO & DCDC regulators, and onkey.
|
||||
|
||||
config MFD_RK806_SPI
|
||||
tristate "RK806 Power Management chip with SPI"
|
||||
select MFD_RK806
|
||||
select REGMAP_SPI
|
||||
depends on SPI_MASTER
|
||||
help
|
||||
If you say yes here you get support for the RK806 PM chips with SPI interface.
|
||||
|
||||
config MFD_RK808
|
||||
tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip"
|
||||
depends on I2C && OF
|
||||
|
|
|
|||
|
|
@ -222,6 +222,8 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
|
|||
obj-$(CONFIG_MFD_RK630) += rk630.o
|
||||
obj-$(CONFIG_MFD_RK630_I2C) += rk630-i2c.o
|
||||
obj-$(CONFIG_MFD_RK630_SPI) += rk630-spi.o
|
||||
obj-$(CONFIG_MFD_RK806) += rk806-core.o
|
||||
obj-$(CONFIG_MFD_RK806_SPI) += rk806-spi.o
|
||||
obj-$(CONFIG_MFD_RK808) += rk808.o
|
||||
obj-$(CONFIG_MFD_RK1000) += rk1000-core.o
|
||||
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,637 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MFD core driver for Rockchip RK806
|
||||
*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Xu Shengfei <xsf@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rk806.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define TSD_TEMP_140 0x00
|
||||
#define TSD_TEMP_160 0x01
|
||||
#define VB_LO_ACT_SD 0x00
|
||||
#define VB_LO_ACT_INT 0x01
|
||||
|
||||
static const struct reg_field rk806_reg_fields[] = {
|
||||
[POWER_EN0] = REG_FIELD(0x00, 0, 7),
|
||||
[POWER_EN1] = REG_FIELD(0x01, 0, 7),
|
||||
[POWER_EN2] = REG_FIELD(0x02, 0, 7),
|
||||
[POWER_EN3] = REG_FIELD(0x03, 0, 7),
|
||||
[POWER_EN4] = REG_FIELD(0x04, 0, 7),
|
||||
[POWER_EN5] = REG_FIELD(0x05, 0, 7),
|
||||
|
||||
[BUCK4_EN_MASK] = REG_FIELD(0x00, 7, 7),
|
||||
[BUCK3_EN_MASK] = REG_FIELD(0x00, 6, 6),
|
||||
[BUCK2_EN_MASK] = REG_FIELD(0x00, 5, 5),
|
||||
[BUCK1_EN_MASK] = REG_FIELD(0x00, 4, 4),
|
||||
[BUCK4_EN] = REG_FIELD(0X00, 3, 3),
|
||||
[BUCK3_EN] = REG_FIELD(0X00, 2, 2),
|
||||
[BUCK2_EN] = REG_FIELD(0X00, 1, 1),
|
||||
[BUCK1_EN] = REG_FIELD(0X00, 0, 0),
|
||||
[BUCK8_EN_MASK] = REG_FIELD(0x01, 7, 7),
|
||||
[BUCK7_EN_MASK] = REG_FIELD(0x01, 6, 6),
|
||||
[BUCK6_EN_MASK] = REG_FIELD(0x01, 5, 5),
|
||||
[BUCK5_EN_MASK] = REG_FIELD(0x01, 4, 4),
|
||||
[BUCK8_EN] = REG_FIELD(0x01, 3, 3),
|
||||
[BUCK7_EN] = REG_FIELD(0x01, 2, 2),
|
||||
[BUCK6_EN] = REG_FIELD(0x01, 1, 1),
|
||||
[BUCK5_EN] = REG_FIELD(0x01, 0, 0),
|
||||
[BUCK10_EN_MASK] = REG_FIELD(0x02, 5, 5),
|
||||
[BUCK9_EN_MASK] = REG_FIELD(0x02, 4, 4),
|
||||
[BUCK10_EN] = REG_FIELD(0x02, 1, 1),
|
||||
[BUCK9_EN] = REG_FIELD(0x02, 0, 0),
|
||||
[NLDO4_EN_MASK] = REG_FIELD(0x03, 7, 7),
|
||||
[NLDO3_EN_MASK] = REG_FIELD(0x03, 6, 6),
|
||||
[NLDO2_EN_MASK] = REG_FIELD(0x03, 5, 5),
|
||||
[NLDO1_EN_MASK] = REG_FIELD(0x03, 4, 4),
|
||||
[NLDO4_EN] = REG_FIELD(0x03, 3, 3),
|
||||
[NLDO3_EN] = REG_FIELD(0x03, 2, 2),
|
||||
[NLDO2_EN] = REG_FIELD(0x03, 1, 1),
|
||||
[NLDO1_EN] = REG_FIELD(0x03, 0, 0),
|
||||
[PLDO4_EN_MASK] = REG_FIELD(0x04, 7, 7),
|
||||
[PLDO3_EN_MASK] = REG_FIELD(0x04, 6, 6),
|
||||
[PLDO2_EN_MASK] = REG_FIELD(0x04, 5, 5),
|
||||
[PLDO1_EN_MASK] = REG_FIELD(0x04, 4, 4),
|
||||
[PLDO4_EN] = REG_FIELD(0x04, 3, 3),
|
||||
[PLDO3_EN] = REG_FIELD(0x04, 2, 2),
|
||||
[PLDO2_EN] = REG_FIELD(0x04, 1, 1),
|
||||
[PLDO1_EN] = REG_FIELD(0x04, 0, 0),
|
||||
[NLDO5_EN_MASK] = REG_FIELD(0x05, 6, 6),
|
||||
[PLDO6_EN_MASK] = REG_FIELD(0x05, 5, 5),
|
||||
[PLDO5_EN_MASK] = REG_FIELD(0x05, 4, 4),
|
||||
[NLDO5_EN] = REG_FIELD(0x05, 3, 3),
|
||||
[PLDO6_EN] = REG_FIELD(0x05, 2, 2),
|
||||
[PLDO5_EN] = REG_FIELD(0x05, 1, 1),
|
||||
|
||||
[BUCK8_SLP_EN] = REG_FIELD(0x06, 7, 7),
|
||||
[BUCK7_SLP_EN] = REG_FIELD(0x06, 6, 6),
|
||||
[BUCK6_SLP_EN] = REG_FIELD(0x06, 5, 5),
|
||||
[BUCK5_SLP_EN] = REG_FIELD(0x06, 4, 4),
|
||||
[BUCK4_SLP_EN] = REG_FIELD(0x06, 3, 3),
|
||||
[BUCK3_SLP_EN] = REG_FIELD(0x06, 2, 2),
|
||||
[BUCK2_SLP_EN] = REG_FIELD(0x06, 1, 1),
|
||||
[BUCK1_SLP_EN] = REG_FIELD(0x06, 0, 0),
|
||||
|
||||
[BUCK10_SLP_EN] = REG_FIELD(0x07, 7, 7),
|
||||
[BUCK9_SLP_EN] = REG_FIELD(0x07, 6, 6),
|
||||
[NLDO5_SLP_EN] = REG_FIELD(0x07, 4, 4),
|
||||
[NLDO4_SLP_EN] = REG_FIELD(0x07, 3, 3),
|
||||
[NLDO3_SLP_EN] = REG_FIELD(0x07, 2, 2),
|
||||
[NLDO2_SLP_EN] = REG_FIELD(0x07, 1, 1),
|
||||
[NLDO1_SLP_EN] = REG_FIELD(0x07, 0, 0),
|
||||
|
||||
[PLDO6_SLP_EN] = REG_FIELD(0x08, 5, 5),
|
||||
[PLDO5_SLP_EN] = REG_FIELD(0x08, 4, 4),
|
||||
[PLDO4_SLP_EN] = REG_FIELD(0x08, 3, 3),
|
||||
[PLDO3_SLP_EN] = REG_FIELD(0x08, 2, 2),
|
||||
[PLDO2_SLP_EN] = REG_FIELD(0x08, 1, 1),
|
||||
[PLDO1_SLP_EN] = REG_FIELD(0x08, 0, 0),
|
||||
|
||||
[BUCK1_RATE] = REG_FIELD(0x10, 6, 7),
|
||||
[BUCK2_RATE] = REG_FIELD(0x11, 6, 7),
|
||||
[BUCK3_RATE] = REG_FIELD(0x12, 6, 7),
|
||||
[BUCK4_RATE] = REG_FIELD(0x13, 6, 7),
|
||||
[BUCK5_RATE] = REG_FIELD(0x14, 6, 7),
|
||||
[BUCK6_RATE] = REG_FIELD(0x15, 6, 7),
|
||||
[BUCK7_RATE] = REG_FIELD(0x16, 6, 7),
|
||||
[BUCK8_RATE] = REG_FIELD(0x17, 6, 7),
|
||||
[BUCK9_RATE] = REG_FIELD(0x18, 6, 7),
|
||||
[BUCK10_RATE] = REG_FIELD(0x19, 6, 7),
|
||||
|
||||
[BUCK1_ON_VSEL] = REG_FIELD(0x1A, 0, 7),
|
||||
[BUCK2_ON_VSEL] = REG_FIELD(0x1B, 0, 7),
|
||||
[BUCK3_ON_VSEL] = REG_FIELD(0x1C, 0, 7),
|
||||
[BUCK4_ON_VSEL] = REG_FIELD(0x1D, 0, 7),
|
||||
[BUCK5_ON_VSEL] = REG_FIELD(0x1E, 0, 7),
|
||||
[BUCK6_ON_VSEL] = REG_FIELD(0x1F, 0, 7),
|
||||
[BUCK7_ON_VSEL] = REG_FIELD(0x20, 0, 7),
|
||||
[BUCK8_ON_VSEL] = REG_FIELD(0x21, 0, 7),
|
||||
[BUCK9_ON_VSEL] = REG_FIELD(0x22, 0, 7),
|
||||
[BUCK10_ON_VSEL] = REG_FIELD(0x23, 0, 7),
|
||||
|
||||
[BUCK1_SLP_VSEL] = REG_FIELD(0x24, 0, 7),
|
||||
[BUCK2_SLP_VSEL] = REG_FIELD(0x25, 0, 7),
|
||||
[BUCK3_SLP_VSEL] = REG_FIELD(0x26, 0, 7),
|
||||
[BUCK4_SLP_VSEL] = REG_FIELD(0x27, 0, 7),
|
||||
[BUCK5_SLP_VSEL] = REG_FIELD(0x28, 0, 7),
|
||||
[BUCK6_SLP_VSEL] = REG_FIELD(0x29, 0, 7),
|
||||
[BUCK7_SLP_VSEL] = REG_FIELD(0x2A, 0, 7),
|
||||
[BUCK8_SLP_VSEL] = REG_FIELD(0x2B, 0, 7),
|
||||
[BUCK9_SLP_VSEL] = REG_FIELD(0x2C, 0, 7),
|
||||
[BUCK10_SLP_VSEL] = REG_FIELD(0x2D, 0, 7),
|
||||
|
||||
[NLDO1_ON_VSEL] = REG_FIELD(0x43, 0, 7),
|
||||
[NLDO2_ON_VSEL] = REG_FIELD(0x44, 0, 7),
|
||||
[NLDO3_ON_VSEL] = REG_FIELD(0x45, 0, 7),
|
||||
[NLDO4_ON_VSEL] = REG_FIELD(0x46, 0, 7),
|
||||
[NLDO5_ON_VSEL] = REG_FIELD(0x47, 0, 7),
|
||||
[NLDO1_SLP_VSEL] = REG_FIELD(0x48, 0, 7),
|
||||
[NLDO2_SLP_VSEL] = REG_FIELD(0x49, 0, 7),
|
||||
[NLDO3_SLP_VSEL] = REG_FIELD(0x4A, 0, 7),
|
||||
[NLDO4_SLP_VSEL] = REG_FIELD(0x4B, 0, 7),
|
||||
[NLDO5_SLP_VSEL] = REG_FIELD(0x4C, 0, 7),
|
||||
|
||||
[PLDO1_ON_VSEL] = REG_FIELD(0x4E, 0, 7),
|
||||
[PLDO2_ON_VSEL] = REG_FIELD(0x4F, 0, 7),
|
||||
[PLDO3_ON_VSEL] = REG_FIELD(0x50, 0, 7),
|
||||
[PLDO4_ON_VSEL] = REG_FIELD(0x51, 0, 7),
|
||||
[PLDO5_ON_VSEL] = REG_FIELD(0x52, 0, 7),
|
||||
[PLDO6_ON_VSEL] = REG_FIELD(0x53, 0, 7),
|
||||
|
||||
[PLDO1_SLP_VSEL] = REG_FIELD(0x54, 0, 7),
|
||||
[PLDO2_SLP_VSEL] = REG_FIELD(0x55, 0, 7),
|
||||
[PLDO3_SLP_VSEL] = REG_FIELD(0x56, 0, 7),
|
||||
[PLDO4_SLP_VSEL] = REG_FIELD(0x57, 0, 7),
|
||||
[PLDO5_SLP_VSEL] = REG_FIELD(0x58, 0, 7),
|
||||
[PLDO6_SLP_VSEL] = REG_FIELD(0x59, 0, 7),
|
||||
|
||||
[CHIP_NAME_H] = REG_FIELD(0x5A, 0, 7),
|
||||
[CHIP_NAME_L] = REG_FIELD(0x5B, 4, 7),
|
||||
[CHIP_VER] = REG_FIELD(0x5B, 0, 3),
|
||||
[OTP_VER] = REG_FIELD(0x5C, 0, 3),
|
||||
/* SYS_STS */
|
||||
[PWRON_STS] = REG_FIELD(0x5D, 7, 7),
|
||||
[VDC_STS] = REG_FIELD(0x5D, 6, 6),
|
||||
[VB_UV_STSS] = REG_FIELD(0x5D, 5, 5),
|
||||
[VB_LO_STS] = REG_FIELD(0x5D, 4, 4),
|
||||
[HOTDIE_STS] = REG_FIELD(0x5D, 3, 3),
|
||||
[TSD_STS] = REG_FIELD(0x5D, 2, 2),
|
||||
[VB_OV_STS] = REG_FIELD(0x5D, 0, 0),
|
||||
/* SYS_CFG0 */
|
||||
[VB_UV_DLY] = REG_FIELD(0x5E, 7, 7),
|
||||
[VB_UV_SEL] = REG_FIELD(0x5E, 4, 6),
|
||||
[VB_LO_ACT] = REG_FIELD(0x5E, 3, 3),
|
||||
[VB_LO_SEL] = REG_FIELD(0x5E, 0, 2),
|
||||
/* SYS_CFG1 */
|
||||
[TSD_TEMP] = REG_FIELD(0x5F, 6, 6),
|
||||
[HOTDIE_TMP] = REG_FIELD(0x5F, 4, 5),
|
||||
[VPREREG_SEL] = REG_FIELD(0x5F, 0, 1),
|
||||
/* SYS_OPTION */
|
||||
[VCCXDET_DIS] = REG_FIELD(0x61, 4, 5),
|
||||
[OSC_TC] = REG_FIELD(0x61, 2, 3),
|
||||
[ENB2_2M] = REG_FIELD(0x61, 1, 1),
|
||||
[ENB_32K] = REG_FIELD(0x61, 0, 0),
|
||||
/* SLEEP_CONFIG0 */
|
||||
[SLP2_POL] = REG_FIELD(0x62, 7, 7),
|
||||
[SLP2_FUN] = REG_FIELD(0x62, 4, 6),
|
||||
[SLP1_POL] = REG_FIELD(0x62, 3, 3),
|
||||
[SLP1_FUN] = REG_FIELD(0x62, 0, 2),
|
||||
/* SLEEP_CONFIG1 */
|
||||
[SLP3_POL] = REG_FIELD(0x63, 3, 3),
|
||||
[SLP3_FUN] = REG_FIELD(0x63, 0, 2),
|
||||
/* SLEEP_SLP_CTR_SEL0 */
|
||||
[BUCK4_SLP_CTR_SEL] = REG_FIELD(0x65, 4, 5),
|
||||
[BUCK3_SLP_CTR_SEL] = REG_FIELD(0x65, 0, 1),
|
||||
[BUCK2_SLP_CTR_SEL] = REG_FIELD(0x64, 4, 5),
|
||||
[BUCK1_SLP_CTR_SEL] = REG_FIELD(0x64, 0, 1),
|
||||
/* SLEEP_SLP_CTR_SEL1 */
|
||||
[BUCK8_SLP_CTR_SEL] = REG_FIELD(0x67, 4, 5),
|
||||
[BUCK7_SLP_CTR_SEL] = REG_FIELD(0x67, 0, 1),
|
||||
[BUCK6_SLP_CTR_SEL] = REG_FIELD(0x66, 4, 5),
|
||||
[BUCK5_SLP_CTR_SEL] = REG_FIELD(0x66, 0, 1),
|
||||
/* SLEEP_SLP_CTR_SEL2 */
|
||||
[NLDO2_SLP_CTR_SEL] = REG_FIELD(0x69, 4, 5),
|
||||
[NLDO1_SLP_CTR_SEL] = REG_FIELD(0x69, 0, 1),
|
||||
[BUCK10_SLP_CTR_SEL] = REG_FIELD(0x68, 4, 5),
|
||||
[BUCK9_SLP_CTR_SEL] = REG_FIELD(0x68, 0, 1),
|
||||
/* SLEEP_SLP_CTR_SEL3 */
|
||||
[NLDO5_SLP_CTR_SEL] = REG_FIELD(0x6b, 0, 1),
|
||||
[NLDO4_SLP_CTR_SEL] = REG_FIELD(0x6a, 4, 5),
|
||||
[NLDO3_SLP_CTR_SEL] = REG_FIELD(0x6a, 0, 1),
|
||||
/* SLEEP_SLP_CTR_SEL4 */
|
||||
[PLDO4_SLP_CTR_SEL] = REG_FIELD(0x6d, 4, 5),
|
||||
[PLDO3_SLP_CTR_SEL] = REG_FIELD(0x6d, 0, 0),
|
||||
[PLDO2_SLP_CTR_SEL] = REG_FIELD(0x6c, 4, 5),
|
||||
[PLDO1_SLP_CTR_SEL] = REG_FIELD(0x6c, 0, 1),
|
||||
/* SLEEP_SLP_CTR_SEL5 */
|
||||
[PLDO6_SLP_CTR_SEL] = REG_FIELD(0x6e, 4, 5),
|
||||
[PLDO5_SLP_CTR_SEL] = REG_FIELD(0x6e, 0, 1),
|
||||
/* DVS_CTRL_SEL0 */
|
||||
[BUCK4_DVS_CTR_SEL] = REG_FIELD(0x65, 6, 7),
|
||||
[BUCK3_DVS_CTR_SEL] = REG_FIELD(0x65, 2, 3),
|
||||
[BUCK2_DVS_CTR_SEL] = REG_FIELD(0x64, 6, 7),
|
||||
[BUCK1_DVS_CTR_SEL] = REG_FIELD(0x64, 2, 3),
|
||||
/* DVS_CTRL_SEL1*/
|
||||
[BUCK8_DVS_CTR_SEL] = REG_FIELD(0x67, 6, 7),
|
||||
[BUCK7_DVS_CTR_SEL] = REG_FIELD(0x67, 2, 3),
|
||||
[BUCK6_DVS_CTR_SEL] = REG_FIELD(0x66, 6, 7),
|
||||
[BUCK5_DVS_CTR_SEL] = REG_FIELD(0x66, 2, 3),
|
||||
/* DVS_CTRL_SEL2 */
|
||||
[NLDO2_DVS_CTR_SEL] = REG_FIELD(0x69, 6, 7),
|
||||
[NLDO1_DVS_CTR_SEL] = REG_FIELD(0x69, 2, 3),
|
||||
[BUCK10_DVS_CTR_SEL] = REG_FIELD(0x68, 6, 7),
|
||||
[BUCK9_DVS_CTR_SEL] = REG_FIELD(0x68, 2, 3),
|
||||
/* DVS_CTRL_SEL3 */
|
||||
[NLDO5_DVS_CTR_SEL] = REG_FIELD(0x6b, 2, 3),
|
||||
[NLDO4_DVS_CTR_SEL] = REG_FIELD(0x6a, 6, 7),
|
||||
[NLDO3_DVS_CTR_SEL] = REG_FIELD(0x6a, 2, 3),
|
||||
/* DVS_CTRL_SEL4 */
|
||||
[PLDO4_DVS_CTR_SEL] = REG_FIELD(0x6d, 6, 7),
|
||||
[PLDO3_DVS_CTR_SEL] = REG_FIELD(0x6d, 2, 3),
|
||||
[PLDO2_DVS_CTR_SEL] = REG_FIELD(0x6c, 6, 7),
|
||||
[PLDO1_DVS_CTR_SEL] = REG_FIELD(0x6c, 2, 3),
|
||||
/* DVS_CTRL_SEL5 */
|
||||
[PLDO6_DVS_CTR_SEL] = REG_FIELD(0x6e, 6, 7),
|
||||
[PLDO5_DVS_CTR_SEL] = REG_FIELD(0x6e, 2, 3),
|
||||
/* DVS_START_CTRL */
|
||||
[DVS_START3] = REG_FIELD(0x70, 2, 2),
|
||||
[DVS_START2] = REG_FIELD(0x70, 1, 1),
|
||||
[DVS_START1] = REG_FIELD(0x70, 0, 0),
|
||||
/* SLEEP_GPIO */
|
||||
[SLP3_DATA] = REG_FIELD(0x71, 6, 6),
|
||||
[SLP2_DATA] = REG_FIELD(0x71, 5, 5),
|
||||
[SLP1_DATA] = REG_FIELD(0x71, 4, 4),
|
||||
[SLP3_DR] = REG_FIELD(0x71, 2, 2),
|
||||
[SLP2_DR] = REG_FIELD(0x71, 1, 1),
|
||||
[SLP1_DR] = REG_FIELD(0x71, 0, 0),
|
||||
/* SYS_CFG3 */
|
||||
[RST_FUN] = REG_FIELD(0x72, 6, 7),
|
||||
[DEV_RST] = REG_FIELD(0x72, 5, 5),
|
||||
[DEV_SLP] = REG_FIELD(0x72, 4, 4),
|
||||
[SLAVE_RESTART_FUN] = REG_FIELD(0x72, 1, 1),
|
||||
[DEV_OFF] = REG_FIELD(0x72, 0, 0),
|
||||
[WDT_CLR] = REG_FIELD(0x73, 4, 4),
|
||||
[WDT_EN] = REG_FIELD(0x73, 3, 3),
|
||||
[WDT_SET] = REG_FIELD(0x73, 0, 3),
|
||||
/* PWRON_KEY */
|
||||
[PWRON_ON_TIME] = REG_FIELD(0x76, 7, 7),
|
||||
[PWRON_LP_ACT] = REG_FIELD(0x76, 6, 6),
|
||||
[PWRON_LP_OFF_TIME] = REG_FIELD(0x76, 4, 5),
|
||||
[PWRON_LP_TM_SEL] = REG_FIELD(0x76, 2, 3),
|
||||
[PWRON_DB_SEL] = REG_FIELD(0x76, 0, 1),
|
||||
|
||||
/* GPIO_INT_CONFIG */
|
||||
[INT_FUNCTION] = REG_FIELD(0x7b, 2, 2),
|
||||
[INT_POL] = REG_FIELD(0x7b, 1, 1),
|
||||
[INT_FC_EN] = REG_FIELD(0x7b, 0, 0),
|
||||
[BUCK9_RATE2] = REG_FIELD(0xEA, 0, 0),
|
||||
[BUCK10_RATE2] = REG_FIELD(0xEA, 1, 1),
|
||||
[LDO_RATE] = REG_FIELD(0xEA, 3, 5),
|
||||
[BUCK1_RATE2] = REG_FIELD(0xEB, 0, 0),
|
||||
[BUCK2_RATE2] = REG_FIELD(0xEB, 1, 1),
|
||||
[BUCK3_RATE2] = REG_FIELD(0xEB, 2, 2),
|
||||
[BUCK4_RATE2] = REG_FIELD(0xEB, 3, 3),
|
||||
[BUCK5_RATE2] = REG_FIELD(0xEB, 4, 4),
|
||||
[BUCK6_RATE2] = REG_FIELD(0xEB, 5, 5),
|
||||
[BUCK7_RATE2] = REG_FIELD(0xEB, 6, 6),
|
||||
[BUCK8_RATE2] = REG_FIELD(0xEB, 7, 7),
|
||||
};
|
||||
|
||||
static struct resource rk806_pwrkey_resources[] = {
|
||||
DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL),
|
||||
DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE),
|
||||
};
|
||||
|
||||
static const struct mfd_cell rk806_cells[] = {
|
||||
{ .name = "rk806-regulator", },
|
||||
{
|
||||
.name = "rk805-pwrkey",
|
||||
.num_resources = ARRAY_SIZE(rk806_pwrkey_resources),
|
||||
.resources = &rk806_pwrkey_resources[0],
|
||||
},
|
||||
{ .name = "rk806-pinctrl", },
|
||||
};
|
||||
|
||||
static const struct regmap_irq rk806_irqs[] = {
|
||||
/* INT_STS0 IRQs */
|
||||
REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO),
|
||||
/* INT_STS1 IRQs */
|
||||
REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO),
|
||||
REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip rk806_irq_chip = {
|
||||
.name = "rk806",
|
||||
.irqs = rk806_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rk806_irqs),
|
||||
.num_regs = 2,
|
||||
.irq_reg_stride = 2,
|
||||
.mask_base = RK806_INT_MSK0,
|
||||
.status_base = RK806_INT_STS0,
|
||||
.ack_base = RK806_INT_STS0,
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
static const struct regmap_range rk806_yes_ranges[] = {
|
||||
/* regmap_reg_range(RK806_INT_STS0, RK806_GPIO_INT_CONFIG), */
|
||||
regmap_reg_range(0x00, 0xff),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table rk806_volatile_table = {
|
||||
.yes_ranges = rk806_yes_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(rk806_yes_ranges),
|
||||
};
|
||||
|
||||
const struct regmap_config rk806_regmap_config_spi = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.volatile_table = &rk806_volatile_table,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(rk806_regmap_config_spi);
|
||||
|
||||
int rk806_field_read(struct rk806 *rk806,
|
||||
enum rk806_fields field_id)
|
||||
{
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
ret = regmap_field_read(rk806->rmap_fields[field_id], &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_field_read);
|
||||
|
||||
int rk806_field_write(struct rk806 *rk806,
|
||||
enum rk806_fields field_id,
|
||||
unsigned int val)
|
||||
{
|
||||
return regmap_field_write(rk806->rmap_fields[field_id], val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_field_write);
|
||||
|
||||
static void rk806_irq_init(struct rk806 *rk806)
|
||||
{
|
||||
/* INT pin polarity active low */
|
||||
rk806_field_write(rk806, INT_POL, RK806_INT_POL_LOW);
|
||||
}
|
||||
|
||||
static int rk806_pinctrl_init(struct rk806 *rk806)
|
||||
{
|
||||
struct device *dev = rk806->dev;
|
||||
|
||||
rk806->pins = devm_kzalloc(dev,
|
||||
sizeof(struct rk806_pin_info),
|
||||
GFP_KERNEL);
|
||||
if (!rk806->pins)
|
||||
return -ENOMEM;
|
||||
|
||||
rk806->pins->p = devm_pinctrl_get(dev);
|
||||
if (IS_ERR(rk806->pins->p)) {
|
||||
rk806->pins->p = NULL;
|
||||
dev_err(dev, "no pinctrl handle\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rk806->pins->default_st = pinctrl_lookup_state(rk806->pins->p,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
|
||||
if (IS_ERR(rk806->pins->default_st))
|
||||
dev_err(dev, "no default pinctrl state\n");
|
||||
|
||||
rk806->pins->power_off = pinctrl_lookup_state(rk806->pins->p,
|
||||
"pmic-power-off");
|
||||
if (IS_ERR(rk806->pins->power_off)) {
|
||||
rk806->pins->power_off = NULL;
|
||||
dev_err(dev, "no power-off pinctrl state\n");
|
||||
}
|
||||
|
||||
rk806->pins->sleep = pinctrl_lookup_state(rk806->pins->p,
|
||||
"pmic-sleep");
|
||||
if (IS_ERR(rk806->pins->sleep)) {
|
||||
rk806->pins->sleep = NULL;
|
||||
dev_err(dev, "no sleep-setting state\n");
|
||||
}
|
||||
|
||||
rk806->pins->reset = pinctrl_lookup_state(rk806->pins->p,
|
||||
"pmic-reset");
|
||||
if (IS_ERR(rk806->pins->reset)) {
|
||||
rk806->pins->reset = NULL;
|
||||
dev_err(dev, "no reset-setting pinctrl state\n");
|
||||
}
|
||||
|
||||
rk806->pins->dvs = pinctrl_lookup_state(rk806->pins->p,
|
||||
"pmic-dvs");
|
||||
if (IS_ERR(rk806->pins->dvs)) {
|
||||
rk806->pins->dvs = NULL;
|
||||
dev_err(dev, "no dvs-setting pinctrl state\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rk806_vb_low_irq(int irq, void *rk806)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rk806_low_power_irqs(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata;
|
||||
int ret, vb_lo_irq;
|
||||
|
||||
pdata = rk806->pdata;
|
||||
|
||||
if (!pdata->low_voltage_threshold)
|
||||
return 0;
|
||||
|
||||
rk806_field_write(rk806, VB_LO_ACT, VB_LO_ACT_INT);
|
||||
|
||||
rk806_field_write(rk806, VB_LO_SEL,
|
||||
(pdata->low_voltage_threshold - 2800) / 100);
|
||||
|
||||
vb_lo_irq = regmap_irq_get_virq(rk806->irq_data, RK806_IRQ_VB_LO);
|
||||
if (vb_lo_irq < 0) {
|
||||
dev_err(rk806->dev, "vb_lo_irq request failed!\n");
|
||||
return vb_lo_irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rk806->dev, vb_lo_irq,
|
||||
NULL,
|
||||
rk806_vb_low_irq,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
"rk806_vb_low", rk806);
|
||||
if (ret) {
|
||||
dev_err(rk806->dev, "vb_lo_irq request failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rk806->vb_lo_irq = vb_lo_irq;
|
||||
disable_irq(rk806->vb_lo_irq);
|
||||
enable_irq_wake(vb_lo_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk806_parse_dt(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata;
|
||||
struct device *dev = rk806->dev;
|
||||
int ret;
|
||||
|
||||
pdata = rk806->pdata;
|
||||
|
||||
pdata->shutdown_voltage_threshold = 2700;
|
||||
pdata->shutdown_temperture_threshold = 160;
|
||||
pdata->hotdie_temperture_threshold = 115;
|
||||
pdata->force_shutdown_enable = 1;
|
||||
|
||||
ret = device_property_read_u32(dev,
|
||||
"low_voltage_threshold",
|
||||
&pdata->low_voltage_threshold);
|
||||
if (ret < 0) {
|
||||
pdata->low_voltage_threshold = 0;
|
||||
dev_info(dev, "low_voltage_threshold missing!\n");
|
||||
} else {
|
||||
if ((pdata->low_voltage_threshold > 3500) ||
|
||||
(pdata->low_voltage_threshold < 2800)) {
|
||||
dev_err(dev, "low_voltage_threshold out [2800 3500]!\n");
|
||||
pdata->low_voltage_threshold = 2800;
|
||||
}
|
||||
}
|
||||
ret = device_property_read_u32(dev,
|
||||
"shutdown_voltage_threshold",
|
||||
&pdata->shutdown_voltage_threshold);
|
||||
if (ret < 0) {
|
||||
pdata->force_shutdown_enable = 0;
|
||||
dev_info(dev, "shutdown_voltage_threshold missing!\n");
|
||||
}
|
||||
|
||||
if ((pdata->shutdown_voltage_threshold > 3400) ||
|
||||
(pdata->shutdown_voltage_threshold < 2700)) {
|
||||
dev_err(dev, "shutdown_voltage_threshold out [2700 3400]!\n");
|
||||
pdata->shutdown_voltage_threshold = 2700;
|
||||
}
|
||||
|
||||
ret = device_property_read_u32(dev,
|
||||
"shutdown_temperture_threshold",
|
||||
&pdata->shutdown_temperture_threshold);
|
||||
if (ret < 0)
|
||||
dev_info(dev, "shutdown_temperture_threshold missing!\n");
|
||||
|
||||
ret = device_property_read_u32(dev,
|
||||
"hotdie_temperture_threshold",
|
||||
&pdata->hotdie_temperture_threshold);
|
||||
if (ret < 0)
|
||||
dev_info(dev, "hotdie_temperture_threshold missing!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk806_init(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata;
|
||||
int vb_uv_sel;
|
||||
|
||||
pdata = rk806->pdata;
|
||||
|
||||
if (pdata->force_shutdown_enable) {
|
||||
if (pdata->shutdown_voltage_threshold <= 2700)
|
||||
vb_uv_sel = VB_UV_SEL_2700;
|
||||
else
|
||||
vb_uv_sel = (pdata->shutdown_voltage_threshold - 2700) / 100;
|
||||
|
||||
rk806_field_write(rk806, VB_UV_SEL, vb_uv_sel);
|
||||
}
|
||||
|
||||
if (pdata->hotdie_temperture_threshold >= 160)
|
||||
rk806_field_write(rk806, TSD_TEMP, TSD_TEMP_160);
|
||||
|
||||
rk806_low_power_irqs(rk806);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rk806_device_init(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata;
|
||||
int name_h, name_l, chip_ver, otp_ver;
|
||||
int on_source, off_source;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
pdata = devm_kzalloc(rk806->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
rk806->pdata = pdata;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk806_reg_fields); i++) {
|
||||
const struct reg_field *reg_fields = rk806_reg_fields;
|
||||
|
||||
rk806->rmap_fields[i] =
|
||||
devm_regmap_field_alloc(rk806->dev,
|
||||
rk806->regmap,
|
||||
reg_fields[i]);
|
||||
if (IS_ERR(rk806->rmap_fields[i])) {
|
||||
dev_err(rk806->dev, "cannot allocate regmap field\n");
|
||||
return PTR_ERR(rk806->rmap_fields[i]);
|
||||
}
|
||||
}
|
||||
|
||||
name_h = rk806_field_read(rk806, CHIP_NAME_H);
|
||||
name_l = rk806_field_read(rk806, CHIP_NAME_L);
|
||||
chip_ver = rk806_field_read(rk806, CHIP_VER);
|
||||
otp_ver = rk806_field_read(rk806, OTP_VER);
|
||||
dev_info(rk806->dev, "chip id: RK%x%x,ver:0x%x, 0x%x\n",
|
||||
name_h, name_l, chip_ver, otp_ver);
|
||||
|
||||
on_source = regmap_read(rk806->regmap, RK806_ON_SOURCE, &on_source);
|
||||
off_source = regmap_read(rk806->regmap, RK806_OFF_SOURCE, &off_source);
|
||||
dev_info(rk806->dev, "ON: 0x%x OFF:0x%x\n", on_source, off_source);
|
||||
|
||||
rk806_parse_dt(rk806);
|
||||
|
||||
rk806_irq_init(rk806);
|
||||
ret = devm_regmap_add_irq_chip(rk806->dev,
|
||||
rk806->regmap,
|
||||
rk806->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED,
|
||||
0,
|
||||
&rk806_irq_chip,
|
||||
&rk806->irq_data);
|
||||
if (ret) {
|
||||
dev_err(rk806->dev, "Failed to add IRQ chip: err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(rk806->dev,
|
||||
PLATFORM_DEVID_AUTO,
|
||||
rk806_cells,
|
||||
ARRAY_SIZE(rk806_cells),
|
||||
NULL,
|
||||
0,
|
||||
regmap_irq_get_domain(rk806->irq_data));
|
||||
if (ret < 0) {
|
||||
dev_err(rk806->dev, "mfd_add_devices failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rk806_pinctrl_init(rk806);
|
||||
rk806_init(rk806);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_device_init);
|
||||
|
||||
int rk806_device_exit(struct rk806 *rk806)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_device_exit);
|
||||
|
||||
MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("rk806 MFD Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* SPI access driver for rockchip rk806
|
||||
*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Xu Shengfei <xsf@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/mfd/rk806.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
static const struct of_device_id rk806_spi_of_match_table[] = {
|
||||
{ .compatible = "rockchip,rk806", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rk806_spi_of_match_table);
|
||||
|
||||
static int rk806_spi_write(struct spi_device *spi,
|
||||
char addr,
|
||||
const char *data,
|
||||
size_t data_len)
|
||||
{
|
||||
char write_cmd = RK806_CMD_WRITE | (data_len - 1);
|
||||
char addrh = RK806_REG_H;
|
||||
struct spi_message m;
|
||||
char addrl = addr;
|
||||
int ret = 0;
|
||||
|
||||
struct spi_transfer write_cmd_packet = {
|
||||
.tx_buf = &write_cmd,
|
||||
.len = sizeof(write_cmd),
|
||||
};
|
||||
struct spi_transfer addrl_packet = {
|
||||
.tx_buf = &addrl,
|
||||
.len = sizeof(addrl),
|
||||
};
|
||||
struct spi_transfer addrh_packet = {
|
||||
.tx_buf = &addrh,
|
||||
.len = sizeof(addrh),
|
||||
};
|
||||
|
||||
struct spi_transfer data_packet = {
|
||||
.tx_buf = data,
|
||||
.len = data_len,
|
||||
};
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&write_cmd_packet, &m);
|
||||
spi_message_add_tail(&addrl_packet, &m);
|
||||
spi_message_add_tail(&addrh_packet, &m);
|
||||
spi_message_add_tail(&data_packet, &m);
|
||||
ret = spi_sync(spi, &m);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk806_spi_bus_write(void *context, const void *data, size_t count)
|
||||
{
|
||||
struct device *dev = context;
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
char buf[2];
|
||||
|
||||
if (count < 2) {
|
||||
dev_err(&spi->dev, "regmap write err!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(buf, data, 2);
|
||||
|
||||
return rk806_spi_write(spi, buf[0], &buf[1], (count - 1));
|
||||
}
|
||||
|
||||
static int rk806_spi_bus_read(void *context,
|
||||
const void *reg,
|
||||
size_t reg_size,
|
||||
void *val,
|
||||
size_t val_size)
|
||||
{
|
||||
struct device *dev = context;
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
char addr;
|
||||
char txbuf[3] = { 0 };
|
||||
|
||||
if (reg_size != sizeof(char) || val_size < 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy address to read from into first element of SPI buffer. */
|
||||
memcpy(&addr, reg, sizeof(char));
|
||||
|
||||
txbuf[0] = RK806_CMD_READ | (val_size - 1);
|
||||
txbuf[1] = addr;
|
||||
txbuf[2] = RK806_REG_H;
|
||||
|
||||
return spi_write_then_read(spi, txbuf, 3, val, val_size);
|
||||
}
|
||||
|
||||
static const struct regmap_bus rk806_regmap_bus_spi = {
|
||||
.write = rk806_spi_bus_write,
|
||||
.read = rk806_spi_bus_read,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
};
|
||||
|
||||
static int rk806_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct rk806 *rk806;
|
||||
|
||||
rk806 = devm_kzalloc(&spi->dev, sizeof(*rk806), GFP_KERNEL);
|
||||
if (!rk806)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, rk806);
|
||||
rk806->dev = &spi->dev;
|
||||
rk806->irq = spi->irq;
|
||||
|
||||
rk806->regmap = devm_regmap_init(&spi->dev,
|
||||
&rk806_regmap_bus_spi,
|
||||
&spi->dev,
|
||||
&rk806_regmap_config_spi);
|
||||
if (IS_ERR(rk806->regmap)) {
|
||||
dev_err(rk806->dev, "Failed to initialize register map\n");
|
||||
return PTR_ERR(rk806->regmap);
|
||||
}
|
||||
|
||||
return rk806_device_init(rk806);
|
||||
}
|
||||
|
||||
static int rk806_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct rk806 *rk806 = spi_get_drvdata(spi);
|
||||
|
||||
return rk806_device_exit(rk806);
|
||||
}
|
||||
|
||||
static const struct spi_device_id rk806_spi_id_table[] = {
|
||||
{ "rk806", 0 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, rk806_spi_id_table);
|
||||
|
||||
static struct spi_driver rk806_spi_driver = {
|
||||
.driver = {
|
||||
.name = "rk806",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rk806_spi_of_match_table,
|
||||
},
|
||||
.probe = rk806_spi_probe,
|
||||
.remove = rk806_spi_remove,
|
||||
.id_table = rk806_spi_id_table,
|
||||
};
|
||||
module_spi_driver(rk806_spi_driver);
|
||||
|
||||
MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("RK806 SPI Interface Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -367,6 +367,15 @@ config PINCTRL_RK805
|
|||
help
|
||||
This selects the pinctrl driver for RK805.
|
||||
|
||||
config PINCTRL_RK806
|
||||
tristate "Pinctrl and GPIO driver for RK806 PMIC"
|
||||
depends on MFD_RK806
|
||||
select GPIOLIB
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
This selects the pinctrl driver for RK806
|
||||
|
||||
config PINCTRL_OCELOT
|
||||
bool "Pinctrl driver for the Microsemi Ocelot and Jaguar2 SoCs"
|
||||
depends on OF
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
|
|||
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
|
||||
obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
|
||||
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
|
||||
obj-$(CONFIG_PINCTRL_RK806) += pinctrl-rk806.o
|
||||
obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
|
||||
obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += pinctrl-equilibrium.o
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,577 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl driver for Rockchip RK806 PMIC
|
||||
*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Xu Shengfei <xsf@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/rk806.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include "pinctrl-utils.h"
|
||||
|
||||
struct rk806_pin_function {
|
||||
const char *name;
|
||||
const char *const *groups;
|
||||
unsigned int ngroups;
|
||||
int mux_option;
|
||||
};
|
||||
|
||||
struct rk806_pin_group {
|
||||
const char *name;
|
||||
const unsigned int pins[1];
|
||||
unsigned int npins;
|
||||
};
|
||||
|
||||
/*
|
||||
* @reg: gpio setting register;
|
||||
* @fun_mask: functions select mask value, when set is gpio;
|
||||
* @dir_mask: input or output mask value, when set is output, otherwise input;
|
||||
* @val_mask: gpio set value, when set is level high, otherwise low;
|
||||
*
|
||||
* Different PMIC has different pin features, belowing 3 mask members are not
|
||||
* all necessary for every PMIC. For example, RK805 has 2 pins that can be used
|
||||
* as output only GPIOs, so func_mask and dir_mask are not needed. RK816 has 1
|
||||
* pin that can be used as TS/GPIO, so fun_mask, dir_mask and val_mask are all
|
||||
* necessary.
|
||||
*/
|
||||
struct rk806_pin_config {
|
||||
u8 fun_reg;
|
||||
u8 fun_msk;
|
||||
u8 reg;
|
||||
u8 dir_msk;
|
||||
u8 val_msk;
|
||||
};
|
||||
|
||||
struct rk806_pctrl_info {
|
||||
struct rk806 *rk806;
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
struct gpio_chip gpio_chip;
|
||||
struct pinctrl_desc pinctrl_desc;
|
||||
const struct rk806_pin_function *functions;
|
||||
unsigned int num_functions;
|
||||
const struct rk806_pin_group *groups;
|
||||
int num_pin_groups;
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned int num_pins;
|
||||
const struct rk806_pin_config *pin_cfg;
|
||||
};
|
||||
|
||||
#define RK806_PWRCTRL1_DR BIT(0)
|
||||
#define RK806_PWRCTRL2_DR BIT(1)
|
||||
#define RK806_PWRCTRL3_DR BIT(2)
|
||||
#define RK806_PWRCTRL1_DATA BIT(4)
|
||||
#define RK806_PWRCTRL2_DATA BIT(5)
|
||||
#define RK806_PWRCTRL3_DATA BIT(6)
|
||||
#define RK806_PWRCTRL1_FUN 0x07
|
||||
#define RK806_PWRCTRL2_FUN 0x70
|
||||
#define RK806_PWRCTRL3_FUN 0x07
|
||||
|
||||
enum rk806_pinmux_option {
|
||||
RK806_PINMUX_FUN0 = 0,
|
||||
RK806_PINMUX_FUN1,
|
||||
RK806_PINMUX_FUN2,
|
||||
RK806_PINMUX_FUN3,
|
||||
RK806_PINMUX_FUN4,
|
||||
RK806_PINMUX_FUN5,
|
||||
};
|
||||
|
||||
enum {
|
||||
RK806_GPIO_DVS1,
|
||||
RK806_GPIO_DVS2,
|
||||
RK806_GPIO_DVS3
|
||||
};
|
||||
|
||||
static const char *const rk806_gpio_groups[] = {
|
||||
"gpio_pwrctrl1",
|
||||
"gpio_pwrctrl2",
|
||||
"gpio_pwrctrl3",
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc rk806_pins_desc[] = {
|
||||
PINCTRL_PIN(RK806_GPIO_DVS1, "gpio_pwrctrl1"), /* dvs1 pin */
|
||||
PINCTRL_PIN(RK806_GPIO_DVS2, "gpio_pwrctrl2"), /* dvs2 pin */
|
||||
PINCTRL_PIN(RK806_GPIO_DVS3, "gpio_pwrctrl3") /* dvs3 pin */
|
||||
};
|
||||
|
||||
static const struct rk806_pin_function rk806_pin_functions[] = {
|
||||
{
|
||||
.name = "pin_fun0",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN0,
|
||||
},
|
||||
{
|
||||
.name = "pin_fun1",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN1,
|
||||
},
|
||||
{
|
||||
.name = "pin_fun2",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN2,
|
||||
},
|
||||
{
|
||||
.name = "pin_fun3",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN3,
|
||||
},
|
||||
{
|
||||
.name = "pin_fun4",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN4,
|
||||
},
|
||||
{
|
||||
.name = "pin_fun5",
|
||||
.groups = rk806_gpio_groups,
|
||||
.ngroups = ARRAY_SIZE(rk806_gpio_groups),
|
||||
.mux_option = RK806_PINMUX_FUN5,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const struct rk806_pin_group rk806_pin_groups[] = {
|
||||
{
|
||||
.name = "gpio_pwrctrl1",
|
||||
.pins = { RK806_GPIO_DVS1 },
|
||||
.npins = 1,
|
||||
},
|
||||
{
|
||||
.name = "gpio_pwrctrl2",
|
||||
.pins = { RK806_GPIO_DVS2 },
|
||||
.npins = 1,
|
||||
},
|
||||
{
|
||||
.name = "gpio_pwrctrl3",
|
||||
.pins = { RK806_GPIO_DVS3 },
|
||||
.npins = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct rk806_pin_config rk806_gpio_cfgs[] = {
|
||||
{
|
||||
.fun_reg = RK806_SLEEP_CONFIG0,
|
||||
.fun_msk = RK806_PWRCTRL1_FUN,
|
||||
.reg = RK806_SLEEP_GPIO,
|
||||
.val_msk = RK806_PWRCTRL1_DATA,
|
||||
.dir_msk = RK806_PWRCTRL1_DR,
|
||||
},
|
||||
{
|
||||
.fun_reg = RK806_SLEEP_CONFIG0,
|
||||
.fun_msk = RK806_PWRCTRL2_FUN,
|
||||
.reg = RK806_SLEEP_GPIO,
|
||||
.val_msk = RK806_PWRCTRL2_DATA,
|
||||
.dir_msk = RK806_PWRCTRL2_DR,
|
||||
},
|
||||
{
|
||||
.fun_reg = RK806_SLEEP_CONFIG1,
|
||||
.fun_msk = RK806_PWRCTRL3_FUN,
|
||||
.reg = RK806_SLEEP_GPIO,
|
||||
.val_msk = RK806_PWRCTRL3_DATA,
|
||||
.dir_msk = RK806_PWRCTRL3_DR,
|
||||
}
|
||||
};
|
||||
|
||||
/* generic gpio chip */
|
||||
static int rk806_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = gpiochip_get_data(chip);
|
||||
int ret, val;
|
||||
|
||||
if (!pci->pin_cfg[offset].val_msk) {
|
||||
dev_dbg(pci->dev, "getting gpio%d value is not support\n",
|
||||
offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = regmap_read(pci->rk806->regmap, pci->pin_cfg[offset].reg, &val);
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "get gpio%d value failed\n", offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !!(val & pci->pin_cfg[offset].val_msk);
|
||||
}
|
||||
|
||||
static void rk806_gpio_set(struct gpio_chip *chip,
|
||||
unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
if (!pci->pin_cfg[offset].val_msk)
|
||||
return;
|
||||
|
||||
ret = regmap_update_bits(pci->rk806->regmap,
|
||||
pci->pin_cfg[offset].reg,
|
||||
pci->pin_cfg[offset].val_msk,
|
||||
value ? pci->pin_cfg[offset].val_msk : 0);
|
||||
if (ret)
|
||||
dev_err(pci->dev, "set gpio%d value %d failed\n",
|
||||
offset, value);
|
||||
}
|
||||
|
||||
static int rk806_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + offset);
|
||||
}
|
||||
|
||||
static int rk806_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
rk806_gpio_set(chip, offset, value);
|
||||
return pinctrl_gpio_direction_output(chip->base + offset);
|
||||
}
|
||||
|
||||
static int rk806_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = gpiochip_get_data(chip);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/* default output */
|
||||
if (!pci->pin_cfg[offset].dir_msk)
|
||||
return 0;
|
||||
|
||||
ret = regmap_read(pci->rk806->regmap,
|
||||
pci->pin_cfg[offset].reg,
|
||||
&val);
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "get gpio%d direction failed\n", offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !(val & pci->pin_cfg[offset].dir_msk);
|
||||
}
|
||||
|
||||
static struct gpio_chip rk806_gpio_chip = {
|
||||
.label = "rk806-gpio",
|
||||
.request = gpiochip_generic_request,
|
||||
.free = gpiochip_generic_free,
|
||||
.get_direction = rk806_gpio_get_direction,
|
||||
.get = rk806_gpio_get,
|
||||
.set = rk806_gpio_set,
|
||||
.direction_input = rk806_gpio_direction_input,
|
||||
.direction_output = rk806_gpio_direction_output,
|
||||
.can_sleep = true,
|
||||
.base = -1,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/* generic pinctrl */
|
||||
static int rk806_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pci->num_pin_groups;
|
||||
}
|
||||
|
||||
static const char *rk806_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int group)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pci->groups[group].name;
|
||||
}
|
||||
|
||||
static int rk806_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned int group,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = pci->groups[group].pins;
|
||||
*num_pins = pci->groups[group].npins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops rk806_pinctrl_ops = {
|
||||
.get_groups_count = rk806_pinctrl_get_groups_count,
|
||||
.get_group_name = rk806_pinctrl_get_group_name,
|
||||
.get_group_pins = rk806_pinctrl_get_group_pins,
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
};
|
||||
|
||||
static int rk806_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pci->num_functions;
|
||||
}
|
||||
|
||||
static const char *rk806_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int function)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pci->functions[function].name;
|
||||
}
|
||||
|
||||
static int rk806_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned int function,
|
||||
const char *const **groups,
|
||||
unsigned int *const num_groups)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*groups = pci->functions[function].groups;
|
||||
*num_groups = pci->functions[function].ngroups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rk806_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int offset,
|
||||
int mux)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
int ret;
|
||||
|
||||
if (!pci->pin_cfg[offset].fun_msk)
|
||||
return 0;
|
||||
|
||||
mux <<= ffs(pci->pin_cfg[offset].fun_msk) - 1;
|
||||
ret = regmap_update_bits(pci->rk806->regmap,
|
||||
pci->pin_cfg[offset].fun_reg,
|
||||
pci->pin_cfg[offset].fun_msk, mux);
|
||||
|
||||
if (ret)
|
||||
dev_err(pci->dev, "set gpio%d func%d failed\n", offset, mux);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk806_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int function,
|
||||
unsigned int group)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
int mux = pci->functions[function].mux_option;
|
||||
int offset = group;
|
||||
|
||||
return _rk806_pinctrl_set_mux(pctldev, offset, mux);
|
||||
}
|
||||
|
||||
static int rk806_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int offset, bool input)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
int ret;
|
||||
|
||||
/* set direction */
|
||||
if (!pci->pin_cfg[offset].dir_msk)
|
||||
return 0;
|
||||
|
||||
ret = regmap_update_bits(pci->rk806->regmap,
|
||||
pci->pin_cfg[offset].reg,
|
||||
pci->pin_cfg[offset].dir_msk,
|
||||
input ? 0 : pci->pin_cfg[offset].dir_msk);
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "set gpio%d direction failed\n", offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk806_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int offset)
|
||||
{
|
||||
return _rk806_pinctrl_set_mux(pctldev, offset, RK806_PINMUX_FUN5);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops rk806_pinmux_ops = {
|
||||
.gpio_request_enable = rk806_pinctrl_gpio_request_enable,
|
||||
.get_functions_count = rk806_pinctrl_get_funcs_count,
|
||||
.get_function_name = rk806_pinctrl_get_func_name,
|
||||
.get_function_groups = rk806_pinctrl_get_func_groups,
|
||||
.set_mux = rk806_pinctrl_set_mux,
|
||||
.gpio_set_direction = rk806_pmx_gpio_set_direction,
|
||||
};
|
||||
|
||||
static int rk806_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
u32 arg = 0;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
arg = rk806_gpio_get(&pci->gpio_chip, pin);
|
||||
break;
|
||||
default:
|
||||
dev_err(pci->dev, "Properties not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, (u16)arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk806_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct rk806_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum pin_config_param param;
|
||||
u32 i, arg = 0;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
rk806_pmx_gpio_set_direction(pctldev, NULL, pin, false);
|
||||
rk806_gpio_set(&pci->gpio_chip, pin, arg);
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
if (arg)
|
||||
rk806_pmx_gpio_set_direction(pctldev,
|
||||
NULL,
|
||||
pin,
|
||||
true);
|
||||
break;
|
||||
default:
|
||||
dev_err(pci->dev, "Properties not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops rk806_pinconf_ops = {
|
||||
.pin_config_get = rk806_pinconf_get,
|
||||
.pin_config_set = rk806_pinconf_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc rk806_pinctrl_desc = {
|
||||
.name = "rk806-pinctrl",
|
||||
.pctlops = &rk806_pinctrl_ops,
|
||||
.pmxops = &rk806_pinmux_ops,
|
||||
.confops = &rk806_pinconf_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int rk806_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk806_pctrl_info *pci;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL);
|
||||
if (!pci)
|
||||
return -ENOMEM;
|
||||
|
||||
pci->dev = &pdev->dev;
|
||||
np = of_get_child_by_name(pdev->dev.parent->of_node, "pinctrl_rk806");
|
||||
if (np)
|
||||
pci->dev->of_node = np;
|
||||
else
|
||||
pci->dev->of_node = pdev->dev.parent->of_node;
|
||||
pci->rk806 = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
platform_set_drvdata(pdev, pci);
|
||||
|
||||
pci->pinctrl_desc = rk806_pinctrl_desc;
|
||||
pci->gpio_chip = rk806_gpio_chip;
|
||||
pci->pins = rk806_pins_desc;
|
||||
pci->num_pins = ARRAY_SIZE(rk806_pins_desc);
|
||||
pci->functions = rk806_pin_functions;
|
||||
pci->num_functions = ARRAY_SIZE(rk806_pin_functions);
|
||||
pci->groups = rk806_pin_groups;
|
||||
pci->num_pin_groups = ARRAY_SIZE(rk806_pin_groups);
|
||||
pci->pinctrl_desc.pins = rk806_pins_desc;
|
||||
pci->pinctrl_desc.npins = ARRAY_SIZE(rk806_pins_desc);
|
||||
pci->pin_cfg = rk806_gpio_cfgs;
|
||||
pci->gpio_chip.ngpio = ARRAY_SIZE(rk806_gpio_cfgs);
|
||||
|
||||
pci->gpio_chip.parent = &pdev->dev;
|
||||
|
||||
if (np)
|
||||
pci->gpio_chip.of_node = np;
|
||||
else
|
||||
pci->gpio_chip.of_node = pdev->dev.parent->of_node;
|
||||
|
||||
/* Add gpiochip */
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &pci->gpio_chip, pci);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't add gpiochip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add pinctrl */
|
||||
pci->pctl = devm_pinctrl_register(&pdev->dev, &pci->pinctrl_desc, pci);
|
||||
if (IS_ERR(pci->pctl)) {
|
||||
dev_err(&pdev->dev, "Couldn't add pinctrl\n");
|
||||
return PTR_ERR(pci->pctl);
|
||||
}
|
||||
|
||||
/* Add pin range */
|
||||
ret = gpiochip_add_pin_range(&pci->gpio_chip,
|
||||
dev_name(&pdev->dev),
|
||||
0,
|
||||
0,
|
||||
pci->gpio_chip.ngpio);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't add gpiochip pin range\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk806_pinctrl_driver = {
|
||||
.probe = rk806_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "rk806-pinctrl",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init rk806_pinctrl_driver_register(void)
|
||||
{
|
||||
return platform_driver_register(&rk806_pinctrl_driver);
|
||||
}
|
||||
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
|
||||
subsys_initcall(rk806_pinctrl_driver_register);
|
||||
#else
|
||||
fs_initcall_sync(rk806_pinctrl_driver_register);
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("RK806 pin control and GPIO driver");
|
||||
MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -929,6 +929,14 @@ config REGULATOR_RC5T583
|
|||
through regulator interface. The device supports multiple DCDC/LDO
|
||||
outputs which can be controlled by i2c communication.
|
||||
|
||||
config REGULATOR_RK806
|
||||
tristate "Rockchip RK806 Power regulator"
|
||||
depends on MFD_RK806
|
||||
help
|
||||
Select this option to enable the power regulator of ROCKCHIP
|
||||
PMIC RK806. The device supports multiple DCDC/LDO
|
||||
outputs which can be controlled by spi communication.
|
||||
|
||||
config REGULATOR_RK808
|
||||
tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power regulators"
|
||||
depends on MFD_RK808
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RK806) += rk806-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,521 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_REGULATOR_RK806_H
|
||||
#define __LINUX_REGULATOR_RK806_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define RK806_POWER_EN0 0x0
|
||||
#define RK806_POWER_EN1 0x1
|
||||
#define RK806_POWER_EN2 0x2
|
||||
#define RK806_POWER_EN3 0x3
|
||||
#define RK806_POWER_EN4 0x4
|
||||
#define RK806_POWER_EN5 0x5
|
||||
#define RK806_POWER_SLP_EN0 0x6
|
||||
#define RK806_POWER_SLP_EN1 0x7
|
||||
#define RK806_POWER_SLP_EN2 0x8
|
||||
#define RK806_POWER_DISCHRG_EN0 0x9
|
||||
#define RK806_POWER_DISCHRG_EN1 0xA
|
||||
#define RK806_POWER_DISCHRG_EN2 0xB
|
||||
#define RK806_BUCK_FB_CONFIG 0xC
|
||||
#define RK806_SLP_LP_CONFIG 0xD
|
||||
#define RK806_POWER_FPWM_EN0 0xE
|
||||
#define RK806_POWER_FPWM_EN1 0xF
|
||||
#define RK806_BUCK1_CONFIG 0x10
|
||||
#define RK806_BUCK2_CONFIG 0x11
|
||||
#define RK806_BUCK3_CONFIG 0x12
|
||||
#define RK806_BUCK4_CONFIG 0x13
|
||||
#define RK806_BUCK5_CONFIG 0x14
|
||||
#define RK806_BUCK6_CONFIG 0x15
|
||||
#define RK806_BUCK7_CONFIG 0x16
|
||||
#define RK806_BUCK8_CONFIG 0x17
|
||||
#define RK806_BUCK9_CONFIG 0x18
|
||||
#define RK806_BUCK10_CONFIG 0x19
|
||||
#define RK806_BUCK1_ON_VSEL 0x1A
|
||||
#define RK806_BUCK2_ON_VSEL 0x1B
|
||||
#define RK806_BUCK3_ON_VSEL 0x1C
|
||||
#define RK806_BUCK4_ON_VSEL 0x1D
|
||||
#define RK806_BUCK5_ON_VSEL 0x1E
|
||||
#define RK806_BUCK6_ON_VSEL 0x1F
|
||||
#define RK806_BUCK7_ON_VSEL 0x20
|
||||
#define RK806_BUCK8_ON_VSEL 0x21
|
||||
#define RK806_BUCK9_ON_VSEL 0x22
|
||||
#define RK806_BUCK10_ON_VSEL 0x23
|
||||
#define RK806_BUCK1_SLP_VSEL 0x24
|
||||
#define RK806_BUCK2_SLP_VSEL 0x25
|
||||
#define RK806_BUCK3_SLP_VSEL 0x26
|
||||
#define RK806_BUCK4_SLP_VSEL 0x27
|
||||
#define RK806_BUCK5_SLP_VSEL 0x28
|
||||
#define RK806_BUCK6_SLP_VSEL 0x29
|
||||
#define RK806_BUCK7_SLP_VSEL 0x2A
|
||||
#define RK806_BUCK8_SLP_VSEL 0x2B
|
||||
#define RK806_BUCK9_SLP_VSEL 0x2D
|
||||
#define RK806_BUCK10_SLP_VSEL 0x2E
|
||||
#define RK806_BUCK_DEBUG1 0x30
|
||||
#define RK806_BUCK_DEBUG2 0x31
|
||||
#define RK806_BUCK_DEBUG3 0x32
|
||||
#define RK806_BUCK_DEBUG4 0x33
|
||||
#define RK806_BUCK_DEBUG5 0x34
|
||||
#define RK806_BUCK_DEBUG6 0x35
|
||||
#define RK806_BUCK_DEBUG7 0x36
|
||||
#define RK806_BUCK_DEBUG8 0x37
|
||||
#define RK806_BUCK_DEBUG9 0x38
|
||||
#define RK806_BUCK_DEBUG10 0x39
|
||||
#define RK806_BUCK_DEBUG11 0x3A
|
||||
#define RK806_BUCK_DEBUG12 0x3B
|
||||
#define RK806_BUCK_DEBUG13 0x3C
|
||||
#define RK806_BUCK_DEBUG14 0x3D
|
||||
#define RK806_BUCK_DEBUG15 0x3E
|
||||
#define RK806_BUCK_DEBUG16 0x3F
|
||||
#define RK806_BUCK_DEBUG17 0x40
|
||||
#define RK806_BUCK_DEBUG18 0x41
|
||||
#define RK806_NLDO_IMAX 0x42
|
||||
#define RK806_NLDO1_ON_VSEL 0x43
|
||||
#define RK806_NLDO2_ON_VSEL 0x44
|
||||
#define RK806_NLDO3_ON_VSEL 0x45
|
||||
#define RK806_NLDO4_ON_VSEL 0x46
|
||||
#define RK806_NLDO5_ON_VSEL 0x47
|
||||
#define RK806_NLDO1_SLP_VSEL 0x48
|
||||
#define RK806_NLDO2_SLP_VSEL 0x49
|
||||
#define RK806_NLDO3_SLP_VSEL 0x4A
|
||||
#define RK806_NLDO4_SLP_VSEL 0x4B
|
||||
#define RK806_NLDO5_SLP_VSEL 0x4C
|
||||
#define RK806_PLDO_IMAX 0x4D
|
||||
#define RK806_PLDO1_ON_VSEL 0x4E
|
||||
#define RK806_PLDO2_ON_VSEL 0x4F
|
||||
#define RK806_PLDO3_ON_VSEL 0x50
|
||||
#define RK806_PLDO4_ON_VSEL 0x51
|
||||
#define RK806_PLDO5_ON_VSEL 0x52
|
||||
#define RK806_PLDO6_ON_VSEL 0x53
|
||||
#define RK806_PLDO1_SLP_VSEL 0x54
|
||||
#define RK806_PLDO2_SLP_VSEL 0x55
|
||||
#define RK806_PLDO3_SLP_VSEL 0x56
|
||||
#define RK806_PLDO4_SLP_VSEL 0x57
|
||||
#define RK806_PLDO5_SLP_VSEL 0x58
|
||||
#define RK806_PLDO6_SLP_VSEL 0x59
|
||||
#define RK806_CHIP_NAME 0x5A
|
||||
#define RK806_CHIP_VER 0x5B
|
||||
#define RK806_OTP_VER 0x5C
|
||||
#define RK806_SYS_STS 0x5D
|
||||
#define RK806_SYS_CFG0 0x5E
|
||||
#define RK806_SYS_CFG1 0x5F
|
||||
#define RK806_SYS_OPTION 0x61
|
||||
#define RK806_SLEEP_CONFIG0 0x62
|
||||
#define RK806_SLEEP_CONFIG1 0x63
|
||||
#define RK806_SLEEP_CTR_SEL0 0x64
|
||||
#define RK806_SLEEP_CTR_SEL1 0x65
|
||||
#define RK806_SLEEP_CTR_SEL2 0x66
|
||||
#define RK806_SLEEP_CTR_SEL3 0x67
|
||||
#define RK806_SLEEP_CTR_SEL4 0x68
|
||||
#define RK806_SLEEP_CTR_SEL5 0x69
|
||||
#define RK806_DVS_CTRL_SEL0 0x6A
|
||||
#define RK806_DVS_CTRL_SEL1 0x6B
|
||||
#define RK806_DVS_CTRL_SEL2 0x6C
|
||||
#define RK806_DVS_CTRL_SEL3 0x6D
|
||||
#define RK806_DVS_CTRL_SEL4 0x6E
|
||||
#define RK806_DVS_CTRL_SEL5 0x6F
|
||||
#define RK806_DVS_START_CTRL 0x70
|
||||
#define RK806_SLEEP_GPIO 0x71
|
||||
#define RK806_SYS_CFG3 0x72
|
||||
#define RK806_ON_SOURCE 0x74
|
||||
#define RK806_OFF_SOURCE 0x75
|
||||
#define RK806_PWRON_KEY 0x76
|
||||
#define RK806_INT_STS0 0x77
|
||||
#define RK806_INT_MSK0 0x78
|
||||
#define RK806_INT_STS1 0x79
|
||||
#define RK806_INT_MSK1 0x7A
|
||||
#define RK806_GPIO_INT_CONFIG 0x7B
|
||||
#define RK806_DATA_REG0 0x7C
|
||||
#define RK806_DATA_REG1 0x7D
|
||||
#define RK806_DATA_REG2 0x7E
|
||||
#define RK806_DATA_REG3 0x7F
|
||||
#define RK806_DATA_REG4 0x80
|
||||
#define RK806_DATA_REG5 0x81
|
||||
#define RK806_DATA_REG6 0x82
|
||||
#define RK806_DATA_REG7 0x83
|
||||
#define RK806_DATA_REG8 0x84
|
||||
#define RK806_DATA_REG9 0x85
|
||||
#define RK806_DATA_REG10 0x86
|
||||
#define RK806_DATA_REG11 0x87
|
||||
#define RK806_DATA_REG12 0x88
|
||||
#define RK806_DATA_REG13 0x89
|
||||
#define RK806_DATA_REG14 0x8A
|
||||
#define RK806_DATA_REG15 0x8B
|
||||
#define RK806_TM_REG 0x8C
|
||||
#define RK806_OTP_EN_REG 0x8D
|
||||
#define RK806_FUNC_OTP_EN_REG 0x8E
|
||||
#define RK806_TEST_REG1 0x8F
|
||||
#define RK806_TEST_REG2 0x90
|
||||
#define RK806_TEST_REG3 0x91
|
||||
#define RK806_TEST_REG4 0x92
|
||||
#define RK806_TEST_REG5 0x93
|
||||
#define RK806_BUCK_VSEL_OTP_REG0 0x94
|
||||
#define RK806_BUCK_VSEL_OTP_REG1 0x95
|
||||
#define RK806_BUCK_VSEL_OTP_REG2 0x96
|
||||
#define RK806_BUCK_VSEL_OTP_REG3 0x97
|
||||
#define RK806_BUCK_VSEL_OTP_REG4 0x98
|
||||
#define RK806_BUCK_VSEL_OTP_REG5 0x99
|
||||
#define RK806_BUCK_VSEL_OTP_REG6 0x9A
|
||||
#define RK806_BUCK_VSEL_OTP_REG7 0x9B
|
||||
#define RK806_BUCK_VSEL_OTP_REG8 0x9C
|
||||
#define RK806_BUCK_VSEL_OTP_REG9 0x9D
|
||||
#define RK806_NLDO1_VSEL_OTP_REG0 0x9E
|
||||
#define RK806_NLDO1_VSEL_OTP_REG1 0x9F
|
||||
#define RK806_NLDO1_VSEL_OTP_REG2 0xA0
|
||||
#define RK806_NLDO1_VSEL_OTP_REG3 0xA1
|
||||
#define RK806_NLDO1_VSEL_OTP_REG4 0xA2
|
||||
#define RK806_PLDO_VSEL_OTP_REG0 0xA3
|
||||
#define RK806_PLDO_VSEL_OTP_REG1 0xA4
|
||||
#define RK806_PLDO_VSEL_OTP_REG2 0xA5
|
||||
#define RK806_PLDO_VSEL_OTP_REG3 0xA6
|
||||
#define RK806_PLDO_VSEL_OTP_REG4 0xA7
|
||||
#define RK806_PLDO_VSEL_OTP_REG5 0xA8
|
||||
#define RK806_BUCK_EN_OTP_REG1 0xA9
|
||||
#define RK806_NLDO_EN_OTP_REG1 0xAA
|
||||
#define RK806_PLDO_EN_OTP_REG1 0xAB
|
||||
#define RK806_BUCK_FB_RES_OTP_REG1 0xAC
|
||||
#define RK806_OTP_RESEV_REG0 0xAD
|
||||
#define RK806_OTP_RESEV_REG1 0xAE
|
||||
#define RK806_OTP_RESEV_REG2 0xAF
|
||||
#define RK806_OTP_RESEV_REG3 0xB0
|
||||
#define RK806_OTP_RESEV_REG4 0xB1
|
||||
#define RK806_BUCK_SEQ_REG0 0xB2
|
||||
#define RK806_BUCK_SEQ_REG1 0xB3
|
||||
#define RK806_BUCK_SEQ_REG2 0xB4
|
||||
#define RK806_BUCK_SEQ_REG3 0xB5
|
||||
#define RK806_BUCK_SEQ_REG4 0xB6
|
||||
#define RK806_BUCK_SEQ_REG5 0xB7
|
||||
#define RK806_BUCK_SEQ_REG6 0xB8
|
||||
#define RK806_BUCK_SEQ_REG7 0xB9
|
||||
#define RK806_BUCK_SEQ_REG8 0xBA
|
||||
#define RK806_BUCK_SEQ_REG9 0xBB
|
||||
#define RK806_BUCK_SEQ_REG10 0xBC
|
||||
#define RK806_BUCK_SEQ_REG11 0xBD
|
||||
#define RK806_BUCK_SEQ_REG12 0xBE
|
||||
#define RK806_BUCK_SEQ_REG13 0xBF
|
||||
#define RK806_BUCK_SEQ_REG14 0xC0
|
||||
#define RK806_BUCK_SEQ_REG15 0xC1
|
||||
#define RK806_BUCK_SEQ_REG16 0xC2
|
||||
#define RK806_BUCK_SEQ_REG17 0xC3
|
||||
#define RK806_HK_TRIM_REG1 0xC4
|
||||
#define RK806_HK_TRIM_REG2 0xC5
|
||||
#define RK806_BUCK_REF_TRIM_REG1 0xC6
|
||||
#define RK806_BUCK_REF_TRIM_REG2 0xC7
|
||||
#define RK806_BUCK_REF_TRIM_REG3 0xC8
|
||||
#define RK806_BUCK_REF_TRIM_REG4 0xC9
|
||||
#define RK806_BUCK_REF_TRIM_REG5 0xCA
|
||||
#define RK806_BUCK_OSC_TRIM_REG1 0xCB
|
||||
#define RK806_BUCK_OSC_TRIM_REG2 0xCC
|
||||
#define RK806_BUCK_OSC_TRIM_REG3 0xCD
|
||||
#define RK806_BUCK_OSC_TRIM_REG4 0xCE
|
||||
#define RK806_BUCK_OSC_TRIM_REG5 0xCF
|
||||
#define RK806_BUCK_TRIM_ZCDIOS_REG1 0xD0
|
||||
#define RK806_BUCK_TRIM_ZCDIOS_REG2 0xD1
|
||||
#define RK806_NLDO_TRIM_REG1 0xD2
|
||||
#define RK806_NLDO_TRIM_REG2 0xD3
|
||||
#define RK806_NLDO_TRIM_REG3 0xD4
|
||||
#define RK806_PLDO_TRIM_REG1 0xD5
|
||||
#define RK806_PLDO_TRIM_REG2 0xD6
|
||||
#define RK806_PLDO_TRIM_REG3 0xD7
|
||||
#define RK806_TRIM_ICOMP_REG1 0xD8
|
||||
#define RK806_TRIM_ICOMP_REG2 0xD9
|
||||
#define RK806_EFUSE_CONTROL_REGH 0xDA
|
||||
#define RK806_FUSE_PROG_REG 0xDB
|
||||
#define RK806_MAIN_FSM_STS_REG 0xDD
|
||||
#define RK806_FSM_REG 0xDE
|
||||
#define RK806_TOP_RESEV_OFFR 0xEC
|
||||
#define RK806_TOP_RESEV_POR 0xED
|
||||
#define RK806_BUCK_VRSN_REG1 0xEE
|
||||
#define RK806_BUCK_VRSN_REG2 0xEF
|
||||
#define RK806_NLDO_RLOAD_SEL_REG1 0xF0
|
||||
#define RK806_PLDO_RLOAD_SEL_REG1 0xF1
|
||||
#define RK806_PLDO_RLOAD_SEL_REG2 0xF2
|
||||
#define RK806_BUCK_CMIN_MX_REG1 0xF3
|
||||
#define RK806_BUCK_CMIN_MX_REG2 0xF4
|
||||
#define RK806_BUCK_FREQ_SET_REG1 0xF5
|
||||
#define RK806_BUCK_FREQ_SET_REG2 0xF6
|
||||
#define RK806_BUCK_RS_MEABS_REG1 0xF7
|
||||
#define RK806_BUCK_RS_MEABS_REG2 0xF8
|
||||
#define RK806_BUCK_RS_ZDLEB_REG1 0xF9
|
||||
#define RK806_BUCK_RS_ZDLEB_REG2 0xFA
|
||||
#define RK806_BUCK_RSERVE_REG1 0xFB
|
||||
#define RK806_BUCK_RSERVE_REG2 0xFC
|
||||
#define RK806_BUCK_RSERVE_REG3 0xFD
|
||||
#define RK806_BUCK_RSERVE_REG4 0xFE
|
||||
#define RK806_BUCK_RSERVE_REG5 0xFF
|
||||
|
||||
/* INT_STS Register field definitions */
|
||||
#define RK806_INT_STS_PWRON_FALL BIT(0)
|
||||
#define RK806_INT_STS_PWRON_RISE BIT(1)
|
||||
#define RK806_INT_STS_PWRON BIT(2)
|
||||
#define RK806_INT_STS_PWRON_LP BIT(3)
|
||||
#define RK806_INT_STS_HOTDIE BIT(4)
|
||||
#define RK806_INT_STS_VDC_RISE BIT(5)
|
||||
#define RK806_INT_STS_VDC_FALL BIT(6)
|
||||
#define RK806_INT_STS_VB_LO BIT(7)
|
||||
#define RK806_INT_STS_REV0 BIT(0)
|
||||
#define RK806_INT_STS_REV1 BIT(1)
|
||||
#define RK806_INT_STS_REV2 BIT(2)
|
||||
#define RK806_INT_STS_REV3 BIT(3)
|
||||
#define RK806_INT_STS_SLP3_GPIO BIT(4)
|
||||
#define RK806_INT_STS_SLP2_GPIO BIT(5)
|
||||
#define RK806_INT_STS_SLP1_GPIO BIT(6)
|
||||
#define RK806_INT_STS_WDT BIT(7)
|
||||
|
||||
/* spi command */
|
||||
#define RK806_CMD_READ 0
|
||||
#define RK806_CMD_WRITE BIT(7)
|
||||
#define RK806_CMD_CRC_EN BIT(6)
|
||||
#define RK806_CMD_CRC_DIS 0
|
||||
#define RK806_CMD_LEN_MSK 0x0f
|
||||
#define RK806_REG_H 0x00
|
||||
|
||||
enum rk806_reg_id {
|
||||
RK806_ID_DCDC1 = 0,
|
||||
RK806_ID_DCDC2,
|
||||
RK806_ID_DCDC3,
|
||||
RK806_ID_DCDC4,
|
||||
RK806_ID_DCDC5,
|
||||
RK806_ID_DCDC6,
|
||||
RK806_ID_DCDC7,
|
||||
RK806_ID_DCDC8,
|
||||
RK806_ID_DCDC9,
|
||||
RK806_ID_DCDC10,
|
||||
|
||||
RK806_ID_NLDO1,
|
||||
RK806_ID_NLDO2,
|
||||
RK806_ID_NLDO3,
|
||||
RK806_ID_NLDO4,
|
||||
RK806_ID_NLDO5,
|
||||
|
||||
RK806_ID_PLDO1,
|
||||
RK806_ID_PLDO2,
|
||||
RK806_ID_PLDO3,
|
||||
RK806_ID_PLDO4,
|
||||
RK806_ID_PLDO5,
|
||||
RK806_ID_PLDO6,
|
||||
RK806_ID_END,
|
||||
};
|
||||
|
||||
/* Define the rk806 IRQ numbers */
|
||||
enum rk806_irqs {
|
||||
/* INT_STS0 registers */
|
||||
RK806_IRQ_PWRON_FALL,
|
||||
RK806_IRQ_PWRON_RISE,
|
||||
RK806_IRQ_PWRON,
|
||||
RK806_IRQ_PWRON_LP,
|
||||
RK806_IRQ_HOTDIE,
|
||||
RK806_IRQ_VDC_RISE,
|
||||
RK806_IRQ_VDC_FALL,
|
||||
RK806_IRQ_VB_LO,
|
||||
|
||||
/* INT_STS0 registers */
|
||||
RK806_IRQ_REV0,
|
||||
RK806_IRQ_REV1,
|
||||
RK806_IRQ_REV2,
|
||||
RK806_IRQ_REV3,
|
||||
RK806_IRQ_SLP3_GPIO,
|
||||
RK806_IRQ_SLP2_GPIO,
|
||||
RK806_IRQ_SLP1_GPIO,
|
||||
RK806_IRQ_WDT,
|
||||
};
|
||||
|
||||
/* VCC1 low voltage threshold */
|
||||
enum rk806_lv_sel {
|
||||
VB_LO_SEL_2800,
|
||||
VB_LO_SEL_2900,
|
||||
VB_LO_SEL_3000,
|
||||
VB_LO_SEL_3100,
|
||||
VB_LO_SEL_3200,
|
||||
VB_LO_SEL_3300,
|
||||
VB_LO_SEL_3400,
|
||||
VB_LO_SEL_3500,
|
||||
};
|
||||
|
||||
/* system shut down voltage select */
|
||||
enum rk806_uv_sel {
|
||||
VB_UV_SEL_2700,
|
||||
VB_UV_SEL_2800,
|
||||
VB_UV_SEL_2900,
|
||||
VB_UV_SEL_3000,
|
||||
VB_UV_SEL_3100,
|
||||
VB_UV_SEL_3200,
|
||||
VB_UV_SEL_3300,
|
||||
VB_UV_SEL_3400,
|
||||
};
|
||||
|
||||
/* pin function */
|
||||
enum rk806_pin_fun {
|
||||
RK806_PIN_FUN_NULL,
|
||||
RK806_PIN_FUN_SLP,
|
||||
RK806_PIN_FUN_PWROFF,
|
||||
RK806_PIN_FUN_RST,
|
||||
RK806_PIN_FUN_DVS,
|
||||
RK806_PIN_FUN_GPIO,
|
||||
};
|
||||
|
||||
/* pin pol */
|
||||
enum rk806_pin_level {
|
||||
RK806_PIN_POL_LOW,
|
||||
RK806_PIN_POL_HIGH,
|
||||
};
|
||||
|
||||
enum rk806_pin_ctr_sel {
|
||||
CTR_SEL_PIN1,
|
||||
CTR_SEL_PIN2,
|
||||
CTR_SEL_PIN3,
|
||||
};
|
||||
|
||||
enum rk806_start_dvs_sel {
|
||||
CTR_SEL_DVS_START1,
|
||||
CTR_SEL_DVS_START2,
|
||||
CTR_SEL_DVS_START3,
|
||||
};
|
||||
|
||||
enum rk806_pin_dr_sel {
|
||||
RK806_PIN_INPUT,
|
||||
RK806_PIN_OUTPUT,
|
||||
};
|
||||
|
||||
enum rk806_int_pol {
|
||||
RK806_INT_POL_LOW,
|
||||
RK806_INT_POL_HIGH,
|
||||
};
|
||||
|
||||
enum rk806_int_fun {
|
||||
RK806_INT_ONLY,
|
||||
RK806_INT_ADN_WKUP,
|
||||
};
|
||||
|
||||
enum rk806_dvs_mode {
|
||||
RK806_DVS_NOT_SUPPORT,
|
||||
RK806_DVS_BY_CTR_PIN1,
|
||||
RK806_DVS_BY_CTR_PIN2,
|
||||
RK806_DVS_BY_CTR_PIN3,
|
||||
RK806_DVS_BY_CTR_START1,
|
||||
RK806_DVS_BY_CTR_START2,
|
||||
RK806_DVS_BY_CTR_START3,
|
||||
RK806_DVS_END,
|
||||
};
|
||||
|
||||
enum rk806_fields {
|
||||
CHIP_NAME_H, CHIP_NAME_L, CHIP_VER, OTP_VER,
|
||||
POWER_EN0, POWER_EN1, POWER_EN2, POWER_EN3, POWER_EN4, POWER_EN5,
|
||||
BUCK4_EN_MASK, BUCK3_EN_MASK, BUCK2_EN_MASK, BUCK1_EN_MASK,
|
||||
BUCK4_EN, BUCK3_EN, BUCK2_EN, BUCK1_EN,
|
||||
BUCK8_EN_MASK, BUCK7_EN_MASK, BUCK6_EN_MASK, BUCK5_EN_MASK,
|
||||
BUCK8_EN, BUCK7_EN, BUCK6_EN, BUCK5_EN,
|
||||
BUCK10_EN_MASK, BUCK9_EN_MASK, BUCK10_EN, BUCK9_EN,
|
||||
NLDO4_EN_MASK, NLDO3_EN_MASK, NLDO2_EN_MASK, NLDO1_EN_MASK,
|
||||
NLDO4_EN, NLDO3_EN, NLDO2_EN, NLDO1_EN,
|
||||
PLDO4_EN_MASK, PLDO3_EN_MASK, PLDO2_EN_MASK, PLDO1_EN_MASK,
|
||||
PLDO4_EN, PLDO3_EN, PLDO2_EN, PLDO1_EN,
|
||||
NLDO5_EN_MASK, PLDO6_EN_MASK, PLDO5_EN_MASK,
|
||||
NLDO5_EN, PLDO6_EN, PLDO5_EN,
|
||||
BUCK8_SLP_EN, BUCK7_SLP_EN, BUCK6_SLP_EN, BUCK5_SLP_EN, BUCK4_SLP_EN,
|
||||
BUCK3_SLP_EN, BUCK2_SLP_EN, BUCK1_SLP_EN,
|
||||
BUCK10_SLP_EN, BUCK9_SLP_EN, NLDO5_SLP_EN, NLDO4_SLP_EN, NLDO3_SLP_EN,
|
||||
NLDO2_SLP_EN, NLDO1_SLP_EN,
|
||||
PLDO6_SLP_EN, PLDO5_SLP_EN, PLDO4_SLP_EN, PLDO3_SLP_EN,
|
||||
PLDO2_SLP_EN, PLDO1_SLP_EN,
|
||||
BUCK1_ON_VSEL, BUCK2_ON_VSEL, BUCK3_ON_VSEL, BUCK4_ON_VSEL, BUCK5_ON_VSEL,
|
||||
BUCK6_ON_VSEL, BUCK7_ON_VSEL, BUCK8_ON_VSEL, BUCK9_ON_VSEL, BUCK10_ON_VSEL,
|
||||
BUCK1_SLP_VSEL, BUCK2_SLP_VSEL, BUCK3_SLP_VSEL, BUCK4_SLP_VSEL, BUCK5_SLP_VSEL,
|
||||
BUCK6_SLP_VSEL, BUCK7_SLP_VSEL, BUCK8_SLP_VSEL, BUCK9_SLP_VSEL, BUCK10_SLP_VSEL,
|
||||
NLDO1_ON_VSEL, NLDO2_ON_VSEL, NLDO3_ON_VSEL, NLDO4_ON_VSEL, NLDO5_ON_VSEL,
|
||||
NLDO1_SLP_VSEL, NLDO2_SLP_VSEL, NLDO3_SLP_VSEL, NLDO4_SLP_VSEL, NLDO5_SLP_VSEL,
|
||||
PLDO1_ON_VSEL, PLDO2_ON_VSEL, PLDO3_ON_VSEL, PLDO4_ON_VSEL, PLDO5_ON_VSEL,
|
||||
PLDO6_ON_VSEL,
|
||||
PLDO1_SLP_VSEL, PLDO2_SLP_VSEL, PLDO3_SLP_VSEL, PLDO4_SLP_VSEL, PLDO5_SLP_VSEL,
|
||||
PLDO6_SLP_VSEL,
|
||||
BUCK1_RATE, BUCK2_RATE, BUCK3_RATE, BUCK4_RATE, BUCK5_RATE, BUCK6_RATE,
|
||||
BUCK7_RATE, BUCK8_RATE, BUCK9_RATE, BUCK10_RATE,
|
||||
PWRON_STS, VDC_STS, VB_UV_STSS, VB_LO_STS, HOTDIE_STS, TSD_STS, VB_OV_STS,
|
||||
VB_UV_DLY, VB_UV_SEL, VB_LO_ACT, VB_LO_SEL,
|
||||
TSD_TEMP, HOTDIE_TMP, VPREREG_SEL,
|
||||
VCCXDET_DIS, OSC_TC, ENB2_2M, ENB_32K,
|
||||
SLP2_POL, SLP2_FUN, SLP1_POL, SLP1_FUN,
|
||||
SLP3_POL, SLP3_FUN,
|
||||
|
||||
BUCK4_SLP_CTR_SEL, BUCK3_SLP_CTR_SEL, BUCK2_SLP_CTR_SEL, BUCK1_SLP_CTR_SEL,
|
||||
BUCK8_SLP_CTR_SEL, BUCK7_SLP_CTR_SEL, BUCK6_SLP_CTR_SEL, BUCK5_SLP_CTR_SEL,
|
||||
NLDO2_SLP_CTR_SEL, NLDO1_SLP_CTR_SEL, BUCK10_SLP_CTR_SEL, BUCK9_SLP_CTR_SEL,
|
||||
NLDO5_SLP_CTR_SEL, NLDO4_SLP_CTR_SEL, NLDO3_SLP_CTR_SEL,
|
||||
PLDO4_SLP_CTR_SEL, PLDO3_SLP_CTR_SEL, PLDO2_SLP_CTR_SEL, PLDO1_SLP_CTR_SEL,
|
||||
PLDO6_SLP_CTR_SEL, PLDO5_SLP_CTR_SEL,
|
||||
BUCK4_DVS_CTR_SEL, BUCK3_DVS_CTR_SEL, BUCK2_DVS_CTR_SEL, BUCK1_DVS_CTR_SEL,
|
||||
BUCK8_DVS_CTR_SEL, BUCK7_DVS_CTR_SEL, BUCK6_DVS_CTR_SEL, BUCK5_DVS_CTR_SEL,
|
||||
NLDO2_DVS_CTR_SEL, NLDO1_DVS_CTR_SEL, BUCK10_DVS_CTR_SEL, BUCK9_DVS_CTR_SEL,
|
||||
NLDO5_DVS_CTR_SEL, NLDO4_DVS_CTR_SEL, NLDO3_DVS_CTR_SEL,
|
||||
PLDO4_DVS_CTR_SEL, PLDO3_DVS_CTR_SEL, PLDO2_DVS_CTR_SEL, PLDO1_DVS_CTR_SEL,
|
||||
PLDO6_DVS_CTR_SEL, PLDO5_DVS_CTR_SEL,
|
||||
DVS_START3, DVS_START2, DVS_START1,
|
||||
SLP3_DATA, SLP2_DATA, SLP1_DATA, SLP3_DR, SLP2_DR, SLP1_DR,
|
||||
|
||||
RST_FUN, DEV_RST, DEV_SLP, SLAVE_RESTART_FUN, DEV_OFF,
|
||||
WDT_CLR, WDT_EN, WDT_SET,
|
||||
ON_PWRON, ON_VDC, RESTART_RESETB, RESTART_PWRON_LP, RESTART_SLP,
|
||||
RESTART_DEV_RST, RESTART_WDT,
|
||||
OFF_SLP, VB_SYS_OV, OFF_TSD, OFF_DEV_OFF, OFF_PWRON_LP, OFF_VB_LO,
|
||||
PWRON_ON_TIME, PWRON_LP_ACT, PWRON_LP_OFF_TIME, PWRON_LP_TM_SEL, PWRON_DB_SEL,
|
||||
VB_LO_INT, VDC_FALL_INT, VDC_RISE_INT, HOTDIE_INT, PWRON_LP_INT, PWRON_INT,
|
||||
PWRON_RISE_INT, PWRON_FALL_INT,
|
||||
VB_LO_IM, VDC_FALL_INT_IM, VDC_RISE_IM, HOTDIE_IM, PWRON_LP_IM,
|
||||
PWRON_IM, PWRON_RISE_INT_IM, PWRON_FALL_INT_IM,
|
||||
WDT_INT, SLP1_GPIO_INT, SLP2_GPIO_INT, SLP3_GPIO_INT,
|
||||
WDT_INT_IM, SLP1_GPIO_IM, SLP2_GPIO_IM, SLP3_GPIO_IM,
|
||||
INT_FUNCTION, INT_POL, INT_FC_EN,
|
||||
LDO_RATE, BUCK1_RATE2, BUCK2_RATE2, BUCK3_RATE2, BUCK4_RATE2,
|
||||
BUCK5_RATE2, BUCK6_RATE2, BUCK7_RATE2, BUCK8_RATE2, BUCK9_RATE2,
|
||||
BUCK10_RATE2,
|
||||
F_MAX_FIELDS
|
||||
};
|
||||
|
||||
struct rk806_platform_data {
|
||||
int low_voltage_threshold;
|
||||
int shutdown_voltage_threshold;
|
||||
int force_shutdown_enable;
|
||||
int shutdown_temperture_threshold;
|
||||
int hotdie_temperture_threshold;
|
||||
};
|
||||
|
||||
struct rk806_pin_info {
|
||||
struct pinctrl *p;
|
||||
struct pinctrl_state *default_st;
|
||||
struct pinctrl_state *power_off;
|
||||
struct pinctrl_state *reset;
|
||||
struct pinctrl_state *sleep;
|
||||
struct pinctrl_state *dvs;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rk806 - state holder for the rk806 driver
|
||||
*
|
||||
* Device data may be used to access the rk806 chip
|
||||
*/
|
||||
struct rk806 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct regmap_field *rmap_fields[F_MAX_FIELDS];
|
||||
/* IRQ Data */
|
||||
int irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
struct rk806_platform_data *pdata;
|
||||
struct rk806_pin_info *pins;
|
||||
int vb_lo_irq;
|
||||
};
|
||||
|
||||
extern const struct regmap_config rk806_regmap_config_spi;
|
||||
int rk806_device_init(struct rk806 *rk806);
|
||||
int rk806_device_exit(struct rk806 *rk806);
|
||||
int rk806_field_write(struct rk806 *rk806,
|
||||
enum rk806_fields field_id,
|
||||
unsigned int val);
|
||||
int rk806_field_read(struct rk806 *rk806,
|
||||
enum rk806_fields field_id);
|
||||
#endif /* __LINUX_REGULATOR_RK806_H */
|
||||
Loading…
Reference in New Issue