From: andy.shevchenko@gmail.com
To: Yinbo Zhu <zhuyinbo@loongson.cn>
Cc: Mark Brown <broonie@kernel.org>, Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
linux-spi@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Jianmin Lv <lvjianmin@loongson.cn>,
wanghongliang@loongson.cn, Liu Peibao <liupeibao@loongson.cn>,
loongson-kernel@lists.loongnix.cn
Subject: Re: [PATCH v9 2/2] spi: loongson: add bus driver for the loongson spi controller
Date: Mon, 8 May 2023 18:04:06 +0300 [thread overview]
Message-ID: <ZFkPZhF8QqScXAmH@surfacebook> (raw)
In-Reply-To: <20230426071045.20753-3-zhuyinbo@loongson.cn>
Wed, Apr 26, 2023 at 03:10:45PM +0800, Yinbo Zhu kirjoitti:
> This bus driver supports the Loongson spi hardware controller in the
> Loongson platforms and supports to use DTS and PCI framework to
> register spi device resources.
SPI
...
> +config SPI_LOONGSON_CORE
> + tristate "Loongson SPI Controller Core Driver Support"
Does it need to be visible to the user?
> + depends on LOONGARCH || COMPILE_TEST
> + help
> + This core driver supports the Loongson spi hardware controller in
> + the Loongson platforms.
> + Say Y or M here if you want to use the SPI controller on
> + Loongson platform.
...
> +config SPI_LOONGSON_PLATFORM
> + tristate "Loongson SPI Controller Platform Driver Support"
> + select SPI_LOONGSON_CORE
> + depends on OF && (LOONGARCH || COMPILE_TEST)
Is it really dependent to OF? Why?
> + help
> + This bus driver supports the Loongson spi hardware controller in
> + the Loongson platforms and supports to use DTS framework to
> + register spi device resources.
> + Say Y or M here if you want to use the SPI controller on
> + Loongson platform.
...
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/spi/spi.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
Ordered?
...
> + if (loongson_spi->mode & SPI_NO_CS)
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, 0);
Missing {}
> + else {
> + cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG)
> + & ~(0x11 << spi->chip_select);
> + loongson_spi_write_reg(loongson_spi,
> + LOONGSON_SPI_SFCS_REG,
> + (val ? (0x11 << spi->chip_select) :
> + (0x1 << spi->chip_select)) | cs);
Too many parentheses.
> + }
...
> + const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11};
Oh, why?!
...
> + if ((hz && loongson_spi->hz != hz) ||
> + ((spi->mode ^ loongson_spi->mode) & (SPI_CPOL | SPI_CPHA))) {
> + div = DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz);
> + if (div < 2)
> + div = 2;
> + if (div > 4096)
> + div = 4096;
NIH clamp_val()
> + bit = fls(div) - 1;
> + if ((1<<bit) == div)
> + bit--;
> + div_tmp = rdiv[bit];
I believe this can be optimized.
> + dev_dbg(&spi->dev, "clk_rate = %llu hz = %d div_tmp = %d bit = %d\n",
> + loongson_spi->clk_rate, hz, div_tmp, bit);
> +
> + loongson_spi->hz = hz;
> + loongson_spi->spcr = div_tmp & 3;
> + loongson_spi->sper = (div_tmp >> 2) & 3;
> + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
> + val &= ~0xc;
GENMASK()
> + if (spi->mode & SPI_CPOL)
> + val |= 8;
BIT()
> + if (spi->mode & SPI_CPHA)
> + val |= 4;
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, (val & ~3) |
> + loongson_spi->spcr);
> + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, (val & ~3) |
> + loongson_spi->sper);
> + loongson_spi->mode &= SPI_NO_CS;
> + loongson_spi->mode |= spi->mode;
> + }
...
> + while ((loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG) & 0x1) == 1 &&
> + time_after(timeout, jiffies))
> + cpu_relax();
iopoll.h has a suitable macro for this.
...
> + while ((loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG) & 0x1) == 1 &&
> + time_after(timeout, jiffies))
> + cpu_relax();
Ditto.
...
> + master = devm_spi_alloc_master(dev, sizeof(struct loongson_spi));
> + if (master == NULL) {
> + dev_info(dev, "master allocation failed\n");
We do not issue a message for ENOMEM
> + return -ENOMEM;
> + }
...
> + master->dev.of_node = of_node_get(dev->of_node);
device_set_node()
...
> + spi->base = devm_ioremap(dev, res->start, resource_size(res));
Why not devm_ioremap_resource()?
> + if (spi->base == NULL) {
> + dev_err(dev, "cannot map io\n");
> + return -ENXIO;
return dev_err_probe();
> + }
...
> + clk = devm_clk_get(dev, NULL);
Can we hav
> + if (!IS_ERR(clk))
Use _optional variant above instead of this.
Do not forget about deferred probe.
> + spi->clk_rate = clk_get_rate(clk);
...
> + if (of_get_property(dev->of_node, "spi-nocs", NULL))
> + spi->mode |= SPI_NO_CS;
Don't we have something in the SPI core to handle this in a generic way?
...
> +EXPORT_SYMBOL_GPL(loongson_spi_init_master);
Please, use _NS variant.
...
> +MODULE_DESCRIPTION("Loongson spi core driver");
SPI
...
> + struct resource res[2];
> + struct device *dev = &pdev->dev;
> +
> + ret = pci_enable_device(pdev);
pcim_enable_device()
> + if (ret < 0) {
> + dev_err(dev, "cannot enable pci device\n");
> + goto err_out;
return dev_err_probe();
> + }
> +
> + ret = pci_request_region(pdev, 0, "loongson-spi io");
> + if (ret < 0) {
> + dev_err(dev, "cannot request region 0.\n");
> + goto err_out;
> + }
> +
> + res[0].start = pci_resource_start(pdev, 0);
> + res[0].end = pci_resource_end(pdev, 0);
What's wrong with pcim_iomap_regions()?
...
> + ret = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &v8);
What?!
What's wrong with pci_alloc_irq_vectors()?
> +
> + if (ret == PCIBIOS_SUCCESSFUL) {
> + res[1].start = v8;
> + res[1].end = v8;
> + }
> +
> + ret = loongson_spi_init_master(dev, res);
Why not passing the remapped address and IRQ number instead?
> + if (ret)
> + dev_err(dev, "failed to initialize master\n");
return dev_err_probe();
> +
> +err_out:
Completely useless. Return in-line.
> + return ret;
> +}
...
> +static struct pci_device_id loongson_spi_devices[] = {
> + {PCI_DEVICE(0x14, 0x7a0b)},
> + {PCI_DEVICE(0x14, 0x7a1b)},
Can you define vendor ID in pci_ids.h?
> + {0, 0, 0, 0, 0, 0, 0}
What is this? Why {} is not working for you?
> +};
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res == NULL) {
Why not using devm_platform_ioremap_resource()?
> + dev_err(dev, "cannot get io resource memory\n");
> + return -ENOENT;
return dev_err_probe();
> + }
> +
> + ret = loongson_spi_init_master(dev, res);
> + if (ret)
> + dev_err(dev, "failed to initialize master\n");
Ditto.
...
> +static const struct of_device_id loongson_spi_id_table[] = {
> + { .compatible = "loongson,ls2k-spi", },
Inned comma is redundant.
> + { }
> +};
...
> +#ifndef __LINUX_SPI_LOONGSON_H
> +#define __LINUX_SPI_LOONGSON_H
Missing bits.h
Missing types.h
Missing declaration for msecs_to_jiffies()
Missing forward declarations for struct spi_master and struct device.
MIssing declaration for dev_pm_ops.
> +#define LOONGSON_SPI_SPCR_REG 0x00
> +#define LOONGSON_SPI_SPSR_REG 0x01
> +#define LOONGSON_SPI_FIFO_REG 0x02
> +#define LOONGSON_SPI_SPER_REG 0x03
> +#define LOONGSON_SPI_PARA_REG 0x04
> +#define LOONGSON_SPI_SFCS_REG 0x05
> +#define LOONGSON_SPI_TIMI_REG 0x06
> +
> +/* Bits definition for Loongson SPI register */
> +#define LOONGSON_SPI_PARA_MEM_EN BIT(0)
> +#define LOONGSON_SPI_SPSR_SPIF BIT(7)
> +#define LOONGSON_SPI_SPSR_WCOL BIT(6)
> +#define LOONGSON_SPI_SPCR_SPE BIT(6)
> +
> +#define SPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000)
> +
> +struct loongson_spi {
> + struct spi_master *master;
> + void __iomem *base;
> + int cs_active;
> + unsigned int hz;
> + unsigned char spcr;
> + unsigned char sper;
> + unsigned char spsr;
> + unsigned char para;
> + unsigned char sfcs;
> + unsigned char timi;
> + unsigned int mode;
> + u64 clk_rate;
> +};
> +
> +extern int loongson_spi_init_master(struct device *dev, struct resource *res);
No extern for the function declarations.
> +extern const struct dev_pm_ops loongson_spi_dev_pm_ops;
> +#endif /* __LINUX_SPI_LOONGSON_H */
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2023-05-08 15:05 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-26 7:10 [PATCH v9 0/2] spi: loongson: add bus driver for the loongson spi Yinbo Zhu
2023-04-26 7:10 ` [PATCH v9 1/2] dt-bindings: spi: add " Yinbo Zhu
2023-04-26 7:10 ` [PATCH v9 2/2] spi: loongson: add bus driver for the loongson spi controller Yinbo Zhu
2023-05-08 13:20 ` Mark Brown
2023-05-09 1:26 ` zhuyinbo
2023-05-08 15:04 ` andy.shevchenko [this message]
2023-05-09 4:39 ` Mark Brown
2023-05-10 7:03 ` Andy Shevchenko
2023-05-12 8:12 ` zhuyinbo
2023-05-12 9:40 ` Andy Shevchenko
2023-05-13 6:16 ` zhuyinbo
2023-05-11 7:18 ` zhuyinbo
2023-05-15 8:14 ` zhuyinbo
2023-05-15 9:15 ` andy.shevchenko
2023-05-15 12:01 ` zhuyinbo
2023-05-15 13:54 ` Andy Shevchenko
2023-05-16 0:50 ` zhuyinbo
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=ZFkPZhF8QqScXAmH@surfacebook \
--to=andy.shevchenko@gmail.com \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=liupeibao@loongson.cn \
--cc=loongson-kernel@lists.loongnix.cn \
--cc=lvjianmin@loongson.cn \
--cc=robh+dt@kernel.org \
--cc=wanghongliang@loongson.cn \
--cc=zhuyinbo@loongson.cn \
/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.