Merge branch 'org.openembedded.dev' of git@git.openembedded.net:openembedded into...
[vuplus_openembedded] / packages / linux / linux-2.6.28 / collie / 0016-add-gpiolib-support-to-ucb1x00.patch
1 From 1de1b5c2860d889a9422f187ad90d8e38b2431fd Mon Sep 17 00:00:00 2001
2 From: Thomas Kunze <thommycheck@gmx.de>
3 Date: Tue, 10 Feb 2009 14:50:56 +0100
4 Subject: [PATCH 16/23] add gpiolib support to ucb1x00
5
6 The old access methods to the gpios will be removed when
7 all users has been converted. (mainly ucb1x00-ts)
8 ---
9  arch/arm/mach-sa1100/include/mach/mcp.h |    1 +
10  drivers/mfd/mcp-sa11x0.c                |    1 +
11  drivers/mfd/ucb1x00-core.c              |   87 ++++++++++++++++++++++++++++++-
12  include/linux/mfd/mcp.h                 |    1 +
13  include/linux/mfd/ucb1x00.h             |    3 +
14  5 files changed, 91 insertions(+), 2 deletions(-)
15
16 diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h
17 index fb8b09a..ed1a331 100644
18 --- a/arch/arm/mach-sa1100/include/mach/mcp.h
19 +++ b/arch/arm/mach-sa1100/include/mach/mcp.h
20 @@ -16,6 +16,7 @@ struct mcp_plat_data {
21         u32 mccr0;
22         u32 mccr1;
23         unsigned int sclk_rate;
24 +       int gpio_base;
25  };
26  
27  #endif
28 diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
29 index 88c81cf..dfa59eb 100644
30 --- a/drivers/mfd/mcp-sa11x0.c
31 +++ b/drivers/mfd/mcp-sa11x0.c
32 @@ -163,6 +163,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
33         mcp->dma_audio_wr       = DMA_Ser4MCP0Wr;
34         mcp->dma_telco_rd       = DMA_Ser4MCP1Rd;
35         mcp->dma_telco_wr       = DMA_Ser4MCP1Wr;
36 +       mcp->gpio_base          = data->gpio_base;
37  
38         platform_set_drvdata(pdev, mcp);
39  
40 diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
41 index bc2c1ba..b9c3f3d 100644
42 --- a/drivers/mfd/ucb1x00-core.c
43 +++ b/drivers/mfd/ucb1x00-core.c
44 @@ -25,11 +25,11 @@
45  #include <linux/device.h>
46  #include <linux/mutex.h>
47  #include <linux/mfd/ucb1x00.h>
48 +#include <linux/gpio.h>
49  
50  #include <asm/dma.h>
51  #include <mach/hardware.h>
52  
53 -
54  static DEFINE_MUTEX(ucb1x00_mutex);
55  static LIST_HEAD(ucb1x00_drivers);
56  static LIST_HEAD(ucb1x00_devices);
57 @@ -107,6 +107,60 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
58         return ucb1x00_reg_read(ucb, UCB_IO_DATA);
59  }
60  
61 +static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
62 +{
63 +       struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
64 +       unsigned long flags;
65 +
66 +       spin_lock_irqsave(&ucb->io_lock, flags);
67 +       if (value)
68 +               ucb->io_out |= 1 << offset;
69 +       else
70 +               ucb->io_out &= ~(1 << offset);
71 +
72 +       ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
73 +       spin_unlock_irqrestore(&ucb->io_lock, flags);
74 +}
75 +
76 +static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
77 +{
78 +       struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
79 +       return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
80 +}
81 +
82 +static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
83 +{
84 +       struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
85 +       unsigned long flags;
86 +
87 +       spin_lock_irqsave(&ucb->io_lock, flags);
88 +       ucb->io_dir &= ~(1 << offset);
89 +       ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
90 +       spin_unlock_irqrestore(&ucb->io_lock, flags);
91 +
92 +       return 0;
93 +}
94 +
95 +static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
96 +               , int value)
97 +{
98 +       struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
99 +       unsigned long flags;
100 +
101 +       spin_lock_irqsave(&ucb->io_lock, flags);
102 +       ucb->io_dir |= (1 << offset);
103 +       ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
104 +
105 +       if (value)
106 +               ucb->io_out |= 1 << offset;
107 +       else
108 +               ucb->io_out &= ~(1 << offset);
109 +       ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
110 +       spin_unlock_irqrestore(&ucb->io_lock, flags);
111 +
112 +       return 0;
113 +}
114 +
115  /*
116   * UCB1300 data sheet says we must:
117   *  1. enable ADC      => 5us (including reference startup time)
118 @@ -475,6 +529,7 @@ static int ucb1x00_probe(struct mcp *mcp)
119         struct ucb1x00_driver *drv;
120         unsigned int id;
121         int ret = -ENODEV;
122 +       int temp;
123  
124         mcp_enable(mcp);
125         id = mcp_reg_read(mcp, UCB_ID);
126 @@ -507,12 +562,27 @@ static int ucb1x00_probe(struct mcp *mcp)
127                 goto err_free;
128         }
129  
130 +       ucb->gpio.base = -1;
131 +       if (mcp->gpio_base != 0) {
132 +               ucb->gpio.label = dev_name(&ucb->dev);
133 +               ucb->gpio.base = mcp->gpio_base;
134 +               ucb->gpio.ngpio = 10;
135 +               ucb->gpio.set = ucb1x00_gpio_set;
136 +               ucb->gpio.get = ucb1x00_gpio_get;
137 +               ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
138 +               ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
139 +               ret = gpiochip_add(&ucb->gpio);
140 +               if (ret)
141 +                       goto err_free;
142 +       } else
143 +               dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
144 +
145         ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
146                           "UCB1x00", ucb);
147         if (ret) {
148                 printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
149                         ucb->irq, ret);
150 -               goto err_free;
151 +               goto err_gpio;
152         }
153  
154         mcp_set_drvdata(mcp, ucb);
155 @@ -521,6 +591,7 @@ static int ucb1x00_probe(struct mcp *mcp)
156         if (ret)
157                 goto err_irq;
158  
159 +
160         INIT_LIST_HEAD(&ucb->devs);
161         mutex_lock(&ucb1x00_mutex);
162         list_add(&ucb->node, &ucb1x00_devices);
163 @@ -528,10 +599,14 @@ static int ucb1x00_probe(struct mcp *mcp)
164                 ucb1x00_add_dev(ucb, drv);
165         }
166         mutex_unlock(&ucb1x00_mutex);
167 +
168         goto out;
169  
170   err_irq:
171         free_irq(ucb->irq, ucb);
172 + err_gpio:
173 +       if (ucb->gpio.base != -1)
174 +               temp = gpiochip_remove(&ucb->gpio);
175   err_free:
176         kfree(ucb);
177   err_disable:
178 @@ -544,6 +619,7 @@ static void ucb1x00_remove(struct mcp *mcp)
179  {
180         struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
181         struct list_head *l, *n;
182 +       int ret;
183  
184         mutex_lock(&ucb1x00_mutex);
185         list_del(&ucb->node);
186 @@ -553,6 +629,12 @@ static void ucb1x00_remove(struct mcp *mcp)
187         }
188         mutex_unlock(&ucb1x00_mutex);
189  
190 +       if (ucb->gpio.base != -1) {
191 +               ret = gpiochip_remove(&ucb->gpio);
192 +               if (ret)
193 +                       dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
194 +       }
195 +
196         free_irq(ucb->irq, ucb);
197         device_unregister(&ucb->dev);
198  }
199 @@ -603,6 +685,7 @@ static int ucb1x00_resume(struct mcp *mcp)
200         struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
201         struct ucb1x00_dev *dev;
202  
203 +       ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
204         mutex_lock(&ucb1x00_mutex);
205         list_for_each_entry(dev, &ucb->devs, dev_node) {
206                 if (dev->drv->resume)
207 diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h
208 index be95e09..ee49670 100644
209 --- a/include/linux/mfd/mcp.h
210 +++ b/include/linux/mfd/mcp.h
211 @@ -26,6 +26,7 @@ struct mcp {
212         dma_device_t    dma_telco_rd;
213         dma_device_t    dma_telco_wr;
214         struct device   attached_device;
215 +       int             gpio_base;
216  };
217  
218  struct mcp_ops {
219 diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
220 index 70eb763..b13171e 100644
221 --- a/include/linux/mfd/ucb1x00.h
222 +++ b/include/linux/mfd/ucb1x00.h
223 @@ -11,6 +11,8 @@
224  #define UCB1200_H
225  
226  #include <linux/mfd/mcp.h>
227 +#include <linux/gpio.h>
228 +
229  #define UCB_IO_DATA    0x00
230  #define UCB_IO_DIR     0x01
231  
232 @@ -126,6 +128,7 @@ struct ucb1x00 {
233         struct device           dev;
234         struct list_head        node;
235         struct list_head        devs;
236 +       struct gpio_chip        gpio;
237  };
238  
239  struct ucb1x00_driver;
240 -- 
241 1.5.6.5
242