linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
To: Linus Walleij <linus.walleij@linaro.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	linux-watchdog@vger.kernel.org,
	"linux-arm-kernel@lists.infradead.org" 
	<linux-arm-kernel@lists.infradead.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	kernel <kernel@savoirfairelinux.com>,
	Rob Herring <robh@kernel.org>, Guenter Roeck <linux@roeck-us.net>,
	Fabio Estevam <fabio.estevam@nxp.com>,
	Mark Featherston <mark@embeddedarm.com>,
	kris@embeddedarm.com, Simon Horman <horms+renesas@verge.net.au>,
	Thierry Reding <treding@nvidia.com>,
	Jon Hunter <jonathanh@nvidia.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Sascha Hauer <kernel@pengutronix.de>,
	Shawn Guo <shawnguo@kernel.org>,
	Russell King <linux@armlinux.org.uk>,
	Wim Van Sebroeck <wim@iguana.be>,
	Mark Rutland <mark.rutland@arm.com>,
	damien.riegel@savoirfairelinux.com,
	Lucile Quirion <lucile.quirion@savoirfairelinux.com>,
	Olof Johansson <olof@lixom.net>, Arnd Bergmann <arnd@arndb.de>,
	"Suzuki K. Poulose" <suzuki.poulose@arm.com>,
	Will Deacon <will.deacon@arm.com>,
	Masahiro Yamada <yamada.masahiro@socionext.com>
Subject: Re: [PATCH v2 4/6] bus: add driver for the Technologic Systems NBUS
Date: Wed, 22 Feb 2017 11:56:40 -0500	[thread overview]
Message-ID: <82dfdbb8-58fc-45b4-685c-98be11341e45@savoirfairelinux.com> (raw)
In-Reply-To: <CACRpkdYfGmVBYgAc4KZGN6634WM_EyzNj_SBbALEs4WYipXRQA@mail.gmail.com>

Hi Linus,

First thanks for your code review!

On 02/04/2017 05:14 AM, Linus Walleij wrote:
> On Fri, Feb 3, 2017 at 8:47 PM, Sebastien Bourdelin
> <sebastien.bourdelin@savoirfairelinux.com> wrote:
> 
>> This driver implements a GPIOs bit-banged bus, called the NBUS by
>> Technologic Systems. It is used to communicate with the peripherals in
>> the FPGA on the TS-4600 SoM.
>>
>> ---
>> Changes v1 -> v2:
>>   - rebase on master
>>   - the driver now populate its child nodes
>>   - remove the 'default y' option from the Kconfig
>>   - rework the driver to not use singleton anymore (suggested by Linus
>>   Walleij)
>>   - replace the use of the legacy GPIO API with gpiod (suggested by
>>   Linus Walleij)
>>   - use the ts vendor prefix for gpios (suggested by Rob Herring)
>>
>> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> 
> This is starting to look nice!
> 
> More comments:
> 
> First, you sprinked "inline" like cinnamon over everything, skip that. The
> compiler will inline selectively as it seems fit if you turn on optimization.
> 
Ok.

>> +static DEFINE_MUTEX(ts_nbus_lock);
> 
> Move this into struct ts_nbus, initialize the mutex in probe()
> and just mutex_lock(&ts_nbus->lock); etc.
> 
Ok.

>> + * the txrx gpio is used by the FPGA to know if the following transactions
>> + * should be handled to read or write a value.
>> + */
>> +static inline void ts_nbus_set_mode(struct ts_nbus *ts_nbus, int mode)
> 
> Why inline? Let the compiler decide about that.
> 
Ok.

>> +{
>> +       if (mode == TS_NBUS_READ_MODE)
> 
> This mode parameter is too complicated. Isn't it just a bool?
> (not superimportant)
> 
>> +               gpiod_set_value_cansleep(ts_nbus->txrx, 0);
>> +       else
>> +               gpiod_set_value_cansleep(ts_nbus->txrx, 1);
>> +}
> 
> You're certainly just using it as a bool.
> 
I will remove this function to simplify the logic.

>> +static inline void ts_nbus_set_direction(struct ts_nbus *ts_nbus, int direction)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; i < ts_nbus->data->ndescs; i++) {
>> +               if (direction == TS_NBUS_DIRECTION_IN)
>> +                       gpiod_direction_input(ts_nbus->data->desc[i]);
>> +               else
>> +                       gpiod_direction_output(ts_nbus->data->desc[i], 1);
> 
> Add a comment here explaining why you driver the line high by default
> when setting it to output mode. It certainly makes sense but how
> does the electronics work and why?
> 
Ok.

>> +static inline void ts_nbus_reset_bus(struct ts_nbus *ts_nbus)
>> +{
>> +       int i;
>> +       int values[ts_nbus->data->ndescs];
>> +
>> +       for (i = 0; i < ts_nbus->data->ndescs; i++)
>> +               values[i] = 0;
>> +
>> +       gpiod_set_array_value_cansleep(ts_nbus->data->ndescs,
>> +                       ts_nbus->data->desc, values);
>> +       gpiod_set_value_cansleep(ts_nbus->csn, 0);
>> +       gpiod_set_value_cansleep(ts_nbus->strobe, 0);
>> +       gpiod_set_value_cansleep(ts_nbus->ale, 0);
> 
> Add a comment about the process taken when this bus is reset. We
> see what is happening, but why?
> 
Ok.

>> +/*
>> + * let the FPGA knows it can process.
>> + */
>> +static inline void ts_nbus_start_transaction(struct ts_nbus *ts_nbus)
> 
> Why inline?
> 
I will remove all the inline.

>> +{
>> +       gpiod_set_value_cansleep(ts_nbus->strobe, 1);
>> +}
> 
> For example this is a well commented function. We see what is happening
> and stobe has an evident name. Nice work!
> 
>> +/*
>> + * return the byte value read from the data gpios.
>> + */
>> +static inline u8 ts_nbus_read_byte(struct ts_nbus *ts_nbus)
> 
> Why inline?
> 
Ditto.

> Then this cannot fail can it?
> 
> I think this accessor should be changed to return an error code.
> 
> static int ts_nbus_read_byte(struct ts_nbus *ts_nbus, u8 *val);
> 
> Then if the return value from the function is != 0 it failed. Simple
> to check, just pass a pointer to the value you are getting in
> val.
> 
> I KNOW I KNOW, not you have to put in error handling everywhere,
> what a DRAG! But we usually follow that pattern because...
> 
>> +{
>> +       struct gpio_descs *gpios = ts_nbus->data;
>> +       int i;
>> +       u8 value = 0;
>> +
>> +       for (i = 0; i < gpios->ndescs; i++)
> 
> Using gpios->ndescs is a bit overparametrized right? Isn't it
> simply 8 bits? Just putting 8 there is fine IMO. All 8 descs
> must be available for the thing to work anyway right?
> 
>> +               if (gpiod_get_value_cansleep(gpios->desc[i]))
> 
> This can fail and you should return an error if < 0...
> 
> You are ignoring that right now. That is why the function should
> be returning an error code that is usually 0.
> 
You are right,
this can fail, i will propagate the "gpiod_get_value_cansleep(...)"
errno value.

>> +                       value |= 1 << i;
> 
> Use:
> #include <linux/bitops.h>
> 
> value |= BIT(i);
>
Ok.

>> +/*
>> + * set the data gpios accordingly to the byte value.
>> + */
>> +static inline void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte)
>> +{
>> +       struct gpio_descs *gpios = ts_nbus->data;
>> +       int i;
>> +       int values[gpios->ndescs];
>> +
>> +       for (i = 0; i < gpios->ndescs; i++)
>> +               if (byte & (1 << i))
>> +                       values[i] = 1;
>> +               else
>> +                       values[i] = 0;
>> +
>> +       gpiod_set_array_value_cansleep(gpios->ndescs, gpios->desc, values);
> 
> This can also fail and you should check the return code and print an error
> message if it does.
> 
As far as i understood, the "gpiod_set_array_value_cansleep(...)"
function doesn't return
anything, it will return immediately if gpios->desc is null but nothing
else.
Did i miss something?

>> +/*
>> + * reading the bus consists of resetting the bus, then notifying the FPGA to
>> + * send the data in the data gpios and return the read value.
>> + */
>> +static inline u8 ts_nbus_read_bus(struct ts_nbus *ts_nbus)
> 
> All this inline...
Ok :)

> 
>> +/*
>> + * writing to the bus consists of resetting the bus, then define the type of
>> + * command (address/value), write the data and notify the FPGA to retrieve the
>> + * value in the data gpios.
>> + */
>> +static inline void ts_nbus_write_bus(struct ts_nbus *ts_nbus, int cmd, u8 value)
>> +{
>> +       ts_nbus_reset_bus(ts_nbus);
>> +
>> +       if (cmd == TS_NBUS_WRITE_ADR)
>> +               gpiod_set_value_cansleep(ts_nbus->ale, 1);
>> +
>> +       ts_nbus_write_byte(ts_nbus, value);
>> +       ts_nbus_start_transaction(ts_nbus);
> 
> Error codes?
> 
Same question here, these functions only make call to
"gpiod_set_value_cansleep(...)",
which as far as i understood doesn't return any error code.

>> +       /* reading value MSB first */
>> +       do {
>> +               val = 0;
>> +               for (i = 1; i >= 0; i--)
>> +                       val |= (ts_nbus_read_bus(ts_nbus) << (i * 8));
> 
> Hard to deal with errors in this loop!
I will reformat this part.

> 
>> +               gpiod_set_value_cansleep(ts_nbus->csn, 1);
> 
> Here too.
>
Same question, doesn't seem to have an error code.

>> +++ b/include/linux/ts-nbus.h
>> @@ -0,0 +1,26 @@
>> +/*
>> + * Copyright (c) 2016 - Savoir-faire Linux
>> + * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef _TS_NBUS_H
>> +#define _TS_NBUS_H
>> +
>> +struct ts_nbus {
>> +       struct pwm_device *pwm;
>> +       struct gpio_descs *data;
>> +       struct gpio_desc *csn;
>> +       struct gpio_desc *txrx;
>> +       struct gpio_desc *strobe;
>> +       struct gpio_desc *ale;
>> +       struct gpio_desc *rdy;
>> +};
> 
> Is any consumer really looking into this struct? If not, why
> do you expose it?
> 
> Move it to the ts-nbus.c file.
> 
> The only thing you need in this header is:
> 
> struct ts_nbus;
> 
> Just that one line. The rest of the code, like the declarations
> below and all call sites, are just dealing with "pointers to something",
> they don't need to know what it is. You'll be amazed to see how it compiles.
> struct gpio_desc works exactly like that.
> 
Ok.

>> +extern u16 ts_nbus_read(struct ts_nbus *, u8 adr);
>> +extern int ts_nbus_write(struct ts_nbus *, u8 adr, u16 value);
> 
> I suspect the first function should be augmented to return an error code.
> 
Yes it will.

> Yours,
> Linus Walleij
> 

Thanks you Linus,

Best Regards,
Sebastien Bourdelin.

  reply	other threads:[~2017-02-22 16:57 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-03 19:47 [PATCH v2 0/6] Add board support for TS-4600 Sebastien Bourdelin
2017-02-03 19:47 ` [PATCH v2 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
2017-03-07 11:48   ` Shawn Guo
2017-02-03 19:47 ` [PATCH v2 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
2017-02-03 19:47 ` [PATCH v2 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
2017-02-08 21:48   ` Rob Herring
2017-02-03 19:47 ` [PATCH v2 4/6] bus: add driver " Sebastien Bourdelin
2017-02-04 10:14   ` Linus Walleij
2017-02-22 16:56     ` Sebastien Bourdelin [this message]
2017-03-14 13:23       ` Linus Walleij
2017-03-14 15:40         ` Sebastien Bourdelin
2017-02-03 19:47 ` [PATCH v2 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
2017-02-03 19:47 ` [PATCH v2 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
2017-02-05  0:21   ` [v2,6/6] " Guenter Roeck
2017-02-08 21:50   ` [PATCH v2 6/6] " Rob Herring

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=82dfdbb8-58fc-45b4-685c-98be11341e45@savoirfairelinux.com \
    --to=sebastien.bourdelin@savoirfairelinux.com \
    --cc=arnd@arndb.de \
    --cc=damien.riegel@savoirfairelinux.com \
    --cc=devicetree@vger.kernel.org \
    --cc=f.fainelli@gmail.com \
    --cc=fabio.estevam@nxp.com \
    --cc=horms+renesas@verge.net.au \
    --cc=jonathanh@nvidia.com \
    --cc=kernel@pengutronix.de \
    --cc=kernel@savoirfairelinux.com \
    --cc=kris@embeddedarm.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=linux@roeck-us.net \
    --cc=lucile.quirion@savoirfairelinux.com \
    --cc=mark.rutland@arm.com \
    --cc=mark@embeddedarm.com \
    --cc=olof@lixom.net \
    --cc=robh@kernel.org \
    --cc=shawnguo@kernel.org \
    --cc=suzuki.poulose@arm.com \
    --cc=treding@nvidia.com \
    --cc=will.deacon@arm.com \
    --cc=wim@iguana.be \
    --cc=yamada.masahiro@socionext.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).