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#define pr_fmt(fmt) "%s: " fmt, __func__ 23 24#include <linux/module.h> 25#include <linux/kernel.h> 26#include <linux/interrupt.h> 27#include <linux/delay.h> 28#include <linux/stddef.h> 29#include <linux/slab.h> 30#include <linux/ioport.h> 31#include <linux/init.h> 32#include <linux/io.h> 33#include <linux/gpio.h> 34#include <asm/intel_scu_ipc.h> 35#include <linux/device.h> 36#include <linux/intel_pmic_gpio.h> 37#include <linux/platform_device.h> 38 39#define DRIVER_NAME "pmic_gpio" 40 41/* register offset that IPC driver should use 42 * 8 GPIO + 8 GPOSW (6 controllable) + 8GPO 43 */ 44enum pmic_gpio_register { 45 GPIO0 = 0xE0, 46 GPIO7 = 0xE7, 47 GPIOINT = 0xE8, 48 GPOSWCTL0 = 0xEC, 49 GPOSWCTL5 = 0xF1, 50 GPO = 0xF4, 51}; 52 53/* bits definition for GPIO & GPOSW */ 54#define GPIO_DRV 0x01 55#define GPIO_DIR 0x02 56#define GPIO_DIN 0x04 57#define GPIO_DOU 0x08 58#define GPIO_INTCTL 0x30 59#define GPIO_DBC 0xc0 60 61#define GPOSW_DRV 0x01 62#define GPOSW_DOU 0x08 63#define GPOSW_RDRV 0x30 64 65#define GPIO_UPDATE_TYPE 0x80000000 66 67#define NUM_GPIO 24 68 69struct pmic_gpio { 70 struct mutex buslock; 71 struct gpio_chip chip; 72 void *gpiointr; 73 int irq; 74 unsigned irq_base; 75 unsigned int update_type; 76 u32 trigger_type; 77}; 78 79static void pmic_program_irqtype(int gpio, int type) 80{ 81 if (type & IRQ_TYPE_EDGE_RISING) 82 intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20); 83 else 84 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20); 85 86 if (type & IRQ_TYPE_EDGE_FALLING) 87 intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10); 88 else 89 intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10); 90}; 91 92static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 93{ 94 if (offset >= 8) { 95 pr_err("only pin 0-7 support input\n"); 96 return -1;/* we only have 8 GPIO can use as input */ 97 } 98 return intel_scu_ipc_update_register(GPIO0 + offset, 99 GPIO_DIR, GPIO_DIR); 100} 101 102static int pmic_gpio_direction_output(struct gpio_chip *chip, 103 unsigned offset, int value) 104{ 105 int rc = 0; 106 107 if (offset < 8)/* it is GPIO */ 108 rc = intel_scu_ipc_update_register(GPIO0 + offset, 109 GPIO_DRV | (value ? GPIO_DOU : 0), 110 GPIO_DRV | GPIO_DOU | GPIO_DIR); 111 else if (offset < 16)/* it is GPOSW */ 112 rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 113 GPOSW_DRV | (value ? GPOSW_DOU : 0), 114 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV); 115 else if (offset > 15 && offset < 24)/* it is GPO */ 116 rc = intel_scu_ipc_update_register(GPO, 117 value ? 1 << (offset - 16) : 0, 118 1 << (offset - 16)); 119 else { 120 pr_err("invalid PMIC GPIO pin %d!\n", offset); 121 WARN_ON(1); 122 } 123 124 return rc; 125} 126 127static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset) 128{ 129 u8 r; 130 int ret; 131 132 /* we only have 8 GPIO pins we can use as input */ 133 if (offset >= 8) 134 return -EOPNOTSUPP; 135 ret = intel_scu_ipc_ioread8(GPIO0 + offset, &r); 136 if (ret < 0) 137 return ret; 138 return r & GPIO_DIN; 139} 140 141static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 142{ 143 if (offset < 8)/* it is GPIO */ 144 intel_scu_ipc_update_register(GPIO0 + offset, 145 GPIO_DRV | (value ? GPIO_DOU : 0), 146 GPIO_DRV | GPIO_DOU); 147 else if (offset < 16)/* it is GPOSW */ 148 intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 149 GPOSW_DRV | (value ? GPOSW_DOU : 0), 150 GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV); 151 else if (offset > 15 && offset < 24) /* it is GPO */ 152 intel_scu_ipc_update_register(GPO, 153 value ? 1 << (offset - 16) : 0, 154 1 << (offset - 16)); 155} 156 157/* 158 * This is called from genirq with pg->buslock locked and 159 * irq_desc->lock held. We can not access the scu bus here, so we 160 * store the change and update in the bus_sync_unlock() function below 161 */ 162static int pmic_irq_type(struct irq_data *data, unsigned type) 163{ 164 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data); 165 u32 gpio = data->irq - pg->irq_base; 166 167 if (gpio >= pg->chip.ngpio) 168 return -EINVAL; 169 170 pg->trigger_type = type; 171 pg->update_type = gpio | GPIO_UPDATE_TYPE; 172 return 0; 173} 174 175static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 176{ 177 struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); 178 179 return pg->irq_base + offset; 180} 181 182static void pmic_bus_lock(struct irq_data *data) 183{ 184 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data); 185 186 mutex_lock(&pg->buslock); 187} 188 189static void pmic_bus_sync_unlock(struct irq_data *data) 190{ 191 struct pmic_gpio *pg = irq_data_get_irq_chip_data(data); 192 193 if (pg->update_type) { 194 unsigned int gpio = pg->update_type & ~GPIO_UPDATE_TYPE; 195 196 pmic_program_irqtype(gpio, pg->trigger_type); 197 pg->update_type = 0; 198 } 199 mutex_unlock(&pg->buslock); 200} 201 202/* the gpiointr register is read-clear, so just do nothing. */ 203static void pmic_irq_unmask(struct irq_data *data) { } 204 205static void pmic_irq_mask(struct irq_data *data) { } 206 207static struct irq_chip pmic_irqchip = { 208 .name = "PMIC-GPIO", 209 .irq_mask = pmic_irq_mask, 210 .irq_unmask = pmic_irq_unmask, 211 .irq_set_type = pmic_irq_type, 212 .irq_bus_lock = pmic_bus_lock, 213 .irq_bus_sync_unlock = pmic_bus_sync_unlock, 214}; 215 216static irqreturn_t pmic_irq_handler(int irq, void *data) 217{ 218 struct pmic_gpio *pg = data; 219 u8 intsts = *((u8 *)pg->gpiointr + 4); 220 int gpio; 221 irqreturn_t ret = IRQ_NONE; 222 223 for (gpio = 0; gpio < 8; gpio++) { 224 if (intsts & (1 << gpio)) { 225 pr_debug("pmic pin %d triggered\n", gpio); 226 generic_handle_irq(pg->irq_base + gpio); 227 ret = IRQ_HANDLED; 228 } 229 } 230 return ret; 231} 232 233static int platform_pmic_gpio_probe(struct platform_device *pdev) 234{ 235 struct device *dev = &pdev->dev; 236 int irq = platform_get_irq(pdev, 0); 237 struct intel_pmic_gpio_platform_data *pdata = dev->platform_data; 238 239 struct pmic_gpio *pg; 240 int retval; 241 int i; 242 243 if (irq < 0) { 244 dev_dbg(dev, "no IRQ line\n"); 245 return -EINVAL; 246 } 247 248 if (!pdata || !pdata->gpio_base || !pdata->irq_base) { 249 dev_dbg(dev, "incorrect or missing platform data\n"); 250 return -EINVAL; 251 } 252 253 pg = kzalloc(sizeof(*pg), GFP_KERNEL); 254 if (!pg) 255 return -ENOMEM; 256 257 dev_set_drvdata(dev, pg); 258 259 pg->irq = irq; 260 /* setting up SRAM mapping for GPIOINT register */ 261 pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8); 262 if (!pg->gpiointr) { 263 pr_err("Can not map GPIOINT\n"); 264 retval = -EINVAL; 265 goto err2; 266 } 267 pg->irq_base = pdata->irq_base; 268 pg->chip.label = "intel_pmic"; 269 pg->chip.direction_input = pmic_gpio_direction_input; 270 pg->chip.direction_output = pmic_gpio_direction_output; 271 pg->chip.get = pmic_gpio_get; 272 pg->chip.set = pmic_gpio_set; 273 pg->chip.to_irq = pmic_gpio_to_irq; 274 pg->chip.base = pdata->gpio_base; 275 pg->chip.ngpio = NUM_GPIO; 276 pg->chip.can_sleep = 1; 277 pg->chip.dev = dev; 278 279 mutex_init(&pg->buslock); 280 281 pg->chip.dev = dev; 282 retval = gpiochip_add(&pg->chip); 283 if (retval) { 284 pr_err("Can not add pmic gpio chip\n"); 285 goto err; 286 } 287 288 retval = request_irq(pg->irq, pmic_irq_handler, 0, "pmic", pg); 289 if (retval) { 290 pr_warn("Interrupt request failed\n"); 291 goto fail_request_irq; 292 } 293 294 for (i = 0; i < 8; i++) { 295 irq_set_chip_and_handler_name(i + pg->irq_base, 296 &pmic_irqchip, 297 handle_simple_irq, 298 "demux"); 299 irq_set_chip_data(i + pg->irq_base, pg); 300 } 301 return 0; 302 303fail_request_irq: 304 gpiochip_remove(&pg->chip); 305err: 306 iounmap(pg->gpiointr); 307err2: 308 kfree(pg); 309 return retval; 310} 311 312/* at the same time, register a platform driver 313 * this supports the sfi 0.81 fw */ 314static struct platform_driver platform_pmic_gpio_driver = { 315 .driver = { 316 .name = DRIVER_NAME, 317 }, 318 .probe = platform_pmic_gpio_probe, 319}; 320 321static int __init platform_pmic_gpio_init(void) 322{ 323 return platform_driver_register(&platform_pmic_gpio_driver); 324} 325 326subsys_initcall(platform_pmic_gpio_init); 327 328MODULE_AUTHOR("Alek Du <alek.du@intel.com>"); 329MODULE_DESCRIPTION("Intel Moorestown PMIC GPIO driver"); 330MODULE_LICENSE("GPL v2"); 331