4 * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
13 #include <linux/slab.h>
14 #include <linux/gpio.h>
15 #include <linux/module.h>
16 #include <linux/spinlock.h>
17 #include <linux/platform_device.h>
19 #include <mach/hardware.h>
21 #define CLPS711X_GPIO_PORTS 5
22 #define CLPS711X_GPIO_NAME "gpio-clps711x"
24 struct clps711x_gpio {
25 struct gpio_chip chip[CLPS711X_GPIO_PORTS];
29 static void __iomem *clps711x_ports[] = {
30 CLPS711X_VIRT_BASE + PADR,
31 CLPS711X_VIRT_BASE + PBDR,
32 CLPS711X_VIRT_BASE + PCDR,
33 CLPS711X_VIRT_BASE + PDDR,
34 CLPS711X_VIRT_BASE + PEDR,
37 static void __iomem *clps711x_pdirs[] = {
38 CLPS711X_VIRT_BASE + PADDR,
39 CLPS711X_VIRT_BASE + PBDDR,
40 CLPS711X_VIRT_BASE + PCDDR,
41 CLPS711X_VIRT_BASE + PDDDR,
42 CLPS711X_VIRT_BASE + PEDDR,
45 #define clps711x_port(x) clps711x_ports[x->base / 8]
46 #define clps711x_pdir(x) clps711x_pdirs[x->base / 8]
48 static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
50 return !!(readb(clps711x_port(chip)) & (1 << offset));
53 static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
58 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
60 spin_lock_irqsave(&gpio->lock, flags);
61 tmp = readb(clps711x_port(chip)) & ~(1 << offset);
64 writeb(tmp, clps711x_port(chip));
65 spin_unlock_irqrestore(&gpio->lock, flags);
68 static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset)
72 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
74 spin_lock_irqsave(&gpio->lock, flags);
75 tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
76 writeb(tmp, clps711x_pdir(chip));
77 spin_unlock_irqrestore(&gpio->lock, flags);
82 static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset,
87 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
89 spin_lock_irqsave(&gpio->lock, flags);
90 tmp = readb(clps711x_pdir(chip)) | (1 << offset);
91 writeb(tmp, clps711x_pdir(chip));
92 tmp = readb(clps711x_port(chip)) & ~(1 << offset);
95 writeb(tmp, clps711x_port(chip));
96 spin_unlock_irqrestore(&gpio->lock, flags);
101 static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset)
105 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
107 spin_lock_irqsave(&gpio->lock, flags);
108 tmp = readb(clps711x_pdir(chip)) | (1 << offset);
109 writeb(tmp, clps711x_pdir(chip));
110 spin_unlock_irqrestore(&gpio->lock, flags);
115 static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset,
120 struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
122 spin_lock_irqsave(&gpio->lock, flags);
123 tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
124 writeb(tmp, clps711x_pdir(chip));
125 tmp = readb(clps711x_port(chip)) & ~(1 << offset);
128 writeb(tmp, clps711x_port(chip));
129 spin_unlock_irqrestore(&gpio->lock, flags);
138 } clps711x_gpio_ports[] __initconst = {
146 static int __init gpio_clps711x_init(void)
149 struct platform_device *pdev;
150 struct clps711x_gpio *gpio;
152 pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
154 pr_err("Cannot create platform device: %s\n",
159 platform_device_add(pdev);
161 gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
164 dev_err(&pdev->dev, "GPIO allocating memory error\n");
165 platform_device_unregister(pdev);
169 platform_set_drvdata(pdev, gpio);
171 spin_lock_init(&gpio->lock);
173 for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
174 gpio->chip[i].owner = THIS_MODULE;
175 gpio->chip[i].dev = &pdev->dev;
176 gpio->chip[i].label = clps711x_gpio_ports[i].name;
177 gpio->chip[i].base = i * 8;
178 gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr;
179 gpio->chip[i].get = gpio_clps711x_get;
180 gpio->chip[i].set = gpio_clps711x_set;
181 if (!clps711x_gpio_ports[i].inv_dir) {
182 gpio->chip[i].direction_input = gpio_clps711x_dir_in;
183 gpio->chip[i].direction_output = gpio_clps711x_dir_out;
185 gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv;
186 gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv;
188 WARN_ON(gpiochip_add(&gpio->chip[i]));
191 dev_info(&pdev->dev, "GPIO driver initialized\n");
195 arch_initcall(gpio_clps711x_init);
197 MODULE_LICENSE("GPL v2");
198 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
199 MODULE_DESCRIPTION("CLPS711X GPIO driver");