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