1 /* 2 * max8907.c - mfd driver for MAX8907 3 * 4 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com> 5 * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/err.h> 13 #include <linux/i2c.h> 14 #include <linux/init.h> 15 #include <linux/interrupt.h> 16 #include <linux/irq.h> 17 #include <linux/mfd/core.h> 18 #include <linux/mfd/max8907.h> 19 #include <linux/module.h> 20 #include <linux/of_device.h> 21 #include <linux/regmap.h> 22 #include <linux/slab.h> 23 24 static struct mfd_cell max8907_cells[] = { 25 { .name = "max8907-regulator", }, 26 { .name = "max8907-rtc", }, 27 }; 28 29 static bool max8907_gen_is_volatile_reg(struct device *dev, unsigned int reg) 30 { 31 switch (reg) { 32 case MAX8907_REG_ON_OFF_IRQ1: 33 case MAX8907_REG_ON_OFF_STAT: 34 case MAX8907_REG_ON_OFF_IRQ2: 35 case MAX8907_REG_CHG_IRQ1: 36 case MAX8907_REG_CHG_IRQ2: 37 case MAX8907_REG_CHG_STAT: 38 return true; 39 default: 40 return false; 41 } 42 } 43 44 static bool max8907_gen_is_precious_reg(struct device *dev, unsigned int reg) 45 { 46 switch (reg) { 47 case MAX8907_REG_ON_OFF_IRQ1: 48 case MAX8907_REG_ON_OFF_IRQ2: 49 case MAX8907_REG_CHG_IRQ1: 50 case MAX8907_REG_CHG_IRQ2: 51 return true; 52 default: 53 return false; 54 } 55 } 56 57 static bool max8907_gen_is_writeable_reg(struct device *dev, unsigned int reg) 58 { 59 return !max8907_gen_is_volatile_reg(dev, reg); 60 } 61 62 static const struct regmap_config max8907_regmap_gen_config = { 63 .reg_bits = 8, 64 .val_bits = 8, 65 .volatile_reg = max8907_gen_is_volatile_reg, 66 .precious_reg = max8907_gen_is_precious_reg, 67 .writeable_reg = max8907_gen_is_writeable_reg, 68 .max_register = MAX8907_REG_LDO20VOUT, 69 .cache_type = REGCACHE_RBTREE, 70 }; 71 72 static bool max8907_rtc_is_volatile_reg(struct device *dev, unsigned int reg) 73 { 74 if (reg <= MAX8907_REG_RTC_YEAR2) 75 return true; 76 77 switch (reg) { 78 case MAX8907_REG_RTC_STATUS: 79 case MAX8907_REG_RTC_IRQ: 80 return true; 81 default: 82 return false; 83 } 84 } 85 86 static bool max8907_rtc_is_precious_reg(struct device *dev, unsigned int reg) 87 { 88 switch (reg) { 89 case MAX8907_REG_RTC_IRQ: 90 return true; 91 default: 92 return false; 93 } 94 } 95 96 static bool max8907_rtc_is_writeable_reg(struct device *dev, unsigned int reg) 97 { 98 switch (reg) { 99 case MAX8907_REG_RTC_STATUS: 100 case MAX8907_REG_RTC_IRQ: 101 return false; 102 default: 103 return true; 104 } 105 } 106 107 static const struct regmap_config max8907_regmap_rtc_config = { 108 .reg_bits = 8, 109 .val_bits = 8, 110 .volatile_reg = max8907_rtc_is_volatile_reg, 111 .precious_reg = max8907_rtc_is_precious_reg, 112 .writeable_reg = max8907_rtc_is_writeable_reg, 113 .max_register = MAX8907_REG_MPL_CNTL, 114 .cache_type = REGCACHE_RBTREE, 115 }; 116 117 static const struct regmap_irq max8907_chg_irqs[] = { 118 { .reg_offset = 0, .mask = 1 << 0, }, 119 { .reg_offset = 0, .mask = 1 << 1, }, 120 { .reg_offset = 0, .mask = 1 << 2, }, 121 { .reg_offset = 1, .mask = 1 << 0, }, 122 { .reg_offset = 1, .mask = 1 << 1, }, 123 { .reg_offset = 1, .mask = 1 << 2, }, 124 { .reg_offset = 1, .mask = 1 << 3, }, 125 { .reg_offset = 1, .mask = 1 << 4, }, 126 { .reg_offset = 1, .mask = 1 << 5, }, 127 { .reg_offset = 1, .mask = 1 << 6, }, 128 { .reg_offset = 1, .mask = 1 << 7, }, 129 }; 130 131 static const struct regmap_irq_chip max8907_chg_irq_chip = { 132 .name = "max8907 chg", 133 .status_base = MAX8907_REG_CHG_IRQ1, 134 .mask_base = MAX8907_REG_CHG_IRQ1_MASK, 135 .wake_base = MAX8907_REG_CHG_IRQ1_MASK, 136 .irq_reg_stride = MAX8907_REG_CHG_IRQ2 - MAX8907_REG_CHG_IRQ1, 137 .num_regs = 2, 138 .irqs = max8907_chg_irqs, 139 .num_irqs = ARRAY_SIZE(max8907_chg_irqs), 140 }; 141 142 static const struct regmap_irq max8907_on_off_irqs[] = { 143 { .reg_offset = 0, .mask = 1 << 0, }, 144 { .reg_offset = 0, .mask = 1 << 1, }, 145 { .reg_offset = 0, .mask = 1 << 2, }, 146 { .reg_offset = 0, .mask = 1 << 3, }, 147 { .reg_offset = 0, .mask = 1 << 4, }, 148 { .reg_offset = 0, .mask = 1 << 5, }, 149 { .reg_offset = 0, .mask = 1 << 6, }, 150 { .reg_offset = 0, .mask = 1 << 7, }, 151 { .reg_offset = 1, .mask = 1 << 0, }, 152 { .reg_offset = 1, .mask = 1 << 1, }, 153 }; 154 155 static const struct regmap_irq_chip max8907_on_off_irq_chip = { 156 .name = "max8907 on_off", 157 .status_base = MAX8907_REG_ON_OFF_IRQ1, 158 .mask_base = MAX8907_REG_ON_OFF_IRQ1_MASK, 159 .irq_reg_stride = MAX8907_REG_ON_OFF_IRQ2 - MAX8907_REG_ON_OFF_IRQ1, 160 .num_regs = 2, 161 .irqs = max8907_on_off_irqs, 162 .num_irqs = ARRAY_SIZE(max8907_on_off_irqs), 163 }; 164 165 static const struct regmap_irq max8907_rtc_irqs[] = { 166 { .reg_offset = 0, .mask = 1 << 2, }, 167 { .reg_offset = 0, .mask = 1 << 3, }, 168 }; 169 170 static const struct regmap_irq_chip max8907_rtc_irq_chip = { 171 .name = "max8907 rtc", 172 .status_base = MAX8907_REG_RTC_IRQ, 173 .mask_base = MAX8907_REG_RTC_IRQ_MASK, 174 .num_regs = 1, 175 .irqs = max8907_rtc_irqs, 176 .num_irqs = ARRAY_SIZE(max8907_rtc_irqs), 177 }; 178 179 static struct max8907 *max8907_pm_off; 180 static void max8907_power_off(void) 181 { 182 regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG, 183 MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF); 184 } 185 186 static int max8907_i2c_probe(struct i2c_client *i2c, 187 const struct i2c_device_id *id) 188 { 189 struct max8907 *max8907; 190 int ret; 191 struct max8907_platform_data *pdata = dev_get_platdata(&i2c->dev); 192 bool pm_off = false; 193 194 if (pdata) 195 pm_off = pdata->pm_off; 196 else if (i2c->dev.of_node) 197 pm_off = of_property_read_bool(i2c->dev.of_node, 198 "maxim,system-power-controller"); 199 200 max8907 = devm_kzalloc(&i2c->dev, sizeof(struct max8907), GFP_KERNEL); 201 if (!max8907) { 202 ret = -ENOMEM; 203 goto err_alloc_drvdata; 204 } 205 206 max8907->dev = &i2c->dev; 207 dev_set_drvdata(max8907->dev, max8907); 208 209 max8907->i2c_gen = i2c; 210 i2c_set_clientdata(i2c, max8907); 211 max8907->regmap_gen = devm_regmap_init_i2c(i2c, 212 &max8907_regmap_gen_config); 213 if (IS_ERR(max8907->regmap_gen)) { 214 ret = PTR_ERR(max8907->regmap_gen); 215 dev_err(&i2c->dev, "gen regmap init failed: %d\n", ret); 216 goto err_regmap_gen; 217 } 218 219 max8907->i2c_rtc = i2c_new_dummy(i2c->adapter, MAX8907_RTC_I2C_ADDR); 220 if (!max8907->i2c_rtc) { 221 ret = -ENOMEM; 222 goto err_dummy_rtc; 223 } 224 i2c_set_clientdata(max8907->i2c_rtc, max8907); 225 max8907->regmap_rtc = devm_regmap_init_i2c(max8907->i2c_rtc, 226 &max8907_regmap_rtc_config); 227 if (IS_ERR(max8907->regmap_rtc)) { 228 ret = PTR_ERR(max8907->regmap_rtc); 229 dev_err(&i2c->dev, "rtc regmap init failed: %d\n", ret); 230 goto err_regmap_rtc; 231 } 232 233 irq_set_status_flags(max8907->i2c_gen->irq, IRQ_NOAUTOEN); 234 235 ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq, 236 IRQF_ONESHOT | IRQF_SHARED, -1, 237 &max8907_chg_irq_chip, 238 &max8907->irqc_chg); 239 if (ret != 0) { 240 dev_err(&i2c->dev, "failed to add chg irq chip: %d\n", ret); 241 goto err_irqc_chg; 242 } 243 ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq, 244 IRQF_ONESHOT | IRQF_SHARED, -1, 245 &max8907_on_off_irq_chip, 246 &max8907->irqc_on_off); 247 if (ret != 0) { 248 dev_err(&i2c->dev, "failed to add on off irq chip: %d\n", ret); 249 goto err_irqc_on_off; 250 } 251 ret = regmap_add_irq_chip(max8907->regmap_rtc, max8907->i2c_gen->irq, 252 IRQF_ONESHOT | IRQF_SHARED, -1, 253 &max8907_rtc_irq_chip, 254 &max8907->irqc_rtc); 255 if (ret != 0) { 256 dev_err(&i2c->dev, "failed to add rtc irq chip: %d\n", ret); 257 goto err_irqc_rtc; 258 } 259 260 enable_irq(max8907->i2c_gen->irq); 261 262 ret = mfd_add_devices(max8907->dev, -1, max8907_cells, 263 ARRAY_SIZE(max8907_cells), NULL, 0, NULL); 264 if (ret != 0) { 265 dev_err(&i2c->dev, "failed to add MFD devices %d\n", ret); 266 goto err_add_devices; 267 } 268 269 if (pm_off && !pm_power_off) { 270 max8907_pm_off = max8907; 271 pm_power_off = max8907_power_off; 272 } 273 274 return 0; 275 276 err_add_devices: 277 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc); 278 err_irqc_rtc: 279 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off); 280 err_irqc_on_off: 281 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg); 282 err_irqc_chg: 283 err_regmap_rtc: 284 i2c_unregister_device(max8907->i2c_rtc); 285 err_dummy_rtc: 286 err_regmap_gen: 287 err_alloc_drvdata: 288 return ret; 289 } 290 291 static int max8907_i2c_remove(struct i2c_client *i2c) 292 { 293 struct max8907 *max8907 = i2c_get_clientdata(i2c); 294 295 mfd_remove_devices(max8907->dev); 296 297 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc); 298 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off); 299 regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg); 300 301 i2c_unregister_device(max8907->i2c_rtc); 302 303 return 0; 304 } 305 306 #ifdef CONFIG_OF 307 static struct of_device_id max8907_of_match[] = { 308 { .compatible = "maxim,max8907" }, 309 { }, 310 }; 311 MODULE_DEVICE_TABLE(of, max8907_of_match); 312 #endif 313 314 static const struct i2c_device_id max8907_i2c_id[] = { 315 {"max8907", 0}, 316 {} 317 }; 318 MODULE_DEVICE_TABLE(i2c, max8907_i2c_id); 319 320 static struct i2c_driver max8907_i2c_driver = { 321 .driver = { 322 .name = "max8907", 323 .owner = THIS_MODULE, 324 .of_match_table = of_match_ptr(max8907_of_match), 325 }, 326 .probe = max8907_i2c_probe, 327 .remove = max8907_i2c_remove, 328 .id_table = max8907_i2c_id, 329 }; 330 331 static int __init max8907_i2c_init(void) 332 { 333 int ret = -ENODEV; 334 335 ret = i2c_add_driver(&max8907_i2c_driver); 336 if (ret != 0) 337 pr_err("Failed to register I2C driver: %d\n", ret); 338 339 return ret; 340 } 341 subsys_initcall(max8907_i2c_init); 342 343 static void __exit max8907_i2c_exit(void) 344 { 345 i2c_del_driver(&max8907_i2c_driver); 346 } 347 module_exit(max8907_i2c_exit); 348 349 MODULE_DESCRIPTION("MAX8907 multi-function core driver"); 350 MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>"); 351 MODULE_LICENSE("GPL v2"); 352