drivers/pps/clients/pps-gpio.c: use devm_kzalloc
[sfrench/cifs-2.6.git] / drivers / pps / clients / pps-gpio.c
1 /*
2  * pps-gpio.c -- PPS client driver using GPIO
3  *
4  *
5  * Copyright (C) 2010 Ricardo Martins <rasm@fe.up.pt>
6  * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
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 as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #define PPS_GPIO_NAME "pps-gpio"
24 #define pr_fmt(fmt) PPS_GPIO_NAME ": " fmt
25
26 #include <linux/init.h>
27 #include <linux/kernel.h>
28 #include <linux/interrupt.h>
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <linux/slab.h>
32 #include <linux/pps_kernel.h>
33 #include <linux/pps-gpio.h>
34 #include <linux/gpio.h>
35 #include <linux/list.h>
36
37 /* Info for each registered platform device */
38 struct pps_gpio_device_data {
39         int irq;                        /* IRQ used as PPS source */
40         struct pps_device *pps;         /* PPS source device */
41         struct pps_source_info info;    /* PPS source information */
42         const struct pps_gpio_platform_data *pdata;
43 };
44
45 /*
46  * Report the PPS event
47  */
48
49 static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
50 {
51         const struct pps_gpio_device_data *info;
52         struct pps_event_time ts;
53         int rising_edge;
54
55         /* Get the time stamp first */
56         pps_get_ts(&ts);
57
58         info = data;
59
60         rising_edge = gpio_get_value(info->pdata->gpio_pin);
61         if ((rising_edge && !info->pdata->assert_falling_edge) ||
62                         (!rising_edge && info->pdata->assert_falling_edge))
63                 pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
64         else if (info->pdata->capture_clear &&
65                         ((rising_edge && info->pdata->assert_falling_edge) ||
66                          (!rising_edge && !info->pdata->assert_falling_edge)))
67                 pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
68
69         return IRQ_HANDLED;
70 }
71
72 static int pps_gpio_setup(struct platform_device *pdev)
73 {
74         int ret;
75         const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
76
77         ret = gpio_request(pdata->gpio_pin, pdata->gpio_label);
78         if (ret) {
79                 pr_warning("failed to request GPIO %u\n", pdata->gpio_pin);
80                 return -EINVAL;
81         }
82
83         ret = gpio_direction_input(pdata->gpio_pin);
84         if (ret) {
85                 pr_warning("failed to set pin direction\n");
86                 gpio_free(pdata->gpio_pin);
87                 return -EINVAL;
88         }
89
90         return 0;
91 }
92
93 static unsigned long
94 get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata)
95 {
96         unsigned long flags = pdata->assert_falling_edge ?
97                 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
98
99         if (pdata->capture_clear) {
100                 flags |= ((flags & IRQF_TRIGGER_RISING) ?
101                                 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
102         }
103
104         return flags;
105 }
106
107 static int pps_gpio_probe(struct platform_device *pdev)
108 {
109         struct pps_gpio_device_data *data;
110         int irq;
111         int ret;
112         int err;
113         int pps_default_params;
114         const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
115
116
117         /* GPIO setup */
118         ret = pps_gpio_setup(pdev);
119         if (ret)
120                 return -EINVAL;
121
122         /* IRQ setup */
123         irq = gpio_to_irq(pdata->gpio_pin);
124         if (irq < 0) {
125                 pr_err("failed to map GPIO to IRQ: %d\n", irq);
126                 err = -EINVAL;
127                 goto return_error;
128         }
129
130         /* allocate space for device info */
131         data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data),
132                             GFP_KERNEL);
133         if (data == NULL) {
134                 err = -ENOMEM;
135                 goto return_error;
136         }
137
138         /* initialize PPS specific parts of the bookkeeping data structure. */
139         data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
140                 PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
141         if (pdata->capture_clear)
142                 data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
143                         PPS_ECHOCLEAR;
144         data->info.owner = THIS_MODULE;
145         snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
146                  pdev->name, pdev->id);
147
148         /* register PPS source */
149         pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
150         if (pdata->capture_clear)
151                 pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
152         data->pps = pps_register_source(&data->info, pps_default_params);
153         if (data->pps == NULL) {
154                 pr_err("failed to register IRQ %d as PPS source\n", irq);
155                 err = -EINVAL;
156                 goto return_error;
157         }
158
159         data->irq = irq;
160         data->pdata = pdata;
161
162         /* register IRQ interrupt handler */
163         ret = request_irq(irq, pps_gpio_irq_handler,
164                         get_irqf_trigger_flags(pdata), data->info.name, data);
165         if (ret) {
166                 pps_unregister_source(data->pps);
167                 pr_err("failed to acquire IRQ %d\n", irq);
168                 err = -EINVAL;
169                 goto return_error;
170         }
171
172         platform_set_drvdata(pdev, data);
173         dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq);
174
175         return 0;
176
177 return_error:
178         gpio_free(pdata->gpio_pin);
179         return err;
180 }
181
182 static int pps_gpio_remove(struct platform_device *pdev)
183 {
184         struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
185         const struct pps_gpio_platform_data *pdata = data->pdata;
186
187         platform_set_drvdata(pdev, NULL);
188         free_irq(data->irq, data);
189         gpio_free(pdata->gpio_pin);
190         pps_unregister_source(data->pps);
191         pr_info("removed IRQ %d as PPS source\n", data->irq);
192         return 0;
193 }
194
195 static struct platform_driver pps_gpio_driver = {
196         .probe          = pps_gpio_probe,
197         .remove         = pps_gpio_remove,
198         .driver         = {
199                 .name   = PPS_GPIO_NAME,
200                 .owner  = THIS_MODULE
201         },
202 };
203
204 static int __init pps_gpio_init(void)
205 {
206         int ret = platform_driver_register(&pps_gpio_driver);
207         if (ret < 0)
208                 pr_err("failed to register platform driver\n");
209         return ret;
210 }
211
212 static void __exit pps_gpio_exit(void)
213 {
214         platform_driver_unregister(&pps_gpio_driver);
215         pr_debug("unregistered platform driver\n");
216 }
217
218 module_init(pps_gpio_init);
219 module_exit(pps_gpio_exit);
220
221 MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
222 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
223 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
224 MODULE_LICENSE("GPL");
225 MODULE_VERSION("1.0.0");