Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/arch/arm/common/scoop.c

  1 /*
  2  * Support code for the SCOOP interface found on various Sharp PDAs
  3  *
  4  * Copyright (c) 2004 Richard Purdie
  5  *
  6  *      Based on code written by Sharp/Lineo for 2.4 kernels
  7  *
  8  * This program is free software; you can redistribute it and/or modify
  9  * it under the terms of the GNU General Public License version 2 as
 10  * published by the Free Software Foundation.
 11  *
 12  */
 13 
 14 #include <linux/device.h>
 15 #include <linux/gpio.h>
 16 #include <linux/string.h>
 17 #include <linux/slab.h>
 18 #include <linux/platform_device.h>
 19 #include <linux/export.h>
 20 #include <linux/io.h>
 21 #include <asm/hardware/scoop.h>
 22 
 23 /* PCMCIA to Scoop linkage
 24 
 25    There is no easy way to link multiple scoop devices into one
 26    single entity for the pxa2xx_pcmcia device so this structure
 27    is used which is setup by the platform code.
 28 
 29    This file is never modular so this symbol is always
 30    accessile to the board support files.
 31 */
 32 struct scoop_pcmcia_config *platform_scoop_config;
 33 EXPORT_SYMBOL(platform_scoop_config);
 34 
 35 struct  scoop_dev {
 36         void __iomem *base;
 37         struct gpio_chip gpio;
 38         spinlock_t scoop_lock;
 39         unsigned short suspend_clr;
 40         unsigned short suspend_set;
 41         u32 scoop_gpwr;
 42 };
 43 
 44 void reset_scoop(struct device *dev)
 45 {
 46         struct scoop_dev *sdev = dev_get_drvdata(dev);
 47 
 48         iowrite16(0x0100, sdev->base + SCOOP_MCR);  /* 00 */
 49         iowrite16(0x0000, sdev->base + SCOOP_CDR);  /* 04 */
 50         iowrite16(0x0000, sdev->base + SCOOP_CCR);  /* 10 */
 51         iowrite16(0x0000, sdev->base + SCOOP_IMR);  /* 18 */
 52         iowrite16(0x00FF, sdev->base + SCOOP_IRM);  /* 14 */
 53         iowrite16(0x0000, sdev->base + SCOOP_ISR);  /* 1C */
 54         iowrite16(0x0000, sdev->base + SCOOP_IRM);
 55 }
 56 
 57 static void __scoop_gpio_set(struct scoop_dev *sdev,
 58                         unsigned offset, int value)
 59 {
 60         unsigned short gpwr;
 61 
 62         gpwr = ioread16(sdev->base + SCOOP_GPWR);
 63         if (value)
 64                 gpwr |= 1 << (offset + 1);
 65         else
 66                 gpwr &= ~(1 << (offset + 1));
 67         iowrite16(gpwr, sdev->base + SCOOP_GPWR);
 68 }
 69 
 70 static void scoop_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 71 {
 72         struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
 73         unsigned long flags;
 74 
 75         spin_lock_irqsave(&sdev->scoop_lock, flags);
 76 
 77         __scoop_gpio_set(sdev, offset, value);
 78 
 79         spin_unlock_irqrestore(&sdev->scoop_lock, flags);
 80 }
 81 
 82 static int scoop_gpio_get(struct gpio_chip *chip, unsigned offset)
 83 {
 84         struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
 85 
 86         /* XXX: I'm unsure, but it seems so */
 87         return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1));
 88 }
 89 
 90 static int scoop_gpio_direction_input(struct gpio_chip *chip,
 91                         unsigned offset)
 92 {
 93         struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
 94         unsigned long flags;
 95         unsigned short gpcr;
 96 
 97         spin_lock_irqsave(&sdev->scoop_lock, flags);
 98 
 99         gpcr = ioread16(sdev->base + SCOOP_GPCR);
100         gpcr &= ~(1 << (offset + 1));
101         iowrite16(gpcr, sdev->base + SCOOP_GPCR);
102 
103         spin_unlock_irqrestore(&sdev->scoop_lock, flags);
104 
105         return 0;
106 }
107 
108 static int scoop_gpio_direction_output(struct gpio_chip *chip,
109                         unsigned offset, int value)
110 {
111         struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
112         unsigned long flags;
113         unsigned short gpcr;
114 
115         spin_lock_irqsave(&sdev->scoop_lock, flags);
116 
117         __scoop_gpio_set(sdev, offset, value);
118 
119         gpcr = ioread16(sdev->base + SCOOP_GPCR);
120         gpcr |= 1 << (offset + 1);
121         iowrite16(gpcr, sdev->base + SCOOP_GPCR);
122 
123         spin_unlock_irqrestore(&sdev->scoop_lock, flags);
124 
125         return 0;
126 }
127 
128 unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
129 {
130         struct scoop_dev *sdev = dev_get_drvdata(dev);
131         return ioread16(sdev->base + reg);
132 }
133 
134 void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
135 {
136         struct scoop_dev *sdev = dev_get_drvdata(dev);
137         iowrite16(data, sdev->base + reg);
138 }
139 
140 EXPORT_SYMBOL(reset_scoop);
141 EXPORT_SYMBOL(read_scoop_reg);
142 EXPORT_SYMBOL(write_scoop_reg);
143 
144 #ifdef CONFIG_PM
145 static void check_scoop_reg(struct scoop_dev *sdev)
146 {
147         unsigned short mcr;
148 
149         mcr = ioread16(sdev->base + SCOOP_MCR);
150         if ((mcr & 0x100) == 0)
151                 iowrite16(0x0101, sdev->base + SCOOP_MCR);
152 }
153 
154 static int scoop_suspend(struct platform_device *dev, pm_message_t state)
155 {
156         struct scoop_dev *sdev = platform_get_drvdata(dev);
157 
158         check_scoop_reg(sdev);
159         sdev->scoop_gpwr = ioread16(sdev->base + SCOOP_GPWR);
160         iowrite16((sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set, sdev->base + SCOOP_GPWR);
161 
162         return 0;
163 }
164 
165 static int scoop_resume(struct platform_device *dev)
166 {
167         struct scoop_dev *sdev = platform_get_drvdata(dev);
168 
169         check_scoop_reg(sdev);
170         iowrite16(sdev->scoop_gpwr, sdev->base + SCOOP_GPWR);
171 
172         return 0;
173 }
174 #else
175 #define scoop_suspend   NULL
176 #define scoop_resume    NULL
177 #endif
178 
179 static int scoop_probe(struct platform_device *pdev)
180 {
181         struct scoop_dev *devptr;
182         struct scoop_config *inf;
183         struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
184         int ret;
185         int temp;
186 
187         if (!mem)
188                 return -EINVAL;
189 
190         devptr = kzalloc(sizeof(struct scoop_dev), GFP_KERNEL);
191         if (!devptr)
192                 return -ENOMEM;
193 
194         spin_lock_init(&devptr->scoop_lock);
195 
196         inf = pdev->dev.platform_data;
197         devptr->base = ioremap(mem->start, resource_size(mem));
198 
199         if (!devptr->base) {
200                 ret = -ENOMEM;
201                 goto err_ioremap;
202         }
203 
204         platform_set_drvdata(pdev, devptr);
205 
206         printk("Sharp Scoop Device found at 0x%08x -> 0x%8p\n",(unsigned int)mem->start, devptr->base);
207 
208         iowrite16(0x0140, devptr->base + SCOOP_MCR);
209         reset_scoop(&pdev->dev);
210         iowrite16(0x0000, devptr->base + SCOOP_CPR);
211         iowrite16(inf->io_dir & 0xffff, devptr->base + SCOOP_GPCR);
212         iowrite16(inf->io_out & 0xffff, devptr->base + SCOOP_GPWR);
213 
214         devptr->suspend_clr = inf->suspend_clr;
215         devptr->suspend_set = inf->suspend_set;
216 
217         devptr->gpio.base = -1;
218 
219         if (inf->gpio_base != 0) {
220                 devptr->gpio.label = dev_name(&pdev->dev);
221                 devptr->gpio.base = inf->gpio_base;
222                 devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
223                 devptr->gpio.set = scoop_gpio_set;
224                 devptr->gpio.get = scoop_gpio_get;
225                 devptr->gpio.direction_input = scoop_gpio_direction_input;
226                 devptr->gpio.direction_output = scoop_gpio_direction_output;
227 
228                 ret = gpiochip_add(&devptr->gpio);
229                 if (ret)
230                         goto err_gpio;
231         }
232 
233         return 0;
234 
235 err_gpio:
236         platform_set_drvdata(pdev, NULL);
237 err_ioremap:
238         iounmap(devptr->base);
239         kfree(devptr);
240 
241         return ret;
242 }
243 
244 static int scoop_remove(struct platform_device *pdev)
245 {
246         struct scoop_dev *sdev = platform_get_drvdata(pdev);
247         int ret;
248 
249         if (!sdev)
250                 return -EINVAL;
251 
252         if (sdev->gpio.base != -1) {
253                 ret = gpiochip_remove(&sdev->gpio);
254                 if (ret) {
255                         dev_err(&pdev->dev, "Can't remove gpio chip: %d\n", ret);
256                         return ret;
257                 }
258         }
259 
260         platform_set_drvdata(pdev, NULL);
261         iounmap(sdev->base);
262         kfree(sdev);
263 
264         return 0;
265 }
266 
267 static struct platform_driver scoop_driver = {
268         .probe          = scoop_probe,
269         .remove         = scoop_remove,
270         .suspend        = scoop_suspend,
271         .resume         = scoop_resume,
272         .driver         = {
273                 .name   = "sharp-scoop",
274         },
275 };
276 
277 static int __init scoop_init(void)
278 {
279         return platform_driver_register(&scoop_driver);
280 }
281 
282 subsys_initcall(scoop_init);
283 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us