1 /* 2 * Copyright 2009-2010 Creative Product Design 3 * Marc Reilly marc@cpdesign.com.au 4 * 5 * This program is free software; you can redistribute it and/or modify it under 6 * the terms of the GNU General Public License version 2 as published by the 7 * Free Software Foundation. 8 */ 9 10 #include <linux/slab.h> 11 #include <linux/module.h> 12 #include <linux/platform_device.h> 13 #include <linux/mutex.h> 14 #include <linux/mfd/core.h> 15 #include <linux/mfd/mc13xxx.h> 16 #include <linux/of.h> 17 #include <linux/of_device.h> 18 #include <linux/of_gpio.h> 19 #include <linux/i2c.h> 20 #include <linux/err.h> 21 22 #include "mc13xxx.h" 23 24 static const struct i2c_device_id mc13xxx_i2c_device_id[] = { 25 { 26 .name = "mc13892", 27 .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892, 28 }, { 29 .name = "mc34708", 30 .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc34708, 31 }, { 32 /* sentinel */ 33 } 34 }; 35 MODULE_DEVICE_TABLE(i2c, mc13xxx_i2c_device_id); 36 37 static const struct of_device_id mc13xxx_dt_ids[] = { 38 { 39 .compatible = "fsl,mc13892", 40 .data = &mc13xxx_variant_mc13892, 41 }, { 42 .compatible = "fsl,mc34708", 43 .data = &mc13xxx_variant_mc34708, 44 }, { 45 /* sentinel */ 46 } 47 }; 48 MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids); 49 50 static struct regmap_config mc13xxx_regmap_i2c_config = { 51 .reg_bits = 8, 52 .val_bits = 24, 53 54 .max_register = MC13XXX_NUMREGS, 55 56 .cache_type = REGCACHE_NONE, 57 }; 58 59 static int mc13xxx_i2c_probe(struct i2c_client *client, 60 const struct i2c_device_id *id) 61 { 62 struct mc13xxx *mc13xxx; 63 struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev); 64 int ret; 65 66 mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL); 67 if (!mc13xxx) 68 return -ENOMEM; 69 70 dev_set_drvdata(&client->dev, mc13xxx); 71 72 mc13xxx->dev = &client->dev; 73 mutex_init(&mc13xxx->lock); 74 75 mc13xxx->regmap = devm_regmap_init_i2c(client, 76 &mc13xxx_regmap_i2c_config); 77 if (IS_ERR(mc13xxx->regmap)) { 78 ret = PTR_ERR(mc13xxx->regmap); 79 dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", 80 ret); 81 return ret; 82 } 83 84 if (client->dev.of_node) { 85 const struct of_device_id *of_id = 86 of_match_device(mc13xxx_dt_ids, &client->dev); 87 mc13xxx->variant = of_id->data; 88 } else { 89 mc13xxx->variant = (void *)id->driver_data; 90 } 91 92 ret = mc13xxx_common_init(mc13xxx, pdata, client->irq); 93 94 return ret; 95 } 96 97 static int mc13xxx_i2c_remove(struct i2c_client *client) 98 { 99 struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev); 100 101 mc13xxx_common_cleanup(mc13xxx); 102 103 return 0; 104 } 105 106 static struct i2c_driver mc13xxx_i2c_driver = { 107 .id_table = mc13xxx_i2c_device_id, 108 .driver = { 109 .owner = THIS_MODULE, 110 .name = "mc13xxx", 111 .of_match_table = mc13xxx_dt_ids, 112 }, 113 .probe = mc13xxx_i2c_probe, 114 .remove = mc13xxx_i2c_remove, 115 }; 116 117 static int __init mc13xxx_i2c_init(void) 118 { 119 return i2c_add_driver(&mc13xxx_i2c_driver); 120 } 121 subsys_initcall(mc13xxx_i2c_init); 122 123 static void __exit mc13xxx_i2c_exit(void) 124 { 125 i2c_del_driver(&mc13xxx_i2c_driver); 126 } 127 module_exit(mc13xxx_i2c_exit); 128 129 MODULE_DESCRIPTION("i2c driver for Freescale MC13XXX PMIC"); 130 MODULE_AUTHOR("Marc Reilly <marc@cpdesign.com.au"); 131 MODULE_LICENSE("GPL v2"); 132