static int pps_gpio_probe(struct platform_device *pdev) { struct pps_gpio_device_data *data; int irq; int ret; int err; int pps_default_params; const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; /* GPIO setup */ ret = pps_gpio_setup(pdev); if (ret) return -EINVAL; /* IRQ setup */ irq = gpio_to_irq(pdata->gpio_pin); if (irq < 0) { pr_err("failed to map GPIO to IRQ: %d\n", irq); err = -EINVAL; goto return_error; } /* allocate space for device info */ data = kzalloc(sizeof(struct pps_gpio_device_data), GFP_KERNEL); if (data == NULL) { err = -ENOMEM; goto return_error; } /* initialize PPS specific parts of the bookkeeping data structure. */ data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC; if (pdata->capture_clear) data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR | PPS_ECHOCLEAR; data->info.owner = THIS_MODULE; snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d", pdev->name, pdev->id); /* register PPS source */ pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT; if (pdata->capture_clear) pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR; data->pps = pps_register_source(&data->info, pps_default_params); if (data->pps == NULL) { kfree(data); pr_err("failed to register IRQ %d as PPS source\n", irq); err = -EINVAL; goto return_error; } data->irq = irq; data->pdata = pdata; /* register IRQ interrupt handler */ ret = request_irq(irq, pps_gpio_irq_handler, get_irqf_trigger_flags(pdata), data->info.name, data); if (ret) { pps_unregister_source(data->pps); kfree(data); pr_err("failed to acquire IRQ %d\n", irq); err = -EINVAL; goto return_error; } platform_set_drvdata(pdev, data); dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq); return 0; return_error: gpio_free(pdata->gpio_pin); return err; }
static int pps_gpio_probe(struct platform_device *pdev) { struct pps_gpio_device_data *data; const char *gpio_label; int ret; int pps_default_params; const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data; struct device_node *np = pdev->dev.of_node; /* allocate space for device info */ data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data), GFP_KERNEL); if (!data) return -ENOMEM; if (pdata) { data->gpio_pin = pdata->gpio_pin; gpio_label = pdata->gpio_label; data->assert_falling_edge = pdata->assert_falling_edge; data->capture_clear = pdata->capture_clear; } else { ret = of_get_gpio(np, 0); if (ret < 0) { dev_err(&pdev->dev, "failed to get GPIO from device tree\n"); return ret; } data->gpio_pin = ret; gpio_label = PPS_GPIO_NAME; if (of_get_property(np, "assert-falling-edge", NULL)) data->assert_falling_edge = true; } /* GPIO setup */ ret = devm_gpio_request(&pdev->dev, data->gpio_pin, gpio_label); if (ret) { dev_err(&pdev->dev, "failed to request GPIO %u\n", data->gpio_pin); return ret; } ret = gpio_direction_input(data->gpio_pin); if (ret) { dev_err(&pdev->dev, "failed to set pin direction\n"); return -EINVAL; } /* IRQ setup */ ret = gpio_to_irq(data->gpio_pin); if (ret < 0) { dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret); return -EINVAL; } data->irq = ret; /* initialize PPS specific parts of the bookkeeping data structure. */ data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC; if (data->capture_clear) data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR | PPS_ECHOCLEAR; data->info.owner = THIS_MODULE; snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d", pdev->name, pdev->id); /* register PPS source */ pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT; if (data->capture_clear) pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR; data->pps = pps_register_source(&data->info, pps_default_params); if (data->pps == NULL) { dev_err(&pdev->dev, "failed to register IRQ %d as PPS source\n", data->irq); return -EINVAL; } /* register IRQ interrupt handler */ ret = devm_request_irq(&pdev->dev, data->irq, pps_gpio_irq_handler, get_irqf_trigger_flags(data), data->info.name, data); if (ret) { pps_unregister_source(data->pps); dev_err(&pdev->dev, "failed to acquire IRQ %d\n", data->irq); return -EINVAL; } platform_set_drvdata(pdev, data); dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", data->irq); return 0; }