Re: [PATCH v2] can: mcp251x: add GPIO support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/9/19 11:31 PM, Marc Kleine-Budde wrote:
> From: Timo Schlüßler <t.schluessler@xxxxxxxxx>
> 
> ---
> Hello,
> 
> for easier reivew send via git-send-email

please fix the following checkpatch warnings:

CHECK: Macro argument 'n' may be better as '(n)' to avoid precedence issues
#166: FILE: drivers/net/can/spi/mcp251x.c:166:
+#define RXFSID(n) ((n < 3) ? 0 : 4)

CHECK: Macro argument reuse 'n' - possible side-effects?
#167: FILE: drivers/net/can/spi/mcp251x.c:167:
+#define RXFSIDH(n) ((n) * 4 + RXFSID(n))

CHECK: Macro argument reuse 'n' - possible side-effects?
#168: FILE: drivers/net/can/spi/mcp251x.c:168:
+#define RXFSIDL(n) ((n) * 4 + 1 + RXFSID(n))

CHECK: Macro argument reuse 'n' - possible side-effects?
#169: FILE: drivers/net/can/spi/mcp251x.c:169:
+#define RXFEID8(n) ((n) * 4 + 2 + RXFSID(n))

CHECK: Macro argument reuse 'n' - possible side-effects?
#170: FILE: drivers/net/can/spi/mcp251x.c:170:
+#define RXFEID0(n) ((n) * 4 + 3 + RXFSID(n))

WARNING: static const char * array should probably be static const char
* const
#901: FILE: drivers/net/can/spi/mcp251x.c:901:
+static const char * mcp251x_gpio_names[] = {

ERROR: "foo * bar" should be "foo *bar"
#901: FILE: drivers/net/can/spi/mcp251x.c:901:
+static const char * mcp251x_gpio_names[] = {

CHECK: braces {} should be used on all arms of this statement
#959: FILE: drivers/net/can/spi/mcp251x.c:959:
+       if (offset <= TX2RTS) {
[...]
+       } else if (offset <= RX1BF) {
[...]
+       } else
[...]

CHECK: Unbalanced braces around else statement
#965: FILE: drivers/net/can/spi/mcp251x.c:965:
+       } else


> 
> Marc
> 
>  drivers/net/can/spi/mcp251x.c | 208 ++++++++++++++++++++++++++++++++++
>  1 file changed, 208 insertions(+)
> 
> diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
> index bee9f7b8dad6..070da1ff7a18 100644
> --- a/drivers/net/can/spi/mcp251x.c
> +++ b/drivers/net/can/spi/mcp251x.c
> @@ -39,6 +39,8 @@
>  #include <linux/spi/spi.h>
>  #include <linux/uaccess.h>
>  #include <linux/regulator/consumer.h>
> +#include <linux/gpio.h>
> +#include <linux/gpio/driver.h>
>  
>  /* SPI interface instruction set */
>  #define INSTRUCTION_WRITE	0x02
> @@ -53,6 +55,15 @@
>  #define INSTRUCTION_RTS(n)	(0x80 | ((n) & 0x07))
>  
>  /* MPC251x registers */
> +#define BFPCTRL			0x0c
> +#  define BFPCTRL_B0BFE		0x04
> +#  define BFPCTRL_B1BFE		0x08
> +#  define BFPCTRL_B0BFS		0x10
> +#  define BFPCTRL_B1BFS		0x20
> +#define TXRTSCTRL		0x0d
> +#  define TXRTSCTRL_B0RTS	0x08
> +#  define TXRTSCTRL_B1RTS	0x10
> +#  define TXRTSCTRL_B2RTS	0x20
>  #define CANSTAT	      0x0e
>  #define CANCTRL	      0x0f
>  #  define CANCTRL_REQOP_MASK	    0xe0
> @@ -226,6 +237,9 @@ struct mcp251x_priv {
>  	struct regulator *power;
>  	struct regulator *transceiver;
>  	struct clk *clk;
> +#ifdef CONFIG_GPIOLIB
> +	struct gpio_chip gpio;
> +#endif
>  };
>  
>  #define MCP251X_IS(_model) \
> @@ -581,6 +595,8 @@ static int mcp251x_hw_reset(struct spi_device *spi)
>  	if (ret)
>  		return ret;
>  
> +	/* TODO: What to do with the GPIOs here? Reset last state? */
> +
>  	/* Wait for oscillator startup timer after reset */
>  	mdelay(MCP251X_OST_DELAY_MS);
>  
> @@ -873,6 +889,183 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>  
> +#ifdef CONFIG_GPIOLIB

please remove the ifdef here

> +
> +#define TX0RTS 0
> +#define TX1RTS 1
> +#define TX2RTS 2
> +#define RX0BF 3
> +#define RX1BF 4
> +#define NGPIO 5

please add a common prefix like MCP251X_

> +
> +static const char * mcp251x_gpio_names[] = {
> +	"TX0RTS",
> +	"TX1RTS",
> +	"TX2RTS",
> +	"RX0BF",
> +	"RX1BF"
> +};
> +
> +static int mcp251x_gpio_request(struct gpio_chip *chip,
> +				unsigned int offset)

You might need to add a "__maybe_unused" to the functions to avoid
warnings, like this:

static int __maybe_unused mcp251x_gpio_request(struct gpio_chip *chip,
					       unsigned int offset)

> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	u8 bit = BFPCTRL_B0BFE << (offset - RX0BF);
> +
> +	if (offset >= NGPIO)
> +		return -EINVAL;
> +	if (offset <= TX2RTS) // nothing to be done for inputs

Please use /* */ for comments.

> +		return 0;
> +
> +	mutex_lock(&priv->mcp_lock);
> +	mcp251x_write_bits(priv->spi, BFPCTRL, bit, bit);
> +	mutex_unlock(&priv->mcp_lock);
> +
> +	return 0;
> +}
> +
> +static void mcp251x_gpio_free(struct gpio_chip *chip,
> +			      unsigned int offset)
> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	u8 bit = BFPCTRL_B0BFE << (offset - RX0BF);
> +
> +	if (offset >= NGPIO)
> +		return;
> +	if (offset <= TX2RTS) // nothing to be done for inputs

same here

> +		return;
> +
> +	mutex_lock(&priv->mcp_lock);
> +	mcp251x_write_bits(priv->spi, BFPCTRL, bit, 0);
> +	mutex_unlock(&priv->mcp_lock);
> +}
> +
> +static int mcp251x_gpio_get_direction(struct gpio_chip *chip,
> +				      unsigned int offset)
> +{
> +	if (offset <= TX2RTS)
> +		return GPIOF_DIR_IN;
> +	else if (offset <= RX1BF)
> +		return GPIOF_DIR_OUT;
> +
> +	return -EINVAL;
> +}
> +
> +static int mcp251x_gpio_get(struct gpio_chip *chip, unsigned int offset)
> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	u8 reg, mask, val;
> +
> +	if (offset <= TX2RTS) {
> +		reg = TXRTSCTRL;
> +		mask = TXRTSCTRL_B0RTS << offset;
> +	} else if (offset <= RX1BF) {
> +		reg = BFPCTRL;
> +		mask = BFPCTRL_B0BFS << (offset - RX0BF);
> +	} else
> +		return -EINVAL;
> +
> +	mutex_lock(&priv->mcp_lock);
> +	val = mcp251x_read_reg(priv->spi, reg);
> +	mutex_unlock(&priv->mcp_lock);
> +
> +	if (val & mask)
> +		return 1;
> +	return 0;
> +}
> +
> +static int mcp251x_gpio_get_multiple(struct gpio_chip *chip,
> +				     unsigned long *mask, unsigned long *bits)
> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	unsigned long retbits = 0;
> +
> +	mutex_lock(&priv->mcp_lock);
> +
> +	if (mask[0] & GENMASK(TX2RTS, TX0RTS))
> +		retbits |= mcp251x_read_reg(priv->spi, TXRTSCTRL)
> +					>> __ffs(TXRTSCTRL_B0RTS);

please move the >> to the end of the preevious line

> +	if (mask[0] & GENMASK(RX1BF, RX0BF))
> +		retbits |= (mcp251x_read_reg(priv->spi, BFPCTRL)
> +					>> (__ffs(BFPCTRL_B0BFS) - RX0BF))
> +					& GENMASK(RX1BF, RX0BF);

same here
> +
> +	mutex_unlock(&priv->mcp_lock);
> +
> +	bits[0] = retbits;
> +	return 0;
> +}
> +
> +static void mcp251x_gpio_set(struct gpio_chip *chip, unsigned int offset,
> +			     int value)
> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	u8 mask;
> +
> +	if (offset < RX0BF)
> +		return;
> +
> +	mask = BFPCTRL_B0BFS << (offset - RX0BF);
> +
> +	mutex_lock(&priv->mcp_lock);
> +	mcp251x_write_bits(priv->spi, BFPCTRL, mask, value ? mask : 0);
> +	mutex_unlock(&priv->mcp_lock);
> +}
> +
> +static void mcp251x_gpio_set_multiple(struct gpio_chip *chip,
> +				      unsigned long *mask, unsigned long *bits)
> +{
> +	struct mcp251x_priv *priv = gpiochip_get_data(chip);
> +	u8 reg_mask = 0, value = 0;
> +	int pin;
> +
> +	for (pin = RX0BF; pin <= RX1BF; pin++) {
> +		if (test_bit(pin, mask)) {
> +			u8 mask_val = BFPCTRL_B0BFS << (pin - RX0BF);
> +
> +			reg_mask |= mask_val;
> +			if (test_bit(pin, bits))
> +				value |= mask_val;
> +		}
> +	}
> +
> +	if (!reg_mask)
> +		return;
> +
> +	mutex_lock(&priv->mcp_lock);
> +	mcp251x_write_bits(priv->spi, BFPCTRL, reg_mask, value);
> +	mutex_unlock(&priv->mcp_lock);
> +}
> +

I think it's enough to move the #ifdef CONFIG_GPIOLIB here...

> +static int mcp251x_gpio_setup(struct mcp251x_priv *priv)
> +{
> +	struct gpio_chip *gpio = &priv->gpio;
> +
> +	/* gpiochip handles TX[0..2]RTS and RX[0..1]BF */
> +	gpio->label                = priv->spi->modalias;
> +	gpio->parent               = &priv->spi->dev;
> +	gpio->owner                = THIS_MODULE;
> +	gpio->request              = mcp251x_gpio_request;
> +	gpio->free                 = mcp251x_gpio_free;
> +	gpio->get_direction        = mcp251x_gpio_get_direction;
> +	gpio->get                  = mcp251x_gpio_get;
> +	gpio->get_multiple         = mcp251x_gpio_get_multiple;
> +	gpio->set                  = mcp251x_gpio_set;
> +	gpio->set_multiple         = mcp251x_gpio_set_multiple;
> +	gpio->base                 = -1;
> +	gpio->ngpio                = NGPIO;
> +	gpio->names                = mcp251x_gpio_names;
> +	gpio->can_sleep            = 1;

please use only one space in front of the "="

> +
> +	return gpiochip_add_data(gpio, priv);
> +}

...and provide a static inline nop for the mcp251x_gpio_setup() and
remove() functions in the #else branch, like this:

static inline int mcp251x_gpio_setup(struct mcp251x_priv *priv)
{
	return 0;
}

> +
> +static void mcp251x_gpio_remove(struct mcp251x_priv *priv)
> +{
> +	gpiochip_remove(&priv->gpio);
> +}
> +#endif // CONFIG_GPIOLIB
> +
>  static int mcp251x_open(struct net_device *net)
>  {
>  	struct mcp251x_priv *priv = netdev_priv(net);
> @@ -1089,9 +1282,20 @@ static int mcp251x_can_probe(struct spi_device *spi)
>  
>  	devm_can_led_init(net);
>  
> +#ifdef CONFIG_GPIOLIB

Then it should be possible to remove these ifdefs...

> +	ret = mcp251x_gpio_setup(priv);
> +	if (ret)
> +		goto error_gpio;
> +#endif
> +
>  	netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
>  	return 0;
>  
> +#ifdef CONFIG_GPIOLIB
> +error_gpio:
> +	mcp251x_gpio_remove(priv);
> +#endif
> +
>  error_probe:
>  	mcp251x_power_enable(priv->power, 0);
>  
> @@ -1112,6 +1316,10 @@ static int mcp251x_can_remove(struct spi_device *spi)
>  
>  	unregister_candev(net);
>  
> +#ifdef CONFIG_GPIOLIB
> +	mcp251x_gpio_remove(priv);
> +#endif
> +
>  	mcp251x_power_enable(priv->power, 0);
>  
>  	clk_disable_unprepare(priv->clk);
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux