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");