mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'spi-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"The only real core work we've got this time around is the completion
of the transition to the new host/target naming for the core APIs,
Kconfig still needs doing but that's a lot less invasive.
Otherwise the big changes are the new drivers that have been added:
- Completion of the conversion to spi_alloc_host()/_target() and
removal of the old naming.
- Cleanups for Rockchip drivers, these brought in a new logging
helper in the driver core for warnings during probe.
- Support for configuration of the word delay via spidev_test.
- Support for AMD HID2 controllers, Apple SPI controller and Realtek
SPI-NAND controllers"
* tag 'spi-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (58 commits)
spi: imx: support word delay
spi: imx: pass struct spi_transfer to prepare_transfer()
spi: cs42l43: Add GPIO speaker id support to the bridge configuration
spi: Delete useless checks
spi: apple: Remove unnecessary .owner for apple_spi_driver
spi: spidev_test: add support for word delay
spi: apple: Add driver for Apple SPI controller
spi: dt-bindings: apple,spi: Add binding for Apple SPI controllers
spi: Use of_property_present() for non-boolean properties
spi: zynqmp-gqspi: Undo runtime PM changes at driver exit time
spi: spi-mem: rtl-snand: Correctly handle DMA transfers
spi: tegra210-quad: Avoid shift-out-of-bounds
spi: axi-spi-engine: Emit trace events for spi transfers
dt-bindings: spi: sprd,sc9860-spi: convert to YAML
spi: Replace deprecated PCI functions
spi: dt-bindings: samsung: Add a compatible for samsung,exynos8895-spi
spi: spi-mem: Add Realtek SPI-NAND controller
dt-bindings: spi: Add realtek,rtl9301-snand
spi: make class structs const
spi: dt-bindings: brcm,bcm2835-aux-spi: Convert to dtschema
...
This commit is contained in:
20
Documentation/ABI/testing/sysfs-driver-spi-intel
Normal file
20
Documentation/ABI/testing/sysfs-driver-spi-intel
Normal file
@@ -0,0 +1,20 @@
|
||||
What: /sys/devices/.../intel_spi_protected
|
||||
Date: Feb 2025
|
||||
KernelVersion: 6.13
|
||||
Contact: Alexander Usyskin <alexander.usyskin@intel.com>
|
||||
Description: This attribute allows the userspace to check if the
|
||||
Intel SPI flash controller is write protected from the host.
|
||||
|
||||
What: /sys/devices/.../intel_spi_locked
|
||||
Date: Feb 2025
|
||||
KernelVersion: 6.13
|
||||
Contact: Alexander Usyskin <alexander.usyskin@intel.com>
|
||||
Description: This attribute allows the user space to check if the
|
||||
Intel SPI flash controller locks supported opcodes.
|
||||
|
||||
What: /sys/devices/.../intel_spi_bios_locked
|
||||
Date: Feb 2025
|
||||
KernelVersion: 6.13
|
||||
Contact: Alexander Usyskin <alexander.usyskin@intel.com>
|
||||
Description: This attribute allows the user space to check if the
|
||||
Intel SPI flash controller BIOS region is locked for writes.
|
||||
62
Documentation/devicetree/bindings/spi/apple,spi.yaml
Normal file
62
Documentation/devicetree/bindings/spi/apple,spi.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/apple,spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Apple ARM SoC SPI controller
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
maintainers:
|
||||
- Hector Martin <marcan@marcan.st>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,t8103-spi
|
||||
- apple,t8112-spi
|
||||
- apple,t6000-spi
|
||||
- const: apple,spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/apple-aic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
spi@39b104000 {
|
||||
compatible = "apple,t6000-spi", "apple,spi";
|
||||
reg = <0x3 0x9b104000 0x0 0x4000>;
|
||||
interrupt-parent = <&aic>;
|
||||
interrupts = <AIC_IRQ 0 1107 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&clk>;
|
||||
};
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
Broadcom BCM2835 auxiliary SPI1/2 controller
|
||||
|
||||
The BCM2835 contains two forms of SPI master controller, one known simply as
|
||||
SPI0, and the other known as the "Universal SPI Master"; part of the
|
||||
auxiliary block. This binding applies to the SPI1/2 controller.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "brcm,bcm2835-aux-spi".
|
||||
- reg: Should contain register location and length for the spi block
|
||||
- interrupts: Should contain shared interrupt of the aux block
|
||||
- clocks: The clock feeding the SPI controller - needs to
|
||||
point to the auxiliary clock driver of the bcm2835,
|
||||
as this clock will enable the output gate for the specific
|
||||
clock.
|
||||
- cs-gpios: the cs-gpios (native cs is NOT supported)
|
||||
see also spi-bus.txt
|
||||
|
||||
Example:
|
||||
|
||||
spi1@7e215080 {
|
||||
compatible = "brcm,bcm2835-aux-spi";
|
||||
reg = <0x7e215080 0x40>;
|
||||
interrupts = <1 29>;
|
||||
clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 18>, <&gpio 17>, <&gpio 16>;
|
||||
};
|
||||
|
||||
spi2@7e2150c0 {
|
||||
compatible = "brcm,bcm2835-aux-spi";
|
||||
reg = <0x7e2150c0 0x40>;
|
||||
interrupts = <1 29>;
|
||||
clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 43>, <&gpio 44>, <&gpio 45>;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/brcm,bcm2835-aux-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM2835 Auxiliary SPI1/2 Controller
|
||||
|
||||
maintainers:
|
||||
- Karan Sanghavi <karansanghvi98@gmail.com>
|
||||
|
||||
description:
|
||||
The BCM2835 contains two forms of SPI master controller. One is known simply
|
||||
as SPI0, and the other as the "Universal SPI Master," which is part of the
|
||||
auxiliary block. This binding applies to the SPI1 and SPI2 auxiliary
|
||||
controllers.
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-aux-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835-aux.h>
|
||||
spi@7e215080 {
|
||||
compatible = "brcm,bcm2835-aux-spi";
|
||||
reg = <0x7e215080 0x40>;
|
||||
interrupts = <1 29>;
|
||||
clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/realtek,rtl9301-snand.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SPI-NAND Flash Controller for Realtek RTL9300 SoCs
|
||||
|
||||
maintainers:
|
||||
- Chris Packham <chris.packham@alliedtelesis.co.nz>
|
||||
|
||||
description:
|
||||
The Realtek RTL9300 SoCs have a built in SPI-NAND controller. It supports
|
||||
typical SPI-NAND page cache operations in single, dual or quad IO mode.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- realtek,rtl9302b-snand
|
||||
- realtek,rtl9302c-snand
|
||||
- realtek,rtl9303-snand
|
||||
- const: realtek,rtl9301-snand
|
||||
- const: realtek,rtl9301-snand
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi@1a400 {
|
||||
compatible = "realtek,rtl9302c-snand", "realtek,rtl9301-snand";
|
||||
reg = <0x1a400 0x44>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <19>;
|
||||
clocks = <&lx_clk>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
flash@0 {
|
||||
compatible = "spi-nand";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
@@ -26,6 +26,10 @@ properties:
|
||||
- samsung,exynos850-spi
|
||||
- samsung,exynosautov9-spi
|
||||
- tesla,fsd-spi
|
||||
- items:
|
||||
- enum:
|
||||
- samsung,exynos8895-spi
|
||||
- const: samsung,exynos850-spi
|
||||
- const: samsung,exynos7-spi
|
||||
deprecated: true
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
Spreadtrum SPI Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "sprd,sc9860-spi".
|
||||
- reg: Offset and length of SPI controller register space.
|
||||
- interrupts: Should contain SPI interrupt.
|
||||
- clock-names: Should contain following entries:
|
||||
"spi" for SPI clock,
|
||||
"source" for SPI source (parent) clock,
|
||||
"enable" for SPI module enable clock.
|
||||
- clocks: List of clock input name strings sorted in the same order
|
||||
as the clock-names property.
|
||||
- #address-cells: The number of cells required to define a chip select
|
||||
address on the SPI bus. Should be set to 1.
|
||||
- #size-cells: Should be set to 0.
|
||||
|
||||
Optional properties:
|
||||
dma-names: Should contain names of the SPI used DMA channel.
|
||||
dmas: Should contain DMA channels and DMA slave ids which the SPI used
|
||||
sorted in the same order as the dma-names property.
|
||||
|
||||
Example:
|
||||
spi0: spi@70a00000{
|
||||
compatible = "sprd,sc9860-spi";
|
||||
reg = <0 0x70a00000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "spi", "source","enable";
|
||||
clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>;
|
||||
dma-names = "rx_chn", "tx_chn";
|
||||
dmas = <&apdma 11 11>, <&apdma 12 12>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
@@ -9,9 +9,6 @@ title: Xilinx Zynq UltraScale+ MPSoC GQSPI controller
|
||||
maintainers:
|
||||
- Michal Simek <michal.simek@amd.com>
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@@ -19,6 +16,7 @@ properties:
|
||||
- xlnx,zynqmp-qspi-1.0
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
@@ -47,6 +45,24 @@ required:
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: xlnx,zynqmp-qspi-1.0
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/xlnx-zynqmp-clk.h>
|
||||
|
||||
72
Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml
Normal file
72
Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml
Normal file
@@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/sprd,sc9860-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Spreadtrum SC9860 SPI Controller
|
||||
|
||||
maintainers:
|
||||
- Orson Zhai <orsonzhai@gmail.com>
|
||||
- Baolin Wang <baolin.wang7@gmail.com>
|
||||
- Chunyan Zhang <zhang.lyra@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sprd,sc9860-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SPI clock
|
||||
- description: SPI source (parent) clock
|
||||
- description: SPI module enable clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: spi
|
||||
- const: source
|
||||
- const: enable
|
||||
|
||||
dmas:
|
||||
maxItems: 2
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx_chn
|
||||
- const: tx_chn
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi@70a00000 {
|
||||
compatible = "sprd,sc9860-spi";
|
||||
reg = <0x70a00000 0x1000>;
|
||||
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>;
|
||||
clock-names = "spi", "source", "enable";
|
||||
dmas = <&apdma 11 11>, <&apdma 12 12>;
|
||||
dma-names = "rx_chn", "tx_chn";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
...
|
||||
@@ -462,8 +462,8 @@ SLAVE DMA ENGINE
|
||||
devm_acpi_dma_controller_free()
|
||||
|
||||
SPI
|
||||
devm_spi_alloc_master()
|
||||
devm_spi_alloc_slave()
|
||||
devm_spi_alloc_host()
|
||||
devm_spi_alloc_target()
|
||||
devm_spi_optimize_message()
|
||||
devm_spi_register_controller()
|
||||
devm_spi_register_host()
|
||||
|
||||
@@ -19504,6 +19504,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
F: drivers/net/dsa/realtek/*
|
||||
|
||||
REALTEK SPI-NAND
|
||||
M: Chris Packham <chris.packham@alliedtelesis.co.nz>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
|
||||
F: drivers/spi/spi-realtek-rtl-snand.c
|
||||
|
||||
REALTEK WIRELESS DRIVER (rtlwifi family)
|
||||
M: Ping-Ke Shih <pkshih@realtek.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
||||
@@ -5012,6 +5012,49 @@ define_dev_printk_level(_dev_info, KERN_INFO);
|
||||
|
||||
#endif
|
||||
|
||||
static void __dev_probe_failed(const struct device *dev, int err, bool fatal,
|
||||
const char *fmt, va_list vargsp)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list vargs;
|
||||
|
||||
/*
|
||||
* On x86_64 and possibly on other architectures, va_list is actually a
|
||||
* size-1 array containing a structure. As a result, function parameter
|
||||
* vargsp decays from T[1] to T*, and &vargsp has type T** rather than
|
||||
* T(*)[1], which is expected by its assignment to vaf.va below.
|
||||
*
|
||||
* One standard way to solve this mess is by creating a copy in a local
|
||||
* variable of type va_list and then using a pointer to that local copy
|
||||
* instead, which is the approach employed here.
|
||||
*/
|
||||
va_copy(vargs, vargsp);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &vargs;
|
||||
|
||||
switch (err) {
|
||||
case -EPROBE_DEFER:
|
||||
device_set_deferred_probe_reason(dev, &vaf);
|
||||
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
||||
break;
|
||||
|
||||
case -ENOMEM:
|
||||
/* Don't print anything on -ENOMEM, there's already enough output */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Log fatal final failures as errors, otherwise produce warnings */
|
||||
if (fatal)
|
||||
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
||||
else
|
||||
dev_warn(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(vargs);
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_err_probe - probe error check and log helper
|
||||
* @dev: the pointer to the struct device
|
||||
@@ -5024,7 +5067,7 @@ define_dev_printk_level(_dev_info, KERN_INFO);
|
||||
* -EPROBE_DEFER and propagate error upwards.
|
||||
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
|
||||
* checked later by reading devices_deferred debugfs attribute.
|
||||
* It replaces code sequence::
|
||||
* It replaces the following code sequence::
|
||||
*
|
||||
* if (err != -EPROBE_DEFER)
|
||||
* dev_err(dev, ...);
|
||||
@@ -5036,48 +5079,78 @@ define_dev_printk_level(_dev_info, KERN_INFO);
|
||||
*
|
||||
* return dev_err_probe(dev, err, ...);
|
||||
*
|
||||
* Using this helper in your probe function is totally fine even if @err is
|
||||
* known to never be -EPROBE_DEFER.
|
||||
* Using this helper in your probe function is totally fine even if @err
|
||||
* is known to never be -EPROBE_DEFER.
|
||||
* The benefit compared to a normal dev_err() is the standardized format
|
||||
* of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
|
||||
* instead of "-35") and the fact that the error code is returned which allows
|
||||
* more compact error paths.
|
||||
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
|
||||
* instead of "-35"), and having the error code returned allows more
|
||||
* compact error paths.
|
||||
*
|
||||
* Returns @err.
|
||||
*/
|
||||
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
va_list vargs;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
va_start(vargs, fmt);
|
||||
|
||||
switch (err) {
|
||||
case -EPROBE_DEFER:
|
||||
device_set_deferred_probe_reason(dev, &vaf);
|
||||
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
||||
break;
|
||||
/* Use dev_err() for logging when err doesn't equal -EPROBE_DEFER */
|
||||
__dev_probe_failed(dev, err, true, fmt, vargs);
|
||||
|
||||
case -ENOMEM:
|
||||
/*
|
||||
* We don't print anything on -ENOMEM, there is already enough
|
||||
* output.
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
va_end(vargs);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_err_probe);
|
||||
|
||||
/**
|
||||
* dev_warn_probe - probe error check and log helper
|
||||
* @dev: the pointer to the struct device
|
||||
* @err: error value to test
|
||||
* @fmt: printf-style format string
|
||||
* @...: arguments as specified in the format string
|
||||
*
|
||||
* This helper implements common pattern present in probe functions for error
|
||||
* checking: print debug or warning message depending if the error value is
|
||||
* -EPROBE_DEFER and propagate error upwards.
|
||||
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
|
||||
* checked later by reading devices_deferred debugfs attribute.
|
||||
* It replaces the following code sequence::
|
||||
*
|
||||
* if (err != -EPROBE_DEFER)
|
||||
* dev_warn(dev, ...);
|
||||
* else
|
||||
* dev_dbg(dev, ...);
|
||||
* return err;
|
||||
*
|
||||
* with::
|
||||
*
|
||||
* return dev_warn_probe(dev, err, ...);
|
||||
*
|
||||
* Using this helper in your probe function is totally fine even if @err
|
||||
* is known to never be -EPROBE_DEFER.
|
||||
* The benefit compared to a normal dev_warn() is the standardized format
|
||||
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
|
||||
* instead of "-35"), and having the error code returned allows more
|
||||
* compact error paths.
|
||||
*
|
||||
* Returns @err.
|
||||
*/
|
||||
int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
|
||||
/* Use dev_warn() for logging when err doesn't equal -EPROBE_DEFER */
|
||||
__dev_probe_failed(dev, err, false, fmt, vargs);
|
||||
|
||||
va_end(vargs);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_warn_probe);
|
||||
|
||||
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
|
||||
{
|
||||
return fwnode && !IS_ERR(fwnode->secondary);
|
||||
|
||||
@@ -175,11 +175,11 @@ int netup_spi_init(struct netup_unidvb_dev *ndev)
|
||||
struct spi_controller *ctlr;
|
||||
struct netup_spi *nspi;
|
||||
|
||||
ctlr = devm_spi_alloc_master(&ndev->pci_dev->dev,
|
||||
sizeof(struct netup_spi));
|
||||
ctlr = devm_spi_alloc_host(&ndev->pci_dev->dev,
|
||||
sizeof(struct netup_spi));
|
||||
if (!ctlr) {
|
||||
dev_err(&ndev->pci_dev->dev,
|
||||
"%s(): unable to alloc SPI master\n", __func__);
|
||||
"%s(): unable to alloc SPI host\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
nspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
@@ -1219,8 +1219,8 @@ static int msi2500_probe(struct usb_interface *intf,
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
/* SPI master adapter */
|
||||
ctlr = spi_alloc_master(dev->dev, 0);
|
||||
/* SPI host adapter */
|
||||
ctlr = spi_alloc_host(dev->dev, 0);
|
||||
if (ctlr == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unregister_v4l2_dev;
|
||||
|
||||
@@ -96,6 +96,17 @@ config SPI_AMLOGIC_SPIFC_A1
|
||||
This enables master mode support for the SPIFC (SPI flash
|
||||
controller) available in Amlogic A1 (A113L SoC).
|
||||
|
||||
config SPI_APPLE
|
||||
tristate "Apple SoC SPI Controller platform driver"
|
||||
depends on ARCH_APPLE || COMPILE_TEST
|
||||
help
|
||||
This enables support for the SPI controller present on
|
||||
many Apple SoCs, including the t8103 (M1), t8112 (M2)
|
||||
and t600x (M1 Pro/Max/Ultra). Multiple SPI controller
|
||||
instances are present on the SoC and each connects usually
|
||||
to a single device like spi-nor (nvram), input device controller
|
||||
or fingerprint sensor.
|
||||
|
||||
config SPI_AR934X
|
||||
tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver"
|
||||
depends on ATH79 || COMPILE_TEST
|
||||
@@ -843,6 +854,17 @@ config SPI_PXA2XX
|
||||
config SPI_PXA2XX_PCI
|
||||
def_tristate SPI_PXA2XX && PCI && COMMON_CLK
|
||||
|
||||
config SPI_REALTEK_SNAND
|
||||
tristate "Realtek SPI-NAND Flash Controller"
|
||||
depends on MACH_REALTEK_RTL || COMPILE_TEST
|
||||
select REGMAP
|
||||
help
|
||||
This enables support for the SPI-NAND Flash controller on
|
||||
Realtek SoCs.
|
||||
|
||||
This driver does not support generic SPI. The implementation
|
||||
only supports the spi-mem interface.
|
||||
|
||||
config SPI_ROCKCHIP
|
||||
tristate "Rockchip SPI controller driver"
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
|
||||
@@ -19,6 +19,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera-platform.o
|
||||
obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o
|
||||
obj-$(CONFIG_SPI_ALTERA_DFL) += spi-altera-dfl.o
|
||||
obj-$(CONFIG_SPI_AMLOGIC_SPIFC_A1) += spi-amlogic-spifc-a1.o
|
||||
obj-$(CONFIG_SPI_APPLE) += spi-apple.o
|
||||
obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o
|
||||
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
|
||||
obj-$(CONFIG_SPI_ASPEED_SMC) += spi-aspeed-smc.o
|
||||
@@ -119,6 +120,7 @@ obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
|
||||
obj-$(CONFIG_SPI_ROCKCHIP_SFC) += spi-rockchip-sfc.o
|
||||
obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
|
||||
obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
|
||||
obj-$(CONFIG_SPI_REALTEK_SNAND) += spi-realtek-rtl-snand.o
|
||||
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
|
||||
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
|
||||
obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o
|
||||
|
||||
@@ -516,21 +516,45 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
|
||||
struct spi_controller *ctrl = spi->controller;
|
||||
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
|
||||
unsigned long clk_rate;
|
||||
u32 cs_inactive;
|
||||
u32 cs_setup;
|
||||
u32 cs_hold;
|
||||
int delay;
|
||||
int ret;
|
||||
|
||||
delay = spi_delay_to_ns(&spi->cs_setup, NULL);
|
||||
if (delay <= 0)
|
||||
return delay;
|
||||
|
||||
clk_rate = clk_get_rate(aq->pclk);
|
||||
if (!clk_rate)
|
||||
return -EINVAL;
|
||||
|
||||
/* hold */
|
||||
delay = spi_delay_to_ns(&spi->cs_hold, NULL);
|
||||
if (aq->mr & QSPI_MR_SMM) {
|
||||
if (delay > 0)
|
||||
dev_warn(&aq->pdev->dev,
|
||||
"Ignoring cs_hold, must be 0 in Serial Memory Mode.\n");
|
||||
cs_hold = 0;
|
||||
} else {
|
||||
delay = spi_delay_to_ns(&spi->cs_hold, NULL);
|
||||
if (delay < 0)
|
||||
return delay;
|
||||
|
||||
cs_hold = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)), 32000);
|
||||
}
|
||||
|
||||
/* setup */
|
||||
delay = spi_delay_to_ns(&spi->cs_setup, NULL);
|
||||
if (delay < 0)
|
||||
return delay;
|
||||
|
||||
cs_setup = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)),
|
||||
1000);
|
||||
|
||||
/* inactive */
|
||||
delay = spi_delay_to_ns(&spi->cs_inactive, NULL);
|
||||
if (delay < 0)
|
||||
return delay;
|
||||
cs_inactive = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)), 1000);
|
||||
|
||||
ret = pm_runtime_resume_and_get(ctrl->dev.parent);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -539,6 +563,10 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
|
||||
aq->scr |= QSPI_SCR_DLYBS(cs_setup);
|
||||
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
|
||||
|
||||
aq->mr &= ~(QSPI_MR_DLYBCT_MASK | QSPI_MR_DLYCS_MASK);
|
||||
aq->mr |= QSPI_MR_DLYBCT(cs_hold) | QSPI_MR_DLYCS(cs_inactive);
|
||||
atmel_qspi_write(aq->mr, aq, QSPI_MR);
|
||||
|
||||
pm_runtime_mark_last_busy(ctrl->dev.parent);
|
||||
pm_runtime_put_autosuspend(ctrl->dev.parent);
|
||||
|
||||
@@ -840,7 +868,7 @@ static struct platform_driver atmel_qspi_driver = {
|
||||
.pm = pm_ptr(&atmel_qspi_pm_ops),
|
||||
},
|
||||
.probe = atmel_qspi_probe,
|
||||
.remove_new = atmel_qspi_remove,
|
||||
.remove = atmel_qspi_remove,
|
||||
};
|
||||
module_platform_driver(atmel_qspi_driver);
|
||||
|
||||
|
||||
@@ -206,13 +206,6 @@ enum airoha_snand_cs {
|
||||
SPI_CHIP_SEL_LOW,
|
||||
};
|
||||
|
||||
struct airoha_snand_dev {
|
||||
size_t buf_len;
|
||||
|
||||
u8 *txrx_buf;
|
||||
dma_addr_t dma_addr;
|
||||
};
|
||||
|
||||
struct airoha_snand_ctrl {
|
||||
struct device *dev;
|
||||
struct regmap *regmap_ctrl;
|
||||
@@ -617,9 +610,9 @@ static bool airoha_snand_supports_op(struct spi_mem *mem,
|
||||
|
||||
static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
struct airoha_snand_dev *as_dev = spi_get_ctldata(desc->mem->spi);
|
||||
u8 *txrx_buf = spi_get_ctldata(desc->mem->spi);
|
||||
|
||||
if (!as_dev->txrx_buf)
|
||||
if (!txrx_buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
@@ -634,10 +627,11 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
dma_addr_t dma_addr;
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
@@ -662,14 +656,17 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* set dma addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
as_dev->dma_addr);
|
||||
dma_addr);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set cust sec size */
|
||||
val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
|
||||
@@ -678,58 +675,58 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_READ_DATA_BYTE_NUM, val);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set read command */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
|
||||
op->cmd.opcode);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set read mode */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, rd_mode));
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set read addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set nfi read */
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 6));
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* trigger dma start read */
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_READ_FROM_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
@@ -739,35 +736,41 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* DMA read need delay for data ready from controller to DRAM */
|
||||
udelay(1);
|
||||
|
||||
dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
memcpy(buf, as_dev->txrx_buf + offs, len);
|
||||
memcpy(buf, txrx_buf + offs, len);
|
||||
|
||||
return len;
|
||||
|
||||
error_dma_unmap:
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, const void *buf)
|
||||
{
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
struct spi_device *spi = desc->mem->spi;
|
||||
u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
dma_addr_t dma_addr;
|
||||
u32 wr_mode, val;
|
||||
int err;
|
||||
|
||||
@@ -776,19 +779,20 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
memcpy(as_dev->txrx_buf + offs, buf, len);
|
||||
dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
memcpy(txrx_buf + offs, buf, len);
|
||||
dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = airoha_snand_nfi_config(as_ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
|
||||
op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
|
||||
@@ -797,9 +801,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
wr_mode = 0;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
as_dev->dma_addr);
|
||||
dma_addr);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
|
||||
as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
|
||||
@@ -807,65 +811,65 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_PROG_LOAD_BYTE_NUM, val);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
|
||||
FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
|
||||
op->cmd.opcode));
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 3));
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_LOAD_TO_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
@@ -875,13 +879,20 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_unmap;
|
||||
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len;
|
||||
|
||||
error_dma_unmap:
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
@@ -956,42 +967,20 @@ static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
|
||||
static int airoha_snand_setup(struct spi_device *spi)
|
||||
{
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
struct airoha_snand_dev *as_dev;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
as_dev = devm_kzalloc(as_ctrl->dev, sizeof(*as_dev), GFP_KERNEL);
|
||||
if (!as_dev)
|
||||
return -ENOMEM;
|
||||
u8 *txrx_buf;
|
||||
|
||||
/* prepare device buffer */
|
||||
as_dev->buf_len = SPI_NAND_CACHE_SIZE;
|
||||
as_dev->txrx_buf = devm_kzalloc(as_ctrl->dev, as_dev->buf_len,
|
||||
GFP_KERNEL);
|
||||
if (!as_dev->txrx_buf)
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
txrx_buf = devm_kzalloc(as_ctrl->dev, SPI_NAND_CACHE_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!txrx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_ctldata(spi, as_dev);
|
||||
spi_set_ctldata(spi, txrx_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void airoha_snand_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
dma_unmap_single(as_ctrl->dev, as_dev->dma_addr,
|
||||
as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
spi_set_ctldata(spi, NULL);
|
||||
}
|
||||
|
||||
static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
|
||||
{
|
||||
u32 val, sec_size, sec_num;
|
||||
@@ -1093,7 +1082,6 @@ static int airoha_snand_probe(struct platform_device *pdev)
|
||||
ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
ctrl->mode_bits = SPI_RX_DUAL;
|
||||
ctrl->setup = airoha_snand_setup;
|
||||
ctrl->cleanup = airoha_snand_cleanup;
|
||||
device_set_node(&ctrl->dev, dev_fwnode(dev));
|
||||
|
||||
err = airoha_snand_nfi_setup(as_ctrl);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
529
drivers/spi/spi-apple.c
Normal file
529
drivers/spi/spi-apple.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user