Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pps-gpio: add device-tree binding and support

Instead of allocating a struct pps_gpio_platform_data in the DT case,
store the necessary information in struct pps_gpio_device_data itself.
This avoids an additional allocation and the ifdef. It also gets rid of
some indirection.

Also use dev_err instead of pr_err in the changed code.

Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Rodolfo Giometti <giometti@enneenne.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jan Luebbe and committed by
Linus Torvalds
c5dbcf8b 05212be3

+97 -58
+20
Documentation/devicetree/bindings/pps/pps-gpio.txt
··· 1 + Device-Tree Bindings for a PPS Signal on GPIO 2 + 3 + These properties describe a PPS (pulse-per-second) signal connected to 4 + a GPIO pin. 5 + 6 + Required properties: 7 + - compatible: should be "pps-gpio" 8 + - gpios: one PPS GPIO in the format described by ../gpio/gpio.txt 9 + 10 + Optional properties: 11 + - assert-falling-edge: when present, assert is indicated by a falling edge 12 + (instead of by a rising edge) 13 + 14 + Example: 15 + pps { 16 + compatible = "pps-gpio"; 17 + gpios = <&gpio2 6 0>; 18 + 19 + assert-falling-edge; 20 + };
+77 -58
drivers/pps/clients/pps-gpio.c
··· 33 33 #include <linux/pps-gpio.h> 34 34 #include <linux/gpio.h> 35 35 #include <linux/list.h> 36 + #include <linux/of_device.h> 37 + #include <linux/of_gpio.h> 36 38 37 39 /* Info for each registered platform device */ 38 40 struct pps_gpio_device_data { 39 41 int irq; /* IRQ used as PPS source */ 40 42 struct pps_device *pps; /* PPS source device */ 41 43 struct pps_source_info info; /* PPS source information */ 42 - const struct pps_gpio_platform_data *pdata; 44 + bool assert_falling_edge; 45 + bool capture_clear; 46 + unsigned int gpio_pin; 43 47 }; 44 48 45 49 /* ··· 61 57 62 58 info = data; 63 59 64 - rising_edge = gpio_get_value(info->pdata->gpio_pin); 65 - if ((rising_edge && !info->pdata->assert_falling_edge) || 66 - (!rising_edge && info->pdata->assert_falling_edge)) 60 + rising_edge = gpio_get_value(info->gpio_pin); 61 + if ((rising_edge && !info->assert_falling_edge) || 62 + (!rising_edge && info->assert_falling_edge)) 67 63 pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL); 68 - else if (info->pdata->capture_clear && 69 - ((rising_edge && info->pdata->assert_falling_edge) || 70 - (!rising_edge && !info->pdata->assert_falling_edge))) 64 + else if (info->capture_clear && 65 + ((rising_edge && info->assert_falling_edge) || 66 + (!rising_edge && !info->assert_falling_edge))) 71 67 pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL); 72 68 73 69 return IRQ_HANDLED; 74 70 } 75 71 76 - static int pps_gpio_setup(struct platform_device *pdev) 77 - { 78 - int ret; 79 - const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; 80 - 81 - ret = devm_gpio_request(&pdev->dev, pdata->gpio_pin, pdata->gpio_label); 82 - if (ret) { 83 - pr_warning("failed to request GPIO %u\n", pdata->gpio_pin); 84 - return -EINVAL; 85 - } 86 - 87 - ret = gpio_direction_input(pdata->gpio_pin); 88 - if (ret) { 89 - pr_warning("failed to set pin direction\n"); 90 - return -EINVAL; 91 - } 92 - 93 - return 0; 94 - } 95 - 96 72 static unsigned long 97 - get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata) 73 + get_irqf_trigger_flags(const struct pps_gpio_device_data *data) 98 74 { 99 - unsigned long flags = pdata->assert_falling_edge ? 75 + unsigned long flags = data->assert_falling_edge ? 100 76 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; 101 77 102 - if (pdata->capture_clear) { 78 + if (data->capture_clear) { 103 79 flags |= ((flags & IRQF_TRIGGER_RISING) ? 104 80 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING); 105 81 } ··· 90 106 static int pps_gpio_probe(struct platform_device *pdev) 91 107 { 92 108 struct pps_gpio_device_data *data; 93 - int irq; 109 + const char *gpio_label; 94 110 int ret; 95 111 int pps_default_params; 96 112 const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; 97 - 98 - 99 - /* GPIO setup */ 100 - ret = pps_gpio_setup(pdev); 101 - if (ret) 102 - return -EINVAL; 103 - 104 - /* IRQ setup */ 105 - irq = gpio_to_irq(pdata->gpio_pin); 106 - if (irq < 0) { 107 - pr_err("failed to map GPIO to IRQ: %d\n", irq); 108 - return -EINVAL; 109 - } 113 + struct device_node *np = pdev->dev.of_node; 110 114 111 115 /* allocate space for device info */ 112 116 data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data), 113 - GFP_KERNEL); 114 - if (data == NULL) 117 + GFP_KERNEL); 118 + if (!data) 115 119 return -ENOMEM; 120 + 121 + if (pdata) { 122 + data->gpio_pin = pdata->gpio_pin; 123 + gpio_label = pdata->gpio_label; 124 + 125 + data->assert_falling_edge = pdata->assert_falling_edge; 126 + data->capture_clear = pdata->capture_clear; 127 + } else { 128 + ret = of_get_gpio(np, 0); 129 + if (ret < 0) { 130 + dev_err(&pdev->dev, "failed to get GPIO from device tree\n"); 131 + return ret; 132 + } 133 + data->gpio_pin = ret; 134 + gpio_label = PPS_GPIO_NAME; 135 + 136 + if (of_get_property(np, "assert-falling-edge", NULL)) 137 + data->assert_falling_edge = true; 138 + } 139 + 140 + /* GPIO setup */ 141 + ret = devm_gpio_request(&pdev->dev, data->gpio_pin, gpio_label); 142 + if (ret) { 143 + dev_err(&pdev->dev, "failed to request GPIO %u\n", 144 + data->gpio_pin); 145 + return ret; 146 + } 147 + 148 + ret = gpio_direction_input(data->gpio_pin); 149 + if (ret) { 150 + dev_err(&pdev->dev, "failed to set pin direction\n"); 151 + return -EINVAL; 152 + } 153 + 154 + /* IRQ setup */ 155 + ret = gpio_to_irq(data->gpio_pin); 156 + if (ret < 0) { 157 + dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret); 158 + return -EINVAL; 159 + } 160 + data->irq = ret; 116 161 117 162 /* initialize PPS specific parts of the bookkeeping data structure. */ 118 163 data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | 119 164 PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC; 120 - if (pdata->capture_clear) 165 + if (data->capture_clear) 121 166 data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR | 122 167 PPS_ECHOCLEAR; 123 168 data->info.owner = THIS_MODULE; ··· 155 142 156 143 /* register PPS source */ 157 144 pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT; 158 - if (pdata->capture_clear) 145 + if (data->capture_clear) 159 146 pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR; 160 147 data->pps = pps_register_source(&data->info, pps_default_params); 161 148 if (data->pps == NULL) { 162 - pr_err("failed to register IRQ %d as PPS source\n", irq); 149 + dev_err(&pdev->dev, "failed to register IRQ %d as PPS source\n", 150 + data->irq); 163 151 return -EINVAL; 164 152 } 165 153 166 - data->irq = irq; 167 - data->pdata = pdata; 168 - 169 154 /* register IRQ interrupt handler */ 170 - ret = devm_request_irq(&pdev->dev, irq, pps_gpio_irq_handler, 171 - get_irqf_trigger_flags(pdata), data->info.name, data); 155 + ret = devm_request_irq(&pdev->dev, data->irq, pps_gpio_irq_handler, 156 + get_irqf_trigger_flags(data), data->info.name, data); 172 157 if (ret) { 173 158 pps_unregister_source(data->pps); 174 - pr_err("failed to acquire IRQ %d\n", irq); 159 + dev_err(&pdev->dev, "failed to acquire IRQ %d\n", data->irq); 175 160 return -EINVAL; 176 161 } 177 162 178 163 platform_set_drvdata(pdev, data); 179 - dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq); 164 + dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", 165 + data->irq); 180 166 181 167 return 0; 182 168 } ··· 186 174 187 175 platform_set_drvdata(pdev, NULL); 188 176 pps_unregister_source(data->pps); 189 - pr_info("removed IRQ %d as PPS source\n", data->irq); 177 + dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq); 190 178 return 0; 191 179 } 180 + 181 + static const struct of_device_id pps_gpio_dt_ids[] = { 182 + { .compatible = "pps-gpio", }, 183 + { /* sentinel */ } 184 + }; 185 + MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids); 192 186 193 187 static struct platform_driver pps_gpio_driver = { 194 188 .probe = pps_gpio_probe, 195 189 .remove = pps_gpio_remove, 196 190 .driver = { 197 191 .name = PPS_GPIO_NAME, 198 - .owner = THIS_MODULE 192 + .owner = THIS_MODULE, 193 + .of_match_table = of_match_ptr(pps_gpio_dt_ids), 199 194 }, 200 195 }; 201 196