intel_pmic_gpio.c revision 456dc301cc3b547b2a674de3028f53fb1453e532
1/* Moorestown PMIC GPIO (access through IPC) driver 2 * Copyright (c) 2008 - 2009, Intel Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 */ 17 18/* Supports: 19 * Moorestown platform PMIC chip 20 */ 21 22#include <linux/module.h> 23#include <linux/kernel.h> 24#include <linux/interrupt.h> 25#include <linux/delay.h> 26#include <linux/stddef.h> 27#include <linux/slab.h> 28#include <linux/ioport.h> 29#include <linux/init.h> 30#include <linux/io.h> 31#include <linux/gpio.h> 32#include <asm/intel_scu_ipc.h> 33#include <linux/device.h> 34#include <linux/intel_pmic_gpio.h> 35#include <linux/platform_device.h> 36 37#define DRIVER_NAME "pmic_gpio" 38 39/* register offset that IPC driver should use 40 * 8 GPIO + 8 GPOSW (6 controllable) + 8GPO 41 */ 42enum pmic_gpio_register { 43 GPIO0 = 0xE0, 44 GPIO7 = 0xE7, 45 GPIOINT = 0xE8, 46 GPOSWCTL0 = 0xEC, 47 GPOSWCTL5 = 0xF1, 48 GPO = 0xF4, 49}; 50 51/* bits definition for GPIO & GPOSW */ 52#define GPIO_DRV 0x01 53#define GPIO_DIR 0x02 54#define GPIO_DIN 0x04 55#define GPIO_DOU 0x08 56#define GPIO_INTCTL 0x30 57#define GPIO_DBC 0xc0 58 59#define GPOSW_DRV 0x01 60#define GPOSW_DOU 0x08 61#define GPOSW_RDRV 0x30 62 63 64#define NUM_GPIO 24 65 66struct pmic_gpio_irq { 67 spinlock_t lock; 68 u32 trigger[NUM_GPIO]; 69 u32 dirty; 70 struct work_struct work; 71}; 72 73 74struct pmic_gpio { 75 struct gpio_chip chip; 76 struct pmic_gpio_irq irqtypes; 77 void *gpiointr; 78 int irq; 79 unsigned irq_base; 80}; 81 82static void pmic_program_irqtype(int gpio, int type) 83{ 84 if (type & IRQ_TYPE_EDGE_RISING) 85 intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20); 86 else 87 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20); 88 89 if (type & IRQ_TYPE_EDGE_FALLING) 90 intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10); 91 else 92 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10); 93}; 94 95static void pmic_irqtype_work(struct work_struct *work) 96{ 97 struct pmic_gpio_irq *t = 98 container_of(work, struct pmic_gpio_irq, work); 99 unsigned long flags; 100 int i; 101 u16 type; 102 103 spin_lock_irqsave(&t->lock, flags); 104 /* As we drop the lock, we may need multiple scans if we race the 105 pmic_irq_type function */ 106 while (t->dirty) { 107 /* 108 * For each pin that has the dirty bit set send an IPC 109 * message to configure the hardware via the PMIC 110 */ 111 for (i = 0; i < NUM_GPIO; i++) { 112 if (!(t->dirty & (1 << i))) 113 continue; 114 t->dirty &= ~(1 << i); 115 /* We can't trust the array entry or dirty 116 once the lock is dropped */ 117 type = t->trigger[i]; 118 spin_unlock_irqrestore(&t->lock, flags); 119 pmic_program_irqtype(i, type); 120 spin_lock_irqsave(&t->lock, flags); 121 } 122 } 123 spin_unlock_irqrestore(&t->lock, flags); 124} 125 126static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 127{ 128 if (offset > 8) { 129 printk(KERN_ERR 130 "%s: only pin 0-7 support input\n", __func__); 131 return -1;/* we only have 8 GPIO can use as input */ 132 } 133 return intel_scu_ipc_update_register(GPIO0 + offset, 134 GPIO_DIR, GPIO_DIR); 135} 136 137static int pmic_gpio_direction_output(struct gpio_chip *chip, 138 unsigned offset, int value) 139{ 140 int rc = 0; 141 142 if (offset < 8)/* it is GPIO */ 143 rc = intel_scu_ipc_update_register(GPIO0 + offset, 144 GPIO_DRV | (value ? GPIO_DOU : 0), 145 GPIO_DRV | GPIO_DOU | GPIO_DIR); 146 else if (offset < 16)/* it is GPOSW */ 147 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 148 GPOSW_DRV | (value ? GPOSW_DOU : 0), 149 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV); 150 else if (offset > 15 && offset < 24)/* it is GPO */ 151 rc = intel_scu_ipc_update_register(GPO, 152 value ? 1 << (offset - 16) : 0, 153 1 << (offset - 16)); 154 else { 155 printk(KERN_ERR 156 "%s: invalid PMIC GPIO pin %d!\n", __func__, offset); 157 WARN_ON(1); 158 } 159 160 return rc; 161} 162 163static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset) 164{ 165 u8 r; 166 int ret; 167 168 /* we only have 8 GPIO pins we can use as input */ 169 if (offset > 8) 170 return -EOPNOTSUPP; 171 ret = intel_scu_ipc_ioread8(GPIO0 + offset, &r); 172 if (ret < 0) 173 return ret; 174 return r & GPIO_DIN; 175} 176 177static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 178{ 179 if (offset < 8)/* it is GPIO */ 180 intel_scu_ipc_update_register(GPIO0 + offset, 181 GPIO_DRV | (value ? GPIO_DOU : 0), 182 GPIO_DRV | GPIO_DOU); 183 else if (offset < 16)/* it is GPOSW */ 184 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 185 GPOSW_DRV | (value ? GPOSW_DOU : 0), 186 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV); 187 else if (offset > 15 && offset < 24) /* it is GPO */ 188 intel_scu_ipc_update_register(GPO, 189 value ? 1 << (offset - 16) : 0, 190 1 << (offset - 16)); 191} 192 193static int pmic_irq_type(unsigned irq, unsigned type) 194{ 195 struct pmic_gpio *pg = get_irq_chip_data(irq); 196 u32 gpio = irq - pg->irq_base; 197 unsigned long flags; 198 199 if (gpio >= pg->chip.ngpio) 200 return -EINVAL; 201 202 spin_lock_irqsave(&pg->irqtypes.lock, flags); 203 pg->irqtypes.trigger[gpio] = type; 204 pg->irqtypes.dirty |= (1 << gpio); 205 spin_unlock_irqrestore(&pg->irqtypes.lock, flags); 206 schedule_work(&pg->irqtypes.work); 207 return 0; 208} 209 210 211 212static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 213{ 214 struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); 215 216 return pg->irq_base + offset; 217} 218 219/* the gpiointr register is read-clear, so just do nothing. */ 220static void pmic_irq_unmask(unsigned irq) 221{ 222}; 223 224static void pmic_irq_mask(unsigned irq) 225{ 226}; 227 228static struct irq_chip pmic_irqchip = { 229 .name = "PMIC-GPIO", 230 .mask = pmic_irq_mask, 231 .unmask = pmic_irq_unmask, 232 .set_type = pmic_irq_type, 233}; 234 235static void pmic_irq_handler(unsigned irq, struct irq_desc *desc) 236{ 237 struct pmic_gpio *pg = (struct pmic_gpio *)get_irq_data(irq); 238 u8 intsts = *((u8 *)pg->gpiointr + 4); 239 int gpio; 240 241 for (gpio = 0; gpio < 8; gpio++) { 242 if (intsts & (1 << gpio)) { 243 pr_debug("pmic pin %d triggered\n", gpio); 244 generic_handle_irq(pg->irq_base + gpio); 245 } 246 } 247 248 if (desc->chip->irq_eoi) 249 desc->chip->irq_eoi(irq_get_irq_data(irq)); 250 else 251 dev_warn(pg->chip.dev, "missing EOI handler for irq %d\n", irq); 252} 253 254static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev) 255{ 256 struct device *dev = &pdev->dev; 257 int irq = platform_get_irq(pdev, 0); 258 struct intel_pmic_gpio_platform_data *pdata = dev->platform_data; 259 260 struct pmic_gpio *pg; 261 int retval; 262 int i; 263 264 if (irq < 0) { 265 dev_dbg(dev, "no IRQ line\n"); 266 return -EINVAL; 267 } 268 269 if (!pdata || !pdata->gpio_base || !pdata->irq_base) { 270 dev_dbg(dev, "incorrect or missing platform data\n"); 271 return -EINVAL; 272 } 273 274 pg = kzalloc(sizeof(*pg), GFP_KERNEL); 275 if (!pg) 276 return -ENOMEM; 277 278 dev_set_drvdata(dev, pg); 279 280 pg->irq = irq; 281 /* setting up SRAM mapping for GPIOINT register */ 282 pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8); 283 if (!pg->gpiointr) { 284 printk(KERN_ERR "%s: Can not map GPIOINT.\n", __func__); 285 retval = -EINVAL; 286 goto err2; 287 } 288 pg->irq_base = pdata->irq_base; 289 pg->chip.label = "intel_pmic"; 290 pg->chip.direction_input = pmic_gpio_direction_input; 291 pg->chip.direction_output = pmic_gpio_direction_output; 292 pg->chip.get = pmic_gpio_get; 293 pg->chip.set = pmic_gpio_set; 294 pg->chip.to_irq = pmic_gpio_to_irq; 295 pg->chip.base = pdata->gpio_base; 296 pg->chip.ngpio = NUM_GPIO; 297 pg->chip.can_sleep = 1; 298 pg->chip.dev = dev; 299 300 INIT_WORK(&pg->irqtypes.work, pmic_irqtype_work); 301 spin_lock_init(&pg->irqtypes.lock); 302 303 pg->chip.dev = dev; 304 retval = gpiochip_add(&pg->chip); 305 if (retval) { 306 printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__); 307 goto err; 308 } 309 set_irq_data(pg->irq, pg); 310 set_irq_chained_handler(pg->irq, pmic_irq_handler); 311 for (i = 0; i < 8; i++) { 312 set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip, 313 handle_simple_irq, "demux"); 314 set_irq_chip_data(i + pg->irq_base, pg); 315 } 316 return 0; 317err: 318 iounmap(pg->gpiointr); 319err2: 320 kfree(pg); 321 return retval; 322} 323 324/* at the same time, register a platform driver 325 * this supports the sfi 0.81 fw */ 326static struct platform_driver platform_pmic_gpio_driver = { 327 .driver = { 328 .name = DRIVER_NAME, 329 .owner = THIS_MODULE, 330 }, 331 .probe = platform_pmic_gpio_probe, 332}; 333 334static int __init platform_pmic_gpio_init(void) 335{ 336 return platform_driver_register(&platform_pmic_gpio_driver); 337} 338 339subsys_initcall(platform_pmic_gpio_init); 340 341MODULE_AUTHOR("Alek Du <alek.du@intel.com>"); 342MODULE_DESCRIPTION("Intel Moorestown PMIC GPIO driver"); 343MODULE_LICENSE("GPL v2"); 344