[LinuxPPS] gpio-pps with echopin

Rodolfo Giometti giometti at enneenne.com
Mon Apr 13 19:45:37 CEST 2015


On Mon, Apr 13, 2015 at 06:36:58PM +0200, f.hiesinger wrote:
> +static void pps_gpio_echo(struct pps_device *pps, int event,
> +		void *data)
> +{
> +		const struct pps_gpio_device_data *info = data;
> +
> +		/* TODO: make polarity of echopin configurable (invertable)
> +		 * TODO: toggle echopin if capture_clear is not set */

Don't use TODO... echo pin polarity can be the same of the source pin.

> +		if (event & PPS_CAPTUREASSERT)
> +			gpio_set_value(info->gpio_echo_pin, SIGNAL);
> +		else
> +			gpio_set_value(info->gpio_echo_pin, NO_SIGNAL);
> +}
>  
>  static unsigned long
>  get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
> @@ -91,6 +113,7 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  {
>  	struct pps_gpio_device_data *data;
>  	const char *gpio_label;
> +	const char *gpio_echo_label;
>  	int ret;
>  	int pps_default_params;
>  	const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
> @@ -103,12 +126,20 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	if (pdata) {
> +		/* Non-DT based instantiation */
>  		data->gpio_pin = pdata->gpio_pin;
> +		data->gpio_echo_pin = pdata->gpio_echo_pin;
>  		gpio_label = pdata->gpio_label;
> +		gpio_echo_label = pdata->gpio_echo_label;
>  
>  		data->assert_falling_edge = pdata->assert_falling_edge;
>  		data->capture_clear = pdata->capture_clear;
> +		dev_dbg(&pdev->dev, "1) data->assert_falling_edge = %d , \
> +				 data->capture_clear = %d\n ", data->assert_falling_edge, \
> +				 data->capture_clear);
> +
>  	} else {
> +		/* DT based instantiation */
>  		ret = of_get_gpio(np, 0);
>  		if (ret < 0) {
>  			dev_err(&pdev->dev, "failed to get GPIO from device tree\n");
> @@ -117,8 +148,23 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  		data->gpio_pin = ret;
>  		gpio_label = PPS_GPIO_NAME;
>  
> +		if (of_get_property(np, "echo-enable", NULL)) {

Nak, you can count how much pins has been defined into gpios property
to decide if the echo function is needed.

> +			dev_dbg(&pdev->dev, "'echo-enable'-property found");
> +			ret = of_get_gpio(np, 1);
> +			if (ret < 0) {
> +				dev_err(&pdev->dev, "failed to get Echo-GPIO from device tree\n");
> +				return ret;
> +			}
> +			data->gpio_echo_pin = ret;
> +			gpio_echo_label = "pps-gpio-echo";
> +		}
>  		if (of_get_property(np, "assert-falling-edge", NULL))
>  			data->assert_falling_edge = true;
> +		if (of_get_property(np, "capture-clear", NULL))
> +			data->capture_clear = true;
> +		dev_dbg(&pdev->dev, "2) data->assert_falling_edge = %d , \
> +				data->capture_clear = %d\n ", data->assert_falling_edge, \
> +				data->capture_clear);

What this chunk is for?

>  	}
>  
>  	/* GPIO setup */
> @@ -135,6 +181,21 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>  
> +	if (of_get_property(np, "echo-enable", NULL)) {

Why using this function again? You can properly set the gpio_echo_pin
to signal if it has been used or not (don't forget to consider the
non-DT based systems).

> +		ret = devm_gpio_request(&pdev->dev, data->gpio_echo_pin, \
> +				gpio_echo_label);
> +			if (ret) {
> +				dev_err(&pdev->dev, "failed to request Echo-GPIO %u\n", \
> +						data->gpio_echo_pin);
> +				return ret;
> +		}
> +		ret = gpio_direction_output(data->gpio_echo_pin, 0);
> +		if (ret) {
> +			dev_err(&pdev->dev, "failed to set (echo)pin direction\n");
> +			return -EINVAL;
> +		}
> +	}
> +
>  	/* IRQ setup */
>  	ret = gpio_to_irq(data->gpio_pin);
>  	if (ret < 0) {
> @@ -150,13 +211,24 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  		data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
>  			PPS_ECHOCLEAR;
>  	data->info.owner = THIS_MODULE;
> +	dev_dbg(&pdev->dev, "1)data->info.mode = %x\n", data->info.mode);
> +	dev_dbg(&pdev->dev, "1)data->info.echo = %p\n", (void *)data->info.echo);

Nak. Please replace with:

     dev_dbg(&pdev->dev, "data->info.mode = %x\n", data->info.mode);
     dev_dbg(&pdev->dev, "data->info.echo = %p\n", (void *) data->info.echo);

However printing a function address is not so useful...

> +	if (of_get_property(np, "echo-enable", NULL))
> +		/* register echo function */
> +		data->info.echo = pps_gpio_echo;
> +
> +	dev_dbg(&pdev->dev, "2)data->info.echo = %p \n", (void *) data->info.echo);

Nak. Use just one dev_dbg(&pdev->dev, "data->info.echo = ...

>  	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;
> +	pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_ECHOASSERT;
>  	if (data->capture_clear)
> -		pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
> +		pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR | PPS_ECHOCLEAR;
> +	dev_dbg(&pdev->dev, "1)pps_default_params = %x\n", pps_default_params);

Nak. Please replace with:

dev_dbg(&pdev->dev, "pps_default_params = %x\n", pps_default_params);

>  	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",
> @@ -183,7 +255,7 @@ static int pps_gpio_probe(struct platform_device *pdev)
>  static int pps_gpio_remove(struct platform_device *pdev)
>  {
>  	struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
> -
> +	/* TODO: Check if gpio_free(...) is necessary */

Drop TODO... patches must be a complete work.

>  	pps_unregister_source(data->pps);
>  	dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
>  	return 0;
> @@ -208,6 +280,6 @@ static struct platform_driver pps_gpio_driver = {
>  module_platform_driver(pps_gpio_driver);
>  MODULE_AUTHOR("Ricardo Martins <rasm at fe.up.pt>");
>  MODULE_AUTHOR("James Nuss <jamesnuss at nanometrics.ca>");
> -MODULE_DESCRIPTION("Use GPIO pin as PPS source");
> +MODULE_DESCRIPTION("Use GPIO pins as PPS source & echo");
>  MODULE_LICENSE("GPL");
> -MODULE_VERSION("1.0.0");
> +MODULE_VERSION("1.0.3");

The code below is against the Linux vanilla? If not just drop it.

> diff --git a/linux/arch/arm/boot/dts/pps-gpio-overlay.dts b/linux/arch/arm/boot/dts/pps-gpio-overlay.dts
> index 5832dc9..e759605 100644
> --- a/linux/arch/arm/boot/dts/pps-gpio-overlay.dts
> +++ b/linux/arch/arm/boot/dts/pps-gpio-overlay.dts
> @@ -10,10 +10,11 @@
>  				compatible = "pps-gpio";
>  				pinctrl-names = "default";
>  				pinctrl-0 = <&pps_pins>;
> -				gpios = <&gpio 18 0>, <&gpio 21 1>; 
> +				gpios = <&gpio 18 0>, <&gpio 21 1>; /* input, output */ 
>  				status = "okay";
>  				assert-falling-edge;
>  				capture-clear;
> +				echo-enable;
>  			};
>  		};
>  	};
> @@ -32,7 +33,7 @@
>  	__overrides__ {
>  		gpiopin = <&pps>,"gpios:4",
>  			      <&pps_pins>,"brcm,pins:0";
> -		gpioechopin = <&pps>,"gpios:16 ",
> +		gpioechopin = <&pps>,"gpios:16",
>  					  <&pps_pins>,"brcm,pins:4";
>  	};
>  };

Ciao,

Rodolfo

-- 

HCE Engineering                      e-mail: giometti at hce-engineering.com
GNU/Linux Solutions                          giometti at enneenne.com
Linux Device Driver                          giometti at linux.it
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti
Cosino Project - the quick prototyping embedded system - www.cosino.io
Freelance ICT Italia - Consulente ICT Italia - www.consulenti-ict.it




More information about the discussions mailing list