1/* 2 * sky81452.c SKY81452 MFD driver 3 * 4 * Copyright 2014 Skyworks Solutions Inc. 5 * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 9 * as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/init.h> 23#include <linux/err.h> 24#include <linux/slab.h> 25#include <linux/i2c.h> 26#include <linux/regmap.h> 27#include <linux/mfd/core.h> 28#include <linux/mfd/sky81452.h> 29 30static const struct regmap_config sky81452_config = { 31 .reg_bits = 8, 32 .val_bits = 8, 33}; 34 35static int sky81452_probe(struct i2c_client *client, 36 const struct i2c_device_id *id) 37{ 38 struct device *dev = &client->dev; 39 const struct sky81452_platform_data *pdata = dev_get_platdata(dev); 40 struct mfd_cell cells[2]; 41 struct regmap *regmap; 42 int ret; 43 44 if (!pdata) { 45 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 46 if (!pdata) 47 return -ENOMEM; 48 } 49 50 regmap = devm_regmap_init_i2c(client, &sky81452_config); 51 if (IS_ERR(regmap)) { 52 dev_err(dev, "failed to initialize.err=%ld\n", PTR_ERR(regmap)); 53 return PTR_ERR(regmap); 54 } 55 56 i2c_set_clientdata(client, regmap); 57 58 memset(cells, 0, sizeof(cells)); 59 cells[0].name = "sky81452-backlight"; 60 cells[0].of_compatible = "skyworks,sky81452-backlight"; 61 cells[0].platform_data = pdata->bl_pdata; 62 cells[0].pdata_size = sizeof(*pdata->bl_pdata); 63 cells[1].name = "sky81452-regulator"; 64 cells[1].platform_data = pdata->regulator_init_data; 65 cells[1].pdata_size = sizeof(*pdata->regulator_init_data); 66 67 ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL); 68 if (ret) 69 dev_err(dev, "failed to add child devices. err=%d\n", ret); 70 71 return ret; 72} 73 74static int sky81452_remove(struct i2c_client *client) 75{ 76 mfd_remove_devices(&client->dev); 77 return 0; 78} 79 80static const struct i2c_device_id sky81452_ids[] = { 81 { "sky81452" }, 82 { } 83}; 84MODULE_DEVICE_TABLE(i2c, sky81452_ids); 85 86#ifdef CONFIG_OF 87static const struct of_device_id sky81452_of_match[] = { 88 { .compatible = "skyworks,sky81452", }, 89 { } 90}; 91MODULE_DEVICE_TABLE(of, sky81452_of_match); 92#endif 93 94static struct i2c_driver sky81452_driver = { 95 .driver = { 96 .name = "sky81452", 97 .of_match_table = of_match_ptr(sky81452_of_match), 98 }, 99 .probe = sky81452_probe, 100 .remove = sky81452_remove, 101 .id_table = sky81452_ids, 102}; 103 104module_i2c_driver(sky81452_driver); 105 106MODULE_DESCRIPTION("Skyworks SKY81452 MFD driver"); 107MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>"); 108MODULE_LICENSE("GPL v2"); 109