1 /* 2 * TI Palmas MFD Driver 3 * 4 * Copyright 2011-2012 Texas Instruments Inc. 5 * 6 * Author: Graeme Gregory <gg@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 */ 14 15 #include <linux/module.h> 16 #include <linux/moduleparam.h> 17 #include <linux/init.h> 18 #include <linux/slab.h> 19 #include <linux/i2c.h> 20 #include <linux/interrupt.h> 21 #include <linux/irq.h> 22 #include <linux/regmap.h> 23 #include <linux/err.h> 24 #include <linux/mfd/core.h> 25 #include <linux/mfd/palmas.h> 26 27 static const struct resource gpadc_resource[] = { 28 { 29 .name = "EOC_SW", 30 .start = PALMAS_GPADC_EOC_SW_IRQ, 31 .end = PALMAS_GPADC_EOC_SW_IRQ, 32 .flags = IORESOURCE_IRQ, 33 } 34 }; 35 36 static const struct resource usb_resource[] = { 37 { 38 .name = "ID", 39 .start = PALMAS_ID_OTG_IRQ, 40 .end = PALMAS_ID_OTG_IRQ, 41 .flags = IORESOURCE_IRQ, 42 }, 43 { 44 .name = "ID_WAKEUP", 45 .start = PALMAS_ID_IRQ, 46 .end = PALMAS_ID_IRQ, 47 .flags = IORESOURCE_IRQ, 48 }, 49 { 50 .name = "VBUS", 51 .start = PALMAS_VBUS_OTG_IRQ, 52 .end = PALMAS_VBUS_OTG_IRQ, 53 .flags = IORESOURCE_IRQ, 54 }, 55 { 56 .name = "VBUS_WAKEUP", 57 .start = PALMAS_VBUS_IRQ, 58 .end = PALMAS_VBUS_IRQ, 59 .flags = IORESOURCE_IRQ, 60 }, 61 }; 62 63 static const struct resource rtc_resource[] = { 64 { 65 .name = "RTC_ALARM", 66 .start = PALMAS_RTC_ALARM_IRQ, 67 .end = PALMAS_RTC_ALARM_IRQ, 68 .flags = IORESOURCE_IRQ, 69 }, 70 }; 71 72 static const struct resource pwron_resource[] = { 73 { 74 .name = "PWRON_BUTTON", 75 .start = PALMAS_PWRON_IRQ, 76 .end = PALMAS_PWRON_IRQ, 77 .flags = IORESOURCE_IRQ, 78 }, 79 }; 80 81 enum palmas_ids { 82 PALMAS_PMIC_ID, 83 PALMAS_GPIO_ID, 84 PALMAS_LEDS_ID, 85 PALMAS_WDT_ID, 86 PALMAS_RTC_ID, 87 PALMAS_PWRBUTTON_ID, 88 PALMAS_GPADC_ID, 89 PALMAS_RESOURCE_ID, 90 PALMAS_CLK_ID, 91 PALMAS_PWM_ID, 92 PALMAS_USB_ID, 93 }; 94 95 static const struct mfd_cell palmas_children[] = { 96 { 97 .name = "palmas-pmic", 98 .id = PALMAS_PMIC_ID, 99 }, 100 { 101 .name = "palmas-gpio", 102 .id = PALMAS_GPIO_ID, 103 }, 104 { 105 .name = "palmas-leds", 106 .id = PALMAS_LEDS_ID, 107 }, 108 { 109 .name = "palmas-wdt", 110 .id = PALMAS_WDT_ID, 111 }, 112 { 113 .name = "palmas-rtc", 114 .num_resources = ARRAY_SIZE(rtc_resource), 115 .resources = rtc_resource, 116 .id = PALMAS_RTC_ID, 117 }, 118 { 119 .name = "palmas-pwrbutton", 120 .num_resources = ARRAY_SIZE(pwron_resource), 121 .resources = pwron_resource, 122 .id = PALMAS_PWRBUTTON_ID, 123 }, 124 { 125 .name = "palmas-gpadc", 126 .num_resources = ARRAY_SIZE(gpadc_resource), 127 .resources = gpadc_resource, 128 .id = PALMAS_GPADC_ID, 129 }, 130 { 131 .name = "palmas-resource", 132 .id = PALMAS_RESOURCE_ID, 133 }, 134 { 135 .name = "palmas-clk", 136 .id = PALMAS_CLK_ID, 137 }, 138 { 139 .name = "palmas-pwm", 140 .id = PALMAS_PWM_ID, 141 }, 142 { 143 .name = "palmas-usb", 144 .num_resources = ARRAY_SIZE(usb_resource), 145 .resources = usb_resource, 146 .id = PALMAS_USB_ID, 147 } 148 }; 149 150 static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { 151 { 152 .reg_bits = 8, 153 .val_bits = 8, 154 .max_register = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 155 PALMAS_PRIMARY_SECONDARY_PAD3), 156 }, 157 { 158 .reg_bits = 8, 159 .val_bits = 8, 160 .max_register = PALMAS_BASE_TO_REG(PALMAS_GPADC_BASE, 161 PALMAS_GPADC_SMPS_VSEL_MONITORING), 162 }, 163 { 164 .reg_bits = 8, 165 .val_bits = 8, 166 .max_register = PALMAS_BASE_TO_REG(PALMAS_TRIM_GPADC_BASE, 167 PALMAS_GPADC_TRIM16), 168 }, 169 }; 170 171 static const struct regmap_irq palmas_irqs[] = { 172 /* INT1 IRQs */ 173 [PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = { 174 .mask = PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV, 175 }, 176 [PALMAS_PWRON_IRQ] = { 177 .mask = PALMAS_INT1_STATUS_PWRON, 178 }, 179 [PALMAS_LONG_PRESS_KEY_IRQ] = { 180 .mask = PALMAS_INT1_STATUS_LONG_PRESS_KEY, 181 }, 182 [PALMAS_RPWRON_IRQ] = { 183 .mask = PALMAS_INT1_STATUS_RPWRON, 184 }, 185 [PALMAS_PWRDOWN_IRQ] = { 186 .mask = PALMAS_INT1_STATUS_PWRDOWN, 187 }, 188 [PALMAS_HOTDIE_IRQ] = { 189 .mask = PALMAS_INT1_STATUS_HOTDIE, 190 }, 191 [PALMAS_VSYS_MON_IRQ] = { 192 .mask = PALMAS_INT1_STATUS_VSYS_MON, 193 }, 194 [PALMAS_VBAT_MON_IRQ] = { 195 .mask = PALMAS_INT1_STATUS_VBAT_MON, 196 }, 197 /* INT2 IRQs*/ 198 [PALMAS_RTC_ALARM_IRQ] = { 199 .mask = PALMAS_INT2_STATUS_RTC_ALARM, 200 .reg_offset = 1, 201 }, 202 [PALMAS_RTC_TIMER_IRQ] = { 203 .mask = PALMAS_INT2_STATUS_RTC_TIMER, 204 .reg_offset = 1, 205 }, 206 [PALMAS_WDT_IRQ] = { 207 .mask = PALMAS_INT2_STATUS_WDT, 208 .reg_offset = 1, 209 }, 210 [PALMAS_BATREMOVAL_IRQ] = { 211 .mask = PALMAS_INT2_STATUS_BATREMOVAL, 212 .reg_offset = 1, 213 }, 214 [PALMAS_RESET_IN_IRQ] = { 215 .mask = PALMAS_INT2_STATUS_RESET_IN, 216 .reg_offset = 1, 217 }, 218 [PALMAS_FBI_BB_IRQ] = { 219 .mask = PALMAS_INT2_STATUS_FBI_BB, 220 .reg_offset = 1, 221 }, 222 [PALMAS_SHORT_IRQ] = { 223 .mask = PALMAS_INT2_STATUS_SHORT, 224 .reg_offset = 1, 225 }, 226 [PALMAS_VAC_ACOK_IRQ] = { 227 .mask = PALMAS_INT2_STATUS_VAC_ACOK, 228 .reg_offset = 1, 229 }, 230 /* INT3 IRQs */ 231 [PALMAS_GPADC_AUTO_0_IRQ] = { 232 .mask = PALMAS_INT3_STATUS_GPADC_AUTO_0, 233 .reg_offset = 2, 234 }, 235 [PALMAS_GPADC_AUTO_1_IRQ] = { 236 .mask = PALMAS_INT3_STATUS_GPADC_AUTO_1, 237 .reg_offset = 2, 238 }, 239 [PALMAS_GPADC_EOC_SW_IRQ] = { 240 .mask = PALMAS_INT3_STATUS_GPADC_EOC_SW, 241 .reg_offset = 2, 242 }, 243 [PALMAS_GPADC_EOC_RT_IRQ] = { 244 .mask = PALMAS_INT3_STATUS_GPADC_EOC_RT, 245 .reg_offset = 2, 246 }, 247 [PALMAS_ID_OTG_IRQ] = { 248 .mask = PALMAS_INT3_STATUS_ID_OTG, 249 .reg_offset = 2, 250 }, 251 [PALMAS_ID_IRQ] = { 252 .mask = PALMAS_INT3_STATUS_ID, 253 .reg_offset = 2, 254 }, 255 [PALMAS_VBUS_OTG_IRQ] = { 256 .mask = PALMAS_INT3_STATUS_VBUS_OTG, 257 .reg_offset = 2, 258 }, 259 [PALMAS_VBUS_IRQ] = { 260 .mask = PALMAS_INT3_STATUS_VBUS, 261 .reg_offset = 2, 262 }, 263 /* INT4 IRQs */ 264 [PALMAS_GPIO_0_IRQ] = { 265 .mask = PALMAS_INT4_STATUS_GPIO_0, 266 .reg_offset = 3, 267 }, 268 [PALMAS_GPIO_1_IRQ] = { 269 .mask = PALMAS_INT4_STATUS_GPIO_1, 270 .reg_offset = 3, 271 }, 272 [PALMAS_GPIO_2_IRQ] = { 273 .mask = PALMAS_INT4_STATUS_GPIO_2, 274 .reg_offset = 3, 275 }, 276 [PALMAS_GPIO_3_IRQ] = { 277 .mask = PALMAS_INT4_STATUS_GPIO_3, 278 .reg_offset = 3, 279 }, 280 [PALMAS_GPIO_4_IRQ] = { 281 .mask = PALMAS_INT4_STATUS_GPIO_4, 282 .reg_offset = 3, 283 }, 284 [PALMAS_GPIO_5_IRQ] = { 285 .mask = PALMAS_INT4_STATUS_GPIO_5, 286 .reg_offset = 3, 287 }, 288 [PALMAS_GPIO_6_IRQ] = { 289 .mask = PALMAS_INT4_STATUS_GPIO_6, 290 .reg_offset = 3, 291 }, 292 [PALMAS_GPIO_7_IRQ] = { 293 .mask = PALMAS_INT4_STATUS_GPIO_7, 294 .reg_offset = 3, 295 }, 296 }; 297 298 static struct regmap_irq_chip palmas_irq_chip = { 299 .name = "palmas", 300 .irqs = palmas_irqs, 301 .num_irqs = ARRAY_SIZE(palmas_irqs), 302 303 .num_regs = 4, 304 .irq_reg_stride = 5, 305 .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 306 PALMAS_INT1_STATUS), 307 .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 308 PALMAS_INT1_MASK), 309 }; 310 311 static int __devinit palmas_i2c_probe(struct i2c_client *i2c, 312 const struct i2c_device_id *id) 313 { 314 struct palmas *palmas; 315 struct palmas_platform_data *pdata; 316 int ret = 0, i; 317 unsigned int reg, addr; 318 int slave; 319 struct mfd_cell *children; 320 321 pdata = dev_get_platdata(&i2c->dev); 322 if (!pdata) 323 return -EINVAL; 324 325 palmas = devm_kzalloc(&i2c->dev, sizeof(struct palmas), GFP_KERNEL); 326 if (palmas == NULL) 327 return -ENOMEM; 328 329 i2c_set_clientdata(i2c, palmas); 330 palmas->dev = &i2c->dev; 331 palmas->id = id->driver_data; 332 palmas->irq = i2c->irq; 333 334 for (i = 0; i < PALMAS_NUM_CLIENTS; i++) { 335 if (i == 0) 336 palmas->i2c_clients[i] = i2c; 337 else { 338 palmas->i2c_clients[i] = 339 i2c_new_dummy(i2c->adapter, 340 i2c->addr + i); 341 if (!palmas->i2c_clients[i]) { 342 dev_err(palmas->dev, 343 "can't attach client %d\n", i); 344 ret = -ENOMEM; 345 goto err; 346 } 347 } 348 palmas->regmap[i] = devm_regmap_init_i2c(palmas->i2c_clients[i], 349 &palmas_regmap_config[i]); 350 if (IS_ERR(palmas->regmap[i])) { 351 ret = PTR_ERR(palmas->regmap[i]); 352 dev_err(palmas->dev, 353 "Failed to allocate regmap %d, err: %d\n", 354 i, ret); 355 goto err; 356 } 357 } 358 359 /* Change IRQ into clear on read mode for efficiency */ 360 slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); 361 addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); 362 reg = PALMAS_INT_CTRL_INT_CLEAR; 363 364 regmap_write(palmas->regmap[slave], addr, reg); 365 366 ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, 367 IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip, 368 &palmas->irq_data); 369 if (ret < 0) 370 goto err; 371 372 slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); 373 addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 374 PALMAS_PRIMARY_SECONDARY_PAD1); 375 376 if (pdata->mux_from_pdata) { 377 reg = pdata->pad1; 378 ret = regmap_write(palmas->regmap[slave], addr, reg); 379 if (ret) 380 goto err; 381 } else { 382 ret = regmap_read(palmas->regmap[slave], addr, ®); 383 if (ret) 384 goto err; 385 } 386 387 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0)) 388 palmas->gpio_muxed |= PALMAS_GPIO_0_MUXED; 389 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK)) 390 palmas->gpio_muxed |= PALMAS_GPIO_1_MUXED; 391 else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == 392 (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) 393 palmas->led_muxed |= PALMAS_LED1_MUXED; 394 else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == 395 (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) 396 palmas->pwm_muxed |= PALMAS_PWM1_MUXED; 397 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK)) 398 palmas->gpio_muxed |= PALMAS_GPIO_2_MUXED; 399 else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == 400 (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) 401 palmas->led_muxed |= PALMAS_LED2_MUXED; 402 else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == 403 (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) 404 palmas->pwm_muxed |= PALMAS_PWM2_MUXED; 405 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3)) 406 palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED; 407 408 addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 409 PALMAS_PRIMARY_SECONDARY_PAD2); 410 411 if (pdata->mux_from_pdata) { 412 reg = pdata->pad2; 413 ret = regmap_write(palmas->regmap[slave], addr, reg); 414 if (ret) 415 goto err; 416 } else { 417 ret = regmap_read(palmas->regmap[slave], addr, ®); 418 if (ret) 419 goto err; 420 } 421 422 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4)) 423 palmas->gpio_muxed |= PALMAS_GPIO_4_MUXED; 424 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK)) 425 palmas->gpio_muxed |= PALMAS_GPIO_5_MUXED; 426 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6)) 427 palmas->gpio_muxed |= PALMAS_GPIO_6_MUXED; 428 if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK)) 429 palmas->gpio_muxed |= PALMAS_GPIO_7_MUXED; 430 431 dev_info(palmas->dev, "Muxing GPIO %x, PWM %x, LED %x\n", 432 palmas->gpio_muxed, palmas->pwm_muxed, 433 palmas->led_muxed); 434 435 reg = pdata->power_ctrl; 436 437 slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); 438 addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL); 439 440 ret = regmap_write(palmas->regmap[slave], addr, reg); 441 if (ret) 442 goto err; 443 444 children = kmemdup(palmas_children, sizeof(palmas_children), 445 GFP_KERNEL); 446 if (!children) { 447 ret = -ENOMEM; 448 goto err; 449 } 450 451 children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata; 452 children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata); 453 454 ret = mfd_add_devices(palmas->dev, -1, 455 children, ARRAY_SIZE(palmas_children), 456 NULL, regmap_irq_chip_get_base(palmas->irq_data)); 457 kfree(children); 458 459 if (ret < 0) 460 goto err; 461 462 return ret; 463 464 err: 465 mfd_remove_devices(palmas->dev); 466 kfree(palmas); 467 return ret; 468 } 469 470 static int palmas_i2c_remove(struct i2c_client *i2c) 471 { 472 struct palmas *palmas = i2c_get_clientdata(i2c); 473 474 mfd_remove_devices(palmas->dev); 475 regmap_del_irq_chip(palmas->irq, palmas->irq_data); 476 477 return 0; 478 } 479 480 static const struct i2c_device_id palmas_i2c_id[] = { 481 { "palmas", }, 482 { "twl6035", }, 483 { "twl6037", }, 484 { "tps65913", }, 485 { /* end */ } 486 }; 487 MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); 488 489 static struct of_device_id __devinitdata of_palmas_match_tbl[] = { 490 { .compatible = "ti,palmas", }, 491 { /* end */ } 492 }; 493 494 static struct i2c_driver palmas_i2c_driver = { 495 .driver = { 496 .name = "palmas", 497 .of_match_table = of_palmas_match_tbl, 498 .owner = THIS_MODULE, 499 }, 500 .probe = palmas_i2c_probe, 501 .remove = palmas_i2c_remove, 502 .id_table = palmas_i2c_id, 503 }; 504 505 static int __init palmas_i2c_init(void) 506 { 507 return i2c_add_driver(&palmas_i2c_driver); 508 } 509 /* init early so consumer devices can complete system boot */ 510 subsys_initcall(palmas_i2c_init); 511 512 static void __exit palmas_i2c_exit(void) 513 { 514 i2c_del_driver(&palmas_i2c_driver); 515 } 516 module_exit(palmas_i2c_exit); 517 518 MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 519 MODULE_DESCRIPTION("Palmas chip family multi-function driver"); 520 MODULE_LICENSE("GPL"); 521