Add HiSilicon SPI Controller Driver for Kunpeng SoCs
Signed-off-by: Jiang Yi <jiangyi38@hisilicon.com>
This commit is contained in:
parent
43123ef52f
commit
c7a6fdffa6
13
kernel.spec
13
kernel.spec
@ -32,7 +32,7 @@
|
||||
|
||||
Name: kernel
|
||||
Version: 4.19.90
|
||||
Release: %{hulkrelease}.0233
|
||||
Release: %{hulkrelease}.0234
|
||||
Summary: Linux Kernel
|
||||
License: GPLv2
|
||||
URL: http://www.kernel.org/
|
||||
@ -832,6 +832,17 @@ fi
|
||||
|
||||
%changelog
|
||||
|
||||
* Mon Nov 6 2023 Jiang Yi <jiangyi38@hisilicon.com> - 4.19.90-2311.1.0.0234
|
||||
- spi: hisi-kunpeng: Fix the debugfs directory name incorrect
|
||||
- spi: hisi-kunpeng: Add debugfs support
|
||||
- spi: hisi-kunpeng: Fix Woverflow warning on conversion
|
||||
- spi: Add HiSilicon SPI Controller Driver for Kunpeng SoCs
|
||||
- Documentation: devres: add missing SPI helper
|
||||
- spi: <linux/spi/spi.h>: add missing struct kernel-doc entry
|
||||
- spi: Fix use-after-free with devm_spi_alloc_*
|
||||
- spi: Introduce device-managed SPI controller allocation
|
||||
- spi: core: allow reporting the effectivly used speed_hz for a transfer
|
||||
|
||||
* Fri Nov 3 2023 Yu Liao <liaoyu15@huawei.com> - 4.19.90-2310.4.0.0233
|
||||
- arm64: HWCAP: add support for AT_HWCAP2
|
||||
- arm64: Expose SVE2 features for userspace
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
From 1df3aa945b6da52d88e2bcfd53a103a55366c4d7 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Sperl <kernel@martin.sperl.org>
|
||||
Date: Sat, 23 Feb 2019 08:49:49 +0000
|
||||
Subject: [PATCH 101/109] spi: core: allow reporting the effectivly used
|
||||
speed_hz for a transfer
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.3-rc1
|
||||
commit 5d7e2b5ed5858fe739d4cb8ad22dcce7bd9dbe7b
|
||||
category: feature
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5d7e2b5ed5858fe739d4cb8ad22dcce7bd9dbe7b
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Provide a means for the spi bus driver to report the effectively used
|
||||
spi clock frequency used for each spi_transfer.
|
||||
|
||||
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
|
||||
Conflicts:
|
||||
include/linux/spi/spi.h
|
||||
---
|
||||
drivers/spi/spi.c | 1 +
|
||||
include/linux/spi/spi.h | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
||||
index f0f21f93d293..c79bf015b4b2 100644
|
||||
--- a/drivers/spi/spi.c
|
||||
+++ b/drivers/spi/spi.c
|
||||
@@ -2892,6 +2892,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
|
||||
*/
|
||||
message->frame_length = 0;
|
||||
list_for_each_entry(xfer, &message->transfers, transfer_list) {
|
||||
+ xfer->effective_speed_hz = 0;
|
||||
message->frame_length += xfer->len;
|
||||
if (!xfer->bits_per_word)
|
||||
xfer->bits_per_word = spi->bits_per_word;
|
||||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
|
||||
index a64235e05321..ec795c5304f0 100644
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -711,6 +711,9 @@ extern void spi_res_release(struct spi_controller *ctlr,
|
||||
* @delay_usecs: microseconds to delay after this transfer before
|
||||
* (optionally) changing the chipselect status, then starting
|
||||
* the next transfer or completing this @spi_message.
|
||||
+ * @effective_speed_hz: the effective SCK-speed that was used to
|
||||
+ * transfer this transfer. Set to 0 if the spi bus driver does
|
||||
+ * not support it.
|
||||
* @transfer_list: transfers are sequenced through @spi_message.transfers
|
||||
* @tx_sg: Scatterlist for transmit, currently not for client use
|
||||
* @rx_sg: Scatterlist for receive, currently not for client use
|
||||
@@ -794,6 +797,8 @@ struct spi_transfer {
|
||||
u16 delay_usecs;
|
||||
u32 speed_hz;
|
||||
|
||||
+ u32 effective_speed_hz;
|
||||
+
|
||||
struct list_head transfer_list;
|
||||
};
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,183 @@
|
||||
From edc0e47f43d73d9164c69688932d989971738b20 Mon Sep 17 00:00:00 2001
|
||||
From: Lukas Wunner <lukas@wunner.de>
|
||||
Date: Wed, 11 Nov 2020 20:07:10 +0100
|
||||
Subject: [PATCH 102/109] spi: Introduce device-managed SPI controller
|
||||
allocation
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.10-rc5
|
||||
commit 5e844cc37a5cbaa460e68f9a989d321d63088a89
|
||||
category: feature
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5e844cc37a5cbaa460e68f9a989d321d63088a89
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
SPI driver probing currently comprises two steps, whereas removal
|
||||
comprises only one step:
|
||||
|
||||
spi_alloc_master()
|
||||
spi_register_controller()
|
||||
|
||||
spi_unregister_controller()
|
||||
|
||||
That's because spi_unregister_controller() calls device_unregister()
|
||||
instead of device_del(), thereby releasing the reference on the
|
||||
spi_controller which was obtained by spi_alloc_master().
|
||||
|
||||
An SPI driver's private data is contained in the same memory allocation
|
||||
as the spi_controller struct. Thus, once spi_unregister_controller()
|
||||
has been called, the private data is inaccessible. But some drivers
|
||||
need to access it after spi_unregister_controller() to perform further
|
||||
teardown steps.
|
||||
|
||||
Introduce devm_spi_alloc_master() and devm_spi_alloc_slave(), which
|
||||
release a reference on the spi_controller struct only after the driver
|
||||
has unbound, thereby keeping the memory allocation accessible. Change
|
||||
spi_unregister_controller() to not release a reference if the
|
||||
spi_controller was allocated by one of these new devm functions.
|
||||
|
||||
The present commit is small enough to be backportable to stable.
|
||||
It allows fixing drivers which use the private data in their ->remove()
|
||||
hook after it's been freed. It also allows fixing drivers which neglect
|
||||
to release a reference on the spi_controller in the probe error path.
|
||||
|
||||
Long-term, most SPI drivers shall be moved over to the devm functions
|
||||
introduced herein. The few that can't shall be changed in a treewide
|
||||
commit to explicitly release the last reference on the controller.
|
||||
That commit shall amend spi_unregister_controller() to no longer release
|
||||
a reference, thereby completing the migration.
|
||||
|
||||
As a result, the behaviour will be less surprising and more consistent
|
||||
with subsystems such as IIO, which also includes the private data in the
|
||||
allocation of the generic iio_dev struct, but calls device_del() in
|
||||
iio_device_unregister().
|
||||
|
||||
Signed-off-by: Lukas Wunner <lukas@wunner.de>
|
||||
Link: https://lore.kernel.org/r/272bae2ef08abd21388c98e23729886663d19192.1605121038.git.lukas@wunner.de
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
|
||||
Conflicts:
|
||||
drivers/spi/spi.c
|
||||
---
|
||||
drivers/spi/spi.c | 58 ++++++++++++++++++++++++++++++++++++++++-
|
||||
include/linux/spi/spi.h | 19 ++++++++++++++
|
||||
2 files changed, 76 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
||||
index c79bf015b4b2..aa50cc5380cf 100644
|
||||
--- a/drivers/spi/spi.c
|
||||
+++ b/drivers/spi/spi.c
|
||||
@@ -2051,6 +2051,49 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__spi_alloc_controller);
|
||||
|
||||
+static void devm_spi_release_controller(struct device *dev, void *ctlr)
|
||||
+{
|
||||
+ spi_controller_put(*(struct spi_controller **)ctlr);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __devm_spi_alloc_controller - resource-managed __spi_alloc_controller()
|
||||
+ * @dev: physical device of SPI controller
|
||||
+ * @size: how much zeroed driver-private data to allocate
|
||||
+ * @slave: whether to allocate an SPI master (false) or SPI slave (true)
|
||||
+ * Context: can sleep
|
||||
+ *
|
||||
+ * Allocate an SPI controller and automatically release a reference on it
|
||||
+ * when @dev is unbound from its driver. Drivers are thus relieved from
|
||||
+ * having to call spi_controller_put().
|
||||
+ *
|
||||
+ * The arguments to this function are identical to __spi_alloc_controller().
|
||||
+ *
|
||||
+ * Return: the SPI controller structure on success, else NULL.
|
||||
+ */
|
||||
+struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
|
||||
+ unsigned int size,
|
||||
+ bool slave)
|
||||
+{
|
||||
+ struct spi_controller **ptr, *ctlr;
|
||||
+
|
||||
+ ptr = devres_alloc(devm_spi_release_controller, sizeof(*ptr),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ptr)
|
||||
+ return NULL;
|
||||
+
|
||||
+ ctlr = __spi_alloc_controller(dev, size, slave);
|
||||
+ if (ctlr) {
|
||||
+ *ptr = ctlr;
|
||||
+ devres_add(dev, ptr);
|
||||
+ } else {
|
||||
+ devres_free(ptr);
|
||||
+ }
|
||||
+
|
||||
+ return ctlr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller);
|
||||
+
|
||||
static int __spi_register_controller(struct spi_controller *ctlr)
|
||||
{
|
||||
int nb, i, *cs;
|
||||
@@ -2301,6 +2344,11 @@ int devm_spi_register_controller(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
|
||||
|
||||
+static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr)
|
||||
+{
|
||||
+ return *(struct spi_controller **)res == ctlr;
|
||||
+}
|
||||
+
|
||||
static int __unregister(struct device *dev, void *null)
|
||||
{
|
||||
spi_unregister_device(to_spi_device(dev));
|
||||
@@ -2342,7 +2390,15 @@ void spi_unregister_controller(struct spi_controller *ctlr)
|
||||
list_del(&ctlr->list);
|
||||
mutex_unlock(&board_lock);
|
||||
|
||||
- device_unregister(&ctlr->dev);
|
||||
+ device_del(&ctlr->dev);
|
||||
+
|
||||
+ /* Release the last reference on the controller if its driver
|
||||
+ * has not yet been converted to devm_spi_alloc_master/slave().
|
||||
+ */
|
||||
+ if (!devres_find(ctlr->dev.parent, devm_spi_release_controller,
|
||||
+ devm_spi_match_controller, ctlr))
|
||||
+ put_device(&ctlr->dev);
|
||||
+
|
||||
/* free bus id */
|
||||
mutex_lock(&board_lock);
|
||||
if (found == ctlr)
|
||||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
|
||||
index ec795c5304f0..085c8e0e0864 100644
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -634,6 +634,25 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host,
|
||||
return __spi_alloc_controller(host, size, true);
|
||||
}
|
||||
|
||||
+struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
|
||||
+ unsigned int size,
|
||||
+ bool slave);
|
||||
+
|
||||
+static inline struct spi_controller *devm_spi_alloc_master(struct device *dev,
|
||||
+ unsigned int size)
|
||||
+{
|
||||
+ return __devm_spi_alloc_controller(dev, size, false);
|
||||
+}
|
||||
+
|
||||
+static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev,
|
||||
+ unsigned int size)
|
||||
+{
|
||||
+ if (!IS_ENABLED(CONFIG_SPI_SLAVE))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return __devm_spi_alloc_controller(dev, size, true);
|
||||
+}
|
||||
+
|
||||
extern int spi_register_controller(struct spi_controller *ctlr);
|
||||
extern int devm_spi_register_controller(struct device *dev,
|
||||
struct spi_controller *ctlr);
|
||||
--
|
||||
2.23.0
|
||||
|
||||
101
patches/0103-spi-Fix-use-after-free-with-devm_spi_alloc_.patch
Normal file
101
patches/0103-spi-Fix-use-after-free-with-devm_spi_alloc_.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From c52d8916b34838e6d6dcd72b7712e6aa28c8daf4 Mon Sep 17 00:00:00 2001
|
||||
From: "William A. Kennington III" <wak@google.com>
|
||||
Date: Wed, 7 Apr 2021 02:55:27 -0700
|
||||
Subject: [PATCH 103/109] spi: Fix use-after-free with devm_spi_alloc_*
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.13-rc1
|
||||
commit 794aaf01444d4e765e2b067cba01cc69c1c68ed9
|
||||
category: bugfix
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=794aaf01444d4e765e2b067cba01cc69c1c68ed9
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
We can't rely on the contents of the devres list during
|
||||
spi_unregister_controller(), as the list is already torn down at the
|
||||
time we perform devres_find() for devm_spi_release_controller. This
|
||||
causes devices registered with devm_spi_alloc_{master,slave}() to be
|
||||
mistakenly identified as legacy, non-devm managed devices and have their
|
||||
reference counters decremented below 0.
|
||||
|
||||
------------[ cut here ]------------
|
||||
WARNING: CPU: 1 PID: 660 at lib/refcount.c:28 refcount_warn_saturate+0x108/0x174
|
||||
[<b0396f04>] (refcount_warn_saturate) from [<b03c56a4>] (kobject_put+0x90/0x98)
|
||||
[<b03c5614>] (kobject_put) from [<b0447b4c>] (put_device+0x20/0x24)
|
||||
r4:b6700140
|
||||
[<b0447b2c>] (put_device) from [<b07515e8>] (devm_spi_release_controller+0x3c/0x40)
|
||||
[<b07515ac>] (devm_spi_release_controller) from [<b045343c>] (release_nodes+0x84/0xc4)
|
||||
r5:b6700180 r4:b6700100
|
||||
[<b04533b8>] (release_nodes) from [<b0454160>] (devres_release_all+0x5c/0x60)
|
||||
r8:b1638c54 r7:b117ad94 r6:b1638c10 r5:b117ad94 r4:b163dc10
|
||||
[<b0454104>] (devres_release_all) from [<b044e41c>] (__device_release_driver+0x144/0x1ec)
|
||||
r5:b117ad94 r4:b163dc10
|
||||
[<b044e2d8>] (__device_release_driver) from [<b044f70c>] (device_driver_detach+0x84/0xa0)
|
||||
r9:00000000 r8:00000000 r7:b117ad94 r6:b163dc54 r5:b1638c10 r4:b163dc10
|
||||
[<b044f688>] (device_driver_detach) from [<b044d274>] (unbind_store+0xe4/0xf8)
|
||||
|
||||
Instead, determine the devm allocation state as a flag on the
|
||||
controller which is guaranteed to be stable during cleanup.
|
||||
|
||||
Fixes: 5e844cc37a5c ("spi: Introduce device-managed SPI controller allocation")
|
||||
Signed-off-by: William A. Kennington III <wak@google.com>
|
||||
Link: https://lore.kernel.org/r/20210407095527.2771582-1-wak@google.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Jiang Yi <jiangyi38@hisilicon.com>
|
||||
---
|
||||
drivers/spi/spi.c | 9 ++-------
|
||||
include/linux/spi/spi.h | 3 +++
|
||||
2 files changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
||||
index aa50cc5380cf..d2334bfae076 100644
|
||||
--- a/drivers/spi/spi.c
|
||||
+++ b/drivers/spi/spi.c
|
||||
@@ -2084,6 +2084,7 @@ struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
|
||||
|
||||
ctlr = __spi_alloc_controller(dev, size, slave);
|
||||
if (ctlr) {
|
||||
+ ctlr->devm_allocated = true;
|
||||
*ptr = ctlr;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
@@ -2344,11 +2345,6 @@ int devm_spi_register_controller(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
|
||||
|
||||
-static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr)
|
||||
-{
|
||||
- return *(struct spi_controller **)res == ctlr;
|
||||
-}
|
||||
-
|
||||
static int __unregister(struct device *dev, void *null)
|
||||
{
|
||||
spi_unregister_device(to_spi_device(dev));
|
||||
@@ -2395,8 +2391,7 @@ void spi_unregister_controller(struct spi_controller *ctlr)
|
||||
/* Release the last reference on the controller if its driver
|
||||
* has not yet been converted to devm_spi_alloc_master/slave().
|
||||
*/
|
||||
- if (!devres_find(ctlr->dev.parent, devm_spi_release_controller,
|
||||
- devm_spi_match_controller, ctlr))
|
||||
+ if (!ctlr->devm_allocated)
|
||||
put_device(&ctlr->dev);
|
||||
|
||||
/* free bus id */
|
||||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
|
||||
index 085c8e0e0864..3e51ae8bb26e 100644
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -450,6 +450,9 @@ struct spi_controller {
|
||||
|
||||
#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
|
||||
|
||||
+ /* flag indicating this is a non-devres managed controller */
|
||||
+ bool devm_allocated;
|
||||
+
|
||||
/* flag indicating this is an SPI slave controller */
|
||||
bool slave;
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
From 7c836f45222529e7ad99ae667b099ec747e87bd6 Mon Sep 17 00:00:00 2001
|
||||
From: Randy Dunlap <rdunlap@infradead.org>
|
||||
Date: Mon, 28 Jun 2021 14:05:20 -0700
|
||||
Subject: [PATCH 104/109] spi: <linux/spi/spi.h>: add missing struct kernel-doc
|
||||
entry
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.15-rc1
|
||||
commit 8dd591ad0104593f315b6b2ab636a18c002f7d86
|
||||
category: bugfix
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8dd591ad0104593f315b6b2ab636a18c002f7d86
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fix kernel-doc warning in spi.h by adding the missing kernel-doc entry
|
||||
and also correct the original comment so that they both indicate the
|
||||
correct polarity of the flag.
|
||||
|
||||
../include/linux/spi/spi.h:673: warning: Function parameter or member 'devm_allocated' not described in 'spi_controller'
|
||||
|
||||
Fixes: 794aaf01444d ("spi: Fix use-after-free with devm_spi_alloc_*")
|
||||
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
|
||||
Cc: William A. Kennington III <wak@google.com>
|
||||
Cc: Mark Brown <broonie@kernel.org>
|
||||
Cc: linux-spi@vger.kernel.org
|
||||
Cc: Lukas Wunner <lukas@wunner.de>
|
||||
Reviewed-by: Lukas Wunner <lukas@wunner.de>
|
||||
Link: https://lore.kernel.org/r/20210628210520.5712-1-rdunlap@infradead.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Signed-off-by: Jiang Yi <jiangyi38@hisilicon.com>
|
||||
---
|
||||
include/linux/spi/spi.h | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
|
||||
index 3e51ae8bb26e..1c0a0fa34586 100644
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -314,6 +314,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
||||
* @max_speed_hz: Highest supported transfer speed
|
||||
* @flags: other constraints relevant to this driver
|
||||
* @slave: indicates that this is an SPI slave controller
|
||||
+ * @devm_allocated: whether the allocation of this struct is devres-managed
|
||||
* @max_transfer_size: function that returns the max transfer size for
|
||||
* a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
|
||||
* @max_message_size: function that returns the max message size for
|
||||
@@ -450,7 +451,7 @@ struct spi_controller {
|
||||
|
||||
#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
|
||||
|
||||
- /* flag indicating this is a non-devres managed controller */
|
||||
+ /* flag indicating if the allocation of this struct is devres-managed */
|
||||
bool devm_allocated;
|
||||
|
||||
/* flag indicating this is an SPI slave controller */
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From 651036c4c9f6e429306275103b6546a61a8362f7 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Date: Fri, 23 Sep 2022 22:18:03 +0800
|
||||
Subject: [PATCH 105/109] Documentation: devres: add missing SPI helper
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v6.1-rc1
|
||||
commit 49beeea7ebdb1d86ba8465e5021d72ad9e9474b8
|
||||
category: bugfix
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=49beeea7ebdb1d86ba8465e5021d72ad9e9474b8
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Add devm_spi_alloc_master() and devm_spi_alloc_slave() to devres.rst.
|
||||
They are introduced by
|
||||
commit 5e844cc37a5c ("spi: Introduce device-managed SPI controller allocation").
|
||||
|
||||
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Reviewed-by: Lukas Wunner <lukas@wunner.de>
|
||||
Link: https://lore.kernel.org/r/20220923141803.75734-1-yangyingliang@huawei.com
|
||||
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
|
||||
|
||||
Conflicts:
|
||||
Documentation/driver-api/driver-model/devres.rst
|
||||
|
||||
Signed-off-by: Jiang Yi <jiangyi38@hisilicon.com>
|
||||
---
|
||||
Documentation/driver-model/devres.txt | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
|
||||
index 43681ca0837f..c9b019c06f3b 100644
|
||||
--- a/Documentation/driver-model/devres.txt
|
||||
+++ b/Documentation/driver-model/devres.txt
|
||||
@@ -392,6 +392,8 @@ SLAVE DMA ENGINE
|
||||
devm_acpi_dma_controller_register()
|
||||
|
||||
SPI
|
||||
+ devm_spi_alloc_master()
|
||||
+ devm_spi_alloc_slave()
|
||||
devm_spi_register_master()
|
||||
|
||||
WATCHDOG
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,606 @@
|
||||
From 7df3c74b37355c06afee870ace0a8eb1491130dc Mon Sep 17 00:00:00 2001
|
||||
From: Jay Fang <f.fangjian@huawei.com>
|
||||
Date: Mon, 9 Aug 2021 20:18:16 +0800
|
||||
Subject: [PATCH 106/109] spi: Add HiSilicon SPI Controller Driver for Kunpeng
|
||||
SoCs
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.13-rc1
|
||||
commit c770d8631e1810d8f1ce21b18ad5dd67eeb39e5c
|
||||
category: feature
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c770d8631e1810d8f1ce21b18ad5dd67eeb39e5c
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This driver supports SPI Controller for HiSilicon Kunpeng SoCs. This
|
||||
driver supports SPI operations using FIFO mode of transfer.
|
||||
|
||||
DMA is not supported, and we just use IRQ mode for operation completion
|
||||
notification.
|
||||
|
||||
Only ACPI firmware is supported.
|
||||
|
||||
Signed-off-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Link: https://lore.kernel.org/r/1616836200-45827-1-git-send-email-f.fangjian@huawei.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
|
||||
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
|
||||
Conflicts:
|
||||
MAINTAINERS
|
||||
drivers/spi/Kconfig
|
||||
drivers/spi/Makefile
|
||||
---
|
||||
MAINTAINERS | 7 +
|
||||
drivers/spi/Kconfig | 10 +
|
||||
drivers/spi/Makefile | 1 +
|
||||
drivers/spi/spi-hisi-kunpeng.c | 504 +++++++++++++++++++++++++++++++++
|
||||
4 files changed, 522 insertions(+)
|
||||
create mode 100644 drivers/spi/spi-hisi-kunpeng.c
|
||||
|
||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index 3ad1e1b1da4a..29d7531d0595 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -6679,6 +6679,13 @@ S: Maintained
|
||||
F: drivers/infiniband/hw/hns/Makefile
|
||||
F: drivers/infiniband/hw/hns/roce-customer/
|
||||
|
||||
+HISILICON SPI Controller DRIVER FOR KUNPENG SOCS
|
||||
+M: Jay Fang <f.fangjian@huawei.com>
|
||||
+L: linux-spi@vger.kernel.org
|
||||
+S: Maintained
|
||||
+W: http://www.hisilicon.com
|
||||
+F: drivers/spi/spi-hisi-kunpeng.c
|
||||
+
|
||||
HISILICON WARPDRIVE USER
|
||||
M: Zaibo Xu <xuzaibo@huawei.com>
|
||||
M: Zhou Wang <wangzhou1@hisilicon.com>
|
||||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
|
||||
index 0a7fd56c1ed9..7bfdf8d2cbf9 100644
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -251,6 +251,16 @@ config SPI_FSL_LPSPI
|
||||
help
|
||||
This enables Freescale i.MX LPSPI controllers in master mode.
|
||||
|
||||
+config SPI_HISI_KUNPENG
|
||||
+ tristate "HiSilicon SPI Controller for Kunpeng SoCs"
|
||||
+ depends on (ARM64 && ACPI) || COMPILE_TEST
|
||||
+ help
|
||||
+ This enables support for HiSilicon SPI controller found on
|
||||
+ Kunpeng SoCs.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module
|
||||
+ will be called hisi-kunpeng-spi.
|
||||
+
|
||||
config SPI_GPIO
|
||||
tristate "GPIO-based bitbanging SPI Master"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
|
||||
index a90d55970036..49c499d5e1a2 100644
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
|
||||
obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o
|
||||
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
|
||||
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
|
||||
+obj-$(CONFIG_SPI_HISI_KUNPENG) += spi-hisi-kunpeng.o
|
||||
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
|
||||
obj-$(CONFIG_SPI_IMX) += spi-imx.o
|
||||
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
|
||||
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
|
||||
new file mode 100644
|
||||
index 000000000000..ea87b4fba5d6
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi-hisi-kunpeng.c
|
||||
@@ -0,0 +1,504 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+//
|
||||
+// HiSilicon SPI Controller Driver for Kunpeng SoCs
|
||||
+//
|
||||
+// Copyright (c) 2021 HiSilicon Technologies Co., Ltd.
|
||||
+// Author: Jay Fang <f.fangjian@huawei.com>
|
||||
+//
|
||||
+// This code is based on spi-dw-core.c.
|
||||
+
|
||||
+#include <linux/acpi.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/property.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+
|
||||
+/* Register offsets */
|
||||
+#define HISI_SPI_CSCR 0x00 /* cs control register */
|
||||
+#define HISI_SPI_CR 0x04 /* spi common control register */
|
||||
+#define HISI_SPI_ENR 0x08 /* spi enable register */
|
||||
+#define HISI_SPI_FIFOC 0x0c /* fifo level control register */
|
||||
+#define HISI_SPI_IMR 0x10 /* interrupt mask register */
|
||||
+#define HISI_SPI_DIN 0x14 /* data in register */
|
||||
+#define HISI_SPI_DOUT 0x18 /* data out register */
|
||||
+#define HISI_SPI_SR 0x1c /* status register */
|
||||
+#define HISI_SPI_RISR 0x20 /* raw interrupt status register */
|
||||
+#define HISI_SPI_ISR 0x24 /* interrupt status register */
|
||||
+#define HISI_SPI_ICR 0x28 /* interrupt clear register */
|
||||
+#define HISI_SPI_VERSION 0xe0 /* version register */
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_CR */
|
||||
+#define CR_LOOP_MASK GENMASK(1, 1)
|
||||
+#define CR_CPOL_MASK GENMASK(2, 2)
|
||||
+#define CR_CPHA_MASK GENMASK(3, 3)
|
||||
+#define CR_DIV_PRE_MASK GENMASK(11, 4)
|
||||
+#define CR_DIV_POST_MASK GENMASK(19, 12)
|
||||
+#define CR_BPW_MASK GENMASK(24, 20)
|
||||
+#define CR_SPD_MODE_MASK GENMASK(25, 25)
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_FIFOC */
|
||||
+#define FIFOC_TX_MASK GENMASK(5, 3)
|
||||
+#define FIFOC_RX_MASK GENMASK(11, 9)
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_IMR, 4 bits */
|
||||
+#define IMR_RXOF BIT(0) /* Receive Overflow */
|
||||
+#define IMR_RXTO BIT(1) /* Receive Timeout */
|
||||
+#define IMR_RX BIT(2) /* Receive */
|
||||
+#define IMR_TX BIT(3) /* Transmit */
|
||||
+#define IMR_MASK (IMR_RXOF | IMR_RXTO | IMR_RX | IMR_TX)
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_SR, 5 bits */
|
||||
+#define SR_TXE BIT(0) /* Transmit FIFO empty */
|
||||
+#define SR_TXNF BIT(1) /* Transmit FIFO not full */
|
||||
+#define SR_RXNE BIT(2) /* Receive FIFO not empty */
|
||||
+#define SR_RXF BIT(3) /* Receive FIFO full */
|
||||
+#define SR_BUSY BIT(4) /* Busy Flag */
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_ISR, 4 bits */
|
||||
+#define ISR_RXOF BIT(0) /* Receive Overflow */
|
||||
+#define ISR_RXTO BIT(1) /* Receive Timeout */
|
||||
+#define ISR_RX BIT(2) /* Receive */
|
||||
+#define ISR_TX BIT(3) /* Transmit */
|
||||
+#define ISR_MASK (ISR_RXOF | ISR_RXTO | ISR_RX | ISR_TX)
|
||||
+
|
||||
+/* Bit fields in HISI_SPI_ICR, 2 bits */
|
||||
+#define ICR_RXOF BIT(0) /* Receive Overflow */
|
||||
+#define ICR_RXTO BIT(1) /* Receive Timeout */
|
||||
+#define ICR_MASK (ICR_RXOF | ICR_RXTO)
|
||||
+
|
||||
+#define DIV_POST_MAX 0xFF
|
||||
+#define DIV_POST_MIN 0x00
|
||||
+#define DIV_PRE_MAX 0xFE
|
||||
+#define DIV_PRE_MIN 0x02
|
||||
+#define CLK_DIV_MAX ((1 + DIV_POST_MAX) * DIV_PRE_MAX)
|
||||
+#define CLK_DIV_MIN ((1 + DIV_POST_MIN) * DIV_PRE_MIN)
|
||||
+
|
||||
+#define DEFAULT_NUM_CS 1
|
||||
+
|
||||
+#define HISI_SPI_WAIT_TIMEOUT_MS 10UL
|
||||
+
|
||||
+enum hisi_spi_rx_level_trig {
|
||||
+ HISI_SPI_RX_1,
|
||||
+ HISI_SPI_RX_4,
|
||||
+ HISI_SPI_RX_8,
|
||||
+ HISI_SPI_RX_16,
|
||||
+ HISI_SPI_RX_32,
|
||||
+ HISI_SPI_RX_64,
|
||||
+ HISI_SPI_RX_128
|
||||
+};
|
||||
+
|
||||
+enum hisi_spi_tx_level_trig {
|
||||
+ HISI_SPI_TX_1_OR_LESS,
|
||||
+ HISI_SPI_TX_4_OR_LESS,
|
||||
+ HISI_SPI_TX_8_OR_LESS,
|
||||
+ HISI_SPI_TX_16_OR_LESS,
|
||||
+ HISI_SPI_TX_32_OR_LESS,
|
||||
+ HISI_SPI_TX_64_OR_LESS,
|
||||
+ HISI_SPI_TX_128_OR_LESS
|
||||
+};
|
||||
+
|
||||
+enum hisi_spi_frame_n_bytes {
|
||||
+ HISI_SPI_N_BYTES_NULL,
|
||||
+ HISI_SPI_N_BYTES_U8,
|
||||
+ HISI_SPI_N_BYTES_U16,
|
||||
+ HISI_SPI_N_BYTES_U32 = 4
|
||||
+};
|
||||
+
|
||||
+/* Slave spi_dev related */
|
||||
+struct hisi_chip_data {
|
||||
+ u32 cr;
|
||||
+ u32 speed_hz; /* baud rate */
|
||||
+ u16 clk_div; /* baud rate divider */
|
||||
+
|
||||
+ /* clk_div = (1 + div_post) * div_pre */
|
||||
+ u8 div_post; /* value from 0 to 255 */
|
||||
+ u8 div_pre; /* value from 2 to 254 (even only!) */
|
||||
+};
|
||||
+
|
||||
+struct hisi_spi {
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ void __iomem *regs;
|
||||
+ int irq;
|
||||
+ u32 fifo_len; /* depth of the FIFO buffer */
|
||||
+
|
||||
+ /* Current message transfer state info */
|
||||
+ const void *tx;
|
||||
+ unsigned int tx_len;
|
||||
+ void *rx;
|
||||
+ unsigned int rx_len;
|
||||
+ u8 n_bytes; /* current is a 1/2/4 bytes op */
|
||||
+};
|
||||
+
|
||||
+static u32 hisi_spi_busy(struct hisi_spi *hs)
|
||||
+{
|
||||
+ return readl(hs->regs + HISI_SPI_SR) & SR_BUSY;
|
||||
+}
|
||||
+
|
||||
+static u32 hisi_spi_rx_not_empty(struct hisi_spi *hs)
|
||||
+{
|
||||
+ return readl(hs->regs + HISI_SPI_SR) & SR_RXNE;
|
||||
+}
|
||||
+
|
||||
+static u32 hisi_spi_tx_not_full(struct hisi_spi *hs)
|
||||
+{
|
||||
+ return readl(hs->regs + HISI_SPI_SR) & SR_TXNF;
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_flush_fifo(struct hisi_spi *hs)
|
||||
+{
|
||||
+ unsigned long limit = loops_per_jiffy << 1;
|
||||
+
|
||||
+ do {
|
||||
+ while (hisi_spi_rx_not_empty(hs))
|
||||
+ readl(hs->regs + HISI_SPI_DOUT);
|
||||
+ } while (hisi_spi_busy(hs) && limit--);
|
||||
+}
|
||||
+
|
||||
+/* Disable the controller and all interrupts */
|
||||
+static void hisi_spi_disable(struct hisi_spi *hs)
|
||||
+{
|
||||
+ writel(0, hs->regs + HISI_SPI_ENR);
|
||||
+ writel(IMR_MASK, hs->regs + HISI_SPI_IMR);
|
||||
+ writel(ICR_MASK, hs->regs + HISI_SPI_ICR);
|
||||
+}
|
||||
+
|
||||
+static u8 hisi_spi_n_bytes(struct spi_transfer *transfer)
|
||||
+{
|
||||
+ if (transfer->bits_per_word <= 8)
|
||||
+ return HISI_SPI_N_BYTES_U8;
|
||||
+ else if (transfer->bits_per_word <= 16)
|
||||
+ return HISI_SPI_N_BYTES_U16;
|
||||
+ else
|
||||
+ return HISI_SPI_N_BYTES_U32;
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_reader(struct hisi_spi *hs)
|
||||
+{
|
||||
+ u32 max = min_t(u32, hs->rx_len, hs->fifo_len);
|
||||
+ u32 rxw;
|
||||
+
|
||||
+ while (hisi_spi_rx_not_empty(hs) && max--) {
|
||||
+ rxw = readl(hs->regs + HISI_SPI_DOUT);
|
||||
+ /* Check the transfer's original "rx" is not null */
|
||||
+ if (hs->rx) {
|
||||
+ switch (hs->n_bytes) {
|
||||
+ case HISI_SPI_N_BYTES_U8:
|
||||
+ *(u8 *)(hs->rx) = rxw;
|
||||
+ break;
|
||||
+ case HISI_SPI_N_BYTES_U16:
|
||||
+ *(u16 *)(hs->rx) = rxw;
|
||||
+ break;
|
||||
+ case HISI_SPI_N_BYTES_U32:
|
||||
+ *(u32 *)(hs->rx) = rxw;
|
||||
+ break;
|
||||
+ }
|
||||
+ hs->rx += hs->n_bytes;
|
||||
+ }
|
||||
+ --hs->rx_len;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_writer(struct hisi_spi *hs)
|
||||
+{
|
||||
+ u32 max = min_t(u32, hs->tx_len, hs->fifo_len);
|
||||
+ u32 txw = 0;
|
||||
+
|
||||
+ while (hisi_spi_tx_not_full(hs) && max--) {
|
||||
+ /* Check the transfer's original "tx" is not null */
|
||||
+ if (hs->tx) {
|
||||
+ switch (hs->n_bytes) {
|
||||
+ case HISI_SPI_N_BYTES_U8:
|
||||
+ txw = *(u8 *)(hs->tx);
|
||||
+ break;
|
||||
+ case HISI_SPI_N_BYTES_U16:
|
||||
+ txw = *(u16 *)(hs->tx);
|
||||
+ break;
|
||||
+ case HISI_SPI_N_BYTES_U32:
|
||||
+ txw = *(u32 *)(hs->tx);
|
||||
+ break;
|
||||
+ }
|
||||
+ hs->tx += hs->n_bytes;
|
||||
+ }
|
||||
+ writel(txw, hs->regs + HISI_SPI_DIN);
|
||||
+ --hs->tx_len;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __hisi_calc_div_reg(struct hisi_chip_data *chip)
|
||||
+{
|
||||
+ chip->div_pre = DIV_PRE_MAX;
|
||||
+ while (chip->div_pre >= DIV_PRE_MIN) {
|
||||
+ if (chip->clk_div % chip->div_pre == 0)
|
||||
+ break;
|
||||
+
|
||||
+ chip->div_pre -= 2;
|
||||
+ }
|
||||
+
|
||||
+ if (chip->div_pre > chip->clk_div)
|
||||
+ chip->div_pre = chip->clk_div;
|
||||
+
|
||||
+ chip->div_post = (chip->clk_div / chip->div_pre) - 1;
|
||||
+}
|
||||
+
|
||||
+static u32 hisi_calc_effective_speed(struct spi_controller *master,
|
||||
+ struct hisi_chip_data *chip, u32 speed_hz)
|
||||
+{
|
||||
+ u32 effective_speed;
|
||||
+
|
||||
+ /* Note clock divider doesn't support odd numbers */
|
||||
+ chip->clk_div = DIV_ROUND_UP(master->max_speed_hz, speed_hz) + 1;
|
||||
+ chip->clk_div &= 0xfffe;
|
||||
+ if (chip->clk_div > CLK_DIV_MAX)
|
||||
+ chip->clk_div = CLK_DIV_MAX;
|
||||
+
|
||||
+ effective_speed = master->max_speed_hz / chip->clk_div;
|
||||
+ if (chip->speed_hz != effective_speed) {
|
||||
+ __hisi_calc_div_reg(chip);
|
||||
+ chip->speed_hz = effective_speed;
|
||||
+ }
|
||||
+
|
||||
+ return effective_speed;
|
||||
+}
|
||||
+
|
||||
+static u32 hisi_spi_prepare_cr(struct spi_device *spi)
|
||||
+{
|
||||
+ u32 cr = FIELD_PREP(CR_SPD_MODE_MASK, 1);
|
||||
+
|
||||
+ cr |= FIELD_PREP(CR_CPHA_MASK, (spi->mode & SPI_CPHA) ? 1 : 0);
|
||||
+ cr |= FIELD_PREP(CR_CPOL_MASK, (spi->mode & SPI_CPOL) ? 1 : 0);
|
||||
+ cr |= FIELD_PREP(CR_LOOP_MASK, (spi->mode & SPI_LOOP) ? 1 : 0);
|
||||
+
|
||||
+ return cr;
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_hw_init(struct hisi_spi *hs)
|
||||
+{
|
||||
+ hisi_spi_disable(hs);
|
||||
+
|
||||
+ /* FIFO default config */
|
||||
+ writel(FIELD_PREP(FIFOC_TX_MASK, HISI_SPI_TX_64_OR_LESS) |
|
||||
+ FIELD_PREP(FIFOC_RX_MASK, HISI_SPI_RX_16),
|
||||
+ hs->regs + HISI_SPI_FIFOC);
|
||||
+
|
||||
+ hs->fifo_len = 256;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t hisi_spi_irq(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct spi_controller *master = dev_id;
|
||||
+ struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
+ u32 irq_status = readl(hs->regs + HISI_SPI_ISR) & ISR_MASK;
|
||||
+
|
||||
+ if (!irq_status)
|
||||
+ return IRQ_NONE;
|
||||
+
|
||||
+ if (!master->cur_msg)
|
||||
+ return IRQ_HANDLED;
|
||||
+
|
||||
+ /* Error handling */
|
||||
+ if (irq_status & ISR_RXOF) {
|
||||
+ dev_err(hs->dev, "interrupt_transfer: fifo overflow\n");
|
||||
+ master->cur_msg->status = -EIO;
|
||||
+ goto finalize_transfer;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Read data from the Rx FIFO every time. If there is
|
||||
+ * nothing left to receive, finalize the transfer.
|
||||
+ */
|
||||
+ hisi_spi_reader(hs);
|
||||
+ if (!hs->rx_len)
|
||||
+ goto finalize_transfer;
|
||||
+
|
||||
+ /* Send data out when Tx FIFO IRQ triggered */
|
||||
+ if (irq_status & ISR_TX)
|
||||
+ hisi_spi_writer(hs);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+
|
||||
+finalize_transfer:
|
||||
+ hisi_spi_disable(hs);
|
||||
+ spi_finalize_current_transfer(master);
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int hisi_spi_transfer_one(struct spi_controller *master,
|
||||
+ struct spi_device *spi, struct spi_transfer *transfer)
|
||||
+{
|
||||
+ struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
+ struct hisi_chip_data *chip = spi_get_ctldata(spi);
|
||||
+ u32 cr = chip->cr;
|
||||
+
|
||||
+ /* Update per transfer options for speed and bpw */
|
||||
+ transfer->effective_speed_hz =
|
||||
+ hisi_calc_effective_speed(master, chip, transfer->speed_hz);
|
||||
+ cr |= FIELD_PREP(CR_DIV_PRE_MASK, chip->div_pre);
|
||||
+ cr |= FIELD_PREP(CR_DIV_POST_MASK, chip->div_post);
|
||||
+ cr |= FIELD_PREP(CR_BPW_MASK, transfer->bits_per_word - 1);
|
||||
+ writel(cr, hs->regs + HISI_SPI_CR);
|
||||
+
|
||||
+ hisi_spi_flush_fifo(hs);
|
||||
+
|
||||
+ hs->n_bytes = hisi_spi_n_bytes(transfer);
|
||||
+ hs->tx = transfer->tx_buf;
|
||||
+ hs->tx_len = transfer->len / hs->n_bytes;
|
||||
+ hs->rx = transfer->rx_buf;
|
||||
+ hs->rx_len = hs->tx_len;
|
||||
+
|
||||
+ /*
|
||||
+ * Ensure that the transfer data above has been updated
|
||||
+ * before the interrupt to start.
|
||||
+ */
|
||||
+ smp_mb();
|
||||
+
|
||||
+ /* Enable all interrupts and the controller */
|
||||
+ writel(~IMR_MASK, hs->regs + HISI_SPI_IMR);
|
||||
+ writel(1, hs->regs + HISI_SPI_ENR);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_handle_err(struct spi_controller *master,
|
||||
+ struct spi_message *msg)
|
||||
+{
|
||||
+ struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
+
|
||||
+ hisi_spi_disable(hs);
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for interrupt handler that is
|
||||
+ * already in timeout to complete.
|
||||
+ */
|
||||
+ msleep(HISI_SPI_WAIT_TIMEOUT_MS);
|
||||
+}
|
||||
+
|
||||
+static int hisi_spi_setup(struct spi_device *spi)
|
||||
+{
|
||||
+ struct hisi_chip_data *chip;
|
||||
+
|
||||
+ /* Only alloc on first setup */
|
||||
+ chip = spi_get_ctldata(spi);
|
||||
+ if (!chip) {
|
||||
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
+ if (!chip)
|
||||
+ return -ENOMEM;
|
||||
+ spi_set_ctldata(spi, chip);
|
||||
+ }
|
||||
+
|
||||
+ chip->cr = hisi_spi_prepare_cr(spi);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void hisi_spi_cleanup(struct spi_device *spi)
|
||||
+{
|
||||
+ struct hisi_chip_data *chip = spi_get_ctldata(spi);
|
||||
+
|
||||
+ kfree(chip);
|
||||
+ spi_set_ctldata(spi, NULL);
|
||||
+}
|
||||
+
|
||||
+static int hisi_spi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct spi_controller *master;
|
||||
+ struct hisi_spi *hs;
|
||||
+ int ret, irq;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ master = devm_spi_alloc_master(dev, sizeof(*hs));
|
||||
+ if (!master)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, master);
|
||||
+
|
||||
+ hs = spi_controller_get_devdata(master);
|
||||
+ hs->dev = dev;
|
||||
+ hs->irq = irq;
|
||||
+
|
||||
+ hs->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(hs->regs))
|
||||
+ return PTR_ERR(hs->regs);
|
||||
+
|
||||
+ /* Specify maximum SPI clocking speed (master only) by firmware */
|
||||
+ ret = device_property_read_u32(dev, "spi-max-frequency",
|
||||
+ &master->max_speed_hz);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to get max SPI clocking speed, ret=%d\n",
|
||||
+ ret);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = device_property_read_u16(dev, "num-cs",
|
||||
+ &master->num_chipselect);
|
||||
+ if (ret)
|
||||
+ master->num_chipselect = DEFAULT_NUM_CS;
|
||||
+
|
||||
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
||||
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
+ master->bus_num = pdev->id;
|
||||
+ master->setup = hisi_spi_setup;
|
||||
+ master->cleanup = hisi_spi_cleanup;
|
||||
+ master->transfer_one = hisi_spi_transfer_one;
|
||||
+ master->handle_err = hisi_spi_handle_err;
|
||||
+ master->dev.fwnode = dev->fwnode;
|
||||
+
|
||||
+ hisi_spi_hw_init(hs);
|
||||
+
|
||||
+ ret = devm_request_irq(dev, hs->irq, hisi_spi_irq, 0, dev_name(dev),
|
||||
+ master);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "failed to get IRQ=%d, ret=%d\n", hs->irq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = spi_register_controller(master);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to register spi master, ret=%d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(dev, "hw version:0x%x max-freq:%u kHz\n",
|
||||
+ readl(hs->regs + HISI_SPI_VERSION),
|
||||
+ master->max_speed_hz / 1000);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int hisi_spi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct spi_controller *master = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ spi_unregister_controller(master);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct acpi_device_id hisi_spi_acpi_match[] = {
|
||||
+ {"HISI03E1", 0},
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(acpi, hisi_spi_acpi_match);
|
||||
+
|
||||
+static struct platform_driver hisi_spi_driver = {
|
||||
+ .probe = hisi_spi_probe,
|
||||
+ .remove = hisi_spi_remove,
|
||||
+ .driver = {
|
||||
+ .name = "hisi-kunpeng-spi",
|
||||
+ .acpi_match_table = hisi_spi_acpi_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(hisi_spi_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Jay Fang <f.fangjian@huawei.com>");
|
||||
+MODULE_DESCRIPTION("HiSilicon SPI Controller Driver for Kunpeng SoCs");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From 95f7eaa29a23fb4d0a47962a43f6d72db89b03a7 Mon Sep 17 00:00:00 2001
|
||||
From: Jay Fang <f.fangjian@huawei.com>
|
||||
Date: Mon, 9 Aug 2021 20:18:17 +0800
|
||||
Subject: [PATCH 107/109] spi: hisi-kunpeng: Fix Woverflow warning on
|
||||
conversion
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.13-rc1
|
||||
commit 9a446cf97af70ee81ba177703b67ac4955a5edcc
|
||||
category: bugfix
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9a446cf97af70ee81ba177703b67ac4955a5edcc
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fix warning Woverflow on type conversion reported on x86_64:
|
||||
|
||||
drivers/spi/spi-hisi-kunpeng.c:361:9: warning: conversion from 'long unsigned int' to 'u32'
|
||||
{aka 'unsigned int'} changes value from '18446744073709551600' to '4294967280' [-Woverflow]
|
||||
|
||||
The registers are 32 bit, so fix by casting to u32.
|
||||
|
||||
Fixes: c770d8631e18 ("spi: Add HiSilicon SPI Controller Driver for Kunpeng SoCs")
|
||||
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
|
||||
Reported-by: kernel test robot <lkp@intel.com>
|
||||
Signed-off-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Link: https://lore.kernel.org/r/1617762660-54681-1-git-send-email-f.fangjian@huawei.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
|
||||
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
---
|
||||
drivers/spi/spi-hisi-kunpeng.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
|
||||
index ea87b4fba5d6..c0db9b5e37ea 100644
|
||||
--- a/drivers/spi/spi-hisi-kunpeng.c
|
||||
+++ b/drivers/spi/spi-hisi-kunpeng.c
|
||||
@@ -358,7 +358,7 @@ static int hisi_spi_transfer_one(struct spi_controller *master,
|
||||
smp_mb();
|
||||
|
||||
/* Enable all interrupts and the controller */
|
||||
- writel(~IMR_MASK, hs->regs + HISI_SPI_IMR);
|
||||
+ writel(~(u32)IMR_MASK, hs->regs + HISI_SPI_IMR);
|
||||
writel(1, hs->regs + HISI_SPI_ENR);
|
||||
|
||||
return 1;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
142
patches/0108-spi-hisi-kunpeng-Add-debugfs-support.patch
Normal file
142
patches/0108-spi-hisi-kunpeng-Add-debugfs-support.patch
Normal file
@ -0,0 +1,142 @@
|
||||
From 595343f586ead33c62480e1369d1ba3f22f908a0 Mon Sep 17 00:00:00 2001
|
||||
From: Jay Fang <f.fangjian@huawei.com>
|
||||
Date: Tue, 19 Apr 2022 17:06:40 +0800
|
||||
Subject: [PATCH 108/109] spi: hisi-kunpeng: Add debugfs support
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.14-rc1
|
||||
commit 2b2142f247ebeef74aaadc1a646261c19627fd7e
|
||||
category: feature
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2b2142f247ebeef74aaadc1a646261c19627fd7e
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
This patch uses debugfs_regset32 interface to create the registers dump
|
||||
file. Use it instead of creating a generic debugfs file with manually
|
||||
written read callback function.
|
||||
|
||||
With these entries, users can check all the SPI controller registers
|
||||
during run time.
|
||||
|
||||
Signed-off-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Link: https://lore.kernel.org/r/1622789718-13977-1-git-send-email-f.fangjian@huawei.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Reviewed-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Acked-by: Xie XiuQi <xiexiuqi@huawei.com>
|
||||
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
---
|
||||
drivers/spi/spi-hisi-kunpeng.c | 51 +++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 50 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
|
||||
index c0db9b5e37ea..4595044a530b 100644
|
||||
--- a/drivers/spi/spi-hisi-kunpeng.c
|
||||
+++ b/drivers/spi/spi-hisi-kunpeng.c
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitfield.h>
|
||||
+#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -126,6 +127,7 @@ struct hisi_spi {
|
||||
void __iomem *regs;
|
||||
int irq;
|
||||
u32 fifo_len; /* depth of the FIFO buffer */
|
||||
+ u16 bus_num;
|
||||
|
||||
/* Current message transfer state info */
|
||||
const void *tx;
|
||||
@@ -133,8 +135,49 @@ struct hisi_spi {
|
||||
void *rx;
|
||||
unsigned int rx_len;
|
||||
u8 n_bytes; /* current is a 1/2/4 bytes op */
|
||||
+
|
||||
+ struct dentry *debugfs;
|
||||
+ struct debugfs_regset32 regset;
|
||||
+};
|
||||
+
|
||||
+#define HISI_SPI_DBGFS_REG(_name, _off) \
|
||||
+{ \
|
||||
+ .name = _name, \
|
||||
+ .offset = _off, \
|
||||
+}
|
||||
+
|
||||
+static const struct debugfs_reg32 hisi_spi_regs[] = {
|
||||
+ HISI_SPI_DBGFS_REG("CSCR", HISI_SPI_CSCR),
|
||||
+ HISI_SPI_DBGFS_REG("CR", HISI_SPI_CR),
|
||||
+ HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
|
||||
+ HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
|
||||
+ HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
|
||||
+ HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN),
|
||||
+ HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT),
|
||||
+ HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
|
||||
+ HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
|
||||
+ HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
|
||||
+ HISI_SPI_DBGFS_REG("ICR", HISI_SPI_ICR),
|
||||
+ HISI_SPI_DBGFS_REG("VERSION", HISI_SPI_VERSION),
|
||||
};
|
||||
|
||||
+static int hisi_spi_debugfs_init(struct hisi_spi *hs)
|
||||
+{
|
||||
+ char name[32];
|
||||
+
|
||||
+ snprintf(name, 32, "hisi_spi%d", hs->bus_num);
|
||||
+ hs->debugfs = debugfs_create_dir(name, NULL);
|
||||
+ if (!hs->debugfs)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ hs->regset.regs = hisi_spi_regs;
|
||||
+ hs->regset.nregs = ARRAY_SIZE(hisi_spi_regs);
|
||||
+ hs->regset.base = hs->regs;
|
||||
+ debugfs_create_regset32("registers", 0400, hs->debugfs, &hs->regset);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static u32 hisi_spi_busy(struct hisi_spi *hs)
|
||||
{
|
||||
return readl(hs->regs + HISI_SPI_SR) & SR_BUSY;
|
||||
@@ -424,6 +467,7 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
hs = spi_controller_get_devdata(master);
|
||||
hs->dev = dev;
|
||||
hs->irq = irq;
|
||||
+ hs->bus_num = pdev->id;
|
||||
|
||||
hs->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hs->regs))
|
||||
@@ -445,7 +489,7 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
- master->bus_num = pdev->id;
|
||||
+ master->bus_num = hs->bus_num;
|
||||
master->setup = hisi_spi_setup;
|
||||
master->cleanup = hisi_spi_cleanup;
|
||||
master->transfer_one = hisi_spi_transfer_one;
|
||||
@@ -461,6 +505,9 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ if (hisi_spi_debugfs_init(hs))
|
||||
+ dev_info(dev, "failed to create debugfs dir\n");
|
||||
+
|
||||
ret = spi_register_controller(master);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register spi master, ret=%d\n", ret);
|
||||
@@ -477,7 +524,9 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
static int hisi_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *master = platform_get_drvdata(pdev);
|
||||
+ struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
|
||||
+ debugfs_remove_recursive(hs->debugfs);
|
||||
spi_unregister_controller(master);
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
From 12c5d4361e40e06999e4e0e9865fc61052841424 Mon Sep 17 00:00:00 2001
|
||||
From: oujiefeng <oujiefeng@huawei.com>
|
||||
Date: Tue, 19 Apr 2022 17:06:41 +0800
|
||||
Subject: [PATCH 109/109] spi: hisi-kunpeng: Fix the debugfs directory name
|
||||
incorrect
|
||||
|
||||
mainline inclusion
|
||||
from mainline-v5.17-rc1
|
||||
commit 40fafc8eca3f0d41b9dade5c10afb2dad723aad7
|
||||
category: bugfix
|
||||
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8DDF5
|
||||
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=40fafc8eca3f0d41b9dade5c10afb2dad723aad7
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Change the debugfs directory name from hisi_spi65535 to hisi_spi0.
|
||||
|
||||
Fixes: 2b2142f247eb ("spi: hisi-kunpeng: Add debugfs support")
|
||||
Signed-off-by: oujiefeng <oujiefeng@huawei.com>
|
||||
Signed-off-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Link: https://lore.kernel.org/r/20211117012119.55558-1-f.fangjian@huawei.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
Reviewed-by: Jay Fang <f.fangjian@huawei.com>
|
||||
Acked-by: Xie XiuQi <xiexiuqi@huawei.com>
|
||||
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
||||
Signed-off-by: YunYi Yang <yangyunyi2@huawei.com>
|
||||
---
|
||||
drivers/spi/spi-hisi-kunpeng.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
|
||||
index 4595044a530b..9832faadb324 100644
|
||||
--- a/drivers/spi/spi-hisi-kunpeng.c
|
||||
+++ b/drivers/spi/spi-hisi-kunpeng.c
|
||||
@@ -127,7 +127,6 @@ struct hisi_spi {
|
||||
void __iomem *regs;
|
||||
int irq;
|
||||
u32 fifo_len; /* depth of the FIFO buffer */
|
||||
- u16 bus_num;
|
||||
|
||||
/* Current message transfer state info */
|
||||
const void *tx;
|
||||
@@ -165,7 +164,10 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs)
|
||||
{
|
||||
char name[32];
|
||||
|
||||
- snprintf(name, 32, "hisi_spi%d", hs->bus_num);
|
||||
+ struct spi_controller *master;
|
||||
+
|
||||
+ master = container_of(hs->dev, struct spi_controller, dev);
|
||||
+ snprintf(name, 32, "hisi_spi%d", master->bus_num);
|
||||
hs->debugfs = debugfs_create_dir(name, NULL);
|
||||
if (!hs->debugfs)
|
||||
return -ENOMEM;
|
||||
@@ -467,7 +469,6 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
hs = spi_controller_get_devdata(master);
|
||||
hs->dev = dev;
|
||||
hs->irq = irq;
|
||||
- hs->bus_num = pdev->id;
|
||||
|
||||
hs->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hs->regs))
|
||||
@@ -489,7 +490,7 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
- master->bus_num = hs->bus_num;
|
||||
+ master->bus_num = pdev->id;
|
||||
master->setup = hisi_spi_setup;
|
||||
master->cleanup = hisi_spi_cleanup;
|
||||
master->transfer_one = hisi_spi_transfer_one;
|
||||
@@ -505,15 +506,15 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- if (hisi_spi_debugfs_init(hs))
|
||||
- dev_info(dev, "failed to create debugfs dir\n");
|
||||
-
|
||||
ret = spi_register_controller(master);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register spi master, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ if (hisi_spi_debugfs_init(hs))
|
||||
+ dev_info(dev, "failed to create debugfs dir\n");
|
||||
+
|
||||
dev_info(dev, "hw version:0x%x max-freq:%u kHz\n",
|
||||
readl(hs->regs + HISI_SPI_VERSION),
|
||||
master->max_speed_hz / 1000);
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -101,3 +101,12 @@ patches/0097-arm64-HWCAP-add-support-for-AT_HWCAP2.patch
|
||||
patches/0098-arm64-Expose-SVE2-features-for-userspace.patch
|
||||
patches/0099-arm64-cpufeature-Fix-missing-ZFR0-in-__read_sysreg_b.patch
|
||||
patches/0100-arm64-cpufeature-Treat-ID_AA64ZFR0_EL1-as-RAZ-when-S.patch
|
||||
patches/0101-spi-core-allow-reporting-the-effectivly-used-speed_h.patch
|
||||
patches/0102-spi-Introduce-device-managed-SPI-controller-allocati.patch
|
||||
patches/0103-spi-Fix-use-after-free-with-devm_spi_alloc_.patch
|
||||
patches/0104-spi-linux-spi-spi.h-add-missing-struct-kernel-doc-en.patch
|
||||
patches/0105-Documentation-devres-add-missing-SPI-helper.patch
|
||||
patches/0106-spi-Add-HiSilicon-SPI-Controller-Driver-for-Kunpeng-.patch
|
||||
patches/0107-spi-hisi-kunpeng-Fix-Woverflow-warning-on-conversion.patch
|
||||
patches/0108-spi-hisi-kunpeng-Add-debugfs-support.patch
|
||||
patches/0109-spi-hisi-kunpeng-Fix-the-debugfs-directory-name-inco.patch
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user