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