4 * Copyright (C) 2014 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/gpio.h>
16 #include <linux/slab.h>
17 #include <linux/platform_device.h>
19 #include <linux/platform_data/gpio-latch.h>
21 struct gpio_latch_chip
{
25 struct mutex latch_mutex
;
32 static inline struct gpio_latch_chip
*to_gpio_latch_chip(struct gpio_chip
*gc
)
34 return container_of(gc
, struct gpio_latch_chip
, gc
);
37 static void gpio_latch_lock(struct gpio_latch_chip
*glc
, bool enable
)
39 mutex_lock(&glc
->mutex
);
42 glc
->latch_enabled
= true;
44 if (glc
->latch_enabled
)
45 mutex_lock(&glc
->latch_mutex
);
48 static void gpio_latch_unlock(struct gpio_latch_chip
*glc
, bool disable
)
50 if (glc
->latch_enabled
)
51 mutex_unlock(&glc
->latch_mutex
);
54 glc
->latch_enabled
= true;
56 mutex_unlock(&glc
->mutex
);
60 gpio_latch_get(struct gpio_chip
*gc
, unsigned offset
)
62 struct gpio_latch_chip
*glc
= to_gpio_latch_chip(gc
);
65 gpio_latch_lock(glc
, false);
66 ret
= gpio_get_value(glc
->gpios
[offset
]);
67 gpio_latch_unlock(glc
, false);
73 gpio_latch_set(struct gpio_chip
*gc
, unsigned offset
, int value
)
75 struct gpio_latch_chip
*glc
= to_gpio_latch_chip(gc
);
76 bool enable_latch
= false;
77 bool disable_latch
= false;
80 gpio
= glc
->gpios
[offset
];
82 if (gpio
== glc
->le_gpio
) {
83 enable_latch
= value
^ glc
->le_active_low
;
84 disable_latch
= !enable_latch
;
87 gpio_latch_lock(glc
, enable_latch
);
88 gpio_set_value(gpio
, value
);
89 gpio_latch_unlock(glc
, disable_latch
);
93 gpio_latch_direction_input(struct gpio_chip
*gc
, unsigned offset
)
95 struct gpio_latch_chip
*glc
= to_gpio_latch_chip(gc
);
98 gpio_latch_lock(glc
, false);
99 ret
= gpio_direction_input(glc
->gpios
[offset
]);
100 gpio_latch_unlock(glc
, false);
106 gpio_latch_direction_output(struct gpio_chip
*gc
, unsigned offset
, int value
)
108 struct gpio_latch_chip
*glc
= to_gpio_latch_chip(gc
);
109 bool enable_latch
= false;
110 bool disable_latch
= false;
114 gpio
= glc
->gpios
[offset
];
116 if (gpio
== glc
->le_gpio
) {
117 enable_latch
= value
^ glc
->le_active_low
;
118 disable_latch
= !enable_latch
;
121 gpio_latch_lock(glc
, enable_latch
);
122 ret
= gpio_direction_output(gpio
, value
);
123 gpio_latch_unlock(glc
, disable_latch
);
128 static int gpio_latch_probe(struct platform_device
*pdev
)
130 struct gpio_latch_chip
*glc
;
131 struct gpio_latch_platform_data
*pdata
;
132 struct gpio_chip
*gc
;
137 pdata
= dev_get_platdata(&pdev
->dev
);
141 if (pdata
->le_gpio_index
>= pdata
->num_gpios
||
146 for (i
= 0; i
< pdata
->num_gpios
; i
++) {
147 int gpio
= pdata
->gpios
[i
];
149 ret
= devm_gpio_request(&pdev
->dev
, gpio
,
150 GPIO_LATCH_DRIVER_NAME
);
155 glc
= devm_kzalloc(&pdev
->dev
, sizeof(*glc
), GFP_KERNEL
);
159 mutex_init(&glc
->mutex
);
160 mutex_init(&glc
->latch_mutex
);
162 size
= pdata
->num_gpios
* sizeof(glc
->gpios
[0]);
163 glc
->gpios
= devm_kzalloc(&pdev
->dev
, size
, GFP_KERNEL
);
167 memcpy(glc
->gpios
, pdata
->gpios
, size
);
169 glc
->le_gpio
= glc
->gpios
[pdata
->le_gpio_index
];
170 glc
->le_active_low
= pdata
->le_active_low
;
174 gc
->label
= GPIO_LATCH_DRIVER_NAME
;
175 gc
->base
= pdata
->base
;
176 gc
->can_sleep
= true;
177 gc
->ngpio
= pdata
->num_gpios
;
178 gc
->get
= gpio_latch_get
;
179 gc
->set
= gpio_latch_set
;
180 gc
->direction_input
= gpio_latch_direction_input
,
181 gc
->direction_output
= gpio_latch_direction_output
;
183 platform_set_drvdata(pdev
, glc
);
185 ret
= gpiochip_add(&glc
->gc
);
192 static int gpio_latch_remove(struct platform_device
*pdev
)
194 struct gpio_latch_chip
*glc
= platform_get_drvdata(pdev
);
196 return gpiochip_remove(&glc
->gc
);;
200 static struct platform_driver gpio_latch_driver
= {
201 .probe
= gpio_latch_probe
,
202 .remove
= gpio_latch_remove
,
204 .name
= GPIO_LATCH_DRIVER_NAME
,
205 .owner
= THIS_MODULE
,
209 static int __init
gpio_latch_init(void)
211 return platform_driver_register(&gpio_latch_driver
);
214 postcore_initcall(gpio_latch_init
);
216 MODULE_DESCRIPTION("GPIO latch driver");
217 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
218 MODULE_LICENSE("GPL v2");
219 MODULE_ALIAS("platform:" GPIO_LATCH_DRIVER_NAME
);