From: Wolfram Sang <wsa@kernel.org>
To: daire.mcnamara@microchip.com
Cc: linux-i2c@vger.kernel.org, robh+dt@kernel.org,
devicetree@vger.kernel.org, palmer@dabbelt.com,
cyril.jean@microchip.com, padmarao.begari@microchip.com,
lewis.hanly@microchip.com, conor.dooley@microchip.com,
david.abdurachmanov@gmail.com
Subject: Re: [PATCH v1 2/2] i2c: microchip: Add driver for Microchip PolarFire SoC
Date: Fri, 25 Jun 2021 16:36:36 +0200 [thread overview]
Message-ID: <YNXp9DsvMpWllPXT@shikoro> (raw)
In-Reply-To: <20210512112024.1651757-3-daire.mcnamara@microchip.com>
[-- Attachment #1: Type: text/plain, Size: 6212 bytes --]
Hi Daire,
thanks for your driver! Some issues, but nothing major.
some checkpatch errors first:
ERROR: do not set execute permissions for source files
#47: FILE: drivers/i2c/busses/i2c-microchip.c
This must be fixed.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
Are you interested in maintaining the driver? Then, please add a section
to MAINTAINERS as well.
WARNING: From:/Signed-off-by: email address mismatch: 'From: Daire McNamara <Daire.McNamara@microchip.com>' != 'Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>'
Would be nice to have this consistent as well!
> +config I2C_MICROCHIP
> + tristate "Microchip I2C"
> + help
> + If you say yes to this option, support will be included for the
> + Microchip I2C interface.
> +
Document the module name?
> @@ -0,0 +1,519 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Microchip I2C controller driver
> + *
> + * Copyright (c) 2018 - 2021 Microchip Corporation. All rights reserved.
> + *
> + * Author: Daire McNamara <daire.mcnamara@microchip.com>
> + */
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/iopoll.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +
> +#define MICROCHIP_I2C_TIMEOUT (msecs_to_jiffies(1000))
> +
> +#define MPFS_I2C_CTRL (0x00)
> +#define CTRL_CR0 (0x00)
> +#define CTRL_CR1 (0x01)
> +#define CTRL_AA (0x02)
> +#define CTRL_SI (0x03)
> +#define CTRL_STO (0x04)
> +#define CTRL_STA (0x05)
> +#define CTRL_ENS1 (0x06)
> +#define CTRL_CR2 (0x07)
Using the BIT() macros, this would remove a lot of "1 << " from the
driver and make it quite more readable, I'd say.
> +static int mpfs_i2c_init(struct mpfs_i2c_dev *idev)
> +{
> + u32 clk_rate = clk_get_rate(idev->i2c_clk);
> + u32 divisor = clk_rate / idev->bus_clk_rate;
Not protected against division by zero, or?
> + u8 clkval;
> + int ret;
> + u8 ctrl = readl(idev->base + MPFS_I2C_CTRL);
> +
> + ctrl &= ~CLK_MASK;
> +
> + ret = mpfs_generate_divisor(divisor, &clkval);
> +
> + if (ret)
> + return -1;
-EINVAL instead of -1? In mpfs_generate_divisor as well.
> +
> + ctrl |= clkval;
> +
> + writel(ctrl, idev->base + MPFS_I2C_CTRL);
> +
> + ctrl = readl(idev->base + MPFS_I2C_CTRL);
> +
> + /* Reset controller */
Very obvious comment :)
> + mpfs_i2c_reset(idev);
> +
> + return 0;
> +}
> +static irqreturn_t mpfs_i2c_handle_isr(int irq, void *_dev)
> +{
> + bool read, finish = false;
drivers/i2c/busses/i2c-microchip.c: In function ‘mpfs_i2c_handle_isr’:
drivers/i2c/busses/i2c-microchip.c:244:7: warning: variable ‘read’ set but not used [-Wunused-but-set-variable]
> + struct mpfs_i2c_dev *idev = _dev;
> + u32 status = idev->isr_status;
> + u8 ctrl;
> +
> + if (!idev->buf) {
> + dev_warn(idev->dev, "unexpected interrupt\n");
> + return IRQ_HANDLED;
> + }
> +
> + read = idev->msg_read ? 1 : 0;
> +
> + switch (status) {
> + case STATUS_M_START_SENT:
> + case STATUS_M_REPEATED_START_SENT:
> + ctrl = readl(idev->base + MPFS_I2C_CTRL);
> + ctrl &= ~(1 << CTRL_STA);
> + writel(idev->addr, idev->base + MPFS_I2C_DATA);
> + writel(ctrl, idev->base + MPFS_I2C_CTRL);
> + if (idev->msg_len <= 0)
CPPCHECK
drivers/i2c/busses/i2c-microchip.c:263:21: warning: Checking if unsigned expression 'idev->msg_len' is less than zero. [unsignedLessThanZero]
...
> +static int mpfs_i2c_xfer_msg(struct mpfs_i2c_dev *idev, struct i2c_msg *msg)
> +{
> + u8 ctrl;
> + unsigned long time_left;
> +
> + if (msg->len == 0)
> + return -EINVAL;
Use a 'struct i2c_adapter_quirks' with the I2C_AQ_NO_ZERO_LEN flag and
the core will check that for you.
> +static u32 mpfs_i2c_func(struct i2c_adapter *adap)
> +{
> + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
If you can't do zero lenght transfers, you'll need
(I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK).
> +static int mpfs_i2c_probe(struct platform_device *pdev)
> +{
> + struct mpfs_i2c_dev *idev = NULL;
Initialization not needed.
> + idev->dev = &pdev->dev;
> + init_completion(&idev->msg_complete);
> + spin_lock_init(&idev->lock);
This spinlock is not used anywhere? It seems that everything spinlock
related can go?
> +
> + val = device_property_read_u32(idev->dev, "clock-frequency",
> + &idev->bus_clk_rate);
> + if (val) {
> + dev_info(&pdev->dev, "default to 100kHz\n");
> + idev->bus_clk_rate = 100000; /* default clock rate */
> + }
> +
> + if (idev->bus_clk_rate > 400000) {
> + dev_err(&pdev->dev, "invalid clock-frequency %d\n",
> + idev->bus_clk_rate);
> + return -EINVAL;
> + }
> +
> + ret = devm_request_irq(&pdev->dev, irq, mpfs_i2c_isr,
> + IRQF_SHARED, pdev->name, idev);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to claim irq %d\n", irq);
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(idev->i2c_clk);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to enable clock\n");
> + return ret;
> + }
> +
> + ret = mpfs_i2c_init(idev);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to program clock divider\n");
> + return ret;
> + }
> +
> + i2c_set_adapdata(&idev->adapter, idev);
> + snprintf(idev->adapter.name, sizeof(idev->adapter.name),
> + "Microchip I2C hw bus");
Most people add the base address of the registers here to be able to
differentiate multiple adapters in one system.
> + idev->adapter.owner = THIS_MODULE;
> + idev->adapter.algo = &mpfs_i2c_algo;
> + idev->adapter.dev.parent = &pdev->dev;
> + idev->adapter.dev.of_node = pdev->dev.of_node;
> +
> + platform_set_drvdata(pdev, idev);
> +
> + ret = i2c_add_adapter(&idev->adapter);
> + if (ret) {
> + clk_disable_unprepare(idev->i2c_clk);
> + return ret;
> + }
> +
> + dev_info(&pdev->dev, "Microchip I2C Probe Complete\n");
> +
> + return 0;
> +}
But this is all pretty minor stuff. It looks quite good actually!
Happy hacking,
Wolfram
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
prev parent reply other threads:[~2021-06-25 14:36 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-12 11:20 [PATCH v1 0/2] i2c: microchip: Add driver for PolarFire SoC daire.mcnamara
2021-05-12 11:20 ` [PATCH v1 1/2] dt-bindings: i2c: microchip: Add Microchip PolarFire host binding daire.mcnamara
2021-05-12 18:35 ` Rob Herring
2021-06-25 14:37 ` Wolfram Sang
2021-05-12 11:20 ` [PATCH v1 2/2] i2c: microchip: Add driver for Microchip PolarFire SoC daire.mcnamara
2021-06-25 14:36 ` Wolfram Sang [this message]
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=YNXp9DsvMpWllPXT@shikoro \
--to=wsa@kernel.org \
--cc=conor.dooley@microchip.com \
--cc=cyril.jean@microchip.com \
--cc=daire.mcnamara@microchip.com \
--cc=david.abdurachmanov@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=lewis.hanly@microchip.com \
--cc=linux-i2c@vger.kernel.org \
--cc=padmarao.begari@microchip.com \
--cc=palmer@dabbelt.com \
--cc=robh+dt@kernel.org \
/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.