1*b1b3ced3SMatti Vaittinen // SPDX-License-Identifier: GPL-2.0-or-later 2*b1b3ced3SMatti Vaittinen /* 3*b1b3ced3SMatti Vaittinen * Copyright (C) 2021 ROHM Semiconductors 4*b1b3ced3SMatti Vaittinen * 5*b1b3ced3SMatti Vaittinen * ROHM BD9576MUF and BD9573MUF PMIC driver 6*b1b3ced3SMatti Vaittinen */ 7*b1b3ced3SMatti Vaittinen 8*b1b3ced3SMatti Vaittinen #include <linux/i2c.h> 9*b1b3ced3SMatti Vaittinen #include <linux/interrupt.h> 10*b1b3ced3SMatti Vaittinen #include <linux/ioport.h> 11*b1b3ced3SMatti Vaittinen #include <linux/irq.h> 12*b1b3ced3SMatti Vaittinen #include <linux/mfd/core.h> 13*b1b3ced3SMatti Vaittinen #include <linux/mfd/rohm-bd957x.h> 14*b1b3ced3SMatti Vaittinen #include <linux/mfd/rohm-generic.h> 15*b1b3ced3SMatti Vaittinen #include <linux/module.h> 16*b1b3ced3SMatti Vaittinen #include <linux/of_device.h> 17*b1b3ced3SMatti Vaittinen #include <linux/regmap.h> 18*b1b3ced3SMatti Vaittinen #include <linux/types.h> 19*b1b3ced3SMatti Vaittinen 20*b1b3ced3SMatti Vaittinen static struct mfd_cell bd9573_mfd_cells[] = { 21*b1b3ced3SMatti Vaittinen { .name = "bd9573-regulator", }, 22*b1b3ced3SMatti Vaittinen { .name = "bd9576-wdt", }, 23*b1b3ced3SMatti Vaittinen }; 24*b1b3ced3SMatti Vaittinen 25*b1b3ced3SMatti Vaittinen static struct mfd_cell bd9576_mfd_cells[] = { 26*b1b3ced3SMatti Vaittinen { .name = "bd9576-regulator", }, 27*b1b3ced3SMatti Vaittinen { .name = "bd9576-wdt", }, 28*b1b3ced3SMatti Vaittinen }; 29*b1b3ced3SMatti Vaittinen 30*b1b3ced3SMatti Vaittinen static const struct regmap_range volatile_ranges[] = { 31*b1b3ced3SMatti Vaittinen regmap_reg_range(BD957X_REG_SMRB_ASSERT, BD957X_REG_SMRB_ASSERT), 32*b1b3ced3SMatti Vaittinen regmap_reg_range(BD957X_REG_PMIC_INTERNAL_STAT, 33*b1b3ced3SMatti Vaittinen BD957X_REG_PMIC_INTERNAL_STAT), 34*b1b3ced3SMatti Vaittinen regmap_reg_range(BD957X_REG_INT_THERM_STAT, BD957X_REG_INT_THERM_STAT), 35*b1b3ced3SMatti Vaittinen regmap_reg_range(BD957X_REG_INT_OVP_STAT, BD957X_REG_INT_SYS_STAT), 36*b1b3ced3SMatti Vaittinen regmap_reg_range(BD957X_REG_INT_MAIN_STAT, BD957X_REG_INT_MAIN_STAT), 37*b1b3ced3SMatti Vaittinen }; 38*b1b3ced3SMatti Vaittinen 39*b1b3ced3SMatti Vaittinen static const struct regmap_access_table volatile_regs = { 40*b1b3ced3SMatti Vaittinen .yes_ranges = &volatile_ranges[0], 41*b1b3ced3SMatti Vaittinen .n_yes_ranges = ARRAY_SIZE(volatile_ranges), 42*b1b3ced3SMatti Vaittinen }; 43*b1b3ced3SMatti Vaittinen 44*b1b3ced3SMatti Vaittinen static struct regmap_config bd957x_regmap = { 45*b1b3ced3SMatti Vaittinen .reg_bits = 8, 46*b1b3ced3SMatti Vaittinen .val_bits = 8, 47*b1b3ced3SMatti Vaittinen .volatile_table = &volatile_regs, 48*b1b3ced3SMatti Vaittinen .max_register = BD957X_MAX_REGISTER, 49*b1b3ced3SMatti Vaittinen .cache_type = REGCACHE_RBTREE, 50*b1b3ced3SMatti Vaittinen }; 51*b1b3ced3SMatti Vaittinen 52*b1b3ced3SMatti Vaittinen static int bd957x_i2c_probe(struct i2c_client *i2c, 53*b1b3ced3SMatti Vaittinen const struct i2c_device_id *id) 54*b1b3ced3SMatti Vaittinen { 55*b1b3ced3SMatti Vaittinen int ret; 56*b1b3ced3SMatti Vaittinen struct regmap *regmap; 57*b1b3ced3SMatti Vaittinen struct mfd_cell *cells; 58*b1b3ced3SMatti Vaittinen int num_cells; 59*b1b3ced3SMatti Vaittinen unsigned long chip_type; 60*b1b3ced3SMatti Vaittinen 61*b1b3ced3SMatti Vaittinen chip_type = (unsigned long)of_device_get_match_data(&i2c->dev); 62*b1b3ced3SMatti Vaittinen 63*b1b3ced3SMatti Vaittinen switch (chip_type) { 64*b1b3ced3SMatti Vaittinen case ROHM_CHIP_TYPE_BD9576: 65*b1b3ced3SMatti Vaittinen cells = bd9576_mfd_cells; 66*b1b3ced3SMatti Vaittinen num_cells = ARRAY_SIZE(bd9576_mfd_cells); 67*b1b3ced3SMatti Vaittinen break; 68*b1b3ced3SMatti Vaittinen case ROHM_CHIP_TYPE_BD9573: 69*b1b3ced3SMatti Vaittinen cells = bd9573_mfd_cells; 70*b1b3ced3SMatti Vaittinen num_cells = ARRAY_SIZE(bd9573_mfd_cells); 71*b1b3ced3SMatti Vaittinen break; 72*b1b3ced3SMatti Vaittinen default: 73*b1b3ced3SMatti Vaittinen dev_err(&i2c->dev, "Unknown device type"); 74*b1b3ced3SMatti Vaittinen return -EINVAL; 75*b1b3ced3SMatti Vaittinen } 76*b1b3ced3SMatti Vaittinen 77*b1b3ced3SMatti Vaittinen regmap = devm_regmap_init_i2c(i2c, &bd957x_regmap); 78*b1b3ced3SMatti Vaittinen if (IS_ERR(regmap)) { 79*b1b3ced3SMatti Vaittinen dev_err(&i2c->dev, "Failed to initialize Regmap\n"); 80*b1b3ced3SMatti Vaittinen return PTR_ERR(regmap); 81*b1b3ced3SMatti Vaittinen } 82*b1b3ced3SMatti Vaittinen 83*b1b3ced3SMatti Vaittinen ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, cells, 84*b1b3ced3SMatti Vaittinen num_cells, NULL, 0, NULL); 85*b1b3ced3SMatti Vaittinen if (ret) 86*b1b3ced3SMatti Vaittinen dev_err(&i2c->dev, "Failed to create subdevices\n"); 87*b1b3ced3SMatti Vaittinen 88*b1b3ced3SMatti Vaittinen return ret; 89*b1b3ced3SMatti Vaittinen } 90*b1b3ced3SMatti Vaittinen 91*b1b3ced3SMatti Vaittinen static const struct of_device_id bd957x_of_match[] = { 92*b1b3ced3SMatti Vaittinen { .compatible = "rohm,bd9576", .data = (void *)ROHM_CHIP_TYPE_BD9576, }, 93*b1b3ced3SMatti Vaittinen { .compatible = "rohm,bd9573", .data = (void *)ROHM_CHIP_TYPE_BD9573, }, 94*b1b3ced3SMatti Vaittinen { }, 95*b1b3ced3SMatti Vaittinen }; 96*b1b3ced3SMatti Vaittinen MODULE_DEVICE_TABLE(of, bd957x_of_match); 97*b1b3ced3SMatti Vaittinen 98*b1b3ced3SMatti Vaittinen static struct i2c_driver bd957x_drv = { 99*b1b3ced3SMatti Vaittinen .driver = { 100*b1b3ced3SMatti Vaittinen .name = "rohm-bd957x", 101*b1b3ced3SMatti Vaittinen .of_match_table = bd957x_of_match, 102*b1b3ced3SMatti Vaittinen }, 103*b1b3ced3SMatti Vaittinen .probe = &bd957x_i2c_probe, 104*b1b3ced3SMatti Vaittinen }; 105*b1b3ced3SMatti Vaittinen module_i2c_driver(bd957x_drv); 106*b1b3ced3SMatti Vaittinen 107*b1b3ced3SMatti Vaittinen MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 108*b1b3ced3SMatti Vaittinen MODULE_DESCRIPTION("ROHM BD9576MUF and BD9573MUF Power Management IC driver"); 109*b1b3ced3SMatti Vaittinen MODULE_LICENSE("GPL"); 110