/* * Core driver for MAXIM MAX77665 * * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #define MAX77665_INT_STS 0x22 #define MAX77665_INT_MSK 0x23 #define MAX77665_PMIC_FLASH 0x00 ... 0x10 #define MAX77665_PMIC_PMIC 0x20 ... 0x2D #define MAX77665_PMIC_CHARGER 0xB0 ... 0xC6 #define MAX77665_MUIC 0x00 ... 0x0E #define MAX77665_HAPTIC 0x00 ... 0x10 static u8 max77665_i2c_slave_address[] = { [MAX77665_I2C_SLAVE_PMIC] = 0x66, [MAX77665_I2C_SLAVE_MUIC] = 0x25, [MAX77665_I2C_SLAVE_HAPTIC] = 0x48, }; struct max77665_irq_data { int bit; }; #define MAX77665_IRQ(_id, _bit_pos) \ [MAX77665_IRQ_##_id] = { \ .bit = (_bit_pos), \ } static const struct max77665_irq_data max77665_irqs[] = { MAX77665_IRQ(CHARGER, 0), MAX77665_IRQ(TOP_SYS, 1), MAX77665_IRQ(FLASH, 2), MAX77665_IRQ(MUIC, 3), }; static struct mfd_cell max77665s[] = { {.name = "max77665-charger",}, {.name = "max77665-flash",}, {.name = "max77665-muic",}, {.name = "max77665-haptic",}, }; static void max77665_irq_lock(struct irq_data *data) { struct max77665 *max77665 = irq_data_get_irq_chip_data(data); mutex_lock(&max77665->irq_lock); } static void max77665_irq_mask(struct irq_data *irq_data) { struct max77665 *max77665 = irq_data_get_irq_chip_data(irq_data); unsigned int __irq = irq_data->irq - max77665->irq_base; const struct max77665_irq_data *data = &max77665_irqs[__irq]; int ret; ret = max77665_set_bits(max77665->dev, MAX77665_I2C_SLAVE_PMIC, MAX77665_INT_MSK, data->bit); if (ret < 0) dev_err(max77665->dev, "Clearing mask reg failed e = %d\n", ret); } static void max77665_irq_unmask(struct irq_data *irq_data) { struct max77665 *max77665 = irq_data_get_irq_chip_data(irq_data); unsigned int __irq = irq_data->irq - max77665->irq_base; const struct max77665_irq_data *data = &max77665_irqs[__irq]; int ret; ret = max77665_clr_bits(max77665->dev, MAX77665_I2C_SLAVE_PMIC, MAX77665_INT_MSK, data->bit); if (ret < 0) dev_err(max77665->dev, "Setting mask reg failed e = %d\n", ret); } static void max77665_irq_sync_unlock(struct irq_data *data) { struct max77665 *max77665 = irq_data_get_irq_chip_data(data); mutex_unlock(&max77665->irq_lock); } static irqreturn_t max77665_irq(int irq, void *data) { struct max77665 *max77665 = data; int ret = 0; u8 status = 0; unsigned long int acks = 0; int i; ret = max77665_read(max77665->dev, MAX77665_I2C_SLAVE_PMIC, MAX77665_INT_STS, &status); if (ret < 0) { dev_err(max77665->dev, "failed to read status regi, e %d\n", ret); return IRQ_NONE; } acks = status; for_each_set_bit(i, &acks, ARRAY_SIZE(max77665_irqs)) handle_nested_irq(max77665->irq_base + i); return acks ? IRQ_HANDLED : IRQ_NONE; } #ifdef CONFIG_PM_SLEEP static int max77665_irq_set_wake(struct irq_data *data, unsigned int enable) { struct max77665 *max77665 = irq_data_get_irq_chip_data(data); return irq_set_irq_wake(max77665->irq_base, enable); } #else #define max77665_irq_set_wake NULL #endif static int __devinit max77665_irq_init(struct max77665 *max77665, int irq, int irq_base) { int i, ret; if (irq_base <= 0) { dev_err(max77665->dev, "IRQ base not set, int not supported\n"); return -EINVAL; } mutex_init(&max77665->irq_lock); ret = max77665_write(max77665->dev, MAX77665_I2C_SLAVE_PMIC, MAX77665_INT_MSK, 0xFF); if (ret < 0) { dev_err(max77665->dev, "Int mask reg write failed, e %d\n", ret); return ret; } max77665->irq_base = irq_base; max77665->irq_chip.name = "max77665"; max77665->irq_chip.irq_mask = max77665_irq_mask; max77665->irq_chip.irq_unmask = max77665_irq_unmask; max77665->irq_chip.irq_bus_lock = max77665_irq_lock; max77665->irq_chip.irq_bus_sync_unlock = max77665_irq_sync_unlock; max77665->irq_chip.irq_set_wake = max77665_irq_set_wake; for (i = 0; i < ARRAY_SIZE(max77665_irqs); i++) { int __irq = i + max77665->irq_base; irq_set_chip_data(__irq, max77665); irq_set_chip_and_handler(__irq, &max77665->irq_chip, handle_simple_irq); irq_set_nested_thread(__irq, 1); #ifdef CONFIG_ARM set_irq_flags(__irq, IRQF_VALID); #endif } ret = request_threaded_irq(irq, NULL, max77665_irq, IRQF_ONESHOT, "max77665", max77665); if (ret < 0) { dev_err(max77665->dev, "Int registration failed, e %d\n", ret); return ret; } device_init_wakeup(max77665->dev, 1); return ret; } static bool rd_wr_reg_pmic(struct device *dev, unsigned int reg) { switch (reg) { case MAX77665_PMIC_FLASH: case MAX77665_PMIC_PMIC: case MAX77665_PMIC_CHARGER: return true; default: dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg); return false; } } static bool rd_wr_reg_muic(struct device *dev, unsigned int reg) { switch (reg) { case MAX77665_MUIC: return true; default: dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg); return false; } } static bool rd_wr_reg_haptic(struct device *dev, unsigned int reg) { switch (reg) { case MAX77665_HAPTIC: return true; default: dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg); return false; } } static const struct regmap_config max77665_regmap_config[] = { { .reg_bits = 8, .val_bits = 8, .max_register = 0xFF, .writeable_reg = rd_wr_reg_pmic, .readable_reg = rd_wr_reg_pmic, .cache_type = REGCACHE_RBTREE, }, { .reg_bits = 8, .val_bits = 8, .max_register = 0x0E, .writeable_reg = rd_wr_reg_muic, .readable_reg = rd_wr_reg_muic, .cache_type = REGCACHE_RBTREE, }, { .reg_bits = 8, .val_bits = 8, .max_register = 0x10, .writeable_reg = rd_wr_reg_haptic, .readable_reg = rd_wr_reg_haptic, .cache_type = REGCACHE_RBTREE, }, }; static int __devinit max77665_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max77665_platform_data *pdata = client->dev.platform_data; struct max77665 *max77665; struct i2c_client *slv_client; int ret; int i; if (!pdata) { dev_err(&client->dev, "max77665 requires platform data\n"); return -EINVAL; } max77665 = devm_kzalloc(&client->dev, sizeof(*max77665), GFP_KERNEL); if (!max77665) { dev_err(&client->dev, "mem alloc for max77665 failed\n"); return -ENOMEM; } max77665->dev = &client->dev; for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) { slv_client = max77665->client[i]; if (i == 0) slv_client = client; else slv_client = i2c_new_dummy(client->adapter, max77665_i2c_slave_address[i]); if (!slv_client) { dev_err(&client->dev, "can't attach client %d\n", i); ret = -ENOMEM; goto err_exit; } i2c_set_clientdata(slv_client, max77665); max77665->regmap[i] = devm_regmap_init_i2c(slv_client, &max77665_regmap_config[i]); if (IS_ERR(max77665->regmap[i])) { ret = PTR_ERR(max77665->regmap[i]); dev_err(&client->dev, "regmap %d init failed with err: %d\n", i, ret); goto err_exit; } } if (client->irq > 0) max77665_irq_init(max77665, client->irq, pdata->irq_base); ret = mfd_add_devices(max77665->dev, -1, max77665s, ARRAY_SIZE(max77665s), NULL, 0); if (ret) { dev_err(&client->dev, "add mfd devices failed with err: %d\n", ret); goto err_irq_exit; } return 0; err_irq_exit: if (client->irq > 0) free_irq(client->irq, max77665); err_exit: for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) { slv_client = max77665->client[i]; if (slv_client && slv_client != client) i2c_unregister_device(slv_client); } return ret; } static int __devexit max77665_i2c_remove(struct i2c_client *client) { struct max77665 *max77665 = i2c_get_clientdata(client); int i; struct i2c_client *slv_client; mfd_remove_devices(max77665->dev); if (client->irq > 0) free_irq(client->irq, max77665); for (i = 0; i < MAX77665_I2C_SLAVE_MAX; ++i) { slv_client = max77665->client[i]; if (slv_client && slv_client != client) i2c_unregister_device(slv_client); } return 0; } static const struct i2c_device_id max77665_id_table[] = { { "max77665", 0 }, { }, }; MODULE_DEVICE_TABLE(i2c, max77665_id_table); static struct i2c_driver max77665_driver = { .driver = { .name = "max77665", .owner = THIS_MODULE, }, .probe = max77665_i2c_probe, .remove = __devexit_p(max77665_i2c_remove), .id_table = max77665_id_table, }; static int __init max77665_init(void) { return i2c_add_driver(&max77665_driver); } subsys_initcall(max77665_init); static void __exit max77665_exit(void) { i2c_del_driver(&max77665_driver); } module_exit(max77665_exit); MODULE_DESCRIPTION("MAXIM MAX77665 core driver"); MODULE_AUTHOR("Laxman Dewangan "); MODULE_LICENSE("GPL v2");