1/* 2 * tps65912-core.c -- TI TPS65912x 3 * 4 * Copyright 2011 Texas Instruments Inc. 5 * 6 * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * This driver is based on wm8350 implementation. 14 */ 15 16#include <linux/module.h> 17#include <linux/moduleparam.h> 18#include <linux/slab.h> 19#include <linux/gpio.h> 20#include <linux/mfd/core.h> 21#include <linux/mfd/tps65912.h> 22 23static const struct mfd_cell tps65912s[] = { 24 { 25 .name = "tps65912-pmic", 26 }, 27}; 28 29int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask) 30{ 31 u8 data; 32 int err; 33 34 mutex_lock(&tps65912->io_mutex); 35 36 err = tps65912->read(tps65912, reg, 1, &data); 37 if (err) { 38 dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); 39 goto out; 40 } 41 42 data |= mask; 43 err = tps65912->write(tps65912, reg, 1, &data); 44 if (err) 45 dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg); 46 47out: 48 mutex_unlock(&tps65912->io_mutex); 49 return err; 50} 51EXPORT_SYMBOL_GPL(tps65912_set_bits); 52 53int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask) 54{ 55 u8 data; 56 int err; 57 58 mutex_lock(&tps65912->io_mutex); 59 err = tps65912->read(tps65912, reg, 1, &data); 60 if (err) { 61 dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); 62 goto out; 63 } 64 65 data &= ~mask; 66 err = tps65912->write(tps65912, reg, 1, &data); 67 if (err) 68 dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg); 69 70out: 71 mutex_unlock(&tps65912->io_mutex); 72 return err; 73} 74EXPORT_SYMBOL_GPL(tps65912_clear_bits); 75 76static inline int tps65912_read(struct tps65912 *tps65912, u8 reg) 77{ 78 u8 val; 79 int err; 80 81 err = tps65912->read(tps65912, reg, 1, &val); 82 if (err < 0) 83 return err; 84 85 return val; 86} 87 88static inline int tps65912_write(struct tps65912 *tps65912, u8 reg, u8 val) 89{ 90 return tps65912->write(tps65912, reg, 1, &val); 91} 92 93int tps65912_reg_read(struct tps65912 *tps65912, u8 reg) 94{ 95 int data; 96 97 mutex_lock(&tps65912->io_mutex); 98 99 data = tps65912_read(tps65912, reg); 100 if (data < 0) 101 dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); 102 103 mutex_unlock(&tps65912->io_mutex); 104 return data; 105} 106EXPORT_SYMBOL_GPL(tps65912_reg_read); 107 108int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val) 109{ 110 int err; 111 112 mutex_lock(&tps65912->io_mutex); 113 114 err = tps65912_write(tps65912, reg, val); 115 if (err < 0) 116 dev_err(tps65912->dev, "Write for reg 0x%x failed\n", reg); 117 118 mutex_unlock(&tps65912->io_mutex); 119 return err; 120} 121EXPORT_SYMBOL_GPL(tps65912_reg_write); 122 123int tps65912_device_init(struct tps65912 *tps65912) 124{ 125 struct tps65912_board *pmic_plat_data = dev_get_platdata(tps65912->dev); 126 struct tps65912_platform_data *init_data; 127 int ret, dcdc_avs, value; 128 129 init_data = kzalloc(sizeof(struct tps65912_platform_data), GFP_KERNEL); 130 if (init_data == NULL) 131 return -ENOMEM; 132 133 mutex_init(&tps65912->io_mutex); 134 dev_set_drvdata(tps65912->dev, tps65912); 135 136 dcdc_avs = (pmic_plat_data->is_dcdc1_avs << 0 | 137 pmic_plat_data->is_dcdc2_avs << 1 | 138 pmic_plat_data->is_dcdc3_avs << 2 | 139 pmic_plat_data->is_dcdc4_avs << 3); 140 if (dcdc_avs) { 141 tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value); 142 dcdc_avs |= value; 143 tps65912->write(tps65912, TPS65912_I2C_SPI_CFG, 1, &dcdc_avs); 144 } 145 146 ret = mfd_add_devices(tps65912->dev, -1, 147 tps65912s, ARRAY_SIZE(tps65912s), 148 NULL, 0, NULL); 149 if (ret < 0) 150 goto err; 151 152 init_data->irq = pmic_plat_data->irq; 153 init_data->irq_base = pmic_plat_data->irq_base; 154 ret = tps65912_irq_init(tps65912, init_data->irq, init_data); 155 if (ret < 0) 156 goto err; 157 158 kfree(init_data); 159 return ret; 160 161err: 162 kfree(init_data); 163 mfd_remove_devices(tps65912->dev); 164 return ret; 165} 166 167void tps65912_device_exit(struct tps65912 *tps65912) 168{ 169 mfd_remove_devices(tps65912->dev); 170 tps65912_irq_exit(tps65912); 171} 172 173MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>"); 174MODULE_DESCRIPTION("TPS65912x chip family multi-function driver"); 175MODULE_LICENSE("GPL"); 176