Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: Add support for Intel Crystal Cove PMIC

Devices based on Intel SoC products such as Baytrail have a Power
Management IC. In the PMIC there are subsystems for voltage regulation,
A/D conversion, GPIO and PWMs. The PMIC in Baytrail-T platform is
called Crystal Cove.

This patch adds support for the GPIO function in Crystal Cove.

Signed-off-by: Yang, Bin <bin.yang@intel.com>
Signed-off-by: Zhu, Lejun <lejun.zhu@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Zhu, Lejun and committed by
Lee Jones
104fb1d5 7cf0a66f

+393
+13
drivers/gpio/Kconfig
··· 450 450 help 451 451 Support for GPIOs on Wolfson Arizona class devices. 452 452 453 + config GPIO_CRYSTAL_COVE 454 + tristate "GPIO support for Crystal Cove PMIC" 455 + depends on INTEL_SOC_PMIC 456 + select GPIOLIB_IRQCHIP 457 + help 458 + Support for GPIO pins on Crystal Cove PMIC. 459 + 460 + Say Yes if you have a Intel SoC based tablet with Crystal Cove PMIC 461 + inside. 462 + 463 + This driver can also be built as a module. If so, the module will be 464 + called gpio-crystalcove. 465 + 453 466 config GPIO_LP3943 454 467 tristate "TI/National Semiconductor LP3943 GPIO expander" 455 468 depends on MFD_LP3943
+1
drivers/gpio/Makefile
··· 20 20 obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o 21 21 obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o 22 22 obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o 23 + obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o 23 24 obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 24 25 obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o 25 26 obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
+379
drivers/gpio/gpio-crystalcove.c
··· 1 + /* 2 + * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver 3 + * 4 + * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License version 8 + * 2 as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * Author: Yang, Bin <bin.yang@intel.com> 16 + */ 17 + 18 + #include <linux/interrupt.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/gpio.h> 21 + #include <linux/bitops.h> 22 + #include <linux/regmap.h> 23 + #include <linux/mfd/intel_soc_pmic.h> 24 + 25 + #define CRYSTALCOVE_GPIO_NUM 16 26 + 27 + #define UPDATE_IRQ_TYPE BIT(0) 28 + #define UPDATE_IRQ_MASK BIT(1) 29 + 30 + #define GPIO0IRQ 0x0b 31 + #define GPIO1IRQ 0x0c 32 + #define MGPIO0IRQS0 0x19 33 + #define MGPIO1IRQS0 0x1a 34 + #define MGPIO0IRQSX 0x1b 35 + #define MGPIO1IRQSX 0x1c 36 + #define GPIO0P0CTLO 0x2b 37 + #define GPIO0P0CTLI 0x33 38 + #define GPIO1P0CTLO 0x3b 39 + #define GPIO1P0CTLI 0x43 40 + 41 + #define CTLI_INTCNT_DIS (0) 42 + #define CTLI_INTCNT_NE (1 << 1) 43 + #define CTLI_INTCNT_PE (2 << 1) 44 + #define CTLI_INTCNT_BE (3 << 1) 45 + 46 + #define CTLO_DIR_IN (0) 47 + #define CTLO_DIR_OUT (1 << 5) 48 + 49 + #define CTLO_DRV_CMOS (0) 50 + #define CTLO_DRV_OD (1 << 4) 51 + 52 + #define CTLO_DRV_REN (1 << 3) 53 + 54 + #define CTLO_RVAL_2KDW (0) 55 + #define CTLO_RVAL_2KUP (1 << 1) 56 + #define CTLO_RVAL_50KDW (2 << 1) 57 + #define CTLO_RVAL_50KUP (3 << 1) 58 + 59 + #define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP) 60 + #define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET) 61 + 62 + enum ctrl_register { 63 + CTRL_IN, 64 + CTRL_OUT, 65 + }; 66 + 67 + /** 68 + * struct crystalcove_gpio - Crystal Cove GPIO controller 69 + * @buslock: for bus lock/sync and unlock. 70 + * @chip: the abstract gpio_chip structure. 71 + * @regmap: the regmap from the parent device. 72 + * @update: pending IRQ setting update, to be written to the chip upon unlock. 73 + * @intcnt_value: the Interrupt Detect value to be written. 74 + * @set_irq_mask: true if the IRQ mask needs to be set, false to clear. 75 + */ 76 + struct crystalcove_gpio { 77 + struct mutex buslock; /* irq_bus_lock */ 78 + struct gpio_chip chip; 79 + struct regmap *regmap; 80 + int update; 81 + int intcnt_value; 82 + bool set_irq_mask; 83 + }; 84 + 85 + static inline struct crystalcove_gpio *to_cg(struct gpio_chip *gc) 86 + { 87 + return container_of(gc, struct crystalcove_gpio, chip); 88 + } 89 + 90 + static inline int to_reg(int gpio, enum ctrl_register reg_type) 91 + { 92 + int reg; 93 + 94 + if (reg_type == CTRL_IN) { 95 + if (gpio < 8) 96 + reg = GPIO0P0CTLI; 97 + else 98 + reg = GPIO1P0CTLI; 99 + } else { 100 + if (gpio < 8) 101 + reg = GPIO0P0CTLO; 102 + else 103 + reg = GPIO1P0CTLO; 104 + } 105 + 106 + return reg + gpio % 8; 107 + } 108 + 109 + static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg, 110 + int gpio) 111 + { 112 + u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0; 113 + int mask = BIT(gpio % 8); 114 + 115 + if (cg->set_irq_mask) 116 + regmap_update_bits(cg->regmap, mirqs0, mask, mask); 117 + else 118 + regmap_update_bits(cg->regmap, mirqs0, mask, 0); 119 + } 120 + 121 + static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio) 122 + { 123 + int reg = to_reg(gpio, CTRL_IN); 124 + 125 + regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value); 126 + } 127 + 128 + static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) 129 + { 130 + struct crystalcove_gpio *cg = to_cg(chip); 131 + 132 + return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), 133 + CTLO_INPUT_SET); 134 + } 135 + 136 + static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, 137 + int value) 138 + { 139 + struct crystalcove_gpio *cg = to_cg(chip); 140 + 141 + return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), 142 + CTLO_OUTPUT_SET | value); 143 + } 144 + 145 + static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) 146 + { 147 + struct crystalcove_gpio *cg = to_cg(chip); 148 + int ret; 149 + unsigned int val; 150 + 151 + ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); 152 + if (ret) 153 + return ret; 154 + 155 + return val & 0x1; 156 + } 157 + 158 + static void crystalcove_gpio_set(struct gpio_chip *chip, 159 + unsigned gpio, int value) 160 + { 161 + struct crystalcove_gpio *cg = to_cg(chip); 162 + 163 + if (value) 164 + regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); 165 + else 166 + regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0); 167 + } 168 + 169 + static int crystalcove_irq_type(struct irq_data *data, unsigned type) 170 + { 171 + struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data)); 172 + 173 + switch (type) { 174 + case IRQ_TYPE_NONE: 175 + cg->intcnt_value = CTLI_INTCNT_DIS; 176 + break; 177 + case IRQ_TYPE_EDGE_BOTH: 178 + cg->intcnt_value = CTLI_INTCNT_BE; 179 + break; 180 + case IRQ_TYPE_EDGE_RISING: 181 + cg->intcnt_value = CTLI_INTCNT_PE; 182 + break; 183 + case IRQ_TYPE_EDGE_FALLING: 184 + cg->intcnt_value = CTLI_INTCNT_NE; 185 + break; 186 + default: 187 + return -EINVAL; 188 + } 189 + 190 + cg->update |= UPDATE_IRQ_TYPE; 191 + 192 + return 0; 193 + } 194 + 195 + static void crystalcove_bus_lock(struct irq_data *data) 196 + { 197 + struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data)); 198 + 199 + mutex_lock(&cg->buslock); 200 + } 201 + 202 + static void crystalcove_bus_sync_unlock(struct irq_data *data) 203 + { 204 + struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data)); 205 + int gpio = data->hwirq; 206 + 207 + if (cg->update & UPDATE_IRQ_TYPE) 208 + crystalcove_update_irq_ctrl(cg, gpio); 209 + if (cg->update & UPDATE_IRQ_MASK) 210 + crystalcove_update_irq_mask(cg, gpio); 211 + cg->update = 0; 212 + 213 + mutex_unlock(&cg->buslock); 214 + } 215 + 216 + static void crystalcove_irq_unmask(struct irq_data *data) 217 + { 218 + struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data)); 219 + 220 + cg->set_irq_mask = false; 221 + cg->update |= UPDATE_IRQ_MASK; 222 + } 223 + 224 + static void crystalcove_irq_mask(struct irq_data *data) 225 + { 226 + struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data)); 227 + 228 + cg->set_irq_mask = true; 229 + cg->update |= UPDATE_IRQ_MASK; 230 + } 231 + 232 + static struct irq_chip crystalcove_irqchip = { 233 + .name = "Crystal Cove", 234 + .irq_mask = crystalcove_irq_mask, 235 + .irq_unmask = crystalcove_irq_unmask, 236 + .irq_set_type = crystalcove_irq_type, 237 + .irq_bus_lock = crystalcove_bus_lock, 238 + .irq_bus_sync_unlock = crystalcove_bus_sync_unlock, 239 + }; 240 + 241 + static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) 242 + { 243 + struct crystalcove_gpio *cg = data; 244 + unsigned int p0, p1; 245 + int pending; 246 + int gpio; 247 + unsigned int virq; 248 + 249 + if (regmap_read(cg->regmap, GPIO0IRQ, &p0) || 250 + regmap_read(cg->regmap, GPIO1IRQ, &p1)) 251 + return IRQ_NONE; 252 + 253 + regmap_write(cg->regmap, GPIO0IRQ, p0); 254 + regmap_write(cg->regmap, GPIO1IRQ, p1); 255 + 256 + pending = p0 | p1 << 8; 257 + 258 + for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { 259 + if (pending & BIT(gpio)) { 260 + virq = irq_find_mapping(cg->chip.irqdomain, gpio); 261 + generic_handle_irq(virq); 262 + } 263 + } 264 + 265 + return IRQ_HANDLED; 266 + } 267 + 268 + static void crystalcove_gpio_dbg_show(struct seq_file *s, 269 + struct gpio_chip *chip) 270 + { 271 + struct crystalcove_gpio *cg = to_cg(chip); 272 + int gpio, offset; 273 + unsigned int ctlo, ctli, mirqs0, mirqsx, irq; 274 + 275 + for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { 276 + regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); 277 + regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli); 278 + regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0, 279 + &mirqs0); 280 + regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQSX : MGPIO1IRQSX, 281 + &mirqsx); 282 + regmap_read(cg->regmap, gpio < 8 ? GPIO0IRQ : GPIO1IRQ, 283 + &irq); 284 + 285 + offset = gpio % 8; 286 + seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s %s\n", 287 + gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ", 288 + ctli & 0x1 ? "hi" : "lo", 289 + ctli & CTLI_INTCNT_NE ? "fall" : " ", 290 + ctli & CTLI_INTCNT_PE ? "rise" : " ", 291 + ctlo, 292 + mirqs0 & BIT(offset) ? "s0 mask " : "s0 unmask", 293 + mirqsx & BIT(offset) ? "sx mask " : "sx unmask", 294 + irq & BIT(offset) ? "pending" : " "); 295 + } 296 + } 297 + 298 + static int crystalcove_gpio_probe(struct platform_device *pdev) 299 + { 300 + int irq = platform_get_irq(pdev, 0); 301 + struct crystalcove_gpio *cg; 302 + int retval; 303 + struct device *dev = pdev->dev.parent; 304 + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 305 + 306 + if (irq < 0) 307 + return irq; 308 + 309 + cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL); 310 + if (!cg) 311 + return -ENOMEM; 312 + 313 + platform_set_drvdata(pdev, cg); 314 + 315 + mutex_init(&cg->buslock); 316 + cg->chip.label = KBUILD_MODNAME; 317 + cg->chip.direction_input = crystalcove_gpio_dir_in; 318 + cg->chip.direction_output = crystalcove_gpio_dir_out; 319 + cg->chip.get = crystalcove_gpio_get; 320 + cg->chip.set = crystalcove_gpio_set; 321 + cg->chip.base = -1; 322 + cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM; 323 + cg->chip.can_sleep = true; 324 + cg->chip.dev = dev; 325 + cg->chip.dbg_show = crystalcove_gpio_dbg_show; 326 + cg->regmap = pmic->regmap; 327 + 328 + retval = gpiochip_add(&cg->chip); 329 + if (retval) { 330 + dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval); 331 + return retval; 332 + } 333 + 334 + gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0, 335 + handle_simple_irq, IRQ_TYPE_NONE); 336 + 337 + retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler, 338 + IRQF_ONESHOT, KBUILD_MODNAME, cg); 339 + 340 + if (retval) { 341 + dev_warn(&pdev->dev, "request irq failed: %d\n", retval); 342 + goto out_remove_gpio; 343 + } 344 + 345 + return 0; 346 + 347 + out_remove_gpio: 348 + WARN_ON(gpiochip_remove(&cg->chip)); 349 + return retval; 350 + } 351 + 352 + static int crystalcove_gpio_remove(struct platform_device *pdev) 353 + { 354 + struct crystalcove_gpio *cg = platform_get_drvdata(pdev); 355 + int irq = platform_get_irq(pdev, 0); 356 + int err; 357 + 358 + err = gpiochip_remove(&cg->chip); 359 + 360 + if (irq >= 0) 361 + free_irq(irq, cg); 362 + 363 + return err; 364 + } 365 + 366 + static struct platform_driver crystalcove_gpio_driver = { 367 + .probe = crystalcove_gpio_probe, 368 + .remove = crystalcove_gpio_remove, 369 + .driver = { 370 + .name = "crystal_cove_gpio", 371 + .owner = THIS_MODULE, 372 + }, 373 + }; 374 + 375 + module_platform_driver(crystalcove_gpio_driver); 376 + 377 + MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); 378 + MODULE_DESCRIPTION("Intel Crystal Cove GPIO Driver"); 379 + MODULE_LICENSE("GPL v2");