From: Jeff LaBundy <jeff@labundy.com>
To: kamel.bouhara@bootlin.com
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Henrik Rydberg <rydberg@bitmath.org>,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org,
Marco Felsch <m.felsch@pengutronix.de>,
mark.satterthwaite@touchnetix.com, bartp@baasheep.co.uk,
hannah.rossiter@touchnetix.com,
Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
Gregory Clement <gregory.clement@bootlin.com>,
bsp-development.geo@leica-geosystems.com
Subject: Re: [PATCH v3 3/3] Input: Add TouchNetix axiom i2c touchscreen driver
Date: Sat, 25 Nov 2023 21:48:24 -0600 [thread overview]
Message-ID: <ZWLACNZrDzcHHA7D@nixie71> (raw)
In-Reply-To: <d760ad5e60b21816a395713f004ca14c@bootlin.com>
Hi Kamel,
On Mon, Nov 13, 2023 at 02:32:12PM +0100, kamel.bouhara@bootlin.com wrote:
> Le 2023-10-22 23:54, Jeff LaBundy a écrit :
> > Hi Kamel,
>
> Hi Jeff,
>
> >
> > On Thu, Oct 12, 2023 at 09:40:34AM +0200, Kamel Bouhara wrote:
> > > Add a new driver for the TouchNetix's axiom family of
> > > touchscreen controllers. This driver only supports i2c
> > > and can be later adapted for SPI and USB support.
> > >
> > > Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
> > > ---
> > > MAINTAINERS | 1 +
> > > drivers/input/touchscreen/Kconfig | 13 +
> > > drivers/input/touchscreen/Makefile | 1 +
> > > .../input/touchscreen/touchnetix_axiom_i2c.c | 740
> > > ++++++++++++++++++
> > > 4 files changed, 755 insertions(+)
> > > create mode 100644 drivers/input/touchscreen/touchnetix_axiom_i2c.c
> >
> > Please do not include 'i2c' in the filename. If the driver is expanded
> > in
> > the future to support SPI, it would make sense to have
> > touchnetix_axiom.c,
> > touchnetix_axiom_i2c.c and touchnetix_axiom_spi.c. To prevent this
> > driver
> > from having to be renamed in that case, just call it touchnetix_axiom.c.
> >
>
> Sure but the generic part of the code could also be moved to
> touchnetix_axiom.c.
Right; I'm simply saying to do this now as opposed to having a giant patch
later when SPI support comes along. In case I have misunderstood your reply,
please let me know.
[...]
> > > +#include <linux/crc16.h>
> > > +#include <linux/delay.h>
> > > +#include <linux/device.h>
> > > +#include <linux/gpio/consumer.h>
> > > +#include <linux/i2c.h>
> > > +#include <linux/input.h>
> > > +#include <linux/input/mt.h>
> > > +#include <linux/interrupt.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/module.h>
> >
> > Please #include mod_devicetable.h as well.
> >
>
> OK is this only for the sake of clarity ? As mod_devicetable.h is already
> included in linux/of.h ?
I haphazardly wrote this comment while in the process of reviewing
dbce1a7d5dce ("Input: Explicitly include correct DT includes"); however
you are correct. That being said, do you really need the entire of.h
for this driver?
>
> > > +#include <linux/of.h>
> > > +#include <linux/pm.h>
[...]
> > > +static int
> > > +axiom_i2c_read(struct i2c_client *client, u8 usage, u8 page, u8
> > > *buf, u16 len)
> > > +{
> > > + struct axiom_data *ts = i2c_get_clientdata(client);
> > > + struct axiom_cmd_header cmd_header;
> > > + struct i2c_msg msg[2];
> > > + int ret;
> > > +
> > > + cmd_header.target_address =
> > > cpu_to_le16(usage_to_target_address(ts, usage, page, 0));
> > > + cmd_header.length = cpu_to_le16(len);
> > > + cmd_header.read = 1;
> > > +
> > > + msg[0].addr = client->addr;
> > > + msg[0].flags = 0;
> > > + msg[0].len = sizeof(cmd_header);
> > > + msg[0].buf = (u8 *)&cmd_header;
> > > +
> > > + msg[1].addr = client->addr;
> > > + msg[1].flags = I2C_M_RD;
> > > + msg[1].len = len;
> > > + msg[1].buf = (char *)buf;
> >
> > Again, please use u8 in place of char, as was done for the first
> > element.
>
> OK.
>
> >
> > > +
> > > + ret = i2c_transfer(client->adapter, msg, 2);
> >
> > Please use ARRAY_SIZE(msg) above as you do below.
> >
> > > + if (ret != ARRAY_SIZE(msg)) {
> > > + dev_err(&client->dev,
> > > + "Failed reading usage %#x page %#x, error=%d\n",
> > > + usage, page, ret);
> > > + return -EIO;
> > > + }
> >
> > This check papers over negative error codes that may have been returned
> > by
> > i2c_transfer(). For ret < 0 you should return ret, and only return -EIO
> > for
> > 0 <= ret < ARRAY_SIZE(msg).
> >
> > More importantly, however, if this device supports multiple transports
> > and
> > you expect SPI support can be added in the future, you really should use
> > regmap throughout in order to avoid ripping up this driver later.
> >
>
> I have a doubt on wether or not regmap can be used for SPI as there is some
> specific padding required for SPI.
You can still define your own read and write callbacks in the small SPI
driver, leaving generic regmap calls in the core driver.
>
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int
> > > +axiom_i2c_write(struct i2c_client *client, u8 usage, u8 page, u8
> > > *buf, u16 len)
> > > +{
> > > + struct axiom_data *ts = i2c_get_clientdata(client);
> > > + struct axiom_cmd_header cmd_header;
> > > + struct i2c_msg msg[2];
> > > + int ret;
> > > +
> > > + cmd_header.target_address =
> > > cpu_to_le16(usage_to_target_address(ts, usage, page, 0));
> > > + cmd_header.length = cpu_to_le16(len);
> > > + cmd_header.read = 0;
> > > +
> > > + msg[0].addr = client->addr;
> > > + msg[0].flags = 0;
> > > + msg[0].len = sizeof(cmd_header);
> > > + msg[0].buf = (u8 *)&cmd_header;
> > > +
> > > + msg[1].addr = client->addr;
> > > + msg[1].flags = 0;
> > > + msg[1].len = len;
> > > + msg[1].buf = (char *)buf;
> > > +
> > > + ret = i2c_transfer(client->adapter, msg, 2);
> > > + if (ret < 0) {
> > > + dev_err(&client->dev,
> > > + "Failed to write usage %#x page %#x, error=%d\n", usage,
> > > + page, ret);
> > > + return ret;
> > > + }
> >
> > The error handling between your read and write wrappers is inconsistent;
> > please see my comment above.
> >
> > Is there any reason i2c_master_send() cannot work here? I'm guessing the
> > controller needs a repeated start in between the two messages?
> >
>
> Yes reads requires repeated starts between each messages.
>
> For writes I could still use i2c_master_send() but what makes it more
> relevant here ?
The code can be a bit smaller in terms of lines with the header and payload
copied into a small buffer and written with i2c_master_send(), but this is
fine too.
[...]
>
> > For these kind of special requirements, it's helpful to add some
> > comments
> > as to why the HW calls for additional housekeeping.
> >
>
> OK.
>
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/*
> > > + * Decodes and populates the local Usage Table.
> > > + * Given a buffer of data read from page 1 onwards of u31 from an
> > > aXiom
> > > + * device.
> > > + */
> >
> > What is a usage table? These comments aren't helpful unless some of the
> > underlying concepts are defined as well.
>
> It's a set of registers regrouped in categories (data, configuration, device
> and report).
>
> I'll try to clarify it.
ACK, thanks.
[...]
> > > +/* Rebaseline the touchscreen, effectively zero-ing it */
> >
> > What does it mean to rebaseline the touchscreen? I'm guessing it means
> > to null out or normalize pressure? Please consider a less colloquialized
> > function name.
> >
> > Out of curiousity, what happens if the user's hand happens to be on the
> > touch surface at the time you call axiom_rebaseline()? Does the device
> > recover on its own?
>
> This indeed force the controller to measure a new capacitance by zeoring it,
> I don't really know if it's harmful, yet the documentation says rebaseline
> is
> for tuning or debug purpose.
>
> I believe this is done for testing the communication.
ACK, thanks.
>
> >
> > > +static int axiom_rebaseline(struct axiom_data *ts)
> > > +{
> > > + char buffer[8] = {};
> >
> > Are you expecting each element to be initialized to zero?
>
> Yes.
ACK, I merely had not seen this method before.
>
> >
> > > +
> > > + buffer[0] = AXIOM_REBASELINE_CMD;
> > > +
> > > + return axiom_i2c_write(ts->client, AXIOM_REPORT_USAGE_ID, 0,
> > > buffer, sizeof(buffer));
> > > +}
> > > +
> > > +static int axiom_i2c_probe(struct i2c_client *client)
> > > +{
> > > + struct device *dev = &client->dev;
> > > + struct input_dev *input_dev;
> > > + struct axiom_data *ts;
> > > + int ret;
> > > + int target;
> > > +
> > > + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
> > > + if (!ts)
> > > + return -ENOMEM;
> > > +
> > > + ts->client = client;
> > > + i2c_set_clientdata(client, ts);
> > > + ts->dev = dev;
> > > +
> > > + ts->irq_gpio = devm_gpiod_get_optional(dev, "irq", GPIOD_IN);
> > > + if (IS_ERR(ts->irq_gpio))
> > > + return dev_err_probe(dev, PTR_ERR(ts->irq_gpio), "failed to get
> > > irq GPIO");
> > > +
> > > + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset",
> > > GPIOD_OUT_HIGH);
> > > + if (IS_ERR(ts->reset_gpio))
> > > + return dev_err_probe(dev, PTR_ERR(ts->reset_gpio), "failed to get
> > > reset GPIO\n");
> > > +
> > > + axiom_reset(ts->reset_gpio);
> >
> > We shouldn't call axiom_reset() if reset_gpio is NULL. Even though the
> > calls to gpiod_set_value_cansleep() will bail safely, there is no reason
> > to make the CPU sleep for 100 ms if the device was not actually reset.
> >
> > > +
> > > + if (ts->irq_gpio) {
> > > + ret = devm_request_threaded_irq(dev, client->irq, NULL,
> > > + axiom_irq, 0, dev_name(dev), ts);
> >
> > Did you mean to set IRQF_ONESHOT?
>
> No
OK, why not? This is a threaded handler and it's obviously not meant to be
reentrant. Why is this implementation different than any other driver with
a threaded handler? In case I have misunderstood, please let me know.
Kind regards,
Jeff LaBundy
next prev parent reply other threads:[~2023-11-26 3:48 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-13 13:32 [PATCH v3 3/3] Input: Add TouchNetix axiom i2c touchscreen driver kamel.bouhara
2023-11-26 3:48 ` Jeff LaBundy [this message]
-- strict thread matches above, loose matches on Subject: below --
2023-10-12 7:40 [PATCH v3 0/3] Input: Add TouchNetix axiom " Kamel Bouhara
2023-10-12 7:40 ` [PATCH v3 3/3] Input: Add TouchNetix axiom i2c " Kamel Bouhara
2023-10-20 12:03 ` Marco Felsch
2023-10-22 19:35 ` Kamel Bouhara
2023-10-30 8:49 ` Dmitry Torokhov
2023-11-06 12:29 ` Marco Felsch
2023-10-22 21:54 ` Jeff LaBundy
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=ZWLACNZrDzcHHA7D@nixie71 \
--to=jeff@labundy.com \
--cc=bartp@baasheep.co.uk \
--cc=bsp-development.geo@leica-geosystems.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=gregory.clement@bootlin.com \
--cc=hannah.rossiter@touchnetix.com \
--cc=kamel.bouhara@bootlin.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=m.felsch@pengutronix.de \
--cc=mark.satterthwaite@touchnetix.com \
--cc=robh+dt@kernel.org \
--cc=rydberg@bitmath.org \
--cc=thomas.petazzoni@bootlin.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 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.