1 /* 2 * Base driver for Analog Devices ADP5520/ADP5501 MFD PMICs 3 * LCD Backlight: drivers/video/backlight/adp5520_bl 4 * LEDs : drivers/led/leds-adp5520 5 * GPIO : drivers/gpio/adp5520-gpio (ADP5520 only) 6 * Keys : drivers/input/keyboard/adp5520-keys (ADP5520 only) 7 * 8 * Copyright 2009 Analog Devices Inc. 9 * 10 * Author: Michael Hennerich <michael.hennerich@analog.com> 11 * 12 * Derived from da903x: 13 * Copyright (C) 2008 Compulab, Ltd. 14 * Mike Rapoport <mike@compulab.co.il> 15 * 16 * Copyright (C) 2006-2008 Marvell International Ltd. 17 * Eric Miao <eric.miao@marvell.com> 18 * 19 * Licensed under the GPL-2 or later. 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/init.h> 24 #include <linux/platform_device.h> 25 #include <linux/slab.h> 26 #include <linux/interrupt.h> 27 #include <linux/irq.h> 28 #include <linux/err.h> 29 #include <linux/i2c.h> 30 31 #include <linux/mfd/adp5520.h> 32 33 struct adp5520_chip { 34 struct i2c_client *client; 35 struct device *dev; 36 struct mutex lock; 37 struct blocking_notifier_head notifier_list; 38 int irq; 39 unsigned long id; 40 uint8_t mode; 41 }; 42 43 static int __adp5520_read(struct i2c_client *client, 44 int reg, uint8_t *val) 45 { 46 int ret; 47 48 ret = i2c_smbus_read_byte_data(client, reg); 49 if (ret < 0) { 50 dev_err(&client->dev, "failed reading at 0x%02x\n", reg); 51 return ret; 52 } 53 54 *val = (uint8_t)ret; 55 return 0; 56 } 57 58 static int __adp5520_write(struct i2c_client *client, 59 int reg, uint8_t val) 60 { 61 int ret; 62 63 ret = i2c_smbus_write_byte_data(client, reg, val); 64 if (ret < 0) { 65 dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", 66 val, reg); 67 return ret; 68 } 69 return 0; 70 } 71 72 static int __adp5520_ack_bits(struct i2c_client *client, int reg, 73 uint8_t bit_mask) 74 { 75 struct adp5520_chip *chip = i2c_get_clientdata(client); 76 uint8_t reg_val; 77 int ret; 78 79 mutex_lock(&chip->lock); 80 81 ret = __adp5520_read(client, reg, ®_val); 82 83 if (!ret) { 84 reg_val |= bit_mask; 85 ret = __adp5520_write(client, reg, reg_val); 86 } 87 88 mutex_unlock(&chip->lock); 89 return ret; 90 } 91 92 int adp5520_write(struct device *dev, int reg, uint8_t val) 93 { 94 return __adp5520_write(to_i2c_client(dev), reg, val); 95 } 96 EXPORT_SYMBOL_GPL(adp5520_write); 97 98 int adp5520_read(struct device *dev, int reg, uint8_t *val) 99 { 100 return __adp5520_read(to_i2c_client(dev), reg, val); 101 } 102 EXPORT_SYMBOL_GPL(adp5520_read); 103 104 int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask) 105 { 106 struct adp5520_chip *chip = dev_get_drvdata(dev); 107 uint8_t reg_val; 108 int ret; 109 110 mutex_lock(&chip->lock); 111 112 ret = __adp5520_read(chip->client, reg, ®_val); 113 114 if (!ret && ((reg_val & bit_mask) != bit_mask)) { 115 reg_val |= bit_mask; 116 ret = __adp5520_write(chip->client, reg, reg_val); 117 } 118 119 mutex_unlock(&chip->lock); 120 return ret; 121 } 122 EXPORT_SYMBOL_GPL(adp5520_set_bits); 123 124 int adp5520_clr_bits(struct device *dev, int reg, uint8_t bit_mask) 125 { 126 struct adp5520_chip *chip = dev_get_drvdata(dev); 127 uint8_t reg_val; 128 int ret; 129 130 mutex_lock(&chip->lock); 131 132 ret = __adp5520_read(chip->client, reg, ®_val); 133 134 if (!ret && (reg_val & bit_mask)) { 135 reg_val &= ~bit_mask; 136 ret = __adp5520_write(chip->client, reg, reg_val); 137 } 138 139 mutex_unlock(&chip->lock); 140 return ret; 141 } 142 EXPORT_SYMBOL_GPL(adp5520_clr_bits); 143 144 int adp5520_register_notifier(struct device *dev, struct notifier_block *nb, 145 unsigned int events) 146 { 147 struct adp5520_chip *chip = dev_get_drvdata(dev); 148 149 if (chip->irq) { 150 adp5520_set_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, 151 events & (ADP5520_KP_IEN | ADP5520_KR_IEN | 152 ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); 153 154 return blocking_notifier_chain_register(&chip->notifier_list, 155 nb); 156 } 157 158 return -ENODEV; 159 } 160 EXPORT_SYMBOL_GPL(adp5520_register_notifier); 161 162 int adp5520_unregister_notifier(struct device *dev, struct notifier_block *nb, 163 unsigned int events) 164 { 165 struct adp5520_chip *chip = dev_get_drvdata(dev); 166 167 adp5520_clr_bits(chip->dev, ADP5520_INTERRUPT_ENABLE, 168 events & (ADP5520_KP_IEN | ADP5520_KR_IEN | 169 ADP5520_OVP_IEN | ADP5520_CMPR_IEN)); 170 171 return blocking_notifier_chain_unregister(&chip->notifier_list, nb); 172 } 173 EXPORT_SYMBOL_GPL(adp5520_unregister_notifier); 174 175 static irqreturn_t adp5520_irq_thread(int irq, void *data) 176 { 177 struct adp5520_chip *chip = data; 178 unsigned int events; 179 uint8_t reg_val; 180 int ret; 181 182 ret = __adp5520_read(chip->client, ADP5520_MODE_STATUS, ®_val); 183 if (ret) 184 goto out; 185 186 events = reg_val & (ADP5520_OVP_INT | ADP5520_CMPR_INT | 187 ADP5520_GPI_INT | ADP5520_KR_INT | ADP5520_KP_INT); 188 189 blocking_notifier_call_chain(&chip->notifier_list, events, NULL); 190 /* ACK, Sticky bits are W1C */ 191 __adp5520_ack_bits(chip->client, ADP5520_MODE_STATUS, events); 192 193 out: 194 return IRQ_HANDLED; 195 } 196 197 static int __remove_subdev(struct device *dev, void *unused) 198 { 199 platform_device_unregister(to_platform_device(dev)); 200 return 0; 201 } 202 203 static int adp5520_remove_subdevs(struct adp5520_chip *chip) 204 { 205 return device_for_each_child(chip->dev, NULL, __remove_subdev); 206 } 207 208 static int adp5520_probe(struct i2c_client *client, 209 const struct i2c_device_id *id) 210 { 211 struct adp5520_platform_data *pdata = dev_get_platdata(&client->dev); 212 struct platform_device *pdev; 213 struct adp5520_chip *chip; 214 int ret; 215 216 if (!i2c_check_functionality(client->adapter, 217 I2C_FUNC_SMBUS_BYTE_DATA)) { 218 dev_err(&client->dev, "SMBUS Word Data not Supported\n"); 219 return -EIO; 220 } 221 222 if (pdata == NULL) { 223 dev_err(&client->dev, "missing platform data\n"); 224 return -ENODEV; 225 } 226 227 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 228 if (!chip) 229 return -ENOMEM; 230 231 i2c_set_clientdata(client, chip); 232 chip->client = client; 233 234 chip->dev = &client->dev; 235 chip->irq = client->irq; 236 chip->id = id->driver_data; 237 mutex_init(&chip->lock); 238 239 if (chip->irq) { 240 BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list); 241 242 ret = request_threaded_irq(chip->irq, NULL, adp5520_irq_thread, 243 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 244 "adp5520", chip); 245 if (ret) { 246 dev_err(&client->dev, "failed to request irq %d\n", 247 chip->irq); 248 return ret; 249 } 250 } 251 252 ret = adp5520_write(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); 253 if (ret) { 254 dev_err(&client->dev, "failed to write\n"); 255 goto out_free_irq; 256 } 257 258 if (pdata->keys) { 259 pdev = platform_device_register_data(chip->dev, "adp5520-keys", 260 chip->id, pdata->keys, sizeof(*pdata->keys)); 261 if (IS_ERR(pdev)) { 262 ret = PTR_ERR(pdev); 263 goto out_remove_subdevs; 264 } 265 } 266 267 if (pdata->gpio) { 268 pdev = platform_device_register_data(chip->dev, "adp5520-gpio", 269 chip->id, pdata->gpio, sizeof(*pdata->gpio)); 270 if (IS_ERR(pdev)) { 271 ret = PTR_ERR(pdev); 272 goto out_remove_subdevs; 273 } 274 } 275 276 if (pdata->leds) { 277 pdev = platform_device_register_data(chip->dev, "adp5520-led", 278 chip->id, pdata->leds, sizeof(*pdata->leds)); 279 if (IS_ERR(pdev)) { 280 ret = PTR_ERR(pdev); 281 goto out_remove_subdevs; 282 } 283 } 284 285 if (pdata->backlight) { 286 pdev = platform_device_register_data(chip->dev, 287 "adp5520-backlight", 288 chip->id, 289 pdata->backlight, 290 sizeof(*pdata->backlight)); 291 if (IS_ERR(pdev)) { 292 ret = PTR_ERR(pdev); 293 goto out_remove_subdevs; 294 } 295 } 296 297 return 0; 298 299 out_remove_subdevs: 300 adp5520_remove_subdevs(chip); 301 302 out_free_irq: 303 if (chip->irq) 304 free_irq(chip->irq, chip); 305 306 return ret; 307 } 308 309 #ifdef CONFIG_PM_SLEEP 310 static int adp5520_suspend(struct device *dev) 311 { 312 struct i2c_client *client = to_i2c_client(dev); 313 struct adp5520_chip *chip = dev_get_drvdata(&client->dev); 314 315 adp5520_read(chip->dev, ADP5520_MODE_STATUS, &chip->mode); 316 /* All other bits are W1C */ 317 chip->mode &= ADP5520_BL_EN | ADP5520_DIM_EN | ADP5520_nSTNBY; 318 adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); 319 return 0; 320 } 321 322 static int adp5520_resume(struct device *dev) 323 { 324 struct i2c_client *client = to_i2c_client(dev); 325 struct adp5520_chip *chip = dev_get_drvdata(&client->dev); 326 327 adp5520_write(chip->dev, ADP5520_MODE_STATUS, chip->mode); 328 return 0; 329 } 330 #endif 331 332 static SIMPLE_DEV_PM_OPS(adp5520_pm, adp5520_suspend, adp5520_resume); 333 334 static const struct i2c_device_id adp5520_id[] = { 335 { "pmic-adp5520", ID_ADP5520 }, 336 { "pmic-adp5501", ID_ADP5501 }, 337 { } 338 }; 339 340 static struct i2c_driver adp5520_driver = { 341 .driver = { 342 .name = "adp5520", 343 .pm = &adp5520_pm, 344 .suppress_bind_attrs = true, 345 }, 346 .probe = adp5520_probe, 347 .id_table = adp5520_id, 348 }; 349 builtin_i2c_driver(adp5520_driver); 350