diff options
-rw-r--r-- | drivers/pps/clients/pps-gpio.c | 67 | ||||
-rw-r--r-- | include/linux/pps-gpio.h | 3 |
2 files changed, 32 insertions, 38 deletions
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index dd5d1103e02b..4e5e9229814b 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/pps_kernel.h> | 32 | #include <linux/pps_kernel.h> |
33 | #include <linux/pps-gpio.h> | 33 | #include <linux/pps-gpio.h> |
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio/consumer.h> |
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
37 | #include <linux/of_gpio.h> | 37 | #include <linux/of_gpio.h> |
@@ -41,9 +41,9 @@ struct pps_gpio_device_data { | |||
41 | int irq; /* IRQ used as PPS source */ | 41 | int irq; /* IRQ used as PPS source */ |
42 | struct pps_device *pps; /* PPS source device */ | 42 | struct pps_device *pps; /* PPS source device */ |
43 | struct pps_source_info info; /* PPS source information */ | 43 | struct pps_source_info info; /* PPS source information */ |
44 | struct gpio_desc *gpio_pin; /* GPIO port descriptors */ | ||
44 | bool assert_falling_edge; | 45 | bool assert_falling_edge; |
45 | bool capture_clear; | 46 | bool capture_clear; |
46 | unsigned int gpio_pin; | ||
47 | }; | 47 | }; |
48 | 48 | ||
49 | /* | 49 | /* |
@@ -61,18 +61,37 @@ static irqreturn_t pps_gpio_irq_handler(int irq, void *data) | |||
61 | 61 | ||
62 | info = data; | 62 | info = data; |
63 | 63 | ||
64 | rising_edge = gpio_get_value(info->gpio_pin); | 64 | rising_edge = gpiod_get_value(info->gpio_pin); |
65 | if ((rising_edge && !info->assert_falling_edge) || | 65 | if ((rising_edge && !info->assert_falling_edge) || |
66 | (!rising_edge && info->assert_falling_edge)) | 66 | (!rising_edge && info->assert_falling_edge)) |
67 | pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL); | 67 | pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL); |
68 | else if (info->capture_clear && | 68 | else if (info->capture_clear && |
69 | ((rising_edge && info->assert_falling_edge) || | 69 | ((rising_edge && info->assert_falling_edge) || |
70 | (!rising_edge && !info->assert_falling_edge))) | 70 | (!rising_edge && !info->assert_falling_edge))) |
71 | pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL); | 71 | pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL); |
72 | 72 | ||
73 | return IRQ_HANDLED; | 73 | return IRQ_HANDLED; |
74 | } | 74 | } |
75 | 75 | ||
76 | static int pps_gpio_setup(struct platform_device *pdev) | ||
77 | { | ||
78 | struct pps_gpio_device_data *data = platform_get_drvdata(pdev); | ||
79 | struct device_node *np = pdev->dev.of_node; | ||
80 | |||
81 | data->gpio_pin = devm_gpiod_get(&pdev->dev, | ||
82 | NULL, /* request "gpios" */ | ||
83 | GPIOD_IN); | ||
84 | if (IS_ERR(data->gpio_pin)) { | ||
85 | dev_err(&pdev->dev, | ||
86 | "failed to request PPS GPIO\n"); | ||
87 | return PTR_ERR(data->gpio_pin); | ||
88 | } | ||
89 | |||
90 | if (of_property_read_bool(np, "assert-falling-edge")) | ||
91 | data->assert_falling_edge = true; | ||
92 | return 0; | ||
93 | } | ||
94 | |||
76 | static unsigned long | 95 | static unsigned long |
77 | get_irqf_trigger_flags(const struct pps_gpio_device_data *data) | 96 | get_irqf_trigger_flags(const struct pps_gpio_device_data *data) |
78 | { | 97 | { |
@@ -90,53 +109,30 @@ get_irqf_trigger_flags(const struct pps_gpio_device_data *data) | |||
90 | static int pps_gpio_probe(struct platform_device *pdev) | 109 | static int pps_gpio_probe(struct platform_device *pdev) |
91 | { | 110 | { |
92 | struct pps_gpio_device_data *data; | 111 | struct pps_gpio_device_data *data; |
93 | const char *gpio_label; | ||
94 | int ret; | 112 | int ret; |
95 | int pps_default_params; | 113 | int pps_default_params; |
96 | const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; | 114 | const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; |
97 | struct device_node *np = pdev->dev.of_node; | ||
98 | 115 | ||
99 | /* allocate space for device info */ | 116 | /* allocate space for device info */ |
100 | data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data), | 117 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
101 | GFP_KERNEL); | ||
102 | if (!data) | 118 | if (!data) |
103 | return -ENOMEM; | 119 | return -ENOMEM; |
120 | platform_set_drvdata(pdev, data); | ||
104 | 121 | ||
122 | /* GPIO setup */ | ||
105 | if (pdata) { | 123 | if (pdata) { |
106 | data->gpio_pin = pdata->gpio_pin; | 124 | data->gpio_pin = pdata->gpio_pin; |
107 | gpio_label = pdata->gpio_label; | ||
108 | 125 | ||
109 | data->assert_falling_edge = pdata->assert_falling_edge; | 126 | data->assert_falling_edge = pdata->assert_falling_edge; |
110 | data->capture_clear = pdata->capture_clear; | 127 | data->capture_clear = pdata->capture_clear; |
111 | } else { | 128 | } else { |
112 | ret = of_get_gpio(np, 0); | 129 | ret = pps_gpio_setup(pdev); |
113 | if (ret < 0) { | 130 | if (ret) |
114 | dev_err(&pdev->dev, "failed to get GPIO from device tree\n"); | 131 | return -EINVAL; |
115 | return ret; | ||
116 | } | ||
117 | data->gpio_pin = ret; | ||
118 | gpio_label = PPS_GPIO_NAME; | ||
119 | |||
120 | if (of_get_property(np, "assert-falling-edge", NULL)) | ||
121 | data->assert_falling_edge = true; | ||
122 | } | ||
123 | |||
124 | /* GPIO setup */ | ||
125 | ret = devm_gpio_request(&pdev->dev, data->gpio_pin, gpio_label); | ||
126 | if (ret) { | ||
127 | dev_err(&pdev->dev, "failed to request GPIO %u\n", | ||
128 | data->gpio_pin); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | ret = gpio_direction_input(data->gpio_pin); | ||
133 | if (ret) { | ||
134 | dev_err(&pdev->dev, "failed to set pin direction\n"); | ||
135 | return -EINVAL; | ||
136 | } | 132 | } |
137 | 133 | ||
138 | /* IRQ setup */ | 134 | /* IRQ setup */ |
139 | ret = gpio_to_irq(data->gpio_pin); | 135 | ret = gpiod_to_irq(data->gpio_pin); |
140 | if (ret < 0) { | 136 | if (ret < 0) { |
141 | dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret); | 137 | dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret); |
142 | return -EINVAL; | 138 | return -EINVAL; |
@@ -173,7 +169,6 @@ static int pps_gpio_probe(struct platform_device *pdev) | |||
173 | return -EINVAL; | 169 | return -EINVAL; |
174 | } | 170 | } |
175 | 171 | ||
176 | platform_set_drvdata(pdev, data); | ||
177 | dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", | 172 | dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", |
178 | data->irq); | 173 | data->irq); |
179 | 174 | ||
@@ -209,4 +204,4 @@ MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>"); | |||
209 | MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>"); | 204 | MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>"); |
210 | MODULE_DESCRIPTION("Use GPIO pin as PPS source"); | 205 | MODULE_DESCRIPTION("Use GPIO pin as PPS source"); |
211 | MODULE_LICENSE("GPL"); | 206 | MODULE_LICENSE("GPL"); |
212 | MODULE_VERSION("1.0.0"); | 207 | MODULE_VERSION("1.1.0"); |
diff --git a/include/linux/pps-gpio.h b/include/linux/pps-gpio.h index 56f35dd3d01d..f028d2cda6f5 100644 --- a/include/linux/pps-gpio.h +++ b/include/linux/pps-gpio.h | |||
@@ -23,10 +23,9 @@ | |||
23 | #define _PPS_GPIO_H | 23 | #define _PPS_GPIO_H |
24 | 24 | ||
25 | struct pps_gpio_platform_data { | 25 | struct pps_gpio_platform_data { |
26 | struct gpio_desc *gpio_pin; | ||
26 | bool assert_falling_edge; | 27 | bool assert_falling_edge; |
27 | bool capture_clear; | 28 | bool capture_clear; |
28 | unsigned int gpio_pin; | ||
29 | const char *gpio_label; | ||
30 | }; | 29 | }; |
31 | 30 | ||
32 | #endif /* _PPS_GPIO_H */ | 31 | #endif /* _PPS_GPIO_H */ |