1 /* Moorestown PMIC GPIO (access through IPC) driver
2 * Copyright (c) 2008 - 2009, Intel Corporation.
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.
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.
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.
19 * Moorestown platform PMIC chip
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>
31 #include <linux/gpio.h>
32 #include <linux/interrupt.h>
33 #include <asm/intel_scu_ipc.h>
34 #include <linux/device.h>
35 #include <linux/intel_pmic_gpio.h>
36 #include <linux/platform_device.h>
38 #define DRIVER_NAME "pmic_gpio"
40 /* register offset that IPC driver should use
41 * 8 GPIO + 8 GPOSW (6 controllable) + 8GPO
43 enum pmic_gpio_register
{
52 /* bits definition for GPIO & GPOSW */
57 #define GPIO_INTCTL 0x30
60 #define GPOSW_DRV 0x01
61 #define GPOSW_DOU 0x08
62 #define GPOSW_RDRV 0x30
67 struct pmic_gpio_irq
{
69 u32 trigger
[NUM_GPIO
];
71 struct work_struct work
;
76 struct gpio_chip chip
;
77 struct pmic_gpio_irq irqtypes
;
83 static void pmic_program_irqtype(int gpio
, int type
)
85 if (type
& IRQ_TYPE_EDGE_RISING
)
86 intel_scu_ipc_update_register(GPIO0
+ gpio
, 0x20, 0x20);
88 intel_scu_ipc_update_register(GPIO0
+ gpio
, 0x00, 0x20);
90 if (type
& IRQ_TYPE_EDGE_FALLING
)
91 intel_scu_ipc_update_register(GPIO0
+ gpio
, 0x10, 0x10);
93 intel_scu_ipc_update_register(GPIO0
+ gpio
, 0x00, 0x10);
96 static void pmic_irqtype_work(struct work_struct
*work
)
98 struct pmic_gpio_irq
*t
=
99 container_of(work
, struct pmic_gpio_irq
, work
);
104 spin_lock_irqsave(&t
->lock
, flags
);
105 /* As we drop the lock, we may need multiple scans if we race the
106 pmic_irq_type function */
109 * For each pin that has the dirty bit set send an IPC
110 * message to configure the hardware via the PMIC
112 for (i
= 0; i
< NUM_GPIO
; i
++) {
113 if (!(t
->dirty
& (1 << i
)))
115 t
->dirty
&= ~(1 << i
);
116 /* We can't trust the array entry or dirty
117 once the lock is dropped */
118 type
= t
->trigger
[i
];
119 spin_unlock_irqrestore(&t
->lock
, flags
);
120 pmic_program_irqtype(i
, type
);
121 spin_lock_irqsave(&t
->lock
, flags
);
124 spin_unlock_irqrestore(&t
->lock
, flags
);
127 static int pmic_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
131 "%s: only pin 0-7 support input\n", __func__
);
132 return -1;/* we only have 8 GPIO can use as input */
134 return intel_scu_ipc_update_register(GPIO0
+ offset
,
138 static int pmic_gpio_direction_output(struct gpio_chip
*chip
,
139 unsigned offset
, int value
)
143 if (offset
< 8)/* it is GPIO */
144 rc
= intel_scu_ipc_update_register(GPIO0
+ offset
,
145 GPIO_DRV
| (value
? GPIO_DOU
: 0),
146 GPIO_DRV
| GPIO_DOU
| GPIO_DIR
);
147 else if (offset
< 16)/* it is GPOSW */
148 rc
= 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 rc
= intel_scu_ipc_update_register(GPO
,
153 value
? 1 << (offset
- 16) : 0,
157 "%s: invalid PMIC GPIO pin %d!\n", __func__
, offset
);
164 static int pmic_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
169 /* we only have 8 GPIO pins we can use as input */
172 ret
= intel_scu_ipc_ioread8(GPIO0
+ offset
, &r
);
178 static void pmic_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
180 if (offset
< 8)/* it is GPIO */
181 intel_scu_ipc_update_register(GPIO0
+ offset
,
182 GPIO_DRV
| (value
? GPIO_DOU
: 0),
183 GPIO_DRV
| GPIO_DOU
);
184 else if (offset
< 16)/* it is GPOSW */
185 intel_scu_ipc_update_register(GPOSWCTL0
+ offset
- 8,
186 GPOSW_DRV
| (value
? GPOSW_DOU
: 0),
187 GPOSW_DRV
| GPOSW_DOU
| GPOSW_RDRV
);
188 else if (offset
> 15 && offset
< 24) /* it is GPO */
189 intel_scu_ipc_update_register(GPO
,
190 value
? 1 << (offset
- 16) : 0,
194 static int pmic_irq_type(unsigned irq
, unsigned type
)
196 struct pmic_gpio
*pg
= get_irq_chip_data(irq
);
197 u32 gpio
= irq
- pg
->irq_base
;
200 if (gpio
> pg
->chip
.ngpio
)
203 spin_lock_irqsave(&pg
->irqtypes
.lock
, flags
);
204 pg
->irqtypes
.trigger
[gpio
] = type
;
205 pg
->irqtypes
.dirty
|= (1 << gpio
);
206 spin_unlock_irqrestore(&pg
->irqtypes
.lock
, flags
);
207 schedule_work(&pg
->irqtypes
.work
);
213 static int pmic_gpio_to_irq(struct gpio_chip
*chip
, unsigned offset
)
215 struct pmic_gpio
*pg
= container_of(chip
, struct pmic_gpio
, chip
);
217 return pg
->irq_base
+ offset
;
220 /* the gpiointr register is read-clear, so just do nothing. */
221 static void pmic_irq_unmask(unsigned irq
)
225 static void pmic_irq_mask(unsigned irq
)
229 static struct irq_chip pmic_irqchip
= {
231 .mask
= pmic_irq_mask
,
232 .unmask
= pmic_irq_unmask
,
233 .set_type
= pmic_irq_type
,
236 static void pmic_irq_handler(unsigned irq
, struct irq_desc
*desc
)
238 struct pmic_gpio
*pg
= (struct pmic_gpio
*)get_irq_data(irq
);
239 u8 intsts
= *((u8
*)pg
->gpiointr
+ 4);
242 for (gpio
= 0; gpio
< 8; gpio
++) {
243 if (intsts
& (1 << gpio
)) {
244 pr_debug("pmic pin %d triggered\n", gpio
);
245 generic_handle_irq(pg
->irq_base
+ gpio
);
248 desc
->chip
->eoi(irq
);
251 static int __devinit
platform_pmic_gpio_probe(struct platform_device
*pdev
)
253 struct device
*dev
= &pdev
->dev
;
254 int irq
= platform_get_irq(pdev
, 0);
255 struct intel_pmic_gpio_platform_data
*pdata
= dev
->platform_data
;
257 struct pmic_gpio
*pg
;
262 dev_dbg(dev
, "no IRQ line\n");
266 if (!pdata
|| !pdata
->gpio_base
|| !pdata
->irq_base
) {
267 dev_dbg(dev
, "incorrect or missing platform data\n");
271 pg
= kzalloc(sizeof(*pg
), GFP_KERNEL
);
275 dev_set_drvdata(dev
, pg
);
278 /* setting up SRAM mapping for GPIOINT register */
279 pg
->gpiointr
= ioremap_nocache(pdata
->gpiointr
, 8);
281 printk(KERN_ERR
"%s: Can not map GPIOINT.\n", __func__
);
285 pg
->irq_base
= pdata
->irq_base
;
286 pg
->chip
.label
= "intel_pmic";
287 pg
->chip
.direction_input
= pmic_gpio_direction_input
;
288 pg
->chip
.direction_output
= pmic_gpio_direction_output
;
289 pg
->chip
.get
= pmic_gpio_get
;
290 pg
->chip
.set
= pmic_gpio_set
;
291 pg
->chip
.to_irq
= pmic_gpio_to_irq
;
292 pg
->chip
.base
= pdata
->gpio_base
;
293 pg
->chip
.ngpio
= NUM_GPIO
;
294 pg
->chip
.can_sleep
= 1;
297 INIT_WORK(&pg
->irqtypes
.work
, pmic_irqtype_work
);
298 spin_lock_init(&pg
->irqtypes
.lock
);
301 retval
= gpiochip_add(&pg
->chip
);
303 printk(KERN_ERR
"%s: Can not add pmic gpio chip.\n", __func__
);
306 set_irq_data(pg
->irq
, pg
);
307 set_irq_chained_handler(pg
->irq
, pmic_irq_handler
);
308 for (i
= 0; i
< 8; i
++) {
309 set_irq_chip_and_handler_name(i
+ pg
->irq_base
, &pmic_irqchip
,
310 handle_simple_irq
, "demux");
311 set_irq_chip_data(i
+ pg
->irq_base
, pg
);
315 iounmap(pg
->gpiointr
);
321 /* at the same time, register a platform driver
322 * this supports the sfi 0.81 fw */
323 static struct platform_driver platform_pmic_gpio_driver
= {
326 .owner
= THIS_MODULE
,
328 .probe
= platform_pmic_gpio_probe
,
331 static int __init
platform_pmic_gpio_init(void)
333 return platform_driver_register(&platform_pmic_gpio_driver
);
336 subsys_initcall(platform_pmic_gpio_init
);
338 MODULE_AUTHOR("Alek Du <alek.du@intel.com>");
339 MODULE_DESCRIPTION("Intel Moorestown PMIC GPIO driver");
340 MODULE_LICENSE("GPL v2");