Skip to content

Commit 080249d

Browse files
charles-parktobetter
authored andcommitted
ODROID-C2: pps-gpio irq function modified for amlogic.
Change-Id: I369dd6743d51e196f25e5de9a8dcdd758c1fc2a2
1 parent 79a204d commit 080249d

File tree

1 file changed

+119
-91
lines changed

1 file changed

+119
-91
lines changed

drivers/pps/clients/pps-gpio.c

100644100755
Lines changed: 119 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -35,48 +35,58 @@
3535
#include <linux/list.h>
3636
#include <linux/of_device.h>
3737
#include <linux/of_gpio.h>
38+
#include <linux/amlogic/aml_gpio_consumer.h>
39+
#include <linux/amlogic/pinctrl_amlogic.h>
40+
/* AMLogic GPIO irq bank start offset */
41+
#define AMLGPIO_IRQ_BASE 96
3842

3943
/* Info for each registered platform device */
40-
struct pps_gpio_device_data {
44+
static struct pps_gpio_device_data {
4145
int irq; /* IRQ used as PPS source */
4246
struct pps_device *pps; /* PPS source device */
4347
struct pps_source_info info; /* PPS source information */
44-
bool assert_falling_edge;
4548
bool capture_clear;
4649
unsigned int gpio_pin;
47-
};
50+
} pps_data;
51+
52+
// Default GPIO. Use parameters during module load to override.
53+
// note: this only handles one instance of pps-gpio. If you want more, use the devicetree version
54+
static int gpio_pin = 238; // GPIOX_10 / pin 12
55+
module_param(gpio_pin, int, S_IRUSR | S_IRGRP | S_IROTH);
56+
MODULE_PARM_DESC(gpio_pin, "GPIO pin number (\"Export GPIO\" type), default=238 (GPIOX_10 / pin 12)");
57+
58+
static int assert_falling_edge = 0;
59+
module_param(assert_falling_edge, int, S_IRUSR | S_IRGRP | S_IROTH);
60+
MODULE_PARM_DESC(assert_falling_edge, "use the falling edge instead of the rising edge, default=0 (rising)");
4861

4962
/*
5063
* Report the PPS event
5164
*/
5265

5366
static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
5467
{
55-
const struct pps_gpio_device_data *info;
5668
struct pps_event_time ts;
5769
int rising_edge;
5870

5971
/* Get the time stamp first */
6072
pps_get_ts(&ts);
6173

62-
info = data;
63-
64-
rising_edge = gpio_get_value(info->gpio_pin);
65-
if ((rising_edge && !info->assert_falling_edge) ||
66-
(!rising_edge && info->assert_falling_edge))
67-
pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
68-
else if (info->capture_clear &&
69-
((rising_edge && info->assert_falling_edge) ||
70-
(!rising_edge && !info->assert_falling_edge)))
71-
pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
74+
rising_edge = gpio_get_value(pps_data.gpio_pin);
75+
if ((rising_edge && !assert_falling_edge) ||
76+
(!rising_edge && assert_falling_edge))
77+
pps_event(pps_data.pps, &ts, PPS_CAPTUREASSERT, NULL);
78+
else if (pps_data.capture_clear &&
79+
((rising_edge && assert_falling_edge) ||
80+
(!rising_edge && !assert_falling_edge)))
81+
pps_event(pps_data.pps, &ts, PPS_CAPTURECLEAR, NULL);
7282

7383
return IRQ_HANDLED;
7484
}
7585

7686
static unsigned long
7787
get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
7888
{
79-
unsigned long flags = data->assert_falling_edge ?
89+
unsigned long flags = assert_falling_edge ?
8090
IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
8191

8292
if (data->capture_clear) {
@@ -87,125 +97,143 @@ get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
8797
return flags;
8898
}
8999

90-
static int pps_gpio_probe(struct platform_device *pdev)
100+
static int pps_gpio_irq_setup(unsigned int gpio_pin)
101+
{
102+
struct gpio_chip *chip;
103+
int ret;
104+
unsigned long irq_flags;
105+
int irq_banks[2] = {0, 0};
106+
107+
chip = gpio_to_chip(gpio_pin);
108+
if(!chip)
109+
return -EINVAL;
110+
111+
// gpio_to_irq translates from global GPIO # to chip offset, which meson_setup_irq wants
112+
gpio_pin = gpio_to_irq(gpio_pin);
113+
114+
irq_flags = assert_falling_edge ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
115+
ret = meson_setup_irq(chip, gpio_pin, irq_flags, &irq_banks[0]);
116+
if(ret < 0)
117+
return -EINVAL;
118+
119+
if(irq_banks[0] != -1)
120+
return irq_banks[0] + AMLGPIO_IRQ_BASE;
121+
if(irq_banks[1] != -1)
122+
return irq_banks[1] + AMLGPIO_IRQ_BASE;
123+
124+
return -EINVAL;
125+
}
126+
127+
static void pps_gpio_release(struct device *dev) {
128+
// does nothing, everything is allocated as part of the module
129+
}
130+
131+
static struct device pps_gpio_dev = {
132+
.id = 0,
133+
.parent = &platform_bus,
134+
.release = &pps_gpio_release
135+
};
136+
137+
static int __init pps_gpio_init(void)
91138
{
92-
struct pps_gpio_device_data *data;
93-
const char *gpio_label;
94139
int ret;
95140
int pps_default_params;
96-
const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
97-
struct device_node *np = pdev->dev.of_node;
98-
99-
/* allocate space for device info */
100-
data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data),
101-
GFP_KERNEL);
102-
if (!data)
103-
return -ENOMEM;
104-
105-
if (pdata) {
106-
data->gpio_pin = pdata->gpio_pin;
107-
gpio_label = pdata->gpio_label;
108-
109-
data->assert_falling_edge = pdata->assert_falling_edge;
110-
data->capture_clear = pdata->capture_clear;
111-
} else {
112-
ret = of_get_gpio(np, 0);
113-
if (ret < 0) {
114-
dev_err(&pdev->dev, "failed to get GPIO from device tree\n");
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;
141+
142+
/* register the device */
143+
ret = dev_set_name(&pps_gpio_dev, "%s%d", PPS_GPIO_NAME, pps_gpio_dev.id);
144+
if(ret < 0) {
145+
pr_err("dev_set_name failed with %d\n", ret);
146+
return ret;
147+
}
148+
ret = device_register(&pps_gpio_dev);
149+
if(ret < 0) {
150+
pr_err("device_register failed with %d\n", ret);
151+
return ret;
122152
}
123153

154+
pps_data.gpio_pin = gpio_pin;
155+
124156
/* GPIO setup */
125-
ret = devm_gpio_request(&pdev->dev, data->gpio_pin, gpio_label);
157+
ret = devm_gpio_request(&pps_gpio_dev, pps_data.gpio_pin, "PPS-GPIO");
126158
if (ret) {
127-
dev_err(&pdev->dev, "failed to request GPIO %u\n",
128-
data->gpio_pin);
159+
dev_err(&pps_gpio_dev, "failed to request GPIO %u\n",
160+
pps_data.gpio_pin);
129161
return ret;
130162
}
131163

132-
ret = gpio_direction_input(data->gpio_pin);
164+
ret = gpio_direction_input(pps_data.gpio_pin);
133165
if (ret) {
134-
dev_err(&pdev->dev, "failed to set pin direction\n");
166+
dev_err(&pps_gpio_dev, "failed to set pin direction\n");
135167
return -EINVAL;
136168
}
137169

138170
/* IRQ setup */
139-
ret = gpio_to_irq(data->gpio_pin);
171+
ret = pps_gpio_irq_setup(pps_data.gpio_pin);
140172
if (ret < 0) {
141-
dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret);
173+
dev_err(&pps_gpio_dev, "failed to map GPIO to IRQ: %d\n", ret);
142174
return -EINVAL;
143175
}
144-
data->irq = ret;
176+
pps_data.irq = ret;
145177

146178
/* initialize PPS specific parts of the bookkeeping data structure. */
147-
data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
179+
pps_data.info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
148180
PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
149-
if (data->capture_clear)
150-
data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
181+
if (pps_data.capture_clear)
182+
pps_data.info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
151183
PPS_ECHOCLEAR;
152-
data->info.owner = THIS_MODULE;
153-
snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
154-
pdev->name, pdev->id);
184+
pps_data.info.owner = THIS_MODULE;
185+
snprintf(pps_data.info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
186+
PPS_GPIO_NAME, pps_gpio_dev.id);
155187

156188
/* register PPS source */
157189
pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
158-
if (data->capture_clear)
190+
if (pps_data.capture_clear)
159191
pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
160-
data->pps = pps_register_source(&data->info, pps_default_params);
161-
if (data->pps == NULL) {
162-
dev_err(&pdev->dev, "failed to register IRQ %d as PPS source\n",
163-
data->irq);
192+
pps_data.pps = pps_register_source(&pps_data.info, pps_default_params);
193+
if (pps_data.pps == NULL) {
194+
dev_err(&pps_gpio_dev, "failed to register IRQ %d as PPS source\n",
195+
pps_data.irq);
164196
return -EINVAL;
165197
}
166198

167199
/* register IRQ interrupt handler */
168-
ret = devm_request_irq(&pdev->dev, data->irq, pps_gpio_irq_handler,
169-
get_irqf_trigger_flags(data), data->info.name, data);
200+
#if 0
201+
IRQF_DISABLED | IRQF_ONESHOT
202+
ret = devm_request_irq(&pps_gpio_dev, pps_data.irq, pps_gpio_irq_handler,
203+
get_irqf_trigger_flags(&pps_data), pps_data.info.name, NULL);
204+
#endif
205+
ret = devm_request_irq(&pps_gpio_dev, pps_data.irq, pps_gpio_irq_handler,
206+
IRQF_DISABLED | IRQF_ONESHOT, pps_data.info.name, NULL);
170207
if (ret) {
171-
pps_unregister_source(data->pps);
172-
dev_err(&pdev->dev, "failed to acquire IRQ %d\n", data->irq);
208+
pps_unregister_source(pps_data.pps);
209+
dev_err(&pps_gpio_dev, "failed to acquire IRQ %d\n", pps_data.irq);
173210
return -EINVAL;
174211
}
175212

176-
platform_set_drvdata(pdev, data);
177-
dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
178-
data->irq);
213+
dev_info(pps_data.pps->dev, "Registered IRQ %d as PPS source. (gpio = %d, edge = %s)\n",
214+
pps_data.irq, pps_data.gpio_pin, assert_falling_edge ? "falling" : "rising" );
179215

180216
return 0;
181217
}
182218

183-
static int pps_gpio_remove(struct platform_device *pdev)
219+
static void __exit pps_gpio_exit(void)
184220
{
185-
struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
221+
unsigned int gpio_pin;
222+
int irq_banks[2] = {0, 0};
186223

187-
pps_unregister_source(data->pps);
188-
dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
189-
return 0;
224+
// gpio_to_irq translates from global GPIO # to chip offset, which meson_free_irq wants
225+
gpio_pin = gpio_to_irq(pps_data.gpio_pin);
226+
meson_free_irq(gpio_pin, irq_banks);
227+
228+
pps_unregister_source(pps_data.pps);
229+
dev_info(&pps_gpio_dev, "removed IRQ %d as PPS source\n", pps_data.irq);
230+
231+
device_unregister(&pps_gpio_dev);
190232
}
191233

192-
static const struct of_device_id pps_gpio_dt_ids[] = {
193-
{ .compatible = "pps-gpio", },
194-
{ /* sentinel */ }
195-
};
196-
MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids);
197-
198-
static struct platform_driver pps_gpio_driver = {
199-
.probe = pps_gpio_probe,
200-
.remove = pps_gpio_remove,
201-
.driver = {
202-
.name = PPS_GPIO_NAME,
203-
.owner = THIS_MODULE,
204-
.of_match_table = pps_gpio_dt_ids,
205-
},
206-
};
234+
module_init(pps_gpio_init);
235+
module_exit(pps_gpio_exit);
207236

208-
module_platform_driver(pps_gpio_driver);
209237
MODULE_AUTHOR("Ricardo Martins <[email protected]>");
210238
MODULE_AUTHOR("James Nuss <[email protected]>");
211239
MODULE_DESCRIPTION("Use GPIO pin as PPS source");

0 commit comments

Comments
 (0)