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 dev_set_drvdata(&client->dev, NULL); 82 return ret; 83 } 84 85 if (client->dev.of_node) { 86 const struct of_device_id *of_id = 87 of_match_device(mc13xxx_dt_ids, &client->dev); 88 mc13xxx->variant = of_id->data; 89 } else { 90 mc13xxx->variant = (void *)id->driver_data; 91 } 92 93 ret = mc13xxx_common_init(mc13xxx, pdata, client->irq); 94 95 return ret; 96 } 97 98 static int mc13xxx_i2c_remove(struct i2c_client *client) 99 { 100 struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev); 101 102 mc13xxx_common_cleanup(mc13xxx); 103 104 return 0; 105 } 106 107 static struct i2c_driver mc13xxx_i2c_driver = { 108 .id_table = mc13xxx_i2c_device_id, 109 .driver = { 110 .owner = THIS_MODULE, 111 .name = "mc13xxx", 112 .of_match_table = mc13xxx_dt_ids, 113 }, 114 .probe = mc13xxx_i2c_probe, 115 .remove = mc13xxx_i2c_remove, 116 }; 117 118 static int __init mc13xxx_i2c_init(void) 119 { 120 return i2c_add_driver(&mc13xxx_i2c_driver); 121 } 122 subsys_initcall(mc13xxx_i2c_init); 123 124 static void __exit mc13xxx_i2c_exit(void) 125 { 126 i2c_del_driver(&mc13xxx_i2c_driver); 127 } 128 module_exit(mc13xxx_i2c_exit); 129 130 MODULE_DESCRIPTION("i2c driver for Freescale MC13XXX PMIC"); 131 MODULE_AUTHOR("Marc Reilly <marc@cpdesign.com.au"); 132 MODULE_LICENSE("GPL v2"); 133