2023-06-13 08:29:02

by Yinbo Zhu

[permalink] [raw]
Subject: [PATCH v13 0/2] spi: loongson: add bus driver for the loongson spi

Loongson platform support spi hardware controller and this series patch
was to add spi driver and binding support.

Change in v2:
1. This [PATCH v2 1/2] dt-bindings patch need depend on clk patch:
https://
lore.kernel.org/all/[email protected]/
2. Remove the clock-names in spi yaml file.
3. Add "loongson,ls7a-spi" compatible in spi yaml file.
4. Add an || COMPILE_TEST and drop && PCI then add some CONFIG_PCI
macro to limit some pci code.
5. Make the spi driver top code comment block that use C++ style.
6. Drop spi->max_speed_hz.
7. Add a spin_lock for loongson_spi_setup.
8. Add a timeout and cpu_relax() in loongson_spi_write_read_8bit.
9. Add spi_transfer_one and drop transfer and rework entire spi
driver that include some necessary changes.
10. Use module_init replace subsys_initcall.
11. About PM interface that I don't find any issue so I don't add
any changes.
Change in v3:
1. This [PATCH v3 1/2] dt-bindings patch need depend on clk patch:
https://
lore.kernel.org/all/[email protected]/
2. Drop the unused blank line in loongson,ls-spi.yaml file.
3. Replace clock minItems with clock maxItems in yaml file.
4. Separate spi driver into platform module, pci module and core
module.
5. Replace DIV_ROUND_UP with DIV_ROUND_UP_ULL to fix compile error
"undefined reference to `__aeabi_uldivmod'" and "__udivdi3 undefined"
that reported by test robot.
6. Remove the spin lock.
7. Clear the loongson_spi->hz and loongson_spi->mode in setup to fixup
the issue that multiple spi device transfer that maybe cause spi was
be misconfigured.
Change in v4:
1. This [PATCH v4 1/2] dt-bindings patch need depend on clk patch:
https://
lore.kernel.org/all/[email protected]/
2. Add "#include <linux/io.h>" in spi-loongson-core.c for fix the compile
issue which devm_ioremap no declaration.
3. Add "EXPORT_SYMBOL_GPL(loongson_spi_dev_pm_ops)" in
spi-loongson-core.c for fix the compile issue which
loongson_spi_dev_pm_ops undefined.
Change in v5:
1. Get rid of the clock patch's dependency and open-code the clock IDs.
2. Fixup checkpatch issue that by installed ply and gitpython package
locally, but this series of patch's code doesn't have any change.
Change in v6:
1. Remove the "#include <dt-bindings/clock/loongson,ls2k-clk.h>" in
yaml file.
Change in v7:
1. Remove the "loongson,ls7a-spi" and change yaml file name as
"loongson,ls2k-spi.yaml".
2. Use module_pci_driver and module_platform_driver to replace
module_init and module_exit.
3. Drop ".owner = THIS_MODULE" in spi platform driver.
4. Add devm_spi_alloc_master devm_spi_register_master to simplify code.
5. Add pci_disable_device() in loongson_spi_pci_unregister.
Change in v8:
1. Add reviewed-by information for spi bindings patch.
2. Fixup the uncorrect spi yaml file path in MAINTAINERS file.
3. Add spi_master_suspend and spi_master_resume in spi pm function.
Change in v9:
1. Make spi_master_suspend go first in pm suspend.
Change in v10:
1. Fix the compile issue about of_node_get and of_get_property no
declaration.
2. set config SPI_LOONGSON_CORE invisible.
3. Captial "spi" in commit log and Kconfig file.
4. Write header files in alphabetical order.
5. Use clamp_val, GENMASK() and BIT() in spi clock setting.
6. Optimize clock and mode setting code.
7. Use readb_poll_timeout in loongson_spi_write_read_8bit.
8. Remove some useless dmesg print.
9. Use device_set_node replace of_node_get.
10. Use dev_err_probe in code.
11. Use devm_clk_get_optional replace devm_clk_get.
12. Remove SPI_NO_CS for drop 2k500 non common type spi.
13. Use pcim_enable_device() and pcim_iomap_regions() in spi pci
driver.
14. Passing the remapped address in loongson_spi_init_master.
15. Remove the useless goto flag "err_out".
16. Use pci vendor id in pci_ids.h.
17. Use devm_platform_ioremap_resource in spi platform driver.
18. Remove the useless item in pci_device_id.
19. Remove the inned comma in of_device_id.
20. Add some headfile in spi_loongson.h.
21. Remove the useless extern for loongson_spi_init_master in
spi_loongson.h.
Change in v11:
1. Use spi_get_chipselect() to replace all spi->chip_select in
spi driver
Change in v12:
1. Reword the dt-bindings patch title.
2. Use a specific spi compatible in dt-bindings and spi driver.
3. Add Cc list for the reviewers of the previous version.
4. Add a static for rdiv[12] array in loongson_spi_set_clk.
5. Fixup the compile warning for spi HZ that reported by robot.
6. Use "#define LOONGSON_... BIT(0)" in readb_poll_timeout.
7. Add a error code return that when write spi failed.
8. Use spi_controller* instead of spi_master* in all cases.
9. Check for the error first which for clock gain.
10. Drop the ->remove() in spi pci driver.
11. Drop the comma for the terminator entry in pci_device_id.
12. Adjust the head file in spi driver.
13. Use forward declarations for device and spi_controller.
Change in v13:
1. Reword the dt-bindings patch title.
2. Add the items for compatible with 2k500 in dts-bindings.
3. Add a bit changes in commit log.
4. Add a Reviewed-by for spi driver patch.
5. Rework the function loongson_spi_set_cs.
6. Use GENMASK() to replace some constant in function
loongson_spi_set_clk.
7. Add or remove some blank lines.
8. Use LOONGSON_SPI_PARA_MEM_EN replace a constant in
loongson_spi_prepare_message.
9. Use SPI_MODE_X_MASK to replace "SPI_CPOL | SPI_CPHA".
10. Use USEC_PER_MSEC to replace MSEC_PER_SEC.

Yinbo Zhu (2):
spi: dt-bindings: add loongson spi
spi: loongson: add bus driver for the loongson spi controller

.../bindings/spi/loongson,ls2k-spi.yaml | 46 +++
MAINTAINERS | 10 +
drivers/spi/Kconfig | 26 ++
drivers/spi/Makefile | 3 +
drivers/spi/spi-loongson-core.c | 279 ++++++++++++++++++
drivers/spi/spi-loongson-pci.c | 55 ++++
drivers/spi/spi-loongson-plat.c | 47 +++
drivers/spi/spi-loongson.h | 49 +++
8 files changed, 515 insertions(+)

--
2.20.1



2023-06-13 08:30:48

by Yinbo Zhu

[permalink] [raw]
Subject: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller

This bus driver supports the Loongson SPI hardware controller in the
Loongson platforms and supports the use DTS and PCI framework to
register SPI device resources.

Signed-off-by: Yinbo Zhu <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Mark Brown <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
MAINTAINERS | 4 +
drivers/spi/Kconfig | 26 +++
drivers/spi/Makefile | 3 +
drivers/spi/spi-loongson-core.c | 279 ++++++++++++++++++++++++++++++++
drivers/spi/spi-loongson-pci.c | 55 +++++++
drivers/spi/spi-loongson-plat.c | 47 ++++++
drivers/spi/spi-loongson.h | 49 ++++++
7 files changed, 463 insertions(+)
create mode 100644 drivers/spi/spi-loongson-core.c
create mode 100644 drivers/spi/spi-loongson-pci.c
create mode 100644 drivers/spi/spi-loongson-plat.c
create mode 100644 drivers/spi/spi-loongson.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5e604dddd87b..69cb8fb2a0e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12191,6 +12191,10 @@ M: Yinbo Zhu <[email protected]>
L: [email protected]
S: Maintained
F: Documentation/devicetree/bindings/spi/loongson,ls2k-spi.yaml
+F: drivers/spi/spi-loongson-core.c
+F: drivers/spi/spi-loongson-pci.c
+F: drivers/spi/spi-loongson-plat.c
+F: drivers/spi/spi-loongson.h

LOONGSON-2 SOC SERIES GUTS DRIVER
M: Yinbo Zhu <[email protected]>
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3de2ebe8294a..6b953904792e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -516,6 +516,32 @@ config SPI_LM70_LLP
which interfaces to an LM70 temperature sensor using
a parallel port.

+config SPI_LOONGSON_CORE
+ tristate
+ depends on LOONGARCH || COMPILE_TEST
+
+config SPI_LOONGSON_PCI
+ tristate "Loongson SPI Controller PCI Driver Support"
+ select SPI_LOONGSON_CORE
+ depends on PCI && (LOONGARCH || COMPILE_TEST)
+ help
+ This bus driver supports the Loongson SPI hardware controller in
+ the Loongson platforms and supports to use PCI framework to
+ register SPI device resources.
+ 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)
+ 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.
+
config SPI_LP8841_RTC
tristate "ICP DAS LP-8841 SPI Controller for RTC"
depends on MACH_PXA27X_DT || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 28c4817a8a74..3e933064d237 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -71,6 +71,9 @@ obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
obj-$(CONFIG_SPI_JCORE) += spi-jcore.o
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
+obj-$(CONFIG_SPI_LOONGSON_CORE) += spi-loongson-core.o
+obj-$(CONFIG_SPI_LOONGSON_PCI) += spi-loongson-pci.o
+obj-$(CONFIG_SPI_LOONGSON_PLATFORM) += spi-loongson-plat.o
obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c
new file mode 100644
index 000000000000..f97800b6fd65
--- /dev/null
+++ b/drivers/spi/spi-loongson-core.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Loongson SPI Support
+// Copyright (C) 2023 Loongson Technology Corporation Limited
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "spi-loongson.h"
+
+static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg,
+ unsigned char data)
+{
+ writeb(data, spi->base + reg);
+}
+
+static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg)
+{
+ return readb(spi->base + reg);
+}
+
+static void loongson_spi_set_cs(struct spi_device *spi, bool en)
+{
+ int cs;
+ unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0);
+ unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0));
+ struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
+
+ cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG) & ~mask;
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, val | cs);
+}
+
+static void loongson_spi_set_clk(struct loongson_spi *loongson_spi, unsigned int hz)
+{
+ unsigned char val;
+ unsigned int div, div_tmp;
+ static const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11};
+
+ div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096);
+ div_tmp = rdiv[fls(div - 1)];
+ loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0;
+ loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2;
+ val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
+ val &= ~GENMASK(1, 0);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val |
+ loongson_spi->spcr);
+ val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
+ val &= ~GENMASK(1, 0);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, val |
+ loongson_spi->sper);
+ loongson_spi->hz = hz;
+}
+
+static void loongson_spi_set_mode(struct loongson_spi *loongson_spi,
+ struct spi_device *spi)
+{
+ unsigned char val;
+
+ val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
+ val &= ~(LOONGSON_SPI_SPCR_CPOL | LOONGSON_SPI_SPCR_CPHA);
+ if (spi->mode & SPI_CPOL)
+ val |= LOONGSON_SPI_SPCR_CPOL;
+ if (spi->mode & SPI_CPHA)
+ val |= LOONGSON_SPI_SPCR_CPHA;
+
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val);
+ loongson_spi->mode |= spi->mode;
+}
+
+static int loongson_spi_update_state(struct loongson_spi *loongson_spi,
+ struct spi_device *spi, struct spi_transfer *t)
+{
+ if (t && loongson_spi->hz != t->speed_hz)
+ loongson_spi_set_clk(loongson_spi, t->speed_hz);
+
+ if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK)
+ loongson_spi_set_mode(loongson_spi, spi);
+
+ return 0;
+}
+
+static int loongson_spi_setup(struct spi_device *spi)
+{
+ struct loongson_spi *loongson_spi;
+
+ loongson_spi = spi_controller_get_devdata(spi->controller);
+ if (spi->bits_per_word % 8)
+ return -EINVAL;
+
+ if (spi_get_chipselect(spi, 0) >= spi->controller->num_chipselect)
+ return -EINVAL;
+
+ loongson_spi->hz = 0;
+ loongson_spi_set_cs(spi, true);
+
+ return 0;
+}
+
+static int loongson_spi_write_read_8bit(struct spi_device *spi, const u8 **tx_buf,
+ u8 **rx_buf, unsigned int num)
+{
+ int ret;
+ struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
+
+ if (tx_buf && *tx_buf)
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, *((*tx_buf)++));
+ else
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, 0);
+
+ ret = readb_poll_timeout(loongson_spi->base + LOONGSON_SPI_SPSR_REG,
+ loongson_spi->spsr, (loongson_spi->spsr &
+ LOONGSON_SPI_SPSR_RFEMPTY) != LOONGSON_SPI_SPSR_RFEMPTY,
+ 1, USEC_PER_MSEC);
+
+ if (rx_buf && *rx_buf)
+ *(*rx_buf)++ = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
+ else
+ loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
+
+ return ret;
+}
+
+static int loongson_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
+{
+ int ret;
+ unsigned int count;
+ const u8 *tx = xfer->tx_buf;
+ u8 *rx = xfer->rx_buf;
+
+ count = xfer->len;
+ do {
+ ret = loongson_spi_write_read_8bit(spi, &tx, &rx, count);
+ if (ret)
+ break;
+ } while (--count);
+
+ return ret;
+}
+
+static int loongson_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *m)
+{
+ struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctlr);
+
+ loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para &
+ ~LOONGSON_SPI_PARA_MEM_EN);
+
+ return 0;
+}
+
+static int loongson_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
+
+ loongson_spi_update_state(loongson_spi, spi, xfer);
+ if (xfer->len)
+ return loongson_spi_write_read(spi, xfer);
+
+ return 0;
+}
+
+static int loongson_spi_unprepare_message(struct spi_controller *ctrl, struct spi_message *m)
+{
+ struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctrl);
+
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
+
+ return 0;
+}
+
+static void loongson_spi_reginit(struct loongson_spi *loongson_spi_dev)
+{
+ unsigned char val;
+
+ val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
+ val &= ~LOONGSON_SPI_SPCR_SPE;
+ loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
+
+ loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPSR_REG,
+ (LOONGSON_SPI_SPSR_SPIF | LOONGSON_SPI_SPSR_WCOL));
+
+ val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
+ val |= LOONGSON_SPI_SPCR_SPE;
+ loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
+}
+
+int loongson_spi_init_controller(struct device *dev, void __iomem *regs)
+{
+ struct spi_controller *controller;
+ struct loongson_spi *spi;
+ struct clk *clk;
+
+ controller = devm_spi_alloc_host(dev, sizeof(struct loongson_spi));
+ if (controller == NULL)
+ return -ENOMEM;
+
+ controller->mode_bits = SPI_MODE_X_MASK | SPI_CS_HIGH;
+ controller->setup = loongson_spi_setup;
+ controller->prepare_message = loongson_spi_prepare_message;
+ controller->transfer_one = loongson_spi_transfer_one;
+ controller->unprepare_message = loongson_spi_unprepare_message;
+ controller->set_cs = loongson_spi_set_cs;
+ controller->num_chipselect = 4;
+ device_set_node(&controller->dev, dev_fwnode(dev));
+ dev_set_drvdata(dev, controller);
+
+ spi = spi_controller_get_devdata(controller);
+ spi->base = regs;
+ spi->controller = controller;
+
+ clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "unable to get clock\n");
+
+ spi->clk_rate = clk_get_rate(clk);
+ loongson_spi_reginit(spi);
+
+ spi->mode = 0;
+
+ return devm_spi_register_controller(dev, controller);
+}
+EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, SPI_LOONGSON_CORE);
+
+static int __maybe_unused loongson_spi_suspend(struct device *dev)
+{
+ struct loongson_spi *loongson_spi;
+ struct spi_controller *controller;
+
+ controller = dev_get_drvdata(dev);
+ spi_controller_suspend(controller);
+
+ loongson_spi = spi_controller_get_devdata(controller);
+
+ loongson_spi->spcr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
+ loongson_spi->sper = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
+ loongson_spi->spsr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG);
+ loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
+ loongson_spi->sfcs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG);
+ loongson_spi->timi = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_TIMI_REG);
+
+ return 0;
+}
+
+static int __maybe_unused loongson_spi_resume(struct device *dev)
+{
+ struct loongson_spi *loongson_spi;
+ struct spi_controller *controller;
+
+ controller = dev_get_drvdata(dev);
+ loongson_spi = spi_controller_get_devdata(controller);
+
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, loongson_spi->spcr);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, loongson_spi->sper);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPSR_REG, loongson_spi->spsr);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, loongson_spi->sfcs);
+ loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_TIMI_REG, loongson_spi->timi);
+
+ spi_controller_resume(controller);
+
+ return 0;
+}
+
+const struct dev_pm_ops loongson_spi_dev_pm_ops = {
+ .suspend = loongson_spi_suspend,
+ .resume = loongson_spi_resume,
+};
+EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, SPI_LOONGSON_CORE);
+
+MODULE_DESCRIPTION("Loongson SPI core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-loongson-pci.c b/drivers/spi/spi-loongson-pci.c
new file mode 100644
index 000000000000..134cda0c13a5
--- /dev/null
+++ b/drivers/spi/spi-loongson-pci.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+// PCI interface driver for Loongson SPI Support
+// Copyright (C) 2023 Loongson Technology Corporation Limited
+
+#include <linux/mod_devicetable.h>
+#include <linux/pci.h>
+
+#include "spi-loongson.h"
+
+static int loongson_spi_pci_register(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int ret;
+ void __iomem *reg_base;
+ struct device *dev = &pdev->dev;
+ int pci_bar = 0;
+
+ ret = pcim_enable_device(pdev);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "cannot enable pci device\n");
+
+ ret = pcim_iomap_regions(pdev, BIT(pci_bar), pci_name(pdev));
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to request and remap memory\n");
+
+ reg_base = pcim_iomap_table(pdev)[pci_bar];
+
+ ret = loongson_spi_init_controller(dev, reg_base);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to initialize controller\n");
+
+ return 0;
+}
+
+static struct pci_device_id loongson_spi_devices[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a0b) },
+ { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a1b) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, loongson_spi_devices);
+
+static struct pci_driver loongson_spi_pci_driver = {
+ .name = "loongson-spi-pci",
+ .id_table = loongson_spi_devices,
+ .probe = loongson_spi_pci_register,
+ .driver = {
+ .bus = &pci_bus_type,
+ .pm = &loongson_spi_dev_pm_ops,
+ },
+};
+module_pci_driver(loongson_spi_pci_driver);
+
+MODULE_DESCRIPTION("Loongson spi pci driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
diff --git a/drivers/spi/spi-loongson-plat.c b/drivers/spi/spi-loongson-plat.c
new file mode 100644
index 000000000000..c066e5f5891e
--- /dev/null
+++ b/drivers/spi/spi-loongson-plat.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Platform driver for Loongson SPI Support
+// Copyright (C) 2023 Loongson Technology Corporation Limited
+
+#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+
+#include "spi-loongson.h"
+
+static int loongson_spi_platform_probe(struct platform_device *pdev)
+{
+ int ret;
+ void __iomem *reg_base;
+ struct device *dev = &pdev->dev;
+
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg_base))
+ return PTR_ERR(reg_base);
+
+ ret = loongson_spi_init_controller(dev, reg_base);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to initialize controller\n");
+
+ return 0;
+}
+
+static const struct of_device_id loongson_spi_id_table[] = {
+ { .compatible = "loongson,ls2k1000-spi" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, loongson_spi_id_table);
+
+static struct platform_driver loongson_spi_plat_driver = {
+ .probe = loongson_spi_platform_probe,
+ .driver = {
+ .name = "loongson-spi",
+ .bus = &platform_bus_type,
+ .pm = &loongson_spi_dev_pm_ops,
+ .of_match_table = loongson_spi_id_table,
+ },
+};
+module_platform_driver(loongson_spi_plat_driver);
+
+MODULE_DESCRIPTION("Loongson spi platform driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
diff --git a/drivers/spi/spi-loongson.h b/drivers/spi/spi-loongson.h
new file mode 100644
index 000000000000..35f95b161842
--- /dev/null
+++ b/drivers/spi/spi-loongson.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Header File for Loongson SPI Driver. */
+/* Copyright (C) 2023 Loongson Technology Corporation Limited */
+
+#ifndef __LINUX_SPI_LOONGSON_H
+#define __LINUX_SPI_LOONGSON_H
+
+#include <linux/bits.h>
+#include <linux/pm.h>
+#include <linux/types.h>
+
+#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_SPCR_CPHA BIT(2)
+#define LOONGSON_SPI_SPCR_CPOL BIT(3)
+#define LOONGSON_SPI_SPCR_SPE BIT(6)
+#define LOONGSON_SPI_SPSR_RFEMPTY BIT(0)
+#define LOONGSON_SPI_SPSR_WCOL BIT(6)
+#define LOONGSON_SPI_SPSR_SPIF BIT(7)
+
+struct device;
+struct spi_controller;
+
+struct loongson_spi {
+ struct spi_controller *controller;
+ 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;
+};
+
+int loongson_spi_init_controller(struct device *dev, void __iomem *reg);
+extern const struct dev_pm_ops loongson_spi_dev_pm_ops;
+#endif /* __LINUX_SPI_LOONGSON_H */
--
2.20.1


2023-06-13 13:20:15

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller

On Tue, Jun 13, 2023 at 10:58 AM Yinbo Zhu <[email protected]> wrote:

...

> Cc: Andy Shevchenko <[email protected]>

> Reviewed-by: Andy Shevchenko <[email protected]>

Just a remark for the next contribution. When you have a tag, no need
to have a Cc for the same person, Git tools automatically add all
tagged people to the Cc list of email.

--
With Best Regards,
Andy Shevchenko

2023-06-14 02:19:47

by Yinbo Zhu

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller



在 2023/6/13 下午9:03, Andy Shevchenko 写道:
> On Tue, Jun 13, 2023 at 10:58 AM Yinbo Zhu <[email protected]> wrote:
>
> ...
>
>> Cc: Andy Shevchenko <[email protected]>
>
>> Reviewed-by: Andy Shevchenko <[email protected]>
>
> Just a remark for the next contribution. When you have a tag, no need
> to have a Cc for the same person, Git tools automatically add all
> tagged people to the Cc list of email.


okay, I got it.

Thanks,
Yinbo
>


2023-07-27 03:29:46

by Yinbo Zhu

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller


Friendly ping ?


?? 2023/6/13 ????3:58, Yinbo Zhu д??:
> This bus driver supports the Loongson SPI hardware controller in the
> Loongson platforms and supports the use DTS and PCI framework to
> register SPI device resources.
>
> Signed-off-by: Yinbo Zhu <[email protected]>
> Cc: Andy Shevchenko <[email protected]>
> Cc: Mark Brown <[email protected]>
> Reviewed-by: Andy Shevchenko <[email protected]>
> ---
> MAINTAINERS | 4 +
> drivers/spi/Kconfig | 26 +++
> drivers/spi/Makefile | 3 +
> drivers/spi/spi-loongson-core.c | 279 ++++++++++++++++++++++++++++++++
> drivers/spi/spi-loongson-pci.c | 55 +++++++
> drivers/spi/spi-loongson-plat.c | 47 ++++++
> drivers/spi/spi-loongson.h | 49 ++++++
> 7 files changed, 463 insertions(+)
> create mode 100644 drivers/spi/spi-loongson-core.c
> create mode 100644 drivers/spi/spi-loongson-pci.c
> create mode 100644 drivers/spi/spi-loongson-plat.c
> create mode 100644 drivers/spi/spi-loongson.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5e604dddd87b..69cb8fb2a0e1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12191,6 +12191,10 @@ M: Yinbo Zhu <[email protected]>
> L: [email protected]
> S: Maintained
> F: Documentation/devicetree/bindings/spi/loongson,ls2k-spi.yaml
> +F: drivers/spi/spi-loongson-core.c
> +F: drivers/spi/spi-loongson-pci.c
> +F: drivers/spi/spi-loongson-plat.c
> +F: drivers/spi/spi-loongson.h
>
> LOONGSON-2 SOC SERIES GUTS DRIVER
> M: Yinbo Zhu <[email protected]>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 3de2ebe8294a..6b953904792e 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -516,6 +516,32 @@ config SPI_LM70_LLP
> which interfaces to an LM70 temperature sensor using
> a parallel port.
>
> +config SPI_LOONGSON_CORE
> + tristate
> + depends on LOONGARCH || COMPILE_TEST
> +
> +config SPI_LOONGSON_PCI
> + tristate "Loongson SPI Controller PCI Driver Support"
> + select SPI_LOONGSON_CORE
> + depends on PCI && (LOONGARCH || COMPILE_TEST)
> + help
> + This bus driver supports the Loongson SPI hardware controller in
> + the Loongson platforms and supports to use PCI framework to
> + register SPI device resources.
> + 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)
> + 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.
> +
> config SPI_LP8841_RTC
> tristate "ICP DAS LP-8841 SPI Controller for RTC"
> depends on MACH_PXA27X_DT || COMPILE_TEST
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 28c4817a8a74..3e933064d237 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -71,6 +71,9 @@ obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o
> obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
> obj-$(CONFIG_SPI_JCORE) += spi-jcore.o
> obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
> +obj-$(CONFIG_SPI_LOONGSON_CORE) += spi-loongson-core.o
> +obj-$(CONFIG_SPI_LOONGSON_PCI) += spi-loongson-pci.o
> +obj-$(CONFIG_SPI_LOONGSON_PLATFORM) += spi-loongson-plat.o
> obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
> obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
> obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
> diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c
> new file mode 100644
> index 000000000000..f97800b6fd65
> --- /dev/null
> +++ b/drivers/spi/spi-loongson-core.c
> @@ -0,0 +1,279 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Loongson SPI Support
> +// Copyright (C) 2023 Loongson Technology Corporation Limited
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +
> +#include "spi-loongson.h"
> +
> +static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg,
> + unsigned char data)
> +{
> + writeb(data, spi->base + reg);
> +}
> +
> +static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg)
> +{
> + return readb(spi->base + reg);
> +}
> +
> +static void loongson_spi_set_cs(struct spi_device *spi, bool en)
> +{
> + int cs;
> + unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0);
> + unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0));
> + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
> +
> + cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG) & ~mask;
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, val | cs);
> +}
> +
> +static void loongson_spi_set_clk(struct loongson_spi *loongson_spi, unsigned int hz)
> +{
> + unsigned char val;
> + unsigned int div, div_tmp;
> + static const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11};
> +
> + div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096);
> + div_tmp = rdiv[fls(div - 1)];
> + loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0;
> + loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2;
> + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
> + val &= ~GENMASK(1, 0);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val |
> + loongson_spi->spcr);
> + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
> + val &= ~GENMASK(1, 0);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, val |
> + loongson_spi->sper);
> + loongson_spi->hz = hz;
> +}
> +
> +static void loongson_spi_set_mode(struct loongson_spi *loongson_spi,
> + struct spi_device *spi)
> +{
> + unsigned char val;
> +
> + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
> + val &= ~(LOONGSON_SPI_SPCR_CPOL | LOONGSON_SPI_SPCR_CPHA);
> + if (spi->mode & SPI_CPOL)
> + val |= LOONGSON_SPI_SPCR_CPOL;
> + if (spi->mode & SPI_CPHA)
> + val |= LOONGSON_SPI_SPCR_CPHA;
> +
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val);
> + loongson_spi->mode |= spi->mode;
> +}
> +
> +static int loongson_spi_update_state(struct loongson_spi *loongson_spi,
> + struct spi_device *spi, struct spi_transfer *t)
> +{
> + if (t && loongson_spi->hz != t->speed_hz)
> + loongson_spi_set_clk(loongson_spi, t->speed_hz);
> +
> + if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK)
> + loongson_spi_set_mode(loongson_spi, spi);
> +
> + return 0;
> +}
> +
> +static int loongson_spi_setup(struct spi_device *spi)
> +{
> + struct loongson_spi *loongson_spi;
> +
> + loongson_spi = spi_controller_get_devdata(spi->controller);
> + if (spi->bits_per_word % 8)
> + return -EINVAL;
> +
> + if (spi_get_chipselect(spi, 0) >= spi->controller->num_chipselect)
> + return -EINVAL;
> +
> + loongson_spi->hz = 0;
> + loongson_spi_set_cs(spi, true);
> +
> + return 0;
> +}
> +
> +static int loongson_spi_write_read_8bit(struct spi_device *spi, const u8 **tx_buf,
> + u8 **rx_buf, unsigned int num)
> +{
> + int ret;
> + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
> +
> + if (tx_buf && *tx_buf)
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, *((*tx_buf)++));
> + else
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, 0);
> +
> + ret = readb_poll_timeout(loongson_spi->base + LOONGSON_SPI_SPSR_REG,
> + loongson_spi->spsr, (loongson_spi->spsr &
> + LOONGSON_SPI_SPSR_RFEMPTY) != LOONGSON_SPI_SPSR_RFEMPTY,
> + 1, USEC_PER_MSEC);
> +
> + if (rx_buf && *rx_buf)
> + *(*rx_buf)++ = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
> + else
> + loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
> +
> + return ret;
> +}
> +
> +static int loongson_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
> +{
> + int ret;
> + unsigned int count;
> + const u8 *tx = xfer->tx_buf;
> + u8 *rx = xfer->rx_buf;
> +
> + count = xfer->len;
> + do {
> + ret = loongson_spi_write_read_8bit(spi, &tx, &rx, count);
> + if (ret)
> + break;
> + } while (--count);
> +
> + return ret;
> +}
> +
> +static int loongson_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *m)
> +{
> + struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctlr);
> +
> + loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para &
> + ~LOONGSON_SPI_PARA_MEM_EN);
> +
> + return 0;
> +}
> +
> +static int loongson_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
> + struct spi_transfer *xfer)
> +{
> + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
> +
> + loongson_spi_update_state(loongson_spi, spi, xfer);
> + if (xfer->len)
> + return loongson_spi_write_read(spi, xfer);
> +
> + return 0;
> +}
> +
> +static int loongson_spi_unprepare_message(struct spi_controller *ctrl, struct spi_message *m)
> +{
> + struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctrl);
> +
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
> +
> + return 0;
> +}
> +
> +static void loongson_spi_reginit(struct loongson_spi *loongson_spi_dev)
> +{
> + unsigned char val;
> +
> + val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
> + val &= ~LOONGSON_SPI_SPCR_SPE;
> + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
> +
> + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPSR_REG,
> + (LOONGSON_SPI_SPSR_SPIF | LOONGSON_SPI_SPSR_WCOL));
> +
> + val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
> + val |= LOONGSON_SPI_SPCR_SPE;
> + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
> +}
> +
> +int loongson_spi_init_controller(struct device *dev, void __iomem *regs)
> +{
> + struct spi_controller *controller;
> + struct loongson_spi *spi;
> + struct clk *clk;
> +
> + controller = devm_spi_alloc_host(dev, sizeof(struct loongson_spi));
> + if (controller == NULL)
> + return -ENOMEM;
> +
> + controller->mode_bits = SPI_MODE_X_MASK | SPI_CS_HIGH;
> + controller->setup = loongson_spi_setup;
> + controller->prepare_message = loongson_spi_prepare_message;
> + controller->transfer_one = loongson_spi_transfer_one;
> + controller->unprepare_message = loongson_spi_unprepare_message;
> + controller->set_cs = loongson_spi_set_cs;
> + controller->num_chipselect = 4;
> + device_set_node(&controller->dev, dev_fwnode(dev));
> + dev_set_drvdata(dev, controller);
> +
> + spi = spi_controller_get_devdata(controller);
> + spi->base = regs;
> + spi->controller = controller;
> +
> + clk = devm_clk_get_optional(dev, NULL);
> + if (IS_ERR(clk))
> + return dev_err_probe(dev, PTR_ERR(clk), "unable to get clock\n");
> +
> + spi->clk_rate = clk_get_rate(clk);
> + loongson_spi_reginit(spi);
> +
> + spi->mode = 0;
> +
> + return devm_spi_register_controller(dev, controller);
> +}
> +EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, SPI_LOONGSON_CORE);
> +
> +static int __maybe_unused loongson_spi_suspend(struct device *dev)
> +{
> + struct loongson_spi *loongson_spi;
> + struct spi_controller *controller;
> +
> + controller = dev_get_drvdata(dev);
> + spi_controller_suspend(controller);
> +
> + loongson_spi = spi_controller_get_devdata(controller);
> +
> + loongson_spi->spcr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
> + loongson_spi->sper = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
> + loongson_spi->spsr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG);
> + loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
> + loongson_spi->sfcs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG);
> + loongson_spi->timi = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_TIMI_REG);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused loongson_spi_resume(struct device *dev)
> +{
> + struct loongson_spi *loongson_spi;
> + struct spi_controller *controller;
> +
> + controller = dev_get_drvdata(dev);
> + loongson_spi = spi_controller_get_devdata(controller);
> +
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, loongson_spi->spcr);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, loongson_spi->sper);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPSR_REG, loongson_spi->spsr);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, loongson_spi->sfcs);
> + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_TIMI_REG, loongson_spi->timi);
> +
> + spi_controller_resume(controller);
> +
> + return 0;
> +}
> +
> +const struct dev_pm_ops loongson_spi_dev_pm_ops = {
> + .suspend = loongson_spi_suspend,
> + .resume = loongson_spi_resume,
> +};
> +EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, SPI_LOONGSON_CORE);
> +
> +MODULE_DESCRIPTION("Loongson SPI core driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi-loongson-pci.c b/drivers/spi/spi-loongson-pci.c
> new file mode 100644
> index 000000000000..134cda0c13a5
> --- /dev/null
> +++ b/drivers/spi/spi-loongson-pci.c
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// PCI interface driver for Loongson SPI Support
> +// Copyright (C) 2023 Loongson Technology Corporation Limited
> +
> +#include <linux/mod_devicetable.h>
> +#include <linux/pci.h>
> +
> +#include "spi-loongson.h"
> +
> +static int loongson_spi_pci_register(struct pci_dev *pdev,
> + const struct pci_device_id *ent)
> +{
> + int ret;
> + void __iomem *reg_base;
> + struct device *dev = &pdev->dev;
> + int pci_bar = 0;
> +
> + ret = pcim_enable_device(pdev);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "cannot enable pci device\n");
> +
> + ret = pcim_iomap_regions(pdev, BIT(pci_bar), pci_name(pdev));
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to request and remap memory\n");
> +
> + reg_base = pcim_iomap_table(pdev)[pci_bar];
> +
> + ret = loongson_spi_init_controller(dev, reg_base);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to initialize controller\n");
> +
> + return 0;
> +}
> +
> +static struct pci_device_id loongson_spi_devices[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a0b) },
> + { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a1b) },
> + { }
> +};
> +MODULE_DEVICE_TABLE(pci, loongson_spi_devices);
> +
> +static struct pci_driver loongson_spi_pci_driver = {
> + .name = "loongson-spi-pci",
> + .id_table = loongson_spi_devices,
> + .probe = loongson_spi_pci_register,
> + .driver = {
> + .bus = &pci_bus_type,
> + .pm = &loongson_spi_dev_pm_ops,
> + },
> +};
> +module_pci_driver(loongson_spi_pci_driver);
> +
> +MODULE_DESCRIPTION("Loongson spi pci driver");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
> diff --git a/drivers/spi/spi-loongson-plat.c b/drivers/spi/spi-loongson-plat.c
> new file mode 100644
> index 000000000000..c066e5f5891e
> --- /dev/null
> +++ b/drivers/spi/spi-loongson-plat.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Platform driver for Loongson SPI Support
> +// Copyright (C) 2023 Loongson Technology Corporation Limited
> +
> +#include <linux/err.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +
> +#include "spi-loongson.h"
> +
> +static int loongson_spi_platform_probe(struct platform_device *pdev)
> +{
> + int ret;
> + void __iomem *reg_base;
> + struct device *dev = &pdev->dev;
> +
> + reg_base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(reg_base))
> + return PTR_ERR(reg_base);
> +
> + ret = loongson_spi_init_controller(dev, reg_base);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to initialize controller\n");
> +
> + return 0;
> +}
> +
> +static const struct of_device_id loongson_spi_id_table[] = {
> + { .compatible = "loongson,ls2k1000-spi" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, loongson_spi_id_table);
> +
> +static struct platform_driver loongson_spi_plat_driver = {
> + .probe = loongson_spi_platform_probe,
> + .driver = {
> + .name = "loongson-spi",
> + .bus = &platform_bus_type,
> + .pm = &loongson_spi_dev_pm_ops,
> + .of_match_table = loongson_spi_id_table,
> + },
> +};
> +module_platform_driver(loongson_spi_plat_driver);
> +
> +MODULE_DESCRIPTION("Loongson spi platform driver");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
> diff --git a/drivers/spi/spi-loongson.h b/drivers/spi/spi-loongson.h
> new file mode 100644
> index 000000000000..35f95b161842
> --- /dev/null
> +++ b/drivers/spi/spi-loongson.h
> @@ -0,0 +1,49 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/* Header File for Loongson SPI Driver. */
> +/* Copyright (C) 2023 Loongson Technology Corporation Limited */
> +
> +#ifndef __LINUX_SPI_LOONGSON_H
> +#define __LINUX_SPI_LOONGSON_H
> +
> +#include <linux/bits.h>
> +#include <linux/pm.h>
> +#include <linux/types.h>
> +
> +#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_SPCR_CPHA BIT(2)
> +#define LOONGSON_SPI_SPCR_CPOL BIT(3)
> +#define LOONGSON_SPI_SPCR_SPE BIT(6)
> +#define LOONGSON_SPI_SPSR_RFEMPTY BIT(0)
> +#define LOONGSON_SPI_SPSR_WCOL BIT(6)
> +#define LOONGSON_SPI_SPSR_SPIF BIT(7)
> +
> +struct device;
> +struct spi_controller;
> +
> +struct loongson_spi {
> + struct spi_controller *controller;
> + 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;
> +};
> +
> +int loongson_spi_init_controller(struct device *dev, void __iomem *reg);
> +extern const struct dev_pm_ops loongson_spi_dev_pm_ops;
> +#endif /* __LINUX_SPI_LOONGSON_H */
>


2023-07-27 12:17:00

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller

On Thu, Jul 27, 2023 at 11:09:16AM +0800, Yinbo Zhu wrote:

> Friendly ping ?

Please don't send content free pings and please allow a reasonable time
for review. People get busy, go on holiday, attend conferences and so
on so unless there is some reason for urgency (like critical bug fixes)
please allow at least a couple of weeks for review. If there have been
review comments then people may be waiting for those to be addressed.

Sending content free pings adds to the mail volume (if they are seen at
all) which is often the problem and since they can't be reviewed
directly if something has gone wrong you'll have to resend the patches
anyway, so sending again is generally a better approach though there are
some other maintainers who like them - if in doubt look at how patches
for the subsystem are normally handled.


Attachments:
(No filename) (846.00 B)
signature.asc (499.00 B)
Download all attachments

2023-07-28 03:58:13

by Yinbo Zhu

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller



在 2023/7/27 下午7:37, Mark Brown 写道:
> On Thu, Jul 27, 2023 at 11:09:16AM +0800, Yinbo Zhu wrote:
>
>> Friendly ping ?
>
> Please don't send content free pings and please allow a reasonable time
> for review. People get busy, go on holiday, attend conferences and so
> on so unless there is some reason for urgency (like critical bug fixes)
> please allow at least a couple of weeks for review. If there have been
> review comments then people may be waiting for those to be addressed.


Sorry, my community experience is poor. How many weeks does the
community usually take to review ? and this time that I waited for six
weeks and then ping.

>
> Sending content free pings adds to the mail volume (if they are seen at
> all) which is often the problem and since they can't be reviewed
> directly if something has gone wrong you'll have to resend the patches
> anyway, so sending again is generally a better approach though there are
> some other maintainers who like them - if in doubt look at how patches
> for the subsystem are normally handled.


Sorry, I don't got it, that free ping usually only needs to be sent to
the subsystem maintainer?

Not recommended to use free ping? or resend the same patch. If the
patch does not need to be modified, does it require sending the same
patch ? And the version number remains the same?
>

Thanks,
Yinbo


2023-07-28 13:17:52

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller

On Fri, Jul 28, 2023 at 11:36:48AM +0800, Yinbo Zhu wrote:
> 在 2023/7/27 下午7:37, Mark Brown 写道:
> > On Thu, Jul 27, 2023 at 11:09:16AM +0800, Yinbo Zhu wrote:

> > > Friendly ping ?

> > Please don't send content free pings and please allow a reasonable time
> > for review. People get busy, go on holiday, attend conferences and so
> > on so unless there is some reason for urgency (like critical bug fixes)
> > please allow at least a couple of weeks for review. If there have been
> > review comments then people may be waiting for those to be addressed.

> Sorry, my community experience is poor. How many weeks does the
> community usually take to review ? and this time that I waited for six
> weeks and then ping.

The delay here is probably fine - the above is a form letter that I send
whenever people ping so it tries to cover all eventualities. How long
to leave things depends a bit on what the change is, an urgent bugfix is
going to be different from a spelling fix in a comment.

> > Sending content free pings adds to the mail volume (if they are seen at
> > all) which is often the problem and since they can't be reviewed
> > directly if something has gone wrong you'll have to resend the patches
> > anyway, so sending again is generally a better approach though there are
> > some other maintainers who like them - if in doubt look at how patches
> > for the subsystem are normally handled.

> Sorry, I don't got it, that free ping usually only needs to be sent to
> the subsystem maintainer?

> Not recommended to use free ping? or resend the same patch. If the
> patch does not need to be modified, does it require sending the same
> patch ? And the version number remains the same?

I'm saying it's generally better to ping by resending the patch.
Typically keeping the same version number makes sense when doing that -
people normally say [PATCH RESEND vN] in the subject line.


Attachments:
(No filename) (1.91 kB)
signature.asc (499.00 B)
Download all attachments

2023-07-31 06:20:08

by Yinbo Zhu

[permalink] [raw]
Subject: Re: [PATCH v13 2/2] spi: loongson: add bus driver for the loongson spi controller



在 2023/7/28 下午8:31, Mark Brown 写道:
> On Fri, Jul 28, 2023 at 11:36:48AM +0800, Yinbo Zhu wrote:
>> 在 2023/7/27 下午7:37, Mark Brown 写道:
>>> On Thu, Jul 27, 2023 at 11:09:16AM +0800, Yinbo Zhu wrote:
>
>>>> Friendly ping ?
>
>>> Please don't send content free pings and please allow a reasonable time
>>> for review. People get busy, go on holiday, attend conferences and so
>>> on so unless there is some reason for urgency (like critical bug fixes)
>>> please allow at least a couple of weeks for review. If there have been
>>> review comments then people may be waiting for those to be addressed.
>
>> Sorry, my community experience is poor. How many weeks does the
>> community usually take to review ? and this time that I waited for six
>> weeks and then ping.
>
> The delay here is probably fine - the above is a form letter that I send
> whenever people ping so it tries to cover all eventualities. How long
> to leave things depends a bit on what the change is, an urgent bugfix is
> going to be different from a spelling fix in a comment.


okay, I got it.

>
>>> Sending content free pings adds to the mail volume (if they are seen at
>>> all) which is often the problem and since they can't be reviewed
>>> directly if something has gone wrong you'll have to resend the patches
>>> anyway, so sending again is generally a better approach though there are
>>> some other maintainers who like them - if in doubt look at how patches
>>> for the subsystem are normally handled.
>
>> Sorry, I don't got it, that free ping usually only needs to be sent to
>> the subsystem maintainer?
>
>> Not recommended to use free ping? or resend the same patch. If the
>> patch does not need to be modified, does it require sending the same
>> patch ? And the version number remains the same?
>
> I'm saying it's generally better to ping by resending the patch.
> Typically keeping the same version number makes sense when doing that -
> people normally say [PATCH RESEND vN] in the subject line.


okay, I got it

Thanks,
Yinbo


2023-07-31 20:50:21

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v13 0/2] spi: loongson: add bus driver for the loongson spi

On Tue, 13 Jun 2023 15:58:32 +0800, Yinbo Zhu wrote:
> Loongson platform support spi hardware controller and this series patch
> was to add spi driver and binding support.
>
> Change in v2:
> 1. This [PATCH v2 1/2] dt-bindings patch need depend on clk patch:
> https://
> lore.kernel.org/all/[email protected]/
> 2. Remove the clock-names in spi yaml file.
> 3. Add "loongson,ls7a-spi" compatible in spi yaml file.
> 4. Add an || COMPILE_TEST and drop && PCI then add some CONFIG_PCI
> macro to limit some pci code.
> 5. Make the spi driver top code comment block that use C++ style.
> 6. Drop spi->max_speed_hz.
> 7. Add a spin_lock for loongson_spi_setup.
> 8. Add a timeout and cpu_relax() in loongson_spi_write_read_8bit.
> 9. Add spi_transfer_one and drop transfer and rework entire spi
> driver that include some necessary changes.
> 10. Use module_init replace subsys_initcall.
> 11. About PM interface that I don't find any issue so I don't add
> any changes.
> Change in v3:
> 1. This [PATCH v3 1/2] dt-bindings patch need depend on clk patch:
> https://
> lore.kernel.org/all/[email protected]/
> 2. Drop the unused blank line in loongson,ls-spi.yaml file.
> 3. Replace clock minItems with clock maxItems in yaml file.
> 4. Separate spi driver into platform module, pci module and core
> module.
> 5. Replace DIV_ROUND_UP with DIV_ROUND_UP_ULL to fix compile error
> "undefined reference to `__aeabi_uldivmod'" and "__udivdi3 undefined"
> that reported by test robot.
> 6. Remove the spin lock.
> 7. Clear the loongson_spi->hz and loongson_spi->mode in setup to fixup
> the issue that multiple spi device transfer that maybe cause spi was
> be misconfigured.
> Change in v4:
> 1. This [PATCH v4 1/2] dt-bindings patch need depend on clk patch:
> https://
> lore.kernel.org/all/[email protected]/
> 2. Add "#include <linux/io.h>" in spi-loongson-core.c for fix the compile
> issue which devm_ioremap no declaration.
> 3. Add "EXPORT_SYMBOL_GPL(loongson_spi_dev_pm_ops)" in
> spi-loongson-core.c for fix the compile issue which
> loongson_spi_dev_pm_ops undefined.
> Change in v5:
> 1. Get rid of the clock patch's dependency and open-code the clock IDs.
> 2. Fixup checkpatch issue that by installed ply and gitpython package
> locally, but this series of patch's code doesn't have any change.
> Change in v6:
> 1. Remove the "#include <dt-bindings/clock/loongson,ls2k-clk.h>" in
> yaml file.
> Change in v7:
> 1. Remove the "loongson,ls7a-spi" and change yaml file name as
> "loongson,ls2k-spi.yaml".
> 2. Use module_pci_driver and module_platform_driver to replace
> module_init and module_exit.
> 3. Drop ".owner = THIS_MODULE" in spi platform driver.
> 4. Add devm_spi_alloc_master devm_spi_register_master to simplify code.
> 5. Add pci_disable_device() in loongson_spi_pci_unregister.
> Change in v8:
> 1. Add reviewed-by information for spi bindings patch.
> 2. Fixup the uncorrect spi yaml file path in MAINTAINERS file.
> 3. Add spi_master_suspend and spi_master_resume in spi pm function.
> Change in v9:
> 1. Make spi_master_suspend go first in pm suspend.
> Change in v10:
> 1. Fix the compile issue about of_node_get and of_get_property no
> declaration.
> 2. set config SPI_LOONGSON_CORE invisible.
> 3. Captial "spi" in commit log and Kconfig file.
> 4. Write header files in alphabetical order.
> 5. Use clamp_val, GENMASK() and BIT() in spi clock setting.
> 6. Optimize clock and mode setting code.
> 7. Use readb_poll_timeout in loongson_spi_write_read_8bit.
> 8. Remove some useless dmesg print.
> 9. Use device_set_node replace of_node_get.
> 10. Use dev_err_probe in code.
> 11. Use devm_clk_get_optional replace devm_clk_get.
> 12. Remove SPI_NO_CS for drop 2k500 non common type spi.
> 13. Use pcim_enable_device() and pcim_iomap_regions() in spi pci
> driver.
> 14. Passing the remapped address in loongson_spi_init_master.
> 15. Remove the useless goto flag "err_out".
> 16. Use pci vendor id in pci_ids.h.
> 17. Use devm_platform_ioremap_resource in spi platform driver.
> 18. Remove the useless item in pci_device_id.
> 19. Remove the inned comma in of_device_id.
> 20. Add some headfile in spi_loongson.h.
> 21. Remove the useless extern for loongson_spi_init_master in
> spi_loongson.h.
> Change in v11:
> 1. Use spi_get_chipselect() to replace all spi->chip_select in
> spi driver
> Change in v12:
> 1. Reword the dt-bindings patch title.
> 2. Use a specific spi compatible in dt-bindings and spi driver.
> 3. Add Cc list for the reviewers of the previous version.
> 4. Add a static for rdiv[12] array in loongson_spi_set_clk.
> 5. Fixup the compile warning for spi HZ that reported by robot.
> 6. Use "#define LOONGSON_... BIT(0)" in readb_poll_timeout.
> 7. Add a error code return that when write spi failed.
> 8. Use spi_controller* instead of spi_master* in all cases.
> 9. Check for the error first which for clock gain.
> 10. Drop the ->remove() in spi pci driver.
> 11. Drop the comma for the terminator entry in pci_device_id.
> 12. Adjust the head file in spi driver.
> 13. Use forward declarations for device and spi_controller.
> Change in v13:
> 1. Reword the dt-bindings patch title.
> 2. Add the items for compatible with 2k500 in dts-bindings.
> 3. Add a bit changes in commit log.
> 4. Add a Reviewed-by for spi driver patch.
> 5. Rework the function loongson_spi_set_cs.
> 6. Use GENMASK() to replace some constant in function
> loongson_spi_set_clk.
> 7. Add or remove some blank lines.
> 8. Use LOONGSON_SPI_PARA_MEM_EN replace a constant in
> loongson_spi_prepare_message.
> 9. Use SPI_MODE_X_MASK to replace "SPI_CPOL | SPI_CPHA".
> 10. Use USEC_PER_MSEC to replace MSEC_PER_SEC.
>
> [...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/2] spi: dt-bindings: add loongson spi
commit: b350e6c6297aaa2533da23a21398751eeeecc101
[2/2] spi: loongson: add bus driver for the loongson spi controller
commit: 6c7a864007b66e60a3f64858a9555efed408b048

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark