1*53387090SAndré Draszik // SPDX-License-Identifier: GPL-2.0-only 2*53387090SAndré Draszik /* 3*53387090SAndré Draszik * Copyright 2020 Google Inc 4*53387090SAndré Draszik * Copyright 2025 Linaro Ltd. 5*53387090SAndré Draszik * 6*53387090SAndré Draszik * Samsung S2MPG1x ACPM driver 7*53387090SAndré Draszik */ 8*53387090SAndré Draszik 9*53387090SAndré Draszik #include <linux/array_size.h> 10*53387090SAndré Draszik #include <linux/bitops.h> 11*53387090SAndré Draszik #include <linux/device.h> 12*53387090SAndré Draszik #include <linux/firmware/samsung/exynos-acpm-protocol.h> 13*53387090SAndré Draszik #include <linux/mfd/samsung/core.h> 14*53387090SAndré Draszik #include <linux/mfd/samsung/rtc.h> 15*53387090SAndré Draszik #include <linux/mfd/samsung/s2mpg10.h> 16*53387090SAndré Draszik #include <linux/mod_devicetable.h> 17*53387090SAndré Draszik #include <linux/module.h> 18*53387090SAndré Draszik #include <linux/of.h> 19*53387090SAndré Draszik #include <linux/platform_device.h> 20*53387090SAndré Draszik #include <linux/pm.h> 21*53387090SAndré Draszik #include <linux/property.h> 22*53387090SAndré Draszik #include <linux/regmap.h> 23*53387090SAndré Draszik #include "sec-core.h" 24*53387090SAndré Draszik 25*53387090SAndré Draszik #define ACPM_ADDR_BITS 8 26*53387090SAndré Draszik #define ACPM_MAX_BULK_DATA 8 27*53387090SAndré Draszik 28*53387090SAndré Draszik struct sec_pmic_acpm_platform_data { 29*53387090SAndré Draszik int device_type; 30*53387090SAndré Draszik 31*53387090SAndré Draszik unsigned int acpm_chan_id; 32*53387090SAndré Draszik u8 speedy_channel; 33*53387090SAndré Draszik 34*53387090SAndré Draszik const struct regmap_config *regmap_cfg_common; 35*53387090SAndré Draszik const struct regmap_config *regmap_cfg_pmic; 36*53387090SAndré Draszik const struct regmap_config *regmap_cfg_rtc; 37*53387090SAndré Draszik const struct regmap_config *regmap_cfg_meter; 38*53387090SAndré Draszik }; 39*53387090SAndré Draszik 40*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_registers[] = { 41*53387090SAndré Draszik regmap_reg_range(0x00, 0x02), /* CHIP_ID_M, INT, INT_MASK */ 42*53387090SAndré Draszik regmap_reg_range(0x0a, 0x0c), /* Speedy control */ 43*53387090SAndré Draszik regmap_reg_range(0x1a, 0x2a), /* Debug */ 44*53387090SAndré Draszik }; 45*53387090SAndré Draszik 46*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_ro_registers[] = { 47*53387090SAndré Draszik regmap_reg_range(0x00, 0x01), /* CHIP_ID_M, INT */ 48*53387090SAndré Draszik regmap_reg_range(0x28, 0x2a), /* Debug */ 49*53387090SAndré Draszik }; 50*53387090SAndré Draszik 51*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = { 52*53387090SAndré Draszik regmap_reg_range(0x00, 0x00), /* CHIP_ID_M */ 53*53387090SAndré Draszik regmap_reg_range(0x02, 0x02), /* INT_MASK */ 54*53387090SAndré Draszik regmap_reg_range(0x0a, 0x0c), /* Speedy control */ 55*53387090SAndré Draszik }; 56*53387090SAndré Draszik 57*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_precious_registers[] = { 58*53387090SAndré Draszik regmap_reg_range(0x01, 0x01), /* INT */ 59*53387090SAndré Draszik }; 60*53387090SAndré Draszik 61*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_wr_table = { 62*53387090SAndré Draszik .yes_ranges = s2mpg10_common_registers, 63*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers), 64*53387090SAndré Draszik .no_ranges = s2mpg10_common_ro_registers, 65*53387090SAndré Draszik .n_no_ranges = ARRAY_SIZE(s2mpg10_common_ro_registers), 66*53387090SAndré Draszik }; 67*53387090SAndré Draszik 68*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_rd_table = { 69*53387090SAndré Draszik .yes_ranges = s2mpg10_common_registers, 70*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers), 71*53387090SAndré Draszik }; 72*53387090SAndré Draszik 73*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_volatile_table = { 74*53387090SAndré Draszik .no_ranges = s2mpg10_common_nonvolatile_registers, 75*53387090SAndré Draszik .n_no_ranges = ARRAY_SIZE(s2mpg10_common_nonvolatile_registers), 76*53387090SAndré Draszik }; 77*53387090SAndré Draszik 78*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_precious_table = { 79*53387090SAndré Draszik .yes_ranges = s2mpg10_common_precious_registers, 80*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_common_precious_registers), 81*53387090SAndré Draszik }; 82*53387090SAndré Draszik 83*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_common = { 84*53387090SAndré Draszik .name = "common", 85*53387090SAndré Draszik .reg_bits = ACPM_ADDR_BITS, 86*53387090SAndré Draszik .val_bits = 8, 87*53387090SAndré Draszik .max_register = S2MPG10_COMMON_SPD_DEBUG4, 88*53387090SAndré Draszik .wr_table = &s2mpg10_common_wr_table, 89*53387090SAndré Draszik .rd_table = &s2mpg10_common_rd_table, 90*53387090SAndré Draszik .volatile_table = &s2mpg10_common_volatile_table, 91*53387090SAndré Draszik .precious_table = &s2mpg10_common_precious_table, 92*53387090SAndré Draszik .num_reg_defaults_raw = S2MPG10_COMMON_SPD_DEBUG4 + 1, 93*53387090SAndré Draszik .cache_type = REGCACHE_FLAT, 94*53387090SAndré Draszik }; 95*53387090SAndré Draszik 96*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_registers[] = { 97*53387090SAndré Draszik regmap_reg_range(0x00, 0xf6), /* All PMIC registers */ 98*53387090SAndré Draszik }; 99*53387090SAndré Draszik 100*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_ro_registers[] = { 101*53387090SAndré Draszik regmap_reg_range(0x00, 0x05), /* INTx */ 102*53387090SAndré Draszik regmap_reg_range(0x0c, 0x0f), /* STATUSx PWRONSRC OFFSRC */ 103*53387090SAndré Draszik regmap_reg_range(0xc7, 0xc7), /* GPIO input */ 104*53387090SAndré Draszik }; 105*53387090SAndré Draszik 106*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_nonvolatile_registers[] = { 107*53387090SAndré Draszik regmap_reg_range(0x06, 0x0b), /* INTxM */ 108*53387090SAndré Draszik }; 109*53387090SAndré Draszik 110*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_precious_registers[] = { 111*53387090SAndré Draszik regmap_reg_range(0x00, 0x05), /* INTx */ 112*53387090SAndré Draszik }; 113*53387090SAndré Draszik 114*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_wr_table = { 115*53387090SAndré Draszik .yes_ranges = s2mpg10_pmic_registers, 116*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers), 117*53387090SAndré Draszik .no_ranges = s2mpg10_pmic_ro_registers, 118*53387090SAndré Draszik .n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_ro_registers), 119*53387090SAndré Draszik }; 120*53387090SAndré Draszik 121*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_rd_table = { 122*53387090SAndré Draszik .yes_ranges = s2mpg10_pmic_registers, 123*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers), 124*53387090SAndré Draszik }; 125*53387090SAndré Draszik 126*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_volatile_table = { 127*53387090SAndré Draszik .no_ranges = s2mpg10_pmic_nonvolatile_registers, 128*53387090SAndré Draszik .n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_nonvolatile_registers), 129*53387090SAndré Draszik }; 130*53387090SAndré Draszik 131*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_precious_table = { 132*53387090SAndré Draszik .yes_ranges = s2mpg10_pmic_precious_registers, 133*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_precious_registers), 134*53387090SAndré Draszik }; 135*53387090SAndré Draszik 136*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_pmic = { 137*53387090SAndré Draszik .name = "pmic", 138*53387090SAndré Draszik .reg_bits = ACPM_ADDR_BITS, 139*53387090SAndré Draszik .val_bits = 8, 140*53387090SAndré Draszik .max_register = S2MPG10_PMIC_LDO_SENSE4, 141*53387090SAndré Draszik .wr_table = &s2mpg10_pmic_wr_table, 142*53387090SAndré Draszik .rd_table = &s2mpg10_pmic_rd_table, 143*53387090SAndré Draszik .volatile_table = &s2mpg10_pmic_volatile_table, 144*53387090SAndré Draszik .precious_table = &s2mpg10_pmic_precious_table, 145*53387090SAndré Draszik .num_reg_defaults_raw = S2MPG10_PMIC_LDO_SENSE4 + 1, 146*53387090SAndré Draszik .cache_type = REGCACHE_FLAT, 147*53387090SAndré Draszik }; 148*53387090SAndré Draszik 149*53387090SAndré Draszik static const struct regmap_range s2mpg10_rtc_registers[] = { 150*53387090SAndré Draszik regmap_reg_range(0x00, 0x2b), /* All RTC registers */ 151*53387090SAndré Draszik }; 152*53387090SAndré Draszik 153*53387090SAndré Draszik static const struct regmap_range s2mpg10_rtc_volatile_registers[] = { 154*53387090SAndré Draszik regmap_reg_range(0x01, 0x01), /* RTC_UPDATE */ 155*53387090SAndré Draszik regmap_reg_range(0x05, 0x0c), /* Time / date */ 156*53387090SAndré Draszik }; 157*53387090SAndré Draszik 158*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_rtc_rd_table = { 159*53387090SAndré Draszik .yes_ranges = s2mpg10_rtc_registers, 160*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers), 161*53387090SAndré Draszik }; 162*53387090SAndré Draszik 163*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_rtc_volatile_table = { 164*53387090SAndré Draszik .yes_ranges = s2mpg10_rtc_volatile_registers, 165*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_volatile_registers), 166*53387090SAndré Draszik }; 167*53387090SAndré Draszik 168*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_rtc = { 169*53387090SAndré Draszik .name = "rtc", 170*53387090SAndré Draszik .reg_bits = ACPM_ADDR_BITS, 171*53387090SAndré Draszik .val_bits = 8, 172*53387090SAndré Draszik .max_register = S2MPG10_RTC_OSC_CTRL, 173*53387090SAndré Draszik .rd_table = &s2mpg10_rtc_rd_table, 174*53387090SAndré Draszik .volatile_table = &s2mpg10_rtc_volatile_table, 175*53387090SAndré Draszik .num_reg_defaults_raw = S2MPG10_RTC_OSC_CTRL + 1, 176*53387090SAndré Draszik .cache_type = REGCACHE_FLAT, 177*53387090SAndré Draszik }; 178*53387090SAndré Draszik 179*53387090SAndré Draszik static const struct regmap_range s2mpg10_meter_registers[] = { 180*53387090SAndré Draszik regmap_reg_range(0x00, 0x21), /* Meter config */ 181*53387090SAndré Draszik regmap_reg_range(0x40, 0x8a), /* Meter data */ 182*53387090SAndré Draszik regmap_reg_range(0xee, 0xee), /* Offset */ 183*53387090SAndré Draszik regmap_reg_range(0xf1, 0xf1), /* Trim */ 184*53387090SAndré Draszik }; 185*53387090SAndré Draszik 186*53387090SAndré Draszik static const struct regmap_range s2mpg10_meter_ro_registers[] = { 187*53387090SAndré Draszik regmap_reg_range(0x40, 0x8a), /* Meter data */ 188*53387090SAndré Draszik }; 189*53387090SAndré Draszik 190*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_wr_table = { 191*53387090SAndré Draszik .yes_ranges = s2mpg10_meter_registers, 192*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers), 193*53387090SAndré Draszik .no_ranges = s2mpg10_meter_ro_registers, 194*53387090SAndré Draszik .n_no_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers), 195*53387090SAndré Draszik }; 196*53387090SAndré Draszik 197*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_rd_table = { 198*53387090SAndré Draszik .yes_ranges = s2mpg10_meter_registers, 199*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers), 200*53387090SAndré Draszik }; 201*53387090SAndré Draszik 202*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_volatile_table = { 203*53387090SAndré Draszik .yes_ranges = s2mpg10_meter_ro_registers, 204*53387090SAndré Draszik .n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers), 205*53387090SAndré Draszik }; 206*53387090SAndré Draszik 207*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_meter = { 208*53387090SAndré Draszik .name = "meter", 209*53387090SAndré Draszik .reg_bits = ACPM_ADDR_BITS, 210*53387090SAndré Draszik .val_bits = 8, 211*53387090SAndré Draszik .max_register = S2MPG10_METER_BUCK_METER_TRIM3, 212*53387090SAndré Draszik .wr_table = &s2mpg10_meter_wr_table, 213*53387090SAndré Draszik .rd_table = &s2mpg10_meter_rd_table, 214*53387090SAndré Draszik .volatile_table = &s2mpg10_meter_volatile_table, 215*53387090SAndré Draszik .num_reg_defaults_raw = S2MPG10_METER_BUCK_METER_TRIM3 + 1, 216*53387090SAndré Draszik .cache_type = REGCACHE_FLAT, 217*53387090SAndré Draszik }; 218*53387090SAndré Draszik 219*53387090SAndré Draszik struct sec_pmic_acpm_shared_bus_context { 220*53387090SAndré Draszik const struct acpm_handle *acpm; 221*53387090SAndré Draszik unsigned int acpm_chan_id; 222*53387090SAndré Draszik u8 speedy_channel; 223*53387090SAndré Draszik }; 224*53387090SAndré Draszik 225*53387090SAndré Draszik enum sec_pmic_acpm_accesstype { 226*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_COMMON = 0x00, 227*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_PMIC = 0x01, 228*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_RTC = 0x02, 229*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_METER = 0x0a, 230*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_WLWP = 0x0b, 231*53387090SAndré Draszik SEC_PMIC_ACPM_ACCESSTYPE_TRIM = 0x0f, 232*53387090SAndré Draszik }; 233*53387090SAndré Draszik 234*53387090SAndré Draszik struct sec_pmic_acpm_bus_context { 235*53387090SAndré Draszik struct sec_pmic_acpm_shared_bus_context *shared; 236*53387090SAndré Draszik enum sec_pmic_acpm_accesstype type; 237*53387090SAndré Draszik }; 238*53387090SAndré Draszik 239*53387090SAndré Draszik static int sec_pmic_acpm_bus_write(void *context, const void *data, 240*53387090SAndré Draszik size_t count) 241*53387090SAndré Draszik { 242*53387090SAndré Draszik struct sec_pmic_acpm_bus_context *ctx = context; 243*53387090SAndré Draszik const struct acpm_handle *acpm = ctx->shared->acpm; 244*53387090SAndré Draszik const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 245*53387090SAndré Draszik size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS); 246*53387090SAndré Draszik const u8 *d = data; 247*53387090SAndré Draszik const u8 *vals = &d[BITS_TO_BYTES(ACPM_ADDR_BITS)]; 248*53387090SAndré Draszik u8 reg; 249*53387090SAndré Draszik 250*53387090SAndré Draszik if (val_count < 1 || val_count > ACPM_MAX_BULK_DATA) 251*53387090SAndré Draszik return -EINVAL; 252*53387090SAndré Draszik 253*53387090SAndré Draszik reg = d[0]; 254*53387090SAndré Draszik 255*53387090SAndré Draszik return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id, ctx->type, reg, 256*53387090SAndré Draszik ctx->shared->speedy_channel, val_count, vals); 257*53387090SAndré Draszik } 258*53387090SAndré Draszik 259*53387090SAndré Draszik static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf, size_t reg_size, 260*53387090SAndré Draszik void *val_buf, size_t val_size) 261*53387090SAndré Draszik { 262*53387090SAndré Draszik struct sec_pmic_acpm_bus_context *ctx = context; 263*53387090SAndré Draszik const struct acpm_handle *acpm = ctx->shared->acpm; 264*53387090SAndré Draszik const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 265*53387090SAndré Draszik const u8 *r = reg_buf; 266*53387090SAndré Draszik u8 reg; 267*53387090SAndré Draszik 268*53387090SAndré Draszik if (reg_size != BITS_TO_BYTES(ACPM_ADDR_BITS) || !val_size || 269*53387090SAndré Draszik val_size > ACPM_MAX_BULK_DATA) 270*53387090SAndré Draszik return -EINVAL; 271*53387090SAndré Draszik 272*53387090SAndré Draszik reg = r[0]; 273*53387090SAndré Draszik 274*53387090SAndré Draszik return pmic_ops->bulk_read(acpm, ctx->shared->acpm_chan_id, ctx->type, reg, 275*53387090SAndré Draszik ctx->shared->speedy_channel, val_size, val_buf); 276*53387090SAndré Draszik } 277*53387090SAndré Draszik 278*53387090SAndré Draszik static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg, unsigned int mask, 279*53387090SAndré Draszik unsigned int val) 280*53387090SAndré Draszik { 281*53387090SAndré Draszik struct sec_pmic_acpm_bus_context *ctx = context; 282*53387090SAndré Draszik const struct acpm_handle *acpm = ctx->shared->acpm; 283*53387090SAndré Draszik const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 284*53387090SAndré Draszik 285*53387090SAndré Draszik return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff, 286*53387090SAndré Draszik ctx->shared->speedy_channel, val, mask); 287*53387090SAndré Draszik } 288*53387090SAndré Draszik 289*53387090SAndré Draszik static const struct regmap_bus sec_pmic_acpm_regmap_bus = { 290*53387090SAndré Draszik .write = sec_pmic_acpm_bus_write, 291*53387090SAndré Draszik .read = sec_pmic_acpm_bus_read, 292*53387090SAndré Draszik .reg_update_bits = sec_pmic_acpm_bus_reg_update_bits, 293*53387090SAndré Draszik .max_raw_read = ACPM_MAX_BULK_DATA, 294*53387090SAndré Draszik .max_raw_write = ACPM_MAX_BULK_DATA, 295*53387090SAndré Draszik }; 296*53387090SAndré Draszik 297*53387090SAndré Draszik static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev, 298*53387090SAndré Draszik struct sec_pmic_acpm_shared_bus_context *shared_ctx, 299*53387090SAndré Draszik enum sec_pmic_acpm_accesstype type, 300*53387090SAndré Draszik const struct regmap_config *cfg, bool do_attach) 301*53387090SAndré Draszik { 302*53387090SAndré Draszik struct sec_pmic_acpm_bus_context *ctx; 303*53387090SAndré Draszik struct regmap *regmap; 304*53387090SAndré Draszik 305*53387090SAndré Draszik ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 306*53387090SAndré Draszik if (!ctx) 307*53387090SAndré Draszik return ERR_PTR(-ENOMEM); 308*53387090SAndré Draszik 309*53387090SAndré Draszik ctx->shared = shared_ctx; 310*53387090SAndré Draszik ctx->type = type; 311*53387090SAndré Draszik 312*53387090SAndré Draszik regmap = devm_regmap_init(dev, &sec_pmic_acpm_regmap_bus, ctx, cfg); 313*53387090SAndré Draszik if (IS_ERR(regmap)) 314*53387090SAndré Draszik return dev_err_cast_probe(dev, regmap, "regmap init (%s) failed\n", cfg->name); 315*53387090SAndré Draszik 316*53387090SAndré Draszik if (do_attach) { 317*53387090SAndré Draszik int ret; 318*53387090SAndré Draszik 319*53387090SAndré Draszik ret = regmap_attach_dev(dev, regmap, cfg); 320*53387090SAndré Draszik if (ret) 321*53387090SAndré Draszik return dev_err_ptr_probe(dev, ret, "regmap attach (%s) failed\n", 322*53387090SAndré Draszik cfg->name); 323*53387090SAndré Draszik } 324*53387090SAndré Draszik 325*53387090SAndré Draszik return regmap; 326*53387090SAndré Draszik } 327*53387090SAndré Draszik 328*53387090SAndré Draszik static void sec_pmic_acpm_mask_common_irqs(void *regmap_common) 329*53387090SAndré Draszik { 330*53387090SAndré Draszik regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC); 331*53387090SAndré Draszik } 332*53387090SAndré Draszik 333*53387090SAndré Draszik static int sec_pmic_acpm_probe(struct platform_device *pdev) 334*53387090SAndré Draszik { 335*53387090SAndré Draszik struct regmap *regmap_common, *regmap_pmic, *regmap; 336*53387090SAndré Draszik const struct sec_pmic_acpm_platform_data *pdata; 337*53387090SAndré Draszik struct sec_pmic_acpm_shared_bus_context *shared_ctx; 338*53387090SAndré Draszik const struct acpm_handle *acpm; 339*53387090SAndré Draszik struct device *dev = &pdev->dev; 340*53387090SAndré Draszik int ret, irq; 341*53387090SAndré Draszik 342*53387090SAndré Draszik pdata = device_get_match_data(dev); 343*53387090SAndré Draszik if (!pdata) 344*53387090SAndré Draszik return dev_err_probe(dev, -ENODEV, "unsupported device type\n"); 345*53387090SAndré Draszik 346*53387090SAndré Draszik acpm = devm_acpm_get_by_node(dev, dev->parent->of_node); 347*53387090SAndré Draszik if (IS_ERR(acpm)) 348*53387090SAndré Draszik return dev_err_probe(dev, PTR_ERR(acpm), "failed to get acpm\n"); 349*53387090SAndré Draszik 350*53387090SAndré Draszik irq = platform_get_irq(pdev, 0); 351*53387090SAndré Draszik if (irq < 0) 352*53387090SAndré Draszik return irq; 353*53387090SAndré Draszik 354*53387090SAndré Draszik shared_ctx = devm_kzalloc(dev, sizeof(*shared_ctx), GFP_KERNEL); 355*53387090SAndré Draszik if (!shared_ctx) 356*53387090SAndré Draszik return -ENOMEM; 357*53387090SAndré Draszik 358*53387090SAndré Draszik shared_ctx->acpm = acpm; 359*53387090SAndré Draszik shared_ctx->acpm_chan_id = pdata->acpm_chan_id; 360*53387090SAndré Draszik shared_ctx->speedy_channel = pdata->speedy_channel; 361*53387090SAndré Draszik 362*53387090SAndré Draszik regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON, 363*53387090SAndré Draszik pdata->regmap_cfg_common, false); 364*53387090SAndré Draszik if (IS_ERR(regmap_common)) 365*53387090SAndré Draszik return PTR_ERR(regmap_common); 366*53387090SAndré Draszik 367*53387090SAndré Draszik /* Mask all interrupts from 'common' block, until successful init */ 368*53387090SAndré Draszik ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC); 369*53387090SAndré Draszik if (ret) 370*53387090SAndré Draszik return dev_err_probe(dev, ret, "failed to mask common block interrupts\n"); 371*53387090SAndré Draszik 372*53387090SAndré Draszik regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC, 373*53387090SAndré Draszik pdata->regmap_cfg_pmic, false); 374*53387090SAndré Draszik if (IS_ERR(regmap_pmic)) 375*53387090SAndré Draszik return PTR_ERR(regmap_pmic); 376*53387090SAndré Draszik 377*53387090SAndré Draszik regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC, 378*53387090SAndré Draszik pdata->regmap_cfg_rtc, true); 379*53387090SAndré Draszik if (IS_ERR(regmap)) 380*53387090SAndré Draszik return PTR_ERR(regmap); 381*53387090SAndré Draszik 382*53387090SAndré Draszik regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_METER, 383*53387090SAndré Draszik pdata->regmap_cfg_meter, true); 384*53387090SAndré Draszik if (IS_ERR(regmap)) 385*53387090SAndré Draszik return PTR_ERR(regmap); 386*53387090SAndré Draszik 387*53387090SAndré Draszik ret = sec_pmic_probe(dev, pdata->device_type, irq, regmap_pmic, NULL); 388*53387090SAndré Draszik if (ret) 389*53387090SAndré Draszik return ret; 390*53387090SAndré Draszik 391*53387090SAndré Draszik if (device_property_read_bool(dev, "wakeup-source")) 392*53387090SAndré Draszik devm_device_init_wakeup(dev); 393*53387090SAndré Draszik 394*53387090SAndré Draszik /* Unmask PMIC interrupt from 'common' block, now that everything is in place. */ 395*53387090SAndré Draszik ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK, 396*53387090SAndré Draszik S2MPG10_COMMON_INT_SRC_PMIC); 397*53387090SAndré Draszik if (ret) 398*53387090SAndré Draszik return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n"); 399*53387090SAndré Draszik 400*53387090SAndré Draszik /* Mask all interrupts from 'common' block on shutdown */ 401*53387090SAndré Draszik ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common); 402*53387090SAndré Draszik if (ret) 403*53387090SAndré Draszik return ret; 404*53387090SAndré Draszik 405*53387090SAndré Draszik return 0; 406*53387090SAndré Draszik } 407*53387090SAndré Draszik 408*53387090SAndré Draszik static void sec_pmic_acpm_shutdown(struct platform_device *pdev) 409*53387090SAndré Draszik { 410*53387090SAndré Draszik sec_pmic_shutdown(&pdev->dev); 411*53387090SAndré Draszik } 412*53387090SAndré Draszik 413*53387090SAndré Draszik static const struct sec_pmic_acpm_platform_data s2mpg10_data = { 414*53387090SAndré Draszik .device_type = S2MPG10, 415*53387090SAndré Draszik .acpm_chan_id = 2, 416*53387090SAndré Draszik .speedy_channel = 0, 417*53387090SAndré Draszik .regmap_cfg_common = &s2mpg10_regmap_config_common, 418*53387090SAndré Draszik .regmap_cfg_pmic = &s2mpg10_regmap_config_pmic, 419*53387090SAndré Draszik .regmap_cfg_rtc = &s2mpg10_regmap_config_rtc, 420*53387090SAndré Draszik .regmap_cfg_meter = &s2mpg10_regmap_config_meter, 421*53387090SAndré Draszik }; 422*53387090SAndré Draszik 423*53387090SAndré Draszik static const struct of_device_id sec_pmic_acpm_of_match[] = { 424*53387090SAndré Draszik { .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, }, 425*53387090SAndré Draszik { }, 426*53387090SAndré Draszik }; 427*53387090SAndré Draszik MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match); 428*53387090SAndré Draszik 429*53387090SAndré Draszik static struct platform_driver sec_pmic_acpm_driver = { 430*53387090SAndré Draszik .driver = { 431*53387090SAndré Draszik .name = "sec-pmic-acpm", 432*53387090SAndré Draszik .pm = pm_sleep_ptr(&sec_pmic_pm_ops), 433*53387090SAndré Draszik .of_match_table = sec_pmic_acpm_of_match, 434*53387090SAndré Draszik }, 435*53387090SAndré Draszik .probe = sec_pmic_acpm_probe, 436*53387090SAndré Draszik .shutdown = sec_pmic_acpm_shutdown, 437*53387090SAndré Draszik }; 438*53387090SAndré Draszik module_platform_driver(sec_pmic_acpm_driver); 439*53387090SAndré Draszik 440*53387090SAndré Draszik MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>"); 441*53387090SAndré Draszik MODULE_DESCRIPTION("ACPM driver for the Samsung S2MPG1x"); 442*53387090SAndré Draszik MODULE_LICENSE("GPL"); 443