1*162e2365SJoy Zou // SPDX-License-Identifier: GPL-2.0 2*162e2365SJoy Zou // Copyright 2025 NXP. 3*162e2365SJoy Zou // NXP PF0900 pmic driver 4*162e2365SJoy Zou 5*162e2365SJoy Zou #include <linux/bitfield.h> 6*162e2365SJoy Zou #include <linux/crc8.h> 7*162e2365SJoy Zou #include <linux/err.h> 8*162e2365SJoy Zou #include <linux/gpio/consumer.h> 9*162e2365SJoy Zou #include <linux/i2c.h> 10*162e2365SJoy Zou #include <linux/interrupt.h> 11*162e2365SJoy Zou #include <linux/kernel.h> 12*162e2365SJoy Zou #include <linux/module.h> 13*162e2365SJoy Zou #include <linux/of.h> 14*162e2365SJoy Zou #include <linux/of_device.h> 15*162e2365SJoy Zou #include <linux/platform_device.h> 16*162e2365SJoy Zou #include <linux/regmap.h> 17*162e2365SJoy Zou #include <linux/regulator/driver.h> 18*162e2365SJoy Zou #include <linux/regulator/machine.h> 19*162e2365SJoy Zou #include <linux/regulator/of_regulator.h> 20*162e2365SJoy Zou 21*162e2365SJoy Zou enum pf0900_regulators { 22*162e2365SJoy Zou PF0900_SW1 = 0, 23*162e2365SJoy Zou PF0900_SW2, 24*162e2365SJoy Zou PF0900_SW3, 25*162e2365SJoy Zou PF0900_SW4, 26*162e2365SJoy Zou PF0900_SW5, 27*162e2365SJoy Zou PF0900_LDO1, 28*162e2365SJoy Zou PF0900_LDO2, 29*162e2365SJoy Zou PF0900_LDO3, 30*162e2365SJoy Zou PF0900_VAON, 31*162e2365SJoy Zou PF0900_REGULATOR_CNT, 32*162e2365SJoy Zou }; 33*162e2365SJoy Zou 34*162e2365SJoy Zou enum { 35*162e2365SJoy Zou PF0900_DVS_LEVEL_RUN = 0, 36*162e2365SJoy Zou PF0900_DVS_LEVEL_STANDBY, 37*162e2365SJoy Zou PF0900_DVS_LEVEL_MAX, 38*162e2365SJoy Zou }; 39*162e2365SJoy Zou 40*162e2365SJoy Zou 41*162e2365SJoy Zou #define PF0900_VAON_VOLTAGE_NUM 0x03 42*162e2365SJoy Zou #define PF0900_SW_VOLTAGE_NUM 0x100 43*162e2365SJoy Zou #define PF0900_LDO_VOLTAGE_NUM 0x20 44*162e2365SJoy Zou 45*162e2365SJoy Zou #define REGU_SW_CNT 0x5 46*162e2365SJoy Zou #define REGU_LDO_VAON_CNT 0x4 47*162e2365SJoy Zou 48*162e2365SJoy Zou enum { 49*162e2365SJoy Zou PF0900_REG_DEV_ID = 0x00, 50*162e2365SJoy Zou PF0900_REG_DEV_FAM = 0x01, 51*162e2365SJoy Zou PF0900_REG_REV_ID = 0x02, 52*162e2365SJoy Zou PF0900_REG_PROG_ID1 = 0x03, 53*162e2365SJoy Zou PF0900_REG_PROG_ID2 = 0x04, 54*162e2365SJoy Zou PF0900_REG_SYSTEM_INT = 0x05, 55*162e2365SJoy Zou PF0900_REG_STATUS1_INT = 0x06, 56*162e2365SJoy Zou PF0900_REG_STATUS1_MSK = 0x07, 57*162e2365SJoy Zou PF0900_REG_STATUS1_SNS = 0x08, 58*162e2365SJoy Zou PF0900_REG_STATUS2_INT = 0x09, 59*162e2365SJoy Zou PF0900_REG_STATUS2_MSK = 0x0A, 60*162e2365SJoy Zou PF0900_REG_STATUS2_SNS = 0x0B, 61*162e2365SJoy Zou PF0900_REG_STATUS3_INT = 0x0C, 62*162e2365SJoy Zou PF0900_REG_STATUS3_MSK = 0x0D, 63*162e2365SJoy Zou PF0900_REG_SW_MODE_INT = 0x0E, 64*162e2365SJoy Zou PF0900_REG_SW_MODE_MSK = 0x0F, 65*162e2365SJoy Zou PF0900_REG_SW_ILIM_INT = 0x10, 66*162e2365SJoy Zou PF0900_REG_SW_ILIM_MSK = 0x11, 67*162e2365SJoy Zou PF0900_REG_SW_ILIM_SNS = 0x12, 68*162e2365SJoy Zou PF0900_REG_LDO_ILIM_INT = 0x13, 69*162e2365SJoy Zou PF0900_REG_LDO_ILIM_MSK = 0x14, 70*162e2365SJoy Zou PF0900_REG_LDO_ILIM_SNS = 0x15, 71*162e2365SJoy Zou PF0900_REG_SW_UV_INT = 0x16, 72*162e2365SJoy Zou PF0900_REG_SW_UV_MSK = 0x17, 73*162e2365SJoy Zou PF0900_REG_SW_UV_SNS = 0x18, 74*162e2365SJoy Zou PF0900_REG_SW_OV_INT = 0x19, 75*162e2365SJoy Zou PF0900_REG_SW_OV_MSK = 0x1A, 76*162e2365SJoy Zou PF0900_REG_SW_OV_SNS = 0x1B, 77*162e2365SJoy Zou PF0900_REG_LDO_UV_INT = 0x1C, 78*162e2365SJoy Zou PF0900_REG_LDO_UV_MSK = 0x1D, 79*162e2365SJoy Zou PF0900_REG_LDO_UV_SNS = 0x1E, 80*162e2365SJoy Zou PF0900_REG_LDO_OV_INT = 0x1F, 81*162e2365SJoy Zou PF0900_REG_LDO_OV_MSK = 0x20, 82*162e2365SJoy Zou PF0900_REG_LDO_OV_SNS = 0x21, 83*162e2365SJoy Zou PF0900_REG_PWRON_INT = 0x22, 84*162e2365SJoy Zou PF0900_REG_IO_INT = 0x24, 85*162e2365SJoy Zou PF0900_REG_IO_MSK = 0x25, 86*162e2365SJoy Zou PF0900_REG_IO_SNS = 0x26, 87*162e2365SJoy Zou PF0900_REG_IOSHORT_SNS = 0x27, 88*162e2365SJoy Zou PF0900_REG_ABIST_OV1 = 0x28, 89*162e2365SJoy Zou PF0900_REG_ABIST_OV2 = 0x29, 90*162e2365SJoy Zou PF0900_REG_ABIST_UV1 = 0x2A, 91*162e2365SJoy Zou PF0900_REG_ABIST_UV2 = 0x2B, 92*162e2365SJoy Zou PF0900_REG_ABIST_IO = 0x2C, 93*162e2365SJoy Zou PF0900_REG_TEST_FLAGS = 0x2D, 94*162e2365SJoy Zou PF0900_REG_HFAULT_FLAGS = 0x2E, 95*162e2365SJoy Zou PF0900_REG_FAULT_FLAGS = 0x2F, 96*162e2365SJoy Zou PF0900_REG_FS0B_CFG = 0x30, 97*162e2365SJoy Zou PF0900_REG_FCCU_CFG = 0x31, 98*162e2365SJoy Zou PF0900_REG_RSTB_CFG1 = 0x32, 99*162e2365SJoy Zou PF0900_REG_SYSTEM_CMD = 0x33, 100*162e2365SJoy Zou PF0900_REG_FS0B_CMD = 0x34, 101*162e2365SJoy Zou PF0900_REG_SECURE_WR1 = 0x35, 102*162e2365SJoy Zou PF0900_REG_SECURE_WR2 = 0x36, 103*162e2365SJoy Zou PF0900_REG_VMON_CFG1 = 0x37, 104*162e2365SJoy Zou PF0900_REG_SYS_CFG1 = 0x38, 105*162e2365SJoy Zou PF0900_REG_GPO_CFG = 0x39, 106*162e2365SJoy Zou PF0900_REG_GPO_CTRL = 0x3A, 107*162e2365SJoy Zou PF0900_REG_PWRUP_CFG = 0x3B, 108*162e2365SJoy Zou PF0900_REG_RSTB_PWRUP = 0x3C, 109*162e2365SJoy Zou PF0900_REG_GPIO1_PWRUP = 0x3D, 110*162e2365SJoy Zou PF0900_REG_GPIO2_PWRUP = 0x3E, 111*162e2365SJoy Zou PF0900_REG_GPIO3_PWRUP = 0x3F, 112*162e2365SJoy Zou PF0900_REG_GPIO4_PWRUP = 0x40, 113*162e2365SJoy Zou PF0900_REG_VMON1_PWRUP = 0x41, 114*162e2365SJoy Zou PF0900_REG_VMON2_PWRUP = 0x42, 115*162e2365SJoy Zou PF0900_REG_SW1_PWRUP = 0x43, 116*162e2365SJoy Zou PF0900_REG_SW2_PWRUP = 0x44, 117*162e2365SJoy Zou PF0900_REG_SW3_PWRUP = 0x45, 118*162e2365SJoy Zou PF0900_REG_SW4_PWRUP = 0x46, 119*162e2365SJoy Zou PF0900_REG_SW5_PWRUP = 0x47, 120*162e2365SJoy Zou PF0900_REG_LDO1_PWRUP = 0x48, 121*162e2365SJoy Zou PF0900_REG_LDO2_PWRUP = 0x49, 122*162e2365SJoy Zou PF0900_REG_LDO3_PWRUP = 0x4A, 123*162e2365SJoy Zou PF0900_REG_VAON_PWRUP = 0x4B, 124*162e2365SJoy Zou PF0900_REG_FREQ_CTRL = 0x4C, 125*162e2365SJoy Zou PF0900_REG_PWRON_CFG = 0x4D, 126*162e2365SJoy Zou PF0900_REG_WD_CTRL1 = 0x4E, 127*162e2365SJoy Zou PF0900_REG_WD_CTRL2 = 0x4F, 128*162e2365SJoy Zou PF0900_REG_WD_CFG1 = 0x50, 129*162e2365SJoy Zou PF0900_REG_WD_CFG2 = 0x51, 130*162e2365SJoy Zou PF0900_REG_WD_CNT1 = 0x52, 131*162e2365SJoy Zou PF0900_REG_WD_CNT2 = 0x53, 132*162e2365SJoy Zou PF0900_REG_FAULT_CFG = 0x54, 133*162e2365SJoy Zou PF0900_REG_FAULT_CNT = 0x55, 134*162e2365SJoy Zou PF0900_REG_DFS_CNT = 0x56, 135*162e2365SJoy Zou PF0900_REG_AMUX_CFG = 0x57, 136*162e2365SJoy Zou PF0900_REG_VMON1_RUN_CFG = 0x58, 137*162e2365SJoy Zou PF0900_REG_VMON1_STBY_CFG = 0x59, 138*162e2365SJoy Zou PF0900_REG_VMON1_CTRL = 0x5A, 139*162e2365SJoy Zou PF0900_REG_VMON2_RUN_CFG = 0x5B, 140*162e2365SJoy Zou PF0900_REG_VMON2_STBY_CFG = 0x5C, 141*162e2365SJoy Zou PF0900_REG_VMON2_CTRL = 0x5D, 142*162e2365SJoy Zou PF0900_REG_SW1_VRUN = 0x5E, 143*162e2365SJoy Zou PF0900_REG_SW1_VSTBY = 0x5F, 144*162e2365SJoy Zou PF0900_REG_SW1_MODE = 0x60, 145*162e2365SJoy Zou PF0900_REG_SW1_CFG1 = 0x61, 146*162e2365SJoy Zou PF0900_REG_SW1_CFG2 = 0x62, 147*162e2365SJoy Zou PF0900_REG_SW2_VRUN = 0x63, 148*162e2365SJoy Zou PF0900_REG_SW2_VSTBY = 0x64, 149*162e2365SJoy Zou PF0900_REG_SW2_MODE = 0x65, 150*162e2365SJoy Zou PF0900_REG_SW2_CFG1 = 0x66, 151*162e2365SJoy Zou PF0900_REG_SW2_CFG2 = 0x67, 152*162e2365SJoy Zou PF0900_REG_SW3_VRUN = 0x68, 153*162e2365SJoy Zou PF0900_REG_SW3_VSTBY = 0x69, 154*162e2365SJoy Zou PF0900_REG_SW3_MODE = 0x6A, 155*162e2365SJoy Zou PF0900_REG_SW3_CFG1 = 0x6B, 156*162e2365SJoy Zou PF0900_REG_SW3_CFG2 = 0x6C, 157*162e2365SJoy Zou PF0900_REG_SW4_VRUN = 0x6D, 158*162e2365SJoy Zou PF0900_REG_SW4_VSTBY = 0x6E, 159*162e2365SJoy Zou PF0900_REG_SW4_MODE = 0x6F, 160*162e2365SJoy Zou PF0900_REG_SW4_CFG1 = 0x70, 161*162e2365SJoy Zou PF0900_REG_SW4_CFG2 = 0x71, 162*162e2365SJoy Zou PF0900_REG_SW5_VRUN = 0x72, 163*162e2365SJoy Zou PF0900_REG_SW5_VSTBY = 0x73, 164*162e2365SJoy Zou PF0900_REG_SW5_MODE = 0x74, 165*162e2365SJoy Zou PF0900_REG_SW5_CFG1 = 0x75, 166*162e2365SJoy Zou PF0900_REG_SW5_CFG2 = 0x76, 167*162e2365SJoy Zou PF0900_REG_LDO1_RUN = 0x77, 168*162e2365SJoy Zou PF0900_REG_LDO1_STBY = 0x78, 169*162e2365SJoy Zou PF0900_REG_LDO1_CFG2 = 0x79, 170*162e2365SJoy Zou PF0900_REG_LDO2_RUN = 0x7A, 171*162e2365SJoy Zou PF0900_REG_LDO2_STBY = 0x7B, 172*162e2365SJoy Zou PF0900_REG_LDO2_CFG2 = 0x7C, 173*162e2365SJoy Zou PF0900_REG_LDO3_RUN = 0x7D, 174*162e2365SJoy Zou PF0900_REG_LDO3_STBY = 0x7E, 175*162e2365SJoy Zou PF0900_REG_LDO3_CFG2 = 0x7F, 176*162e2365SJoy Zou PF0900_REG_VAON_CFG1 = 0x80, 177*162e2365SJoy Zou PF0900_REG_VAON_CFG2 = 0x81, 178*162e2365SJoy Zou PF0900_REG_SYS_DIAG = 0x82, 179*162e2365SJoy Zou PF0900_MAX_REGISTER, 180*162e2365SJoy Zou }; 181*162e2365SJoy Zou 182*162e2365SJoy Zou /* PF0900 SW MODE */ 183*162e2365SJoy Zou #define SW_RUN_MODE_OFF 0x00 184*162e2365SJoy Zou #define SW_RUN_MODE_PWM 0x01 185*162e2365SJoy Zou #define SW_RUN_MODE_PFM 0x02 186*162e2365SJoy Zou #define SW_STBY_MODE_OFF 0x00 187*162e2365SJoy Zou #define SW_STBY_MODE_PWM 0x04 188*162e2365SJoy Zou #define SW_STBY_MODE_PFM 0x08 189*162e2365SJoy Zou 190*162e2365SJoy Zou /* PF0900 SW MODE MASK */ 191*162e2365SJoy Zou #define SW_RUN_MODE_MASK GENMASK(1, 0) 192*162e2365SJoy Zou #define SW_STBY_MODE_MASK GENMASK(3, 2) 193*162e2365SJoy Zou 194*162e2365SJoy Zou /* PF0900 SW VRUN/VSTBY MASK */ 195*162e2365SJoy Zou #define PF0900_SW_VOL_MASK GENMASK(7, 0) 196*162e2365SJoy Zou 197*162e2365SJoy Zou /* PF0900_REG_VAON_CFG1 bits */ 198*162e2365SJoy Zou #define PF0900_VAON_1P8V 0x01 199*162e2365SJoy Zou 200*162e2365SJoy Zou #define PF0900_VAON_MASK GENMASK(1, 0) 201*162e2365SJoy Zou 202*162e2365SJoy Zou /* PF0900_REG_SWX_CFG1 MASK */ 203*162e2365SJoy Zou #define PF0900_SW_DVS_MASK GENMASK(4, 3) 204*162e2365SJoy Zou 205*162e2365SJoy Zou /* PF0900_REG_LDO_RUN MASK */ 206*162e2365SJoy Zou #define VLDO_RUN_MASK GENMASK(4, 0) 207*162e2365SJoy Zou #define LDO_RUN_EN_MASK BIT(5) 208*162e2365SJoy Zou 209*162e2365SJoy Zou /* PF0900_REG_STATUS1_INT bits */ 210*162e2365SJoy Zou #define PF0900_IRQ_PWRUP BIT(3) 211*162e2365SJoy Zou 212*162e2365SJoy Zou /* PF0900_REG_ILIM_INT bits */ 213*162e2365SJoy Zou #define PF0900_IRQ_SW1_IL BIT(0) 214*162e2365SJoy Zou #define PF0900_IRQ_SW2_IL BIT(1) 215*162e2365SJoy Zou #define PF0900_IRQ_SW3_IL BIT(2) 216*162e2365SJoy Zou #define PF0900_IRQ_SW4_IL BIT(3) 217*162e2365SJoy Zou #define PF0900_IRQ_SW5_IL BIT(4) 218*162e2365SJoy Zou 219*162e2365SJoy Zou #define PF0900_IRQ_LDO1_IL BIT(0) 220*162e2365SJoy Zou #define PF0900_IRQ_LDO2_IL BIT(1) 221*162e2365SJoy Zou #define PF0900_IRQ_LDO3_IL BIT(2) 222*162e2365SJoy Zou 223*162e2365SJoy Zou /* PF0900_REG_UV_INT bits */ 224*162e2365SJoy Zou #define PF0900_IRQ_SW1_UV BIT(0) 225*162e2365SJoy Zou #define PF0900_IRQ_SW2_UV BIT(1) 226*162e2365SJoy Zou #define PF0900_IRQ_SW3_UV BIT(2) 227*162e2365SJoy Zou #define PF0900_IRQ_SW4_UV BIT(3) 228*162e2365SJoy Zou #define PF0900_IRQ_SW5_UV BIT(4) 229*162e2365SJoy Zou 230*162e2365SJoy Zou #define PF0900_IRQ_LDO1_UV BIT(0) 231*162e2365SJoy Zou #define PF0900_IRQ_LDO2_UV BIT(1) 232*162e2365SJoy Zou #define PF0900_IRQ_LDO3_UV BIT(2) 233*162e2365SJoy Zou #define PF0900_IRQ_VAON_UV BIT(3) 234*162e2365SJoy Zou 235*162e2365SJoy Zou /* PF0900_REG_OV_INT bits */ 236*162e2365SJoy Zou #define PF0900_IRQ_SW1_OV BIT(0) 237*162e2365SJoy Zou #define PF0900_IRQ_SW2_OV BIT(1) 238*162e2365SJoy Zou #define PF0900_IRQ_SW3_OV BIT(2) 239*162e2365SJoy Zou #define PF0900_IRQ_SW4_OV BIT(3) 240*162e2365SJoy Zou #define PF0900_IRQ_SW5_OV BIT(4) 241*162e2365SJoy Zou 242*162e2365SJoy Zou #define PF0900_IRQ_LDO1_OV BIT(0) 243*162e2365SJoy Zou #define PF0900_IRQ_LDO2_OV BIT(1) 244*162e2365SJoy Zou #define PF0900_IRQ_LDO3_OV BIT(2) 245*162e2365SJoy Zou #define PF0900_IRQ_VAON_OV BIT(3) 246*162e2365SJoy Zou 247*162e2365SJoy Zou struct pf0900_regulator_desc { 248*162e2365SJoy Zou struct regulator_desc desc; 249*162e2365SJoy Zou unsigned int suspend_enable_mask; 250*162e2365SJoy Zou unsigned int suspend_voltage_reg; 251*162e2365SJoy Zou unsigned int suspend_voltage_cache; 252*162e2365SJoy Zou }; 253*162e2365SJoy Zou 254*162e2365SJoy Zou struct pf0900_drvdata { 255*162e2365SJoy Zou const struct pf0900_regulator_desc *desc; 256*162e2365SJoy Zou unsigned int rcnt; 257*162e2365SJoy Zou }; 258*162e2365SJoy Zou 259*162e2365SJoy Zou struct pf0900 { 260*162e2365SJoy Zou struct device *dev; 261*162e2365SJoy Zou struct regmap *regmap; 262*162e2365SJoy Zou const struct pf0900_drvdata *drvdata; 263*162e2365SJoy Zou struct regulator_dev *rdevs[PF0900_REGULATOR_CNT]; 264*162e2365SJoy Zou int irq; 265*162e2365SJoy Zou unsigned short addr; 266*162e2365SJoy Zou bool crc_en; 267*162e2365SJoy Zou }; 268*162e2365SJoy Zou 269*162e2365SJoy Zou enum pf0900_regulator_type { 270*162e2365SJoy Zou PF0900_SW = 0, 271*162e2365SJoy Zou PF0900_LDO, 272*162e2365SJoy Zou }; 273*162e2365SJoy Zou 274*162e2365SJoy Zou #define PF0900_REGU_IRQ(_reg, _type, _event) \ 275*162e2365SJoy Zou { \ 276*162e2365SJoy Zou .reg = _reg, \ 277*162e2365SJoy Zou .type = _type, \ 278*162e2365SJoy Zou .event = _event, \ 279*162e2365SJoy Zou } 280*162e2365SJoy Zou 281*162e2365SJoy Zou struct pf0900_regulator_irq { 282*162e2365SJoy Zou unsigned int reg; 283*162e2365SJoy Zou unsigned int type; 284*162e2365SJoy Zou unsigned int event; 285*162e2365SJoy Zou }; 286*162e2365SJoy Zou 287*162e2365SJoy Zou static const struct regmap_range pf0900_range = { 288*162e2365SJoy Zou .range_min = PF0900_REG_DEV_ID, 289*162e2365SJoy Zou .range_max = PF0900_REG_SYS_DIAG, 290*162e2365SJoy Zou }; 291*162e2365SJoy Zou 292*162e2365SJoy Zou static const struct regmap_access_table pf0900_volatile_regs = { 293*162e2365SJoy Zou .yes_ranges = &pf0900_range, 294*162e2365SJoy Zou .n_yes_ranges = 1, 295*162e2365SJoy Zou }; 296*162e2365SJoy Zou 297*162e2365SJoy Zou static const struct regmap_config pf0900_regmap_config = { 298*162e2365SJoy Zou .reg_bits = 8, 299*162e2365SJoy Zou .val_bits = 8, 300*162e2365SJoy Zou .volatile_table = &pf0900_volatile_regs, 301*162e2365SJoy Zou .max_register = PF0900_MAX_REGISTER - 1, 302*162e2365SJoy Zou .cache_type = REGCACHE_MAPLE, 303*162e2365SJoy Zou }; 304*162e2365SJoy Zou 305*162e2365SJoy Zou static uint8_t crc8_j1850(unsigned short addr, unsigned int reg, 306*162e2365SJoy Zou unsigned int val) 307*162e2365SJoy Zou { 308*162e2365SJoy Zou uint8_t crcBuf[3]; 309*162e2365SJoy Zou uint8_t t_crc; 310*162e2365SJoy Zou uint8_t i, j; 311*162e2365SJoy Zou 312*162e2365SJoy Zou crcBuf[0] = addr; 313*162e2365SJoy Zou crcBuf[1] = reg; 314*162e2365SJoy Zou crcBuf[2] = val; 315*162e2365SJoy Zou t_crc = 0xFF; 316*162e2365SJoy Zou 317*162e2365SJoy Zou /* 318*162e2365SJoy Zou * The CRC calculation is based on the standard CRC-8-SAE as 319*162e2365SJoy Zou * defined in the SAE-J1850 specification with the following 320*162e2365SJoy Zou * characteristics. 321*162e2365SJoy Zou * Polynomial = 0x1D 322*162e2365SJoy Zou * Initial Value = 0xFF 323*162e2365SJoy Zou * The CRC byte is calculated by shifting 24-bit data through 324*162e2365SJoy Zou * the CRC polynomial.The 24-bits package is built as follows: 325*162e2365SJoy Zou * DEVICE_ADDR[b8] + REGISTER_ADDR [b8] +DATA[b8] 326*162e2365SJoy Zou * The DEVICE_ADDR is calculated as the 7-bit slave address 327*162e2365SJoy Zou * shifted left one space plus the corresponding read/write bit. 328*162e2365SJoy Zou * (7Bit Address [b7] << 1 ) + R/W = DEVICE_ADDR[b8] 329*162e2365SJoy Zou */ 330*162e2365SJoy Zou for (i = 0; i < sizeof(crcBuf); i++) { 331*162e2365SJoy Zou t_crc ^= crcBuf[i]; 332*162e2365SJoy Zou for (j = 0; j < 8; j++) { 333*162e2365SJoy Zou if ((t_crc & 0x80) != 0) { 334*162e2365SJoy Zou t_crc <<= 1; 335*162e2365SJoy Zou t_crc ^= 0x1D; 336*162e2365SJoy Zou } else { 337*162e2365SJoy Zou t_crc <<= 1; 338*162e2365SJoy Zou } 339*162e2365SJoy Zou } 340*162e2365SJoy Zou } 341*162e2365SJoy Zou 342*162e2365SJoy Zou return t_crc; 343*162e2365SJoy Zou } 344*162e2365SJoy Zou 345*162e2365SJoy Zou static int pf0900_regmap_read(void *context, unsigned int reg, 346*162e2365SJoy Zou unsigned int *val) 347*162e2365SJoy Zou { 348*162e2365SJoy Zou struct device *dev = context; 349*162e2365SJoy Zou struct i2c_client *i2c = to_i2c_client(dev); 350*162e2365SJoy Zou struct pf0900 *pf0900 = dev_get_drvdata(dev); 351*162e2365SJoy Zou int ret; 352*162e2365SJoy Zou u8 crc; 353*162e2365SJoy Zou 354*162e2365SJoy Zou if (!pf0900 || !pf0900->dev) 355*162e2365SJoy Zou return -EINVAL; 356*162e2365SJoy Zou 357*162e2365SJoy Zou if (reg >= PF0900_MAX_REGISTER) { 358*162e2365SJoy Zou dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg); 359*162e2365SJoy Zou return -EINVAL; 360*162e2365SJoy Zou } 361*162e2365SJoy Zou 362*162e2365SJoy Zou if (pf0900->crc_en) { 363*162e2365SJoy Zou ret = i2c_smbus_read_word_data(i2c, reg); 364*162e2365SJoy Zou if (ret < 0) { 365*162e2365SJoy Zou dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret); 366*162e2365SJoy Zou return ret; 367*162e2365SJoy Zou } 368*162e2365SJoy Zou 369*162e2365SJoy Zou *val = (u16)ret; 370*162e2365SJoy Zou crc = crc8_j1850(pf0900->addr << 1 | 0x1, reg, FIELD_GET(GENMASK(7, 0), *val)); 371*162e2365SJoy Zou if (crc != FIELD_GET(GENMASK(15, 8), *val)) { 372*162e2365SJoy Zou dev_err(pf0900->dev, "Crc check error!\n"); 373*162e2365SJoy Zou return -EINVAL; 374*162e2365SJoy Zou } 375*162e2365SJoy Zou *val = FIELD_GET(GENMASK(7, 0), *val); 376*162e2365SJoy Zou } else { 377*162e2365SJoy Zou ret = i2c_smbus_read_byte_data(i2c, reg); 378*162e2365SJoy Zou if (ret < 0) { 379*162e2365SJoy Zou dev_err(pf0900->dev, "Read error at reg=0x%x: %d\n", reg, ret); 380*162e2365SJoy Zou return ret; 381*162e2365SJoy Zou } 382*162e2365SJoy Zou *val = ret; 383*162e2365SJoy Zou } 384*162e2365SJoy Zou 385*162e2365SJoy Zou return 0; 386*162e2365SJoy Zou } 387*162e2365SJoy Zou 388*162e2365SJoy Zou static int pf0900_regmap_write(void *context, unsigned int reg, 389*162e2365SJoy Zou unsigned int val) 390*162e2365SJoy Zou { 391*162e2365SJoy Zou struct device *dev = context; 392*162e2365SJoy Zou struct i2c_client *i2c = to_i2c_client(dev); 393*162e2365SJoy Zou struct pf0900 *pf0900 = dev_get_drvdata(dev); 394*162e2365SJoy Zou uint8_t data[2]; 395*162e2365SJoy Zou int ret; 396*162e2365SJoy Zou 397*162e2365SJoy Zou if (!pf0900 || !pf0900->dev) 398*162e2365SJoy Zou return -EINVAL; 399*162e2365SJoy Zou 400*162e2365SJoy Zou if (reg >= PF0900_MAX_REGISTER) { 401*162e2365SJoy Zou dev_err(pf0900->dev, "Invalid register address: 0x%x\n", reg); 402*162e2365SJoy Zou return -EINVAL; 403*162e2365SJoy Zou } 404*162e2365SJoy Zou 405*162e2365SJoy Zou data[0] = val; 406*162e2365SJoy Zou if (pf0900->crc_en) { 407*162e2365SJoy Zou /* Get CRC */ 408*162e2365SJoy Zou data[1] = crc8_j1850(pf0900->addr << 1, reg, data[0]); 409*162e2365SJoy Zou val = FIELD_PREP(GENMASK(15, 8), data[1]) | data[0]; 410*162e2365SJoy Zou ret = i2c_smbus_write_word_data(i2c, reg, val); 411*162e2365SJoy Zou } else { 412*162e2365SJoy Zou ret = i2c_smbus_write_byte_data(i2c, reg, data[0]); 413*162e2365SJoy Zou } 414*162e2365SJoy Zou 415*162e2365SJoy Zou if (ret) { 416*162e2365SJoy Zou dev_err(pf0900->dev, "Write reg=0x%x error!\n", reg); 417*162e2365SJoy Zou return ret; 418*162e2365SJoy Zou } 419*162e2365SJoy Zou 420*162e2365SJoy Zou return 0; 421*162e2365SJoy Zou } 422*162e2365SJoy Zou 423*162e2365SJoy Zou static int pf0900_suspend_enable(struct regulator_dev *rdev) 424*162e2365SJoy Zou { 425*162e2365SJoy Zou struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev); 426*162e2365SJoy Zou struct regmap *rmap = rdev_get_regmap(rdev); 427*162e2365SJoy Zou 428*162e2365SJoy Zou return regmap_update_bits(rmap, rdata->desc.enable_reg, 429*162e2365SJoy Zou rdata->suspend_enable_mask, SW_STBY_MODE_PFM); 430*162e2365SJoy Zou } 431*162e2365SJoy Zou 432*162e2365SJoy Zou static int pf0900_suspend_disable(struct regulator_dev *rdev) 433*162e2365SJoy Zou { 434*162e2365SJoy Zou struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev); 435*162e2365SJoy Zou struct regmap *rmap = rdev_get_regmap(rdev); 436*162e2365SJoy Zou 437*162e2365SJoy Zou return regmap_update_bits(rmap, rdata->desc.enable_reg, 438*162e2365SJoy Zou rdata->suspend_enable_mask, SW_STBY_MODE_OFF); 439*162e2365SJoy Zou } 440*162e2365SJoy Zou 441*162e2365SJoy Zou static int pf0900_set_suspend_voltage(struct regulator_dev *rdev, int uV) 442*162e2365SJoy Zou { 443*162e2365SJoy Zou struct pf0900_regulator_desc *rdata = rdev_get_drvdata(rdev); 444*162e2365SJoy Zou struct regmap *rmap = rdev_get_regmap(rdev); 445*162e2365SJoy Zou int ret; 446*162e2365SJoy Zou 447*162e2365SJoy Zou if (rdata->suspend_voltage_cache == uV) 448*162e2365SJoy Zou return 0; 449*162e2365SJoy Zou 450*162e2365SJoy Zou ret = regulator_map_voltage_iterate(rdev, uV, uV); 451*162e2365SJoy Zou if (ret < 0) { 452*162e2365SJoy Zou dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV); 453*162e2365SJoy Zou return ret; 454*162e2365SJoy Zou } 455*162e2365SJoy Zou 456*162e2365SJoy Zou dev_dbg(rdev_get_dev(rdev), "uV: %i, reg: 0x%x, msk: 0x%x, val: 0x%x\n", 457*162e2365SJoy Zou uV, rdata->suspend_voltage_reg, rdata->desc.vsel_mask, ret); 458*162e2365SJoy Zou ret = regmap_update_bits(rmap, rdata->suspend_voltage_reg, 459*162e2365SJoy Zou rdata->desc.vsel_mask, ret); 460*162e2365SJoy Zou if (ret < 0) { 461*162e2365SJoy Zou dev_err(rdev_get_dev(rdev), "failed to set %i uV\n", uV); 462*162e2365SJoy Zou return ret; 463*162e2365SJoy Zou } 464*162e2365SJoy Zou 465*162e2365SJoy Zou rdata->suspend_voltage_cache = uV; 466*162e2365SJoy Zou 467*162e2365SJoy Zou return 0; 468*162e2365SJoy Zou } 469*162e2365SJoy Zou 470*162e2365SJoy Zou static const struct regmap_bus pf0900_regmap_bus = { 471*162e2365SJoy Zou .reg_read = pf0900_regmap_read, 472*162e2365SJoy Zou .reg_write = pf0900_regmap_write, 473*162e2365SJoy Zou }; 474*162e2365SJoy Zou 475*162e2365SJoy Zou static const struct regulator_ops pf0900_avon_regulator_ops = { 476*162e2365SJoy Zou .list_voltage = regulator_list_voltage_table, 477*162e2365SJoy Zou .set_voltage_sel = regulator_set_voltage_sel_regmap, 478*162e2365SJoy Zou .get_voltage_sel = regulator_get_voltage_sel_regmap, 479*162e2365SJoy Zou }; 480*162e2365SJoy Zou 481*162e2365SJoy Zou static const struct regulator_ops pf0900_dvs_sw_regulator_ops = { 482*162e2365SJoy Zou .enable = regulator_enable_regmap, 483*162e2365SJoy Zou .disable = regulator_disable_regmap, 484*162e2365SJoy Zou .is_enabled = regulator_is_enabled_regmap, 485*162e2365SJoy Zou .list_voltage = regulator_list_voltage_linear_range, 486*162e2365SJoy Zou .set_voltage_sel = regulator_set_voltage_sel_regmap, 487*162e2365SJoy Zou .get_voltage_sel = regulator_get_voltage_sel_regmap, 488*162e2365SJoy Zou .set_voltage_time_sel = regulator_set_voltage_time_sel, 489*162e2365SJoy Zou .set_ramp_delay = regulator_set_ramp_delay_regmap, 490*162e2365SJoy Zou .set_suspend_enable = pf0900_suspend_enable, 491*162e2365SJoy Zou .set_suspend_disable = pf0900_suspend_disable, 492*162e2365SJoy Zou .set_suspend_voltage = pf0900_set_suspend_voltage, 493*162e2365SJoy Zou }; 494*162e2365SJoy Zou 495*162e2365SJoy Zou static const struct regulator_ops pf0900_ldo_regulator_ops = { 496*162e2365SJoy Zou .enable = regulator_enable_regmap, 497*162e2365SJoy Zou .disable = regulator_disable_regmap, 498*162e2365SJoy Zou .is_enabled = regulator_is_enabled_regmap, 499*162e2365SJoy Zou .list_voltage = regulator_list_voltage_linear_range, 500*162e2365SJoy Zou .set_voltage_sel = regulator_set_voltage_sel_regmap, 501*162e2365SJoy Zou .get_voltage_sel = regulator_get_voltage_sel_regmap, 502*162e2365SJoy Zou }; 503*162e2365SJoy Zou 504*162e2365SJoy Zou /* 505*162e2365SJoy Zou * SW1/2/3/4/5 506*162e2365SJoy Zou * SW1_DVS[1:0] SW1 DVS ramp rate setting 507*162e2365SJoy Zou * 00: 15.6mV/8usec 508*162e2365SJoy Zou * 01: 15.6mV/4usec 509*162e2365SJoy Zou * 10: 15.6mV/2usec 510*162e2365SJoy Zou * 11: 15.6mV/1usec 511*162e2365SJoy Zou */ 512*162e2365SJoy Zou static const unsigned int pf0900_dvs_sw_ramp_table[] = { 513*162e2365SJoy Zou 1950, 3900, 7800, 15600 514*162e2365SJoy Zou }; 515*162e2365SJoy Zou 516*162e2365SJoy Zou /* VAON 1.8V, 3.0V, or 3.3V */ 517*162e2365SJoy Zou static const int pf0900_vaon_voltages[] = { 518*162e2365SJoy Zou 0, 1800000, 3000000, 3300000, 519*162e2365SJoy Zou }; 520*162e2365SJoy Zou 521*162e2365SJoy Zou /* 522*162e2365SJoy Zou * SW1 0.5V to 3.3V 523*162e2365SJoy Zou * 0.5V to 1.35V (6.25mV step) 524*162e2365SJoy Zou * 1.8V to 2.5V (125mV step) 525*162e2365SJoy Zou * 2.8V to 3.3V (250mV step) 526*162e2365SJoy Zou */ 527*162e2365SJoy Zou static const struct linear_range pf0900_dvs_sw1_volts[] = { 528*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0x00, 0x08, 0), 529*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(500000, 0x09, 0x91, 6250), 530*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0x92, 0x9E, 0), 531*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1500000, 0x9F, 0x9F, 0), 532*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1800000, 0xA0, 0xD8, 12500), 533*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0xD9, 0xDF, 0), 534*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(2800000, 0xE0, 0xF4, 25000), 535*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0xF5, 0xFF, 0), 536*162e2365SJoy Zou }; 537*162e2365SJoy Zou 538*162e2365SJoy Zou /* 539*162e2365SJoy Zou * SW2/3/4/5 0.3V to 3.3V 540*162e2365SJoy Zou * 0.45V to 1.35V (6.25mV step) 541*162e2365SJoy Zou * 1.8V to 2.5V (125mV step) 542*162e2365SJoy Zou * 2.8V to 3.3V (250mV step) 543*162e2365SJoy Zou */ 544*162e2365SJoy Zou static const struct linear_range pf0900_dvs_sw2345_volts[] = { 545*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(300000, 0x00, 0x00, 0), 546*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(450000, 0x01, 0x91, 6250), 547*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0x92, 0x9E, 0), 548*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1500000, 0x9F, 0x9F, 0), 549*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1800000, 0xA0, 0xD8, 12500), 550*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0xD9, 0xDF, 0), 551*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(2800000, 0xE0, 0xF4, 25000), 552*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(0, 0xF5, 0xFF, 0), 553*162e2365SJoy Zou }; 554*162e2365SJoy Zou 555*162e2365SJoy Zou /* 556*162e2365SJoy Zou * LDO1 557*162e2365SJoy Zou * 0.75V to 3.3V 558*162e2365SJoy Zou */ 559*162e2365SJoy Zou static const struct linear_range pf0900_ldo1_volts[] = { 560*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(750000, 0x00, 0x0F, 50000), 561*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1F, 100000), 562*162e2365SJoy Zou }; 563*162e2365SJoy Zou 564*162e2365SJoy Zou /* 565*162e2365SJoy Zou * LDO2/3 566*162e2365SJoy Zou * 0.65V to 3.3V (50mV step) 567*162e2365SJoy Zou */ 568*162e2365SJoy Zou static const struct linear_range pf0900_ldo23_volts[] = { 569*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(650000, 0x00, 0x0D, 50000), 570*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1400000, 0x0E, 0x0F, 100000), 571*162e2365SJoy Zou REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1F, 100000), 572*162e2365SJoy Zou }; 573*162e2365SJoy Zou 574*162e2365SJoy Zou static const struct pf0900_regulator_desc pf0900_regulators[] = { 575*162e2365SJoy Zou { 576*162e2365SJoy Zou .desc = { 577*162e2365SJoy Zou .name = "sw1", 578*162e2365SJoy Zou .of_match = of_match_ptr("sw1"), 579*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 580*162e2365SJoy Zou .id = PF0900_SW1, 581*162e2365SJoy Zou .ops = &pf0900_dvs_sw_regulator_ops, 582*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 583*162e2365SJoy Zou .n_voltages = PF0900_SW_VOLTAGE_NUM, 584*162e2365SJoy Zou .linear_ranges = pf0900_dvs_sw1_volts, 585*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw1_volts), 586*162e2365SJoy Zou .vsel_reg = PF0900_REG_SW1_VRUN, 587*162e2365SJoy Zou .vsel_mask = PF0900_SW_VOL_MASK, 588*162e2365SJoy Zou .enable_reg = PF0900_REG_SW1_MODE, 589*162e2365SJoy Zou .enable_mask = SW_RUN_MODE_MASK, 590*162e2365SJoy Zou .enable_val = SW_RUN_MODE_PWM, 591*162e2365SJoy Zou .ramp_reg = PF0900_REG_SW1_CFG1, 592*162e2365SJoy Zou .ramp_mask = PF0900_SW_DVS_MASK, 593*162e2365SJoy Zou .ramp_delay_table = pf0900_dvs_sw_ramp_table, 594*162e2365SJoy Zou .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table), 595*162e2365SJoy Zou .owner = THIS_MODULE, 596*162e2365SJoy Zou }, 597*162e2365SJoy Zou .suspend_enable_mask = SW_STBY_MODE_MASK, 598*162e2365SJoy Zou .suspend_voltage_reg = PF0900_REG_SW1_VSTBY, 599*162e2365SJoy Zou }, 600*162e2365SJoy Zou { 601*162e2365SJoy Zou .desc = { 602*162e2365SJoy Zou .name = "sw2", 603*162e2365SJoy Zou .of_match = of_match_ptr("sw2"), 604*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 605*162e2365SJoy Zou .id = PF0900_SW2, 606*162e2365SJoy Zou .ops = &pf0900_dvs_sw_regulator_ops, 607*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 608*162e2365SJoy Zou .n_voltages = PF0900_SW_VOLTAGE_NUM, 609*162e2365SJoy Zou .linear_ranges = pf0900_dvs_sw2345_volts, 610*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts), 611*162e2365SJoy Zou .vsel_reg = PF0900_REG_SW2_VRUN, 612*162e2365SJoy Zou .vsel_mask = PF0900_SW_VOL_MASK, 613*162e2365SJoy Zou .enable_reg = PF0900_REG_SW2_MODE, 614*162e2365SJoy Zou .enable_mask = SW_RUN_MODE_MASK, 615*162e2365SJoy Zou .enable_val = SW_RUN_MODE_PWM, 616*162e2365SJoy Zou .ramp_reg = PF0900_REG_SW2_CFG1, 617*162e2365SJoy Zou .ramp_mask = PF0900_SW_DVS_MASK, 618*162e2365SJoy Zou .ramp_delay_table = pf0900_dvs_sw_ramp_table, 619*162e2365SJoy Zou .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table), 620*162e2365SJoy Zou .owner = THIS_MODULE, 621*162e2365SJoy Zou }, 622*162e2365SJoy Zou .suspend_enable_mask = SW_STBY_MODE_MASK, 623*162e2365SJoy Zou .suspend_voltage_reg = PF0900_REG_SW2_VSTBY, 624*162e2365SJoy Zou }, 625*162e2365SJoy Zou { 626*162e2365SJoy Zou .desc = { 627*162e2365SJoy Zou .name = "sw3", 628*162e2365SJoy Zou .of_match = of_match_ptr("sw3"), 629*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 630*162e2365SJoy Zou .id = PF0900_SW3, 631*162e2365SJoy Zou .ops = &pf0900_dvs_sw_regulator_ops, 632*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 633*162e2365SJoy Zou .n_voltages = PF0900_SW_VOLTAGE_NUM, 634*162e2365SJoy Zou .linear_ranges = pf0900_dvs_sw2345_volts, 635*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts), 636*162e2365SJoy Zou .vsel_reg = PF0900_REG_SW3_VRUN, 637*162e2365SJoy Zou .vsel_mask = PF0900_SW_VOL_MASK, 638*162e2365SJoy Zou .enable_reg = PF0900_REG_SW3_MODE, 639*162e2365SJoy Zou .enable_mask = SW_RUN_MODE_MASK, 640*162e2365SJoy Zou .enable_val = SW_RUN_MODE_PWM, 641*162e2365SJoy Zou .ramp_reg = PF0900_REG_SW3_CFG1, 642*162e2365SJoy Zou .ramp_mask = PF0900_SW_DVS_MASK, 643*162e2365SJoy Zou .ramp_delay_table = pf0900_dvs_sw_ramp_table, 644*162e2365SJoy Zou .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table), 645*162e2365SJoy Zou .owner = THIS_MODULE, 646*162e2365SJoy Zou }, 647*162e2365SJoy Zou .suspend_enable_mask = SW_STBY_MODE_MASK, 648*162e2365SJoy Zou .suspend_voltage_reg = PF0900_REG_SW3_VSTBY, 649*162e2365SJoy Zou }, 650*162e2365SJoy Zou { 651*162e2365SJoy Zou .desc = { 652*162e2365SJoy Zou .name = "sw4", 653*162e2365SJoy Zou .of_match = of_match_ptr("sw4"), 654*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 655*162e2365SJoy Zou .id = PF0900_SW4, 656*162e2365SJoy Zou .ops = &pf0900_dvs_sw_regulator_ops, 657*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 658*162e2365SJoy Zou .n_voltages = PF0900_SW_VOLTAGE_NUM, 659*162e2365SJoy Zou .linear_ranges = pf0900_dvs_sw2345_volts, 660*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts), 661*162e2365SJoy Zou .vsel_reg = PF0900_REG_SW4_VRUN, 662*162e2365SJoy Zou .vsel_mask = PF0900_SW_VOL_MASK, 663*162e2365SJoy Zou .enable_reg = PF0900_REG_SW4_MODE, 664*162e2365SJoy Zou .enable_mask = SW_RUN_MODE_MASK, 665*162e2365SJoy Zou .enable_val = SW_RUN_MODE_PWM, 666*162e2365SJoy Zou .ramp_reg = PF0900_REG_SW4_CFG1, 667*162e2365SJoy Zou .ramp_mask = PF0900_SW_DVS_MASK, 668*162e2365SJoy Zou .ramp_delay_table = pf0900_dvs_sw_ramp_table, 669*162e2365SJoy Zou .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table), 670*162e2365SJoy Zou .owner = THIS_MODULE, 671*162e2365SJoy Zou }, 672*162e2365SJoy Zou .suspend_enable_mask = SW_STBY_MODE_MASK, 673*162e2365SJoy Zou .suspend_voltage_reg = PF0900_REG_SW4_VSTBY, 674*162e2365SJoy Zou }, 675*162e2365SJoy Zou { 676*162e2365SJoy Zou .desc = { 677*162e2365SJoy Zou .name = "sw5", 678*162e2365SJoy Zou .of_match = of_match_ptr("sw5"), 679*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 680*162e2365SJoy Zou .id = PF0900_SW5, 681*162e2365SJoy Zou .ops = &pf0900_dvs_sw_regulator_ops, 682*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 683*162e2365SJoy Zou .n_voltages = PF0900_SW_VOLTAGE_NUM, 684*162e2365SJoy Zou .linear_ranges = pf0900_dvs_sw2345_volts, 685*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_dvs_sw2345_volts), 686*162e2365SJoy Zou .vsel_reg = PF0900_REG_SW5_VRUN, 687*162e2365SJoy Zou .vsel_mask = PF0900_SW_VOL_MASK, 688*162e2365SJoy Zou .enable_reg = PF0900_REG_SW5_MODE, 689*162e2365SJoy Zou .enable_mask = SW_RUN_MODE_MASK, 690*162e2365SJoy Zou .enable_val = SW_RUN_MODE_PWM, 691*162e2365SJoy Zou .ramp_reg = PF0900_REG_SW5_CFG1, 692*162e2365SJoy Zou .ramp_mask = PF0900_SW_DVS_MASK, 693*162e2365SJoy Zou .ramp_delay_table = pf0900_dvs_sw_ramp_table, 694*162e2365SJoy Zou .n_ramp_values = ARRAY_SIZE(pf0900_dvs_sw_ramp_table), 695*162e2365SJoy Zou .owner = THIS_MODULE, 696*162e2365SJoy Zou }, 697*162e2365SJoy Zou .suspend_enable_mask = SW_STBY_MODE_MASK, 698*162e2365SJoy Zou .suspend_voltage_reg = PF0900_REG_SW5_VSTBY, 699*162e2365SJoy Zou }, 700*162e2365SJoy Zou { 701*162e2365SJoy Zou .desc = { 702*162e2365SJoy Zou .name = "ldo1", 703*162e2365SJoy Zou .of_match = of_match_ptr("ldo1"), 704*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 705*162e2365SJoy Zou .id = PF0900_LDO1, 706*162e2365SJoy Zou .ops = &pf0900_ldo_regulator_ops, 707*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 708*162e2365SJoy Zou .n_voltages = PF0900_LDO_VOLTAGE_NUM, 709*162e2365SJoy Zou .linear_ranges = pf0900_ldo1_volts, 710*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_ldo1_volts), 711*162e2365SJoy Zou .vsel_reg = PF0900_REG_LDO1_RUN, 712*162e2365SJoy Zou .vsel_mask = VLDO_RUN_MASK, 713*162e2365SJoy Zou .enable_reg = PF0900_REG_LDO1_RUN, 714*162e2365SJoy Zou .enable_mask = LDO_RUN_EN_MASK, 715*162e2365SJoy Zou .owner = THIS_MODULE, 716*162e2365SJoy Zou }, 717*162e2365SJoy Zou }, 718*162e2365SJoy Zou { 719*162e2365SJoy Zou .desc = { 720*162e2365SJoy Zou .name = "ldo2", 721*162e2365SJoy Zou .of_match = of_match_ptr("ldo2"), 722*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 723*162e2365SJoy Zou .id = PF0900_LDO2, 724*162e2365SJoy Zou .ops = &pf0900_ldo_regulator_ops, 725*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 726*162e2365SJoy Zou .n_voltages = PF0900_LDO_VOLTAGE_NUM, 727*162e2365SJoy Zou .linear_ranges = pf0900_ldo23_volts, 728*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts), 729*162e2365SJoy Zou .vsel_reg = PF0900_REG_LDO2_RUN, 730*162e2365SJoy Zou .vsel_mask = VLDO_RUN_MASK, 731*162e2365SJoy Zou .enable_reg = PF0900_REG_LDO2_RUN, 732*162e2365SJoy Zou .enable_mask = LDO_RUN_EN_MASK, 733*162e2365SJoy Zou .owner = THIS_MODULE, 734*162e2365SJoy Zou }, 735*162e2365SJoy Zou }, 736*162e2365SJoy Zou { 737*162e2365SJoy Zou .desc = { 738*162e2365SJoy Zou .name = "ldo3", 739*162e2365SJoy Zou .of_match = of_match_ptr("ldo3"), 740*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 741*162e2365SJoy Zou .id = PF0900_LDO3, 742*162e2365SJoy Zou .ops = &pf0900_ldo_regulator_ops, 743*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 744*162e2365SJoy Zou .n_voltages = PF0900_LDO_VOLTAGE_NUM, 745*162e2365SJoy Zou .linear_ranges = pf0900_ldo23_volts, 746*162e2365SJoy Zou .n_linear_ranges = ARRAY_SIZE(pf0900_ldo23_volts), 747*162e2365SJoy Zou .vsel_reg = PF0900_REG_LDO3_RUN, 748*162e2365SJoy Zou .vsel_mask = VLDO_RUN_MASK, 749*162e2365SJoy Zou .enable_reg = PF0900_REG_LDO3_RUN, 750*162e2365SJoy Zou .enable_mask = LDO_RUN_EN_MASK, 751*162e2365SJoy Zou .owner = THIS_MODULE, 752*162e2365SJoy Zou }, 753*162e2365SJoy Zou }, 754*162e2365SJoy Zou { 755*162e2365SJoy Zou .desc = { 756*162e2365SJoy Zou .name = "vaon", 757*162e2365SJoy Zou .of_match = of_match_ptr("vaon"), 758*162e2365SJoy Zou .regulators_node = of_match_ptr("regulators"), 759*162e2365SJoy Zou .id = PF0900_VAON, 760*162e2365SJoy Zou .ops = &pf0900_avon_regulator_ops, 761*162e2365SJoy Zou .type = REGULATOR_VOLTAGE, 762*162e2365SJoy Zou .n_voltages = PF0900_VAON_VOLTAGE_NUM, 763*162e2365SJoy Zou .volt_table = pf0900_vaon_voltages, 764*162e2365SJoy Zou .enable_reg = PF0900_REG_VAON_CFG1, 765*162e2365SJoy Zou .enable_mask = PF0900_VAON_MASK, 766*162e2365SJoy Zou .enable_val = PF0900_VAON_1P8V, 767*162e2365SJoy Zou .vsel_reg = PF0900_REG_VAON_CFG1, 768*162e2365SJoy Zou .vsel_mask = PF0900_VAON_MASK, 769*162e2365SJoy Zou .owner = THIS_MODULE, 770*162e2365SJoy Zou }, 771*162e2365SJoy Zou }, 772*162e2365SJoy Zou }; 773*162e2365SJoy Zou 774*162e2365SJoy Zou struct pf0900_regulator_irq regu_irqs[] = { 775*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_SW_ILIM_INT, PF0900_SW, REGULATOR_ERROR_OVER_CURRENT_WARN), 776*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_LDO_ILIM_INT, PF0900_LDO, REGULATOR_ERROR_OVER_CURRENT_WARN), 777*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_SW_UV_INT, PF0900_SW, REGULATOR_ERROR_UNDER_VOLTAGE_WARN), 778*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_LDO_UV_INT, PF0900_LDO, REGULATOR_ERROR_UNDER_VOLTAGE_WARN), 779*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_SW_OV_INT, PF0900_SW, REGULATOR_ERROR_OVER_VOLTAGE_WARN), 780*162e2365SJoy Zou PF0900_REGU_IRQ(PF0900_REG_LDO_OV_INT, PF0900_LDO, REGULATOR_ERROR_OVER_VOLTAGE_WARN), 781*162e2365SJoy Zou }; 782*162e2365SJoy Zou 783*162e2365SJoy Zou static irqreturn_t pf0900_irq_handler(int irq, void *data) 784*162e2365SJoy Zou { 785*162e2365SJoy Zou unsigned int val, regu, i, index; 786*162e2365SJoy Zou struct pf0900 *pf0900 = data; 787*162e2365SJoy Zou int ret; 788*162e2365SJoy Zou 789*162e2365SJoy Zou for (i = 0; i < ARRAY_SIZE(regu_irqs); i++) { 790*162e2365SJoy Zou ret = regmap_read(pf0900->regmap, regu_irqs[i].reg, &val); 791*162e2365SJoy Zou if (ret < 0) { 792*162e2365SJoy Zou dev_err(pf0900->dev, "Failed to read %d\n", ret); 793*162e2365SJoy Zou return IRQ_NONE; 794*162e2365SJoy Zou } 795*162e2365SJoy Zou if (val) { 796*162e2365SJoy Zou ret = regmap_write_bits(pf0900->regmap, regu_irqs[i].reg, val, val); 797*162e2365SJoy Zou if (ret < 0) { 798*162e2365SJoy Zou dev_err(pf0900->dev, "Failed to update %d\n", ret); 799*162e2365SJoy Zou return IRQ_NONE; 800*162e2365SJoy Zou } 801*162e2365SJoy Zou 802*162e2365SJoy Zou if (regu_irqs[i].type == PF0900_SW) { 803*162e2365SJoy Zou for (index = 0; index < REGU_SW_CNT; index++) { 804*162e2365SJoy Zou if (val & BIT(index)) { 805*162e2365SJoy Zou regu = (enum pf0900_regulators)index; 806*162e2365SJoy Zou regulator_notifier_call_chain(pf0900->rdevs[regu], 807*162e2365SJoy Zou regu_irqs[i].event, 808*162e2365SJoy Zou NULL); 809*162e2365SJoy Zou } 810*162e2365SJoy Zou } 811*162e2365SJoy Zou } else if (regu_irqs[i].type == PF0900_LDO) { 812*162e2365SJoy Zou for (index = 0; index < REGU_LDO_VAON_CNT; index++) { 813*162e2365SJoy Zou if (val & BIT(index)) { 814*162e2365SJoy Zou regu = (enum pf0900_regulators)index + PF0900_LDO1; 815*162e2365SJoy Zou regulator_notifier_call_chain(pf0900->rdevs[regu], 816*162e2365SJoy Zou regu_irqs[i].event, 817*162e2365SJoy Zou NULL); 818*162e2365SJoy Zou } 819*162e2365SJoy Zou } 820*162e2365SJoy Zou } 821*162e2365SJoy Zou } 822*162e2365SJoy Zou } 823*162e2365SJoy Zou 824*162e2365SJoy Zou return IRQ_HANDLED; 825*162e2365SJoy Zou } 826*162e2365SJoy Zou 827*162e2365SJoy Zou static int pf0900_i2c_probe(struct i2c_client *i2c) 828*162e2365SJoy Zou { 829*162e2365SJoy Zou const struct pf0900_regulator_desc *regulator_desc; 830*162e2365SJoy Zou const struct pf0900_drvdata *drvdata = NULL; 831*162e2365SJoy Zou struct device_node *np = i2c->dev.of_node; 832*162e2365SJoy Zou unsigned int device_id, device_fam, i; 833*162e2365SJoy Zou struct regulator_config config = { }; 834*162e2365SJoy Zou struct pf0900 *pf0900; 835*162e2365SJoy Zou int ret; 836*162e2365SJoy Zou 837*162e2365SJoy Zou if (!i2c->irq) 838*162e2365SJoy Zou return dev_err_probe(&i2c->dev, -EINVAL, "No IRQ configured?\n"); 839*162e2365SJoy Zou 840*162e2365SJoy Zou pf0900 = devm_kzalloc(&i2c->dev, sizeof(struct pf0900), GFP_KERNEL); 841*162e2365SJoy Zou if (!pf0900) 842*162e2365SJoy Zou return -ENOMEM; 843*162e2365SJoy Zou 844*162e2365SJoy Zou drvdata = device_get_match_data(&i2c->dev); 845*162e2365SJoy Zou if (!drvdata) 846*162e2365SJoy Zou return dev_err_probe(&i2c->dev, -EINVAL, "unable to find driver data\n"); 847*162e2365SJoy Zou 848*162e2365SJoy Zou regulator_desc = drvdata->desc; 849*162e2365SJoy Zou pf0900->drvdata = drvdata; 850*162e2365SJoy Zou pf0900->crc_en = of_property_read_bool(np, "nxp,i2c-crc-enable"); 851*162e2365SJoy Zou pf0900->irq = i2c->irq; 852*162e2365SJoy Zou pf0900->dev = &i2c->dev; 853*162e2365SJoy Zou pf0900->addr = i2c->addr; 854*162e2365SJoy Zou 855*162e2365SJoy Zou dev_set_drvdata(&i2c->dev, pf0900); 856*162e2365SJoy Zou 857*162e2365SJoy Zou pf0900->regmap = devm_regmap_init(&i2c->dev, &pf0900_regmap_bus, &i2c->dev, 858*162e2365SJoy Zou &pf0900_regmap_config); 859*162e2365SJoy Zou if (IS_ERR(pf0900->regmap)) 860*162e2365SJoy Zou return dev_err_probe(&i2c->dev, PTR_ERR(pf0900->regmap), 861*162e2365SJoy Zou "regmap initialization failed\n"); 862*162e2365SJoy Zou ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_ID, &device_id); 863*162e2365SJoy Zou if (ret) 864*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Read device id error\n"); 865*162e2365SJoy Zou 866*162e2365SJoy Zou ret = regmap_read(pf0900->regmap, PF0900_REG_DEV_FAM, &device_fam); 867*162e2365SJoy Zou if (ret) 868*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Read device fam error\n"); 869*162e2365SJoy Zou 870*162e2365SJoy Zou /* Check your board and dts for match the right pmic */ 871*162e2365SJoy Zou if (device_fam == 0x09 && (device_id & 0x1F) != 0x0) 872*162e2365SJoy Zou return dev_err_probe(&i2c->dev, -EINVAL, "Device id(%x) mismatched\n", 873*162e2365SJoy Zou device_id >> 4); 874*162e2365SJoy Zou 875*162e2365SJoy Zou for (i = 0; i < drvdata->rcnt; i++) { 876*162e2365SJoy Zou const struct regulator_desc *desc; 877*162e2365SJoy Zou const struct pf0900_regulator_desc *r; 878*162e2365SJoy Zou 879*162e2365SJoy Zou r = ®ulator_desc[i]; 880*162e2365SJoy Zou desc = &r->desc; 881*162e2365SJoy Zou config.regmap = pf0900->regmap; 882*162e2365SJoy Zou config.driver_data = (void *)r; 883*162e2365SJoy Zou config.dev = pf0900->dev; 884*162e2365SJoy Zou 885*162e2365SJoy Zou pf0900->rdevs[i] = devm_regulator_register(pf0900->dev, desc, &config); 886*162e2365SJoy Zou if (IS_ERR(pf0900->rdevs[i])) 887*162e2365SJoy Zou return dev_err_probe(pf0900->dev, PTR_ERR(pf0900->rdevs[i]), 888*162e2365SJoy Zou "Failed to register regulator(%s)\n", desc->name); 889*162e2365SJoy Zou } 890*162e2365SJoy Zou 891*162e2365SJoy Zou ret = devm_request_threaded_irq(pf0900->dev, pf0900->irq, NULL, 892*162e2365SJoy Zou pf0900_irq_handler, 893*162e2365SJoy Zou (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), 894*162e2365SJoy Zou "pf0900-irq", pf0900); 895*162e2365SJoy Zou 896*162e2365SJoy Zou if (ret != 0) 897*162e2365SJoy Zou return dev_err_probe(pf0900->dev, ret, "Failed to request IRQ: %d\n", 898*162e2365SJoy Zou pf0900->irq); 899*162e2365SJoy Zou /* 900*162e2365SJoy Zou * The PWRUP_M is unmasked by default. When the device enter in RUN state, 901*162e2365SJoy Zou * it will assert the PWRUP_I interrupt and assert the INTB pin to inform 902*162e2365SJoy Zou * the MCU that it has finished the power up sequence properly. 903*162e2365SJoy Zou */ 904*162e2365SJoy Zou ret = regmap_write_bits(pf0900->regmap, PF0900_REG_STATUS1_INT, PF0900_IRQ_PWRUP, 905*162e2365SJoy Zou PF0900_IRQ_PWRUP); 906*162e2365SJoy Zou if (ret) 907*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Clean PWRUP_I error\n"); 908*162e2365SJoy Zou 909*162e2365SJoy Zou /* mask interrupt PWRUP */ 910*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_STATUS1_MSK, PF0900_IRQ_PWRUP, 911*162e2365SJoy Zou PF0900_IRQ_PWRUP); 912*162e2365SJoy Zou if (ret) 913*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 914*162e2365SJoy Zou 915*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_ILIM_MSK, PF0900_IRQ_SW1_IL | 916*162e2365SJoy Zou PF0900_IRQ_SW2_IL | PF0900_IRQ_SW3_IL | PF0900_IRQ_SW4_IL | 917*162e2365SJoy Zou PF0900_IRQ_SW5_IL, 0); 918*162e2365SJoy Zou if (ret) 919*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 920*162e2365SJoy Zou 921*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_UV_MSK, PF0900_IRQ_SW1_UV | 922*162e2365SJoy Zou PF0900_IRQ_SW2_UV | PF0900_IRQ_SW3_UV | PF0900_IRQ_SW4_UV | 923*162e2365SJoy Zou PF0900_IRQ_SW5_UV, 0); 924*162e2365SJoy Zou if (ret) 925*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 926*162e2365SJoy Zou 927*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_SW_OV_MSK, PF0900_IRQ_SW1_OV | 928*162e2365SJoy Zou PF0900_IRQ_SW2_OV | PF0900_IRQ_SW3_OV | PF0900_IRQ_SW4_OV | 929*162e2365SJoy Zou PF0900_IRQ_SW5_OV, 0); 930*162e2365SJoy Zou if (ret) 931*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 932*162e2365SJoy Zou 933*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_ILIM_MSK, PF0900_IRQ_LDO1_IL | 934*162e2365SJoy Zou PF0900_IRQ_LDO2_IL | PF0900_IRQ_LDO3_IL, 0); 935*162e2365SJoy Zou if (ret) 936*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 937*162e2365SJoy Zou 938*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_UV_MSK, PF0900_IRQ_LDO1_UV | 939*162e2365SJoy Zou PF0900_IRQ_LDO2_UV | PF0900_IRQ_LDO3_UV | PF0900_IRQ_VAON_UV, 0); 940*162e2365SJoy Zou if (ret) 941*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 942*162e2365SJoy Zou 943*162e2365SJoy Zou ret = regmap_update_bits(pf0900->regmap, PF0900_REG_LDO_OV_MSK, PF0900_IRQ_LDO1_OV | 944*162e2365SJoy Zou PF0900_IRQ_LDO2_OV | PF0900_IRQ_LDO3_OV | PF0900_IRQ_VAON_OV, 0); 945*162e2365SJoy Zou if (ret) 946*162e2365SJoy Zou return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n"); 947*162e2365SJoy Zou 948*162e2365SJoy Zou return 0; 949*162e2365SJoy Zou } 950*162e2365SJoy Zou 951*162e2365SJoy Zou static struct pf0900_drvdata pf0900_drvdata = { 952*162e2365SJoy Zou .desc = pf0900_regulators, 953*162e2365SJoy Zou .rcnt = ARRAY_SIZE(pf0900_regulators), 954*162e2365SJoy Zou }; 955*162e2365SJoy Zou 956*162e2365SJoy Zou static const struct of_device_id pf0900_of_match[] = { 957*162e2365SJoy Zou { .compatible = "nxp,pf0900", .data = &pf0900_drvdata}, 958*162e2365SJoy Zou { } 959*162e2365SJoy Zou }; 960*162e2365SJoy Zou 961*162e2365SJoy Zou MODULE_DEVICE_TABLE(of, pf0900_of_match); 962*162e2365SJoy Zou 963*162e2365SJoy Zou static struct i2c_driver pf0900_i2c_driver = { 964*162e2365SJoy Zou .driver = { 965*162e2365SJoy Zou .name = "nxp-pf0900", 966*162e2365SJoy Zou .of_match_table = pf0900_of_match, 967*162e2365SJoy Zou }, 968*162e2365SJoy Zou .probe = pf0900_i2c_probe, 969*162e2365SJoy Zou }; 970*162e2365SJoy Zou 971*162e2365SJoy Zou module_i2c_driver(pf0900_i2c_driver); 972*162e2365SJoy Zou 973*162e2365SJoy Zou MODULE_AUTHOR("Joy Zou <joy.zou@nxp.com>"); 974*162e2365SJoy Zou MODULE_DESCRIPTION("NXP PF0900 Power Management IC driver"); 975*162e2365SJoy Zou MODULE_LICENSE("GPL"); 976