aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Kunze <thommycheck@gmx.de>2009-02-10 08:50:56 -0500
committerThomas Kunze <tkunze@tkunze-desktop.(none)>2009-11-27 15:07:21 -0500
commit9ca3dc805cd0d89c44f88b9a399061946781323a (patch)
treef00c3eae8adfb627a4daaae8a02c2883347bdcd8
parentcc647172795713e013f8de4bcdf91860e9e87bff (diff)
add gpiolib support to ucb1x00
The old access methods to the gpios will be removed when all users has been converted. (mainly ucb1x00-ts)
-rw-r--r--arch/arm/mach-sa1100/include/mach/mcp.h1
-rw-r--r--drivers/mfd/mcp-sa11x0.c1
-rw-r--r--drivers/mfd/ucb1x00-core.c87
-rw-r--r--include/linux/mfd/mcp.h1
-rw-r--r--include/linux/mfd/ucb1x00.h3
5 files changed, 91 insertions, 2 deletions
diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h
index fb8b09a57ad7..ed1a331508a7 100644
--- a/arch/arm/mach-sa1100/include/mach/mcp.h
+++ b/arch/arm/mach-sa1100/include/mach/mcp.h
@@ -16,6 +16,7 @@ struct mcp_plat_data {
16 u32 mccr0; 16 u32 mccr0;
17 u32 mccr1; 17 u32 mccr1;
18 unsigned int sclk_rate; 18 unsigned int sclk_rate;
19 int gpio_base;
19}; 20};
20 21
21#endif 22#endif
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 212189815c8e..258427232728 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -163,6 +163,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
163 mcp->dma_audio_wr = DMA_Ser4MCP0Wr; 163 mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
164 mcp->dma_telco_rd = DMA_Ser4MCP1Rd; 164 mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
165 mcp->dma_telco_wr = DMA_Ser4MCP1Wr; 165 mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
166 mcp->gpio_base = data->gpio_base;
166 167
167 platform_set_drvdata(pdev, mcp); 168 platform_set_drvdata(pdev, mcp);
168 169
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index f9de7891e57f..252b74188ec2 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -26,11 +26,11 @@
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/mfd/ucb1x00.h> 28#include <linux/mfd/ucb1x00.h>
29#include <linux/gpio.h>
29 30
30#include <mach/dma.h> 31#include <mach/dma.h>
31#include <mach/hardware.h> 32#include <mach/hardware.h>
32 33
33
34static DEFINE_MUTEX(ucb1x00_mutex); 34static DEFINE_MUTEX(ucb1x00_mutex);
35static LIST_HEAD(ucb1x00_drivers); 35static LIST_HEAD(ucb1x00_drivers);
36static LIST_HEAD(ucb1x00_devices); 36static LIST_HEAD(ucb1x00_devices);
@@ -108,6 +108,60 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
108 return ucb1x00_reg_read(ucb, UCB_IO_DATA); 108 return ucb1x00_reg_read(ucb, UCB_IO_DATA);
109} 109}
110 110
111static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
112{
113 struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
114 unsigned long flags;
115
116 spin_lock_irqsave(&ucb->io_lock, flags);
117 if (value)
118 ucb->io_out |= 1 << offset;
119 else
120 ucb->io_out &= ~(1 << offset);
121
122 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
123 spin_unlock_irqrestore(&ucb->io_lock, flags);
124}
125
126static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
127{
128 struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
129 return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
130}
131
132static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
133{
134 struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
135 unsigned long flags;
136
137 spin_lock_irqsave(&ucb->io_lock, flags);
138 ucb->io_dir &= ~(1 << offset);
139 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
140 spin_unlock_irqrestore(&ucb->io_lock, flags);
141
142 return 0;
143}
144
145static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
146 , int value)
147{
148 struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
149 unsigned long flags;
150
151 spin_lock_irqsave(&ucb->io_lock, flags);
152 ucb->io_dir |= (1 << offset);
153 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
154
155 if (value)
156 ucb->io_out |= 1 << offset;
157 else
158 ucb->io_out &= ~(1 << offset);
159 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
160 spin_unlock_irqrestore(&ucb->io_lock, flags);
161
162 return 0;
163}
164
111/* 165/*
112 * UCB1300 data sheet says we must: 166 * UCB1300 data sheet says we must:
113 * 1. enable ADC => 5us (including reference startup time) 167 * 1. enable ADC => 5us (including reference startup time)
@@ -476,6 +530,7 @@ static int ucb1x00_probe(struct mcp *mcp)
476 struct ucb1x00_driver *drv; 530 struct ucb1x00_driver *drv;
477 unsigned int id; 531 unsigned int id;
478 int ret = -ENODEV; 532 int ret = -ENODEV;
533 int temp;
479 534
480 mcp_enable(mcp); 535 mcp_enable(mcp);
481 id = mcp_reg_read(mcp, UCB_ID); 536 id = mcp_reg_read(mcp, UCB_ID);
@@ -508,12 +563,27 @@ static int ucb1x00_probe(struct mcp *mcp)
508 goto err_free; 563 goto err_free;
509 } 564 }
510 565
566 ucb->gpio.base = -1;
567 if (mcp->gpio_base != 0) {
568 ucb->gpio.label = dev_name(&ucb->dev);
569 ucb->gpio.base = mcp->gpio_base;
570 ucb->gpio.ngpio = 10;
571 ucb->gpio.set = ucb1x00_gpio_set;
572 ucb->gpio.get = ucb1x00_gpio_get;
573 ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
574 ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
575 ret = gpiochip_add(&ucb->gpio);
576 if (ret)
577 goto err_free;
578 } else
579 dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
580
511 ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, 581 ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
512 "UCB1x00", ucb); 582 "UCB1x00", ucb);
513 if (ret) { 583 if (ret) {
514 printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", 584 printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
515 ucb->irq, ret); 585 ucb->irq, ret);
516 goto err_free; 586 goto err_gpio;
517 } 587 }
518 588
519 mcp_set_drvdata(mcp, ucb); 589 mcp_set_drvdata(mcp, ucb);
@@ -522,6 +592,7 @@ static int ucb1x00_probe(struct mcp *mcp)
522 if (ret) 592 if (ret)
523 goto err_irq; 593 goto err_irq;
524 594
595
525 INIT_LIST_HEAD(&ucb->devs); 596 INIT_LIST_HEAD(&ucb->devs);
526 mutex_lock(&ucb1x00_mutex); 597 mutex_lock(&ucb1x00_mutex);
527 list_add(&ucb->node, &ucb1x00_devices); 598 list_add(&ucb->node, &ucb1x00_devices);
@@ -529,10 +600,14 @@ static int ucb1x00_probe(struct mcp *mcp)
529 ucb1x00_add_dev(ucb, drv); 600 ucb1x00_add_dev(ucb, drv);
530 } 601 }
531 mutex_unlock(&ucb1x00_mutex); 602 mutex_unlock(&ucb1x00_mutex);
603
532 goto out; 604 goto out;
533 605
534 err_irq: 606 err_irq:
535 free_irq(ucb->irq, ucb); 607 free_irq(ucb->irq, ucb);
608 err_gpio:
609 if (ucb->gpio.base != -1)
610 temp = gpiochip_remove(&ucb->gpio);
536 err_free: 611 err_free:
537 kfree(ucb); 612 kfree(ucb);
538 err_disable: 613 err_disable:
@@ -545,6 +620,7 @@ static void ucb1x00_remove(struct mcp *mcp)
545{ 620{
546 struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 621 struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
547 struct list_head *l, *n; 622 struct list_head *l, *n;
623 int ret;
548 624
549 mutex_lock(&ucb1x00_mutex); 625 mutex_lock(&ucb1x00_mutex);
550 list_del(&ucb->node); 626 list_del(&ucb->node);
@@ -554,6 +630,12 @@ static void ucb1x00_remove(struct mcp *mcp)
554 } 630 }
555 mutex_unlock(&ucb1x00_mutex); 631 mutex_unlock(&ucb1x00_mutex);
556 632
633 if (ucb->gpio.base != -1) {
634 ret = gpiochip_remove(&ucb->gpio);
635 if (ret)
636 dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
637 }
638
557 free_irq(ucb->irq, ucb); 639 free_irq(ucb->irq, ucb);
558 device_unregister(&ucb->dev); 640 device_unregister(&ucb->dev);
559} 641}
@@ -604,6 +686,7 @@ static int ucb1x00_resume(struct mcp *mcp)
604 struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 686 struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
605 struct ucb1x00_dev *dev; 687 struct ucb1x00_dev *dev;
606 688
689 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
607 mutex_lock(&ucb1x00_mutex); 690 mutex_lock(&ucb1x00_mutex);
608 list_for_each_entry(dev, &ucb->devs, dev_node) { 691 list_for_each_entry(dev, &ucb->devs, dev_node) {
609 if (dev->drv->resume) 692 if (dev->drv->resume)
diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h
index be95e09fd746..ee496708e38b 100644
--- a/include/linux/mfd/mcp.h
+++ b/include/linux/mfd/mcp.h
@@ -26,6 +26,7 @@ struct mcp {
26 dma_device_t dma_telco_rd; 26 dma_device_t dma_telco_rd;
27 dma_device_t dma_telco_wr; 27 dma_device_t dma_telco_wr;
28 struct device attached_device; 28 struct device attached_device;
29 int gpio_base;
29}; 30};
30 31
31struct mcp_ops { 32struct mcp_ops {
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
index eac346336382..aa9c3789bed4 100644
--- a/include/linux/mfd/ucb1x00.h
+++ b/include/linux/mfd/ucb1x00.h
@@ -11,6 +11,8 @@
11#define UCB1200_H 11#define UCB1200_H
12 12
13#include <linux/mfd/mcp.h> 13#include <linux/mfd/mcp.h>
14#include <linux/gpio.h>
15
14#define UCB_IO_DATA 0x00 16#define UCB_IO_DATA 0x00
15#define UCB_IO_DIR 0x01 17#define UCB_IO_DIR 0x01
16 18
@@ -123,6 +125,7 @@ struct ucb1x00 {
123 struct device dev; 125 struct device dev;
124 struct list_head node; 126 struct list_head node;
125 struct list_head devs; 127 struct list_head devs;
128 struct gpio_chip gpio;
126}; 129};
127 130
128struct ucb1x00_driver; 131struct ucb1x00_driver;