1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * MFD core driver for Ricoh RN5T618 PMIC 4 * 5 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> 6 * Copyright (C) 2016 Toradex AG 7 */ 8 9 #include <linux/delay.h> 10 #include <linux/i2c.h> 11 #include <linux/interrupt.h> 12 #include <linux/irq.h> 13 #include <linux/mfd/core.h> 14 #include <linux/mfd/rn5t618.h> 15 #include <linux/module.h> 16 #include <linux/of_device.h> 17 #include <linux/platform_device.h> 18 #include <linux/reboot.h> 19 #include <linux/regmap.h> 20 21 static const struct mfd_cell rn5t618_cells[] = { 22 { .name = "rn5t618-regulator" }, 23 { .name = "rn5t618-wdt" }, 24 }; 25 26 static const struct mfd_cell rc5t619_cells[] = { 27 { .name = "rn5t618-adc" }, 28 { .name = "rn5t618-regulator" }, 29 { .name = "rc5t619-rtc" }, 30 { .name = "rn5t618-wdt" }, 31 }; 32 33 static bool rn5t618_volatile_reg(struct device *dev, unsigned int reg) 34 { 35 switch (reg) { 36 case RN5T618_WATCHDOGCNT: 37 case RN5T618_DCIRQ: 38 case RN5T618_ILIMDATAH ... RN5T618_AIN0DATAL: 39 case RN5T618_ADCCNT3: 40 case RN5T618_IR_ADC1 ... RN5T618_IR_ADC3: 41 case RN5T618_IR_GPR: 42 case RN5T618_IR_GPF: 43 case RN5T618_MON_IOIN: 44 case RN5T618_INTMON: 45 case RN5T618_RTC_CTRL1 ... RN5T618_RTC_CTRL2: 46 case RN5T618_RTC_SECONDS ... RN5T618_RTC_YEAR: 47 case RN5T618_CHGSTATE: 48 case RN5T618_CHGCTRL_IRR ... RN5T618_CHGERR_MONI: 49 case RN5T618_CONTROL ... RN5T618_CC_AVEREG0: 50 return true; 51 default: 52 return false; 53 } 54 } 55 56 static const struct regmap_config rn5t618_regmap_config = { 57 .reg_bits = 8, 58 .val_bits = 8, 59 .volatile_reg = rn5t618_volatile_reg, 60 .max_register = RN5T618_MAX_REG, 61 .cache_type = REGCACHE_RBTREE, 62 }; 63 64 static const struct regmap_irq rc5t619_irqs[] = { 65 REGMAP_IRQ_REG(RN5T618_IRQ_SYS, 0, BIT(0)), 66 REGMAP_IRQ_REG(RN5T618_IRQ_DCDC, 0, BIT(1)), 67 REGMAP_IRQ_REG(RN5T618_IRQ_RTC, 0, BIT(2)), 68 REGMAP_IRQ_REG(RN5T618_IRQ_ADC, 0, BIT(3)), 69 REGMAP_IRQ_REG(RN5T618_IRQ_GPIO, 0, BIT(4)), 70 REGMAP_IRQ_REG(RN5T618_IRQ_CHG, 0, BIT(6)), 71 }; 72 73 static const struct regmap_irq_chip rc5t619_irq_chip = { 74 .name = "rc5t619", 75 .irqs = rc5t619_irqs, 76 .num_irqs = ARRAY_SIZE(rc5t619_irqs), 77 .num_regs = 1, 78 .status_base = RN5T618_INTMON, 79 .mask_base = RN5T618_INTEN, 80 .mask_invert = true, 81 }; 82 83 static struct i2c_client *rn5t618_pm_power_off; 84 static struct notifier_block rn5t618_restart_handler; 85 86 static int rn5t618_irq_init(struct rn5t618 *rn5t618) 87 { 88 const struct regmap_irq_chip *irq_chip = NULL; 89 int ret; 90 91 if (!rn5t618->irq) 92 return 0; 93 94 switch (rn5t618->variant) { 95 case RC5T619: 96 irq_chip = &rc5t619_irq_chip; 97 break; 98 default: 99 dev_err(rn5t618->dev, "Currently no IRQ support for variant %d\n", 100 (int)rn5t618->variant); 101 return -ENOENT; 102 } 103 104 ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap, 105 rn5t618->irq, 106 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 107 0, irq_chip, &rn5t618->irq_data); 108 if (ret) 109 dev_err(rn5t618->dev, "Failed to register IRQ chip\n"); 110 111 return ret; 112 } 113 114 static void rn5t618_trigger_poweroff_sequence(bool repower) 115 { 116 int ret; 117 118 /* disable automatic repower-on */ 119 ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_REPCNT); 120 if (ret < 0) 121 goto err; 122 123 ret &= ~RN5T618_REPCNT_REPWRON; 124 if (repower) 125 ret |= RN5T618_REPCNT_REPWRON; 126 127 ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off, 128 RN5T618_REPCNT, (u8)ret); 129 if (ret < 0) 130 goto err; 131 132 /* start power-off sequence */ 133 ret = i2c_smbus_read_byte_data(rn5t618_pm_power_off, RN5T618_SLPCNT); 134 if (ret < 0) 135 goto err; 136 137 ret |= RN5T618_SLPCNT_SWPWROFF; 138 139 ret = i2c_smbus_write_byte_data(rn5t618_pm_power_off, 140 RN5T618_SLPCNT, (u8)ret); 141 if (ret < 0) 142 goto err; 143 144 return; 145 146 err: 147 dev_alert(&rn5t618_pm_power_off->dev, "Failed to shutdown (err = %d)\n", ret); 148 } 149 150 static void rn5t618_power_off(void) 151 { 152 rn5t618_trigger_poweroff_sequence(false); 153 } 154 155 static int rn5t618_restart(struct notifier_block *this, 156 unsigned long mode, void *cmd) 157 { 158 rn5t618_trigger_poweroff_sequence(true); 159 160 /* 161 * Re-power factor detection on PMIC side is not instant. 1ms 162 * proved to be enough time until reset takes effect. 163 */ 164 mdelay(1); 165 166 return NOTIFY_DONE; 167 } 168 169 static const struct of_device_id rn5t618_of_match[] = { 170 { .compatible = "ricoh,rn5t567", .data = (void *)RN5T567 }, 171 { .compatible = "ricoh,rn5t618", .data = (void *)RN5T618 }, 172 { .compatible = "ricoh,rc5t619", .data = (void *)RC5T619 }, 173 { } 174 }; 175 MODULE_DEVICE_TABLE(of, rn5t618_of_match); 176 177 static int rn5t618_i2c_probe(struct i2c_client *i2c) 178 { 179 const struct of_device_id *of_id; 180 struct rn5t618 *priv; 181 int ret; 182 183 of_id = of_match_device(rn5t618_of_match, &i2c->dev); 184 if (!of_id) { 185 dev_err(&i2c->dev, "Failed to find matching DT ID\n"); 186 return -EINVAL; 187 } 188 189 priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); 190 if (!priv) 191 return -ENOMEM; 192 193 i2c_set_clientdata(i2c, priv); 194 priv->variant = (long)of_id->data; 195 priv->irq = i2c->irq; 196 priv->dev = &i2c->dev; 197 198 priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config); 199 if (IS_ERR(priv->regmap)) { 200 ret = PTR_ERR(priv->regmap); 201 dev_err(&i2c->dev, "regmap init failed: %d\n", ret); 202 return ret; 203 } 204 205 if (priv->variant == RC5T619) 206 ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, 207 rc5t619_cells, 208 ARRAY_SIZE(rc5t619_cells), 209 NULL, 0, NULL); 210 else 211 ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, 212 rn5t618_cells, 213 ARRAY_SIZE(rn5t618_cells), 214 NULL, 0, NULL); 215 if (ret) { 216 dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); 217 return ret; 218 } 219 220 rn5t618_pm_power_off = i2c; 221 if (of_device_is_system_power_controller(i2c->dev.of_node)) { 222 if (!pm_power_off) 223 pm_power_off = rn5t618_power_off; 224 else 225 dev_warn(&i2c->dev, "Poweroff callback already assigned\n"); 226 } 227 228 rn5t618_restart_handler.notifier_call = rn5t618_restart; 229 rn5t618_restart_handler.priority = 192; 230 231 ret = register_restart_handler(&rn5t618_restart_handler); 232 if (ret) { 233 dev_err(&i2c->dev, "cannot register restart handler, %d\n", ret); 234 return ret; 235 } 236 237 return rn5t618_irq_init(priv); 238 } 239 240 static int rn5t618_i2c_remove(struct i2c_client *i2c) 241 { 242 if (i2c == rn5t618_pm_power_off) { 243 rn5t618_pm_power_off = NULL; 244 pm_power_off = NULL; 245 } 246 247 unregister_restart_handler(&rn5t618_restart_handler); 248 249 return 0; 250 } 251 252 static int __maybe_unused rn5t618_i2c_suspend(struct device *dev) 253 { 254 struct rn5t618 *priv = dev_get_drvdata(dev); 255 256 if (priv->irq) 257 disable_irq(priv->irq); 258 259 return 0; 260 } 261 262 static int __maybe_unused rn5t618_i2c_resume(struct device *dev) 263 { 264 struct rn5t618 *priv = dev_get_drvdata(dev); 265 266 if (priv->irq) 267 enable_irq(priv->irq); 268 269 return 0; 270 } 271 272 static SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops, 273 rn5t618_i2c_suspend, 274 rn5t618_i2c_resume); 275 276 static struct i2c_driver rn5t618_i2c_driver = { 277 .driver = { 278 .name = "rn5t618", 279 .of_match_table = of_match_ptr(rn5t618_of_match), 280 .pm = &rn5t618_i2c_dev_pm_ops, 281 }, 282 .probe_new = rn5t618_i2c_probe, 283 .remove = rn5t618_i2c_remove, 284 }; 285 286 module_i2c_driver(rn5t618_i2c_driver); 287 288 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 289 MODULE_DESCRIPTION("Ricoh RN5T567/618 MFD driver"); 290 MODULE_LICENSE("GPL v2"); 291