All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johan Hovold <johan@kernel.org>
To: Karoly Pados <pados@pados.hu>
Cc: Johan Hovold <johan@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	Loic Poulain <loic.poulain@linaro.org>
Subject: [v4] USB: serial: ftdi_sio: implement GPIO support for FT-X devices
Date: Tue, 18 Sep 2018 11:16:34 +0200	[thread overview]
Message-ID: <20180918091634.GC3943@localhost> (raw)

On Sun, Sep 16, 2018 at 07:58:47PM +0200, Karoly Pados wrote:
> This patch allows using the CBUS pins of FT-X devices as GPIO in CBUS
> bitbanging mode. There is no conflict between the GPIO and VCP
> functionality in this mode. Tested on FT230X and FT231X.
> 
> As there is no way to request the current CBUS register configuration
> from the device, all CBUS pins are set to a known state when the first
> GPIO is requested. This allows using libftdi to set the GPIO pins
> before loading this module for UART functionality, a behavior that
> existing applications might be relying upon (though no specific case
> is known to the authors of this patch).
> 
> Signed-off-by: Karoly Pados <pados@pados.hu>
> ---
> Changelog:
> - v2: Fix compile error when CONFIG_GPIOLIB is not defined.
> - v3: Incorporate review feedback.
> - v4: Include linux/gpio/driver.h unconditionally.
>       Replace and invert gpio_input with gpio_output.
>       Make ftdi_gpio_direction_get return 0/1.
>       Change dev_err msg in ftdi_set_bitmode_req.
>       Change formatting of error checking in ftdi_gpio_get.
>       Drop dev_err in ftdi_gpio_set.
>       Remove some line breaks and empty lines.
>       Change error handling in ftdi_read_eeprom (and adjust caller).
>       Replace SIO->FTX in FTDI_SIO_CBUS_MUX_GPIO macro name.

Really nice job with this; looks nice and clean over all. Just a few
comments below.

> +static int ftx_gpioconf_init(struct usb_serial_port *port)
> +{
> +	struct ftdi_private *priv = usb_get_serial_port_data(port);
> +	struct usb_serial *serial = port->serial;
> +	const u16 cbus_cfg_addr = 0x1a;
> +	const u16 cbus_cfg_size = 8;

Looks like you only need to read four bytes.

> +	u8 *cbus_cfg_buf;
> +	int result;
> +	u8 i;
> +
> +	/* Read a part of device EEPROM */
> +	cbus_cfg_buf = kmalloc(cbus_cfg_size, GFP_KERNEL);
> +	if (!cbus_cfg_buf)
> +		return -ENOMEM;
> +
> +	result = ftdi_read_eeprom(serial, cbus_cfg_buf,
> +				  cbus_cfg_addr, cbus_cfg_size);
> +	if (result != 0)

result < 0 would be more informative here.

> +		goto out_free;
> +
> +	/* Chip-type guessing logic based on libftdi. */
> +	priv->gc.ngpio = 4;  /* FT230X, FT231X */
> +	if (le16_to_cpu(serial->dev->descriptor.bcdDevice) != 0x1000)
> +		priv->gc.ngpio = 1;  /* FT234XD */

As I mentioned in my last mail: I've asked FTDI about this, but I fear
that FTX234XD has bcdDevice 0x1000 and we may need to just always
register all four pins after all.

> +	/* Determine which pins are configured for CBUS bitbanging */
> +	priv->gpio_altfunc = 0xff;
> +	for (i = 0; i < priv->gc.ngpio; ++i) {
> +		if (cbus_cfg_buf[i] == FTDI_FTX_CBUS_MUX_GPIO)
> +			priv->gpio_altfunc &= ~BIT(i);
> +	}
> +
> +out_free:
> +	kfree(cbus_cfg_buf);
> +
> +	return result;
> +}

> +static void ftdi_gpio_remove(struct usb_serial_port *port)
> +{
> +	struct ftdi_private *priv = usb_get_serial_port_data(port);
> +
> +	if (priv->gpio_used) {
> +		/* Remark: Exiting CBUS-mode does not reset pin states too */
> +		ftdi_exit_cbus_mode(port);
> +		priv->gpio_used = false;
> +	}

This should go after deregistration or we have a tiny race window here.

> +	if (priv->gpio_registered) {
> +		gpiochip_remove(&priv->gc);
> +		priv->gpio_registered = false;
> +	}
> +}

> diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
> index dcd0b6e05baf..6856ccdac9b4 100644
> --- a/drivers/usb/serial/ftdi_sio.h
> +++ b/drivers/usb/serial/ftdi_sio.h
> @@ -35,7 +35,10 @@
>  #define FTDI_SIO_SET_EVENT_CHAR		6 /* Set the event character */
>  #define FTDI_SIO_SET_ERROR_CHAR		7 /* Set the error character */
>  #define FTDI_SIO_SET_LATENCY_TIMER	9 /* Set the latency timer */
> -#define FTDI_SIO_GET_LATENCY_TIMER	10 /* Get the latency timer */
> +#define FTDI_SIO_GET_LATENCY_TIMER	0x0a /* Get the latency timer */
> +#define FTDI_SIO_SET_BITMODE		0x0b /* Set GPIO mode */

Nit: "Set bitbang mode", I think would be more correct here as this
request is also used to configure the asynchronous bitbang mode, etc.

Thanks,
Johan

WARNING: multiple messages have this Message-ID (diff)
From: Johan Hovold <johan@kernel.org>
To: Karoly Pados <pados@pados.hu>
Cc: Johan Hovold <johan@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	Loic Poulain <loic.poulain@linaro.org>
Subject: Re: [PATCH v4] USB: serial: ftdi_sio: implement GPIO support for FT-X devices
Date: Tue, 18 Sep 2018 11:16:34 +0200	[thread overview]
Message-ID: <20180918091634.GC3943@localhost> (raw)
In-Reply-To: <20180916175847.3288-1-pados@pados.hu>

On Sun, Sep 16, 2018 at 07:58:47PM +0200, Karoly Pados wrote:
> This patch allows using the CBUS pins of FT-X devices as GPIO in CBUS
> bitbanging mode. There is no conflict between the GPIO and VCP
> functionality in this mode. Tested on FT230X and FT231X.
> 
> As there is no way to request the current CBUS register configuration
> from the device, all CBUS pins are set to a known state when the first
> GPIO is requested. This allows using libftdi to set the GPIO pins
> before loading this module for UART functionality, a behavior that
> existing applications might be relying upon (though no specific case
> is known to the authors of this patch).
> 
> Signed-off-by: Karoly Pados <pados@pados.hu>
> ---
> Changelog:
> - v2: Fix compile error when CONFIG_GPIOLIB is not defined.
> - v3: Incorporate review feedback.
> - v4: Include linux/gpio/driver.h unconditionally.
>       Replace and invert gpio_input with gpio_output.
>       Make ftdi_gpio_direction_get return 0/1.
>       Change dev_err msg in ftdi_set_bitmode_req.
>       Change formatting of error checking in ftdi_gpio_get.
>       Drop dev_err in ftdi_gpio_set.
>       Remove some line breaks and empty lines.
>       Change error handling in ftdi_read_eeprom (and adjust caller).
>       Replace SIO->FTX in FTDI_SIO_CBUS_MUX_GPIO macro name.

Really nice job with this; looks nice and clean over all. Just a few
comments below.

> +static int ftx_gpioconf_init(struct usb_serial_port *port)
> +{
> +	struct ftdi_private *priv = usb_get_serial_port_data(port);
> +	struct usb_serial *serial = port->serial;
> +	const u16 cbus_cfg_addr = 0x1a;
> +	const u16 cbus_cfg_size = 8;

Looks like you only need to read four bytes.

> +	u8 *cbus_cfg_buf;
> +	int result;
> +	u8 i;
> +
> +	/* Read a part of device EEPROM */
> +	cbus_cfg_buf = kmalloc(cbus_cfg_size, GFP_KERNEL);
> +	if (!cbus_cfg_buf)
> +		return -ENOMEM;
> +
> +	result = ftdi_read_eeprom(serial, cbus_cfg_buf,
> +				  cbus_cfg_addr, cbus_cfg_size);
> +	if (result != 0)

result < 0 would be more informative here.

> +		goto out_free;
> +
> +	/* Chip-type guessing logic based on libftdi. */
> +	priv->gc.ngpio = 4;  /* FT230X, FT231X */
> +	if (le16_to_cpu(serial->dev->descriptor.bcdDevice) != 0x1000)
> +		priv->gc.ngpio = 1;  /* FT234XD */

As I mentioned in my last mail: I've asked FTDI about this, but I fear
that FTX234XD has bcdDevice 0x1000 and we may need to just always
register all four pins after all.

> +	/* Determine which pins are configured for CBUS bitbanging */
> +	priv->gpio_altfunc = 0xff;
> +	for (i = 0; i < priv->gc.ngpio; ++i) {
> +		if (cbus_cfg_buf[i] == FTDI_FTX_CBUS_MUX_GPIO)
> +			priv->gpio_altfunc &= ~BIT(i);
> +	}
> +
> +out_free:
> +	kfree(cbus_cfg_buf);
> +
> +	return result;
> +}

> +static void ftdi_gpio_remove(struct usb_serial_port *port)
> +{
> +	struct ftdi_private *priv = usb_get_serial_port_data(port);
> +
> +	if (priv->gpio_used) {
> +		/* Remark: Exiting CBUS-mode does not reset pin states too */
> +		ftdi_exit_cbus_mode(port);
> +		priv->gpio_used = false;
> +	}

This should go after deregistration or we have a tiny race window here.

> +	if (priv->gpio_registered) {
> +		gpiochip_remove(&priv->gc);
> +		priv->gpio_registered = false;
> +	}
> +}

> diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
> index dcd0b6e05baf..6856ccdac9b4 100644
> --- a/drivers/usb/serial/ftdi_sio.h
> +++ b/drivers/usb/serial/ftdi_sio.h
> @@ -35,7 +35,10 @@
>  #define FTDI_SIO_SET_EVENT_CHAR		6 /* Set the event character */
>  #define FTDI_SIO_SET_ERROR_CHAR		7 /* Set the error character */
>  #define FTDI_SIO_SET_LATENCY_TIMER	9 /* Set the latency timer */
> -#define FTDI_SIO_GET_LATENCY_TIMER	10 /* Get the latency timer */
> +#define FTDI_SIO_GET_LATENCY_TIMER	0x0a /* Get the latency timer */
> +#define FTDI_SIO_SET_BITMODE		0x0b /* Set GPIO mode */

Nit: "Set bitbang mode", I think would be more correct here as this
request is also used to configure the asynchronous bitbang mode, etc.

Thanks,
Johan

             reply	other threads:[~2018-09-18  9:16 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-18  9:16 Johan Hovold [this message]
2018-09-18  9:16 ` [PATCH v4] USB: serial: ftdi_sio: implement GPIO support for FT-X devices Johan Hovold
  -- strict thread matches above, loose matches on Subject: below --
2018-09-18 11:19 [v4] " Johan Hovold
2018-09-18 11:19 ` [PATCH v4] " Johan Hovold
2018-09-18 10:27 [v4] " Karoly Pados
2018-09-18 10:27 ` [PATCH v4] " Karoly Pados
2018-09-18  9:45 [v4] " Johan Hovold
2018-09-18  9:45 ` [PATCH v4] " Johan Hovold
2018-09-18  9:35 [v4] " Karoly Pados
2018-09-18  9:35 ` [PATCH v4] " Karoly Pados
2018-09-16 17:58 [v4] " Karoly Pados
2018-09-16 17:58 ` [PATCH v4] " Karoly Pados

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180918091634.GC3943@localhost \
    --to=johan@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=loic.poulain@linaro.org \
    --cc=pados@pados.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.