spi: Updates for v5.17

This has mostly been a quiet release for the SPI subsystem, almost all
 cleanups and fixes to existing drivers.  A couple of changes that stand
 out:
 
  - Cleanups and support for version specific features in the DesignWare
    controller.
  - Removal of support for Netlogic devices from the XLP driver, the
    platform had previously been removed by MIPS so the support couldn't
    be used.
  - Conversion of several DT bindings to YAML format.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmHcNHcACgkQJNaLcl1U
 h9Bm0Qf7B+2c0Mi8GGJ1TCL44IGTAs9DDOK1uvtaL6VOP5XA1CAm92na4+xghb05
 xIxvHF/IyC4rAUjg+8btzgIBSmtBXNELO4JFCVXdKnaFPPjIjJfzE9eMdcK6HVdq
 6ZNNVRCFv9E6Dy9cEPyU9dUNKSwJmE6ok8qHxo7f78WeftPWmBvMXa5knE5rj+d4
 IiqaJg0L2jdGkTM5Qy0Mm+dI0dTUEkGCrjMhyJXbhry0H7L8z9f9utWI3QE8IXyG
 oyt2k7+MSrb6jeb9MRuD/9GC6VdaVv6MWTBEA0yTTsaGZhXwcpy9XJXy7xbbdF6P
 g7cd4E4Rlfz4Y9j8GSaDW4AuuUBB3A==
 =LgO4
 -----END PGP SIGNATURE-----

Merge tag 'spi-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "This has mostly been a quiet release for the SPI subsystem, almost all
  cleanups and fixes to existing drivers.

  A couple of changes that stand out:

   - Cleanups and support for version specific features in the
     DesignWare controller.

   - Removal of support for Netlogic devices from the XLP driver, the
     platform had previously been removed by MIPS so the support
     couldn't be used.

   - Conversion of several DT bindings to YAML format"

* tag 'spi-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (53 commits)
  spi: don't include ptp_clock_kernel.h in spi.h
  spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe
  spi: atmel: Fix typo
  spi: dt-bindings: mediatek,spi-mtk-nor: Fix example 'interrupts' property
  spi: qcom: geni: handle timeout for gpi mode
  spi: qcom: geni: set the error code for gpi transfer
  spi: spi-mux: Add reference to spi-peripheral-props.yaml schema
  spi: ar934x: fix transfer size
  spi: pxa2xx: Propagate firmware node
  spi: dw: Propagate firmware node
  spi: dln2: Propagate firmware node
  spi: ar934x: fix transfer and word delays
  spi: uniphier: Fix a bug that doesn't point to private data correctly
  spi: spi-mtk-nor: add new clock name 'axi' for spi nor
  spi: atmel,quadspi: Define sama7g5 QSPI
  spi: atmel,quadspi: Convert to json-schema
  spi: Fix incorrect cs_setup delay handling
  dt-bindings: mtd: spi-nor: Add a reference to spi-peripheral-props.yaml
  spi: dt-bindings: cdns,qspi-nor: Move peripheral-specific properties out
  spi: dt-bindings: add schema listing peripheral-specific properties
  ...
This commit is contained in:
Linus Torvalds 2022-01-11 12:19:47 -08:00
commit 282aa44c21
42 changed files with 846 additions and 681 deletions

View File

@ -11,6 +11,7 @@ maintainers:
allOf:
- $ref: "mtd.yaml#"
- $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@ -88,7 +89,7 @@ patternProperties:
"^otp(-[0-9]+)?$":
type: object
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -0,0 +1,99 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/atmel,quadspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel Quad Serial Peripheral Interface (QSPI)
maintainers:
- Tudor Ambarus <tudor.ambarus@microchip.com>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
enum:
- atmel,sama5d2-qspi
- microchip,sam9x60-qspi
- microchip,sama7g5-qspi
- microchip,sama7g5-ospi
reg:
items:
- description: base registers
- description: mapped memory
reg-names:
items:
- const: qspi_base
- const: qspi_mmap
clocks:
minItems: 1
items:
- description: peripheral clock
- description: system clock or generic clock, if available
clock-names:
minItems: 1
items:
- const: pclk
- enum: [ qspick, gclk ]
interrupts:
maxItems: 1
dmas:
items:
- description: tx DMA channel
- description: rx DMA channel
dma-names:
items:
- const: tx
- const: rx
'#address-cells':
const: 1
'#size-cells':
const: 0
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
- '#address-cells'
- '#size-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/at91.h>
spi@f0020000 {
compatible = "atmel,sama5d2-qspi";
reg = <0xf0020000 0x100>, <0xd0000000 0x8000000>;
reg-names = "qspi_base", "qspi_mmap";
interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 52>;
clock-names = "pclk";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0_default>;
flash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <50000000>;
reg = <0>;
spi-rx-bus-width = <4>;
spi-tx-bus-width = <4>;
};
};

View File

@ -1,37 +0,0 @@
* Atmel Quad Serial Peripheral Interface (QSPI)
Required properties:
- compatible: Should be one of the following:
- "atmel,sama5d2-qspi"
- "microchip,sam9x60-qspi"
- reg: Should contain the locations and lengths of the base registers
and the mapped memory.
- reg-names: Should contain the resource reg names:
- qspi_base: configuration register address space
- qspi_mmap: memory mapped address space
- interrupts: Should contain the interrupt for the device.
- clocks: Should reference the peripheral clock and the QSPI system
clock if available.
- clock-names: Should contain "pclk" for the peripheral clock and "qspick"
for the system clock when available.
- #address-cells: Should be <1>.
- #size-cells: Should be <0>.
Example:
spi@f0020000 {
compatible = "atmel,sama5d2-qspi";
reg = <0xf0020000 0x100>, <0xd0000000 0x8000000>;
reg-names = "qspi_base", "qspi_mmap";
interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 52>;
clock-names = "pclk";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0_default>;
m25p80@0 {
...
};
};

View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/cdns,qspi-nor-peripheral-props.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Peripheral-specific properties for the Cadence QSPI controller.
description:
See spi-peripheral-props.yaml for more info.
maintainers:
- Pratyush Yadav <p.yadav@ti.com>
properties:
# cdns,qspi-nor.yaml
cdns,read-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay for read capture logic, in clock cycles.
cdns,tshsl-ns:
description:
Delay in nanoseconds for the length that the master mode chip select
outputs are de-asserted between transactions.
cdns,tsd2d-ns:
description:
Delay in nanoseconds between one chip select being de-activated
and the activation of another.
cdns,tchsh-ns:
description:
Delay in nanoseconds between last bit of current transaction and
deasserting the device chip select (qspi_n_ss_out).
cdns,tslch-ns:
description:
Delay in nanoseconds between setting qspi_n_ss_out low and
first bit transfer.
additionalProperties: true

View File

@ -87,39 +87,6 @@ properties:
items:
enum: [ qspi, qspi-ocp ]
# subnode's properties
patternProperties:
"@[0-9a-f]+$":
type: object
description:
Flash device uses the below defined properties in the subnode.
properties:
cdns,read-delay:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Delay for read capture logic, in clock cycles.
cdns,tshsl-ns:
description:
Delay in nanoseconds for the length that the master mode chip select
outputs are de-asserted between transactions.
cdns,tsd2d-ns:
description:
Delay in nanoseconds between one chip select being de-activated
and the activation of another.
cdns,tchsh-ns:
description:
Delay in nanoseconds between last bit of current transaction and
deasserting the device chip select (qspi_n_ss_out).
cdns,tslch-ns:
description:
Delay in nanoseconds between setting qspi_n_ss_out low and
first bit transfer.
required:
- compatible
- reg

View File

@ -43,14 +43,19 @@ properties:
maxItems: 1
clocks:
minItems: 2
items:
- description: clock used for spi bus
- description: clock used for controller
- description: clock used for nor dma bus. this depends on hardware
design, so this is optional.
clock-names:
minItems: 2
items:
- const: spi
- const: sf
- const: axi
required:
- compatible
@ -72,7 +77,7 @@ examples:
nor_flash: spi@1100d000 {
compatible = "mediatek,mt8173-nor";
reg = <0 0x1100d000 0 0xe0>;
interrupts = <&spi_flash_irq>;
interrupts = <1>;
clocks = <&pericfg CLK_PERI_SPI>, <&topckgen CLK_TOP_SPINFI_IFR_SEL>;
clock-names = "spi", "sf";
#address-cells = <1>;
@ -84,4 +89,3 @@ examples:
};
};
};

View File

@ -21,7 +21,8 @@ properties:
- enum:
- renesas,rspi-r7s72100 # RZ/A1H
- renesas,rspi-r7s9210 # RZ/A2
- const: renesas,rspi-rz # RZ/A
- renesas,r9a07g044-rspi # RZ/G2{L,LC}
- const: renesas,rspi-rz # RZ/A and RZ/G2{L,LC}
- items:
- enum:
@ -122,6 +123,7 @@ allOf:
contains:
enum:
- renesas,qspi
- renesas,r9a07g044-rspi
then:
required:
- resets

View File

@ -94,73 +94,8 @@ patternProperties:
"^.*@[0-9a-f]+$":
type: object
properties:
compatible:
description:
Compatible of the SPI device.
reg:
minItems: 1
maxItems: 256
items:
minimum: 0
maximum: 256
description:
Chip select used by the device.
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cpha:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires shifted clock phase (CPHA) mode.
spi-cpol:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires inverse clock polarity (CPOL) mode.
spi-cs-high:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires the chip select active high.
spi-lsb-first:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires the LSB first mode.
spi-max-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Maximum SPI clocking speed of the device in Hz.
spi-rx-bus-width:
description:
Bus width to the SPI bus used for read transfers.
If 0 is provided, then no RX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
spi-rx-delay-us:
description:
Delay, in microseconds, after a read transfer.
spi-tx-bus-width:
description:
Bus width to the SPI bus used for write transfers.
If 0 is provided, then no TX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
spi-tx-delay-us:
description:
Delay, in microseconds, after a write transfer.
allOf:
- $ref: spi-peripheral-props.yaml
required:
- compatible

View File

@ -14,10 +14,13 @@ allOf:
properties:
compatible:
enum:
- fsl,imx7ulp-spi
- fsl,imx8qxp-spi
oneOf:
- enum:
- fsl,imx7ulp-spi
- fsl,imx8qxp-spi
- items:
- const: fsl,imx8ulp-spi
- const: fsl,imx7ulp-spi
reg:
maxItems: 1

View File

@ -31,6 +31,7 @@ description: |
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
- $ref: "/schemas/spi/spi-peripheral-props.yaml#"
maintainers:
- Chris Packham <chris.packham@alliedtelesis.co.nz>

View File

@ -0,0 +1,89 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/spi-peripheral-props.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Peripheral-specific properties for a SPI bus.
description:
Many SPI controllers need to add properties to peripheral devices. They could
be common properties like spi-max-frequency, spi-cpha, etc. or they could be
controller specific like delay in clock or data lines, etc. These properties
need to be defined in the peripheral node because they are per-peripheral and
there can be multiple peripherals attached to a controller. All those
properties are listed here. The controller specific properties should go in
their own separate schema that should be referenced from here.
maintainers:
- Pratyush Yadav <p.yadav@ti.com>
properties:
reg:
minItems: 1
maxItems: 256
items:
minimum: 0
maximum: 256
description:
Chip select used by the device.
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cpha:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires shifted clock phase (CPHA) mode.
spi-cpol:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires inverse clock polarity (CPOL) mode.
spi-cs-high:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires the chip select active high.
spi-lsb-first:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires the LSB first mode.
spi-max-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Maximum SPI clocking speed of the device in Hz.
spi-rx-bus-width:
description:
Bus width to the SPI bus used for read transfers.
If 0 is provided, then no RX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
spi-rx-delay-us:
description:
Delay, in microseconds, after a read transfer.
spi-tx-bus-width:
description:
Bus width to the SPI bus used for write transfers.
If 0 is provided, then no TX will be possible on this device.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 4, 8]
default: 1
spi-tx-delay-us:
description:
Delay, in microseconds, after a write transfer.
# The controller specific properties go here.
allOf:
- $ref: cdns,qspi-nor-peripheral-props.yaml#
additionalProperties: true

View File

@ -72,6 +72,9 @@ properties:
- const: rx
- const: tx
resets:
maxItems: 1
patternProperties:
"^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$":
type: object

View File

@ -101,8 +101,7 @@ device. All fields are optional.
u8 rx_threshold;
u8 dma_burst_size;
u32 timeout;
u8 enable_loopback;
void (*cs_control)(u32 command);
int gpio_cs;
};
The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are
@ -128,16 +127,6 @@ dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
slave device. Please note that the PXA2xx SSP 1 does not support trailing byte
timeouts and must busy-wait any trailing bytes.
The "pxa2xx_spi_chip.enable_loopback" field is used to place the SSP porting
into internal loopback mode. In this mode the SSP controller internally
connects the SSPTX pin to the SSPRX pin. This is useful for initial setup
testing.
The "pxa2xx_spi_chip.cs_control" field is used to point to a board specific
function for asserting/deasserting a slave device chip select. If the field is
NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
configured to use GPIO or SSPFRM instead.
NOTE: the SPI driver cannot control the chip select if SSPFRM is used, so the
chipselect is dropped after each spi_transfer. Most devices need chip select
asserted around the complete message. Use SSPFRM as a GPIO (through a descriptor)
@ -152,30 +141,12 @@ field. Below is a sample configuration using the PXA255 NSSP.
::
/* Chip Select control for the CS8415A SPI slave device */
static void cs8415a_cs_control(u32 command)
{
if (command & PXA2XX_CS_ASSERT)
GPCR(2) = GPIO_bit(2);
else
GPSR(2) = GPIO_bit(2);
}
/* Chip Select control for the CS8405A SPI slave device */
static void cs8405a_cs_control(u32 command)
{
if (command & PXA2XX_CS_ASSERT)
GPCR(3) = GPIO_bit(3);
else
GPSR(3) = GPIO_bit(3);
}
static struct pxa2xx_spi_chip cs8415a_chip_info = {
.tx_threshold = 8, /* SSP hardward FIFO threshold */
.rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
.timeout = 235, /* See Intel documentation */
.cs_control = cs8415a_cs_control, /* Use external chip select */
.gpio_cs = 2, /* Use external chip select */
};
static struct pxa2xx_spi_chip cs8405a_chip_info = {
@ -183,7 +154,7 @@ field. Below is a sample configuration using the PXA255 NSSP.
.rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
.timeout = 235, /* See Intel documentation */
.cs_control = cs8405a_cs_control, /* Use external chip select */
.gpio_cs = 3, /* Use external chip select */
};
static struct spi_board_info streetracer_spi_board_info[] __initdata = {

View File

@ -29,21 +29,49 @@ of the driver stack) that are not accessible to userspace.
DEVICE CREATION, DRIVER BINDING
===============================
The simplest way to arrange to use this driver is to just list it in the
spi_board_info for a device as the driver it should use: the "modalias"
entry is "spidev", matching the name of the driver exposing this API.
Set up the other device characteristics (bits per word, SPI clocking,
chipselect polarity, etc) as usual, so you won't always need to override
them later.
(Sysfs also supports userspace driven binding/unbinding of drivers to
devices. That mechanism might be supported here in the future.)
The spidev driver contains lists of SPI devices that are supported for
the different hardware topology representations.
When you do that, the sysfs node for the SPI device will include a child
device node with a "dev" attribute that will be understood by udev or mdev.
(Larger systems will have "udev". Smaller ones may configure "mdev" into
busybox; it's less featureful, but often enough.) For a SPI device with
chipselect C on bus B, you should see:
The following are the SPI device tables supported by the spidev driver:
- struct spi_device_id spidev_spi_ids[]: list of devices that can be
bound when these are defined using a struct spi_board_info with a
.modalias field matching one of the entries in the table.
- struct of_device_id spidev_dt_ids[]: list of devices that can be
bound when these are defined using a Device Tree node that has a
compatible string matching one of the entries in the table.
- struct acpi_device_id spidev_acpi_ids[]: list of devices that can
be bound when these are defined using a ACPI device object with a
_HID matching one of the entries in the table.
You are encouraged to add an entry for your SPI device name to relevant
tables, if these don't already have an entry for the device. To do that,
post a patch for spidev to the linux-spi@vger.kernel.org mailing list.
It used to be supported to define an SPI device using the "spidev" name.
For example, as .modalias = "spidev" or compatible = "spidev". But this
is no longer supported by the Linux kernel and instead a real SPI device
name as listed in one of the tables must be used.
Not having a real SPI device name will lead to an error being printed and
the spidev driver failing to probe.
Sysfs also supports userspace driven binding/unbinding of drivers to
devices that do not bind automatically using one of the tables above.
To make the spidev driver bind to such a device, use the following:
echo spidev > /sys/bus/spi/devices/spiB.C/driver_override
echo spiB.C > /sys/bus/spi/drivers/spidev/bind
When the spidev driver is bound to a SPI device, the sysfs node for the
device will include a child device node with a "dev" attribute that will
be understood by udev or mdev (udev replacement from BusyBox; it's less
featureful, but often enough).
For a SPI device with chipselect C on bus B, you should see:
/dev/spidevB.C ...
character special device, major number 153 with

View File

@ -211,16 +211,17 @@ static struct ads7846_platform_data ads_info = {
// .y_plate_ohms = 500, /* GUESS! */
};
static void ads7846_cs(u32 command)
{
static const unsigned TS_nCS = 1 << 11;
lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS);
}
static struct gpiod_lookup_table ads7846_cs_gpios = {
.dev_id = "ads7846",
.table = {
GPIO_LOOKUP("lubbock", 11, "cs", GPIO_ACTIVE_LOW),
{}
},
};
static struct pxa2xx_spi_chip ads_hw = {
.tx_threshold = 1,
.rx_threshold = 2,
.cs_control = ads7846_cs,
};
static struct spi_board_info spi_board_info[] __initdata = { {
@ -512,6 +513,8 @@ static void __init lubbock_init(void)
lubbock_flash_data[flashboot].name = "boot-rom";
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
gpiod_add_lookup_table(&ads7846_cs_gpios);
pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}

View File

@ -347,7 +347,7 @@ static struct pxa2xx_spi_controller pxa_ssp_master_2_info = {
};
/* An upcoming kernel change will scrap SFRM usage so these
* drivers have been moved to use gpio's via cs_control */
* drivers have been moved to use GPIOs */
static struct pxa2xx_spi_chip staccel_chip_info = {
.tx_threshold = 8,
.rx_threshold = 8,

View File

@ -974,14 +974,13 @@ config SPI_XILINX
Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
config SPI_XLP
tristate "Netlogic XLP SPI controller driver"
depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
tristate "Cavium ThunderX2 SPI controller driver"
depends on ARCH_THUNDER2 || COMPILE_TEST
help
Enable support for the SPI controller on the Netlogic XLP SoCs.
Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX
and XLP5XX.
Enable support for the SPI controller on the Cavium ThunderX2.
(Originally on Netlogic XLP SoCs.)
If you have a Netlogic XLP platform say Y here.
If you have a Cavium ThunderX2 platform say Y here.
If unsure, say N.
config SPI_XTENSA_XTFPGA

View File

@ -82,7 +82,7 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
struct spi_device *spi = m->spi;
unsigned long trx_done, trx_cur;
int stat = 0;
u8 term = 0;
u8 bpw, term = 0;
int div, i;
u32 reg;
const u8 *tx_buf;
@ -90,6 +90,11 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
m->actual_length = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->bits_per_word >= 8 && t->bits_per_word < 32)
bpw = t->bits_per_word >> 3;
else
bpw = 4;
if (t->speed_hz)
div = ar934x_spi_clk_div(sp, t->speed_hz);
else
@ -105,10 +110,10 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL);
iowrite32(0, sp->base + AR934X_SPI_DATAOUT);
for (trx_done = 0; trx_done < t->len; trx_done += 4) {
for (trx_done = 0; trx_done < t->len; trx_done += bpw) {
trx_cur = t->len - trx_done;
if (trx_cur > 4)
trx_cur = 4;
if (trx_cur > bpw)
trx_cur = bpw;
else if (list_is_last(&t->transfer_list, &m->transfers))
term = 1;
@ -137,8 +142,10 @@ static int ar934x_spi_transfer_one_message(struct spi_controller *master,
reg >>= 8;
}
}
spi_delay_exec(&t->word_delay, t);
}
m->actual_length += t->len;
spi_transfer_delay_exec(t);
}
msg_done:
@ -191,7 +198,8 @@ static int ar934x_spi_probe(struct platform_device *pdev)
ctlr->mode_bits = SPI_LSB_FIRST;
ctlr->setup = ar934x_spi_setup;
ctlr->transfer_one_message = ar934x_spi_transfer_one_message;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
ctlr->dev.of_node = pdev->dev.of_node;
ctlr->num_chipselect = 3;

View File

@ -433,26 +433,25 @@ static bool atmel_spi_can_dma(struct spi_master *master,
}
static int atmel_spi_dma_slave_config(struct atmel_spi *as,
struct dma_slave_config *slave_config,
u8 bits_per_word)
static int atmel_spi_dma_slave_config(struct atmel_spi *as, u8 bits_per_word)
{
struct spi_master *master = platform_get_drvdata(as->pdev);
struct dma_slave_config slave_config;
int err = 0;
if (bits_per_word > 8) {
slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
} else {
slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
}
slave_config->dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
slave_config->src_addr = (dma_addr_t)as->phybase + SPI_RDR;
slave_config->src_maxburst = 1;
slave_config->dst_maxburst = 1;
slave_config->device_fc = false;
slave_config.dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
slave_config.src_addr = (dma_addr_t)as->phybase + SPI_RDR;
slave_config.src_maxburst = 1;
slave_config.dst_maxburst = 1;
slave_config.device_fc = false;
/*
* This driver uses fixed peripheral select mode (PS bit set to '0' in
@ -464,12 +463,11 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
* However, the first data has to be written into the lowest 16 bits and
* the second data into the highest 16 bits of the Transmit
* Data Register. For 8bit data (the most frequent case), it would
* require to rework tx_buf so each data would actualy fit 16 bits.
* require to rework tx_buf so each data would actually fit 16 bits.
* So we'd rather write only one data at the time. Hence the transmit
* path works the same whether FIFOs are available (and enabled) or not.
*/
slave_config->direction = DMA_MEM_TO_DEV;
if (dmaengine_slave_config(master->dma_tx, slave_config)) {
if (dmaengine_slave_config(master->dma_tx, &slave_config)) {
dev_err(&as->pdev->dev,
"failed to configure tx dma channel\n");
err = -EINVAL;
@ -483,8 +481,7 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
* So the receive path works the same whether FIFOs are available (and
* enabled) or not.
*/
slave_config->direction = DMA_DEV_TO_MEM;
if (dmaengine_slave_config(master->dma_rx, slave_config)) {
if (dmaengine_slave_config(master->dma_rx, &slave_config)) {
dev_err(&as->pdev->dev,
"failed to configure rx dma channel\n");
err = -EINVAL;
@ -496,7 +493,6 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
static int atmel_spi_configure_dma(struct spi_master *master,
struct atmel_spi *as)
{
struct dma_slave_config slave_config;
struct device *dev = &as->pdev->dev;
int err;
@ -518,7 +514,7 @@ static int atmel_spi_configure_dma(struct spi_master *master,
goto error;
}
err = atmel_spi_dma_slave_config(as, &slave_config, 8);
err = atmel_spi_dma_slave_config(as, 8);
if (err)
goto error;
@ -700,7 +696,6 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
struct dma_chan *txchan = master->dma_tx;
struct dma_async_tx_descriptor *rxdesc;
struct dma_async_tx_descriptor *txdesc;
struct dma_slave_config slave_config;
dma_cookie_t cookie;
dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_dma_submit\n");
@ -712,8 +707,7 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
*plen = xfer->len;
if (atmel_spi_dma_slave_config(as, &slave_config,
xfer->bits_per_word))
if (atmel_spi_dma_slave_config(as, xfer->bits_per_word))
goto err_exit;
/* Send both scatterlists */

View File

@ -287,6 +287,18 @@ static inline int bcm_qspi_spbr_min(struct bcm_qspi *qspi)
return 8;
}
static u32 bcm_qspi_calc_spbr(u32 clk_speed_hz,
const struct bcm_qspi_parms *xp)
{
u32 spbr = 0;
/* SPBR = System Clock/(2 * SCK Baud Rate) */
if (xp->speed_hz)
spbr = clk_speed_hz / (xp->speed_hz * 2);
return spbr;
}
/* Read qspi controller register*/
static inline u32 bcm_qspi_read(struct bcm_qspi *qspi, enum base_type type,
unsigned int offset)
@ -586,12 +598,24 @@ static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs)
qspi->curr_cs = cs;
}
static bool bcmspi_parms_did_change(const struct bcm_qspi_parms * const cur,
const struct bcm_qspi_parms * const prev)
{
return (cur->speed_hz != prev->speed_hz) ||
(cur->mode != prev->mode) ||
(cur->bits_per_word != prev->bits_per_word);
}
/* MSPI helpers */
static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
const struct bcm_qspi_parms *xp)
{
u32 spcr, spbr = 0;
if (!bcmspi_parms_did_change(xp, &qspi->last_parms))
return;
if (!qspi->mspi_maj_rev)
/* legacy controller */
spcr = MSPI_MASTER_BIT;
@ -621,9 +645,17 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
spcr |= MSPI_SPCR3_HALFDUPLEX | MSPI_SPCR3_HDOUTTYPE;
if (bcm_qspi_has_sysclk_108(qspi)) {
/* SYSCLK_108 */
spcr |= MSPI_SPCR3_SYSCLKSEL_108;
qspi->base_clk = MSPI_BASE_FREQ * 4;
/* check requested baud rate before moving to 108Mhz */
spbr = bcm_qspi_calc_spbr(MSPI_BASE_FREQ * 4, xp);
if (spbr > QSPI_SPBR_MAX) {
/* use SYSCLK_27Mhz for slower baud rates */
spcr &= ~MSPI_SPCR3_SYSCLKSEL_MASK;
qspi->base_clk = MSPI_BASE_FREQ;
} else {
/* SYSCLK_108Mhz */
spcr |= MSPI_SPCR3_SYSCLKSEL_108;
qspi->base_clk = MSPI_BASE_FREQ * 4;
}
}
if (xp->bits_per_word > 16) {
@ -649,9 +681,9 @@ static void bcm_qspi_hw_set_parms(struct bcm_qspi *qspi,
bcm_qspi_write(qspi, MSPI, MSPI_SPCR3, spcr);
}
if (xp->speed_hz)
spbr = qspi->base_clk / (2 * xp->speed_hz);
/* SCK Baud Rate = System Clock/(2 * SPBR) */
qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
spbr = bcm_qspi_calc_spbr(qspi->base_clk, xp);
spbr = clamp_val(spbr, bcm_qspi_spbr_min(qspi), QSPI_SPBR_MAX);
bcm_qspi_write(qspi, MSPI, MSPI_SPCR0_LSB, spbr);

View File

@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/mfd/dln2.h>
#include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
@ -688,6 +689,8 @@ static int dln2_spi_probe(struct platform_device *pdev)
if (!master)
return -ENOMEM;
device_set_node(&master->dev, dev_fwnode(dev));
platform_set_drvdata(pdev, master);
dln2 = spi_master_get_devdata(master);
@ -699,7 +702,6 @@ static int dln2_spi_probe(struct platform_device *pdev)
}
dln2->master = master;
dln2->master->dev.of_node = dev->of_node;
dln2->pdev = pdev;
dln2->port = pdata->port;
/* cs/mode can never be 0xff, so the first transfer will set them */

View File

@ -123,7 +123,7 @@ static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,
len = min_t(size_t, len, dwsbt1->map_len - offs);
/* Collect the controller configuration required by the operation */
cfg.tmode = SPI_TMOD_EPROMREAD;
cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;
cfg.dfs = 8;
cfg.ndf = 4;
cfg.freq = mem->spi->max_speed_hz;
@ -131,13 +131,13 @@ static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,
/* Make sure the corresponding CS is de-asserted on transmission */
dw_spi_set_cs(mem->spi, false);
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, mem->spi, &cfg);
spi_umask_intr(dws, SPI_INT_RXFI);
dw_spi_umask_intr(dws, DW_SPI_INT_RXFI);
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
/*
* Enable the transparent mode of the System Boot Controller.
@ -339,3 +339,4 @@ module_platform_driver(dw_spi_bt1_driver);
MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
MODULE_DESCRIPTION("Baikal-T1 System Boot SPI Controller driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SPI_DW_CORE);

View File

@ -5,6 +5,7 @@
* Copyright (c) 2009, Intel Corporation.
*/
#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/module.h>
@ -24,7 +25,7 @@
#endif
/* Slave spi_device related */
struct chip_data {
struct dw_spi_chip_data {
u32 cr0;
u32 rx_sample_dly; /* RX sample delay */
};
@ -106,10 +107,10 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
else
dw_writel(dws, DW_SPI_SER, 0);
}
EXPORT_SYMBOL_GPL(dw_spi_set_cs);
EXPORT_SYMBOL_NS_GPL(dw_spi_set_cs, SPI_DW_CORE);
/* Return the max entries we can fill into tx fifo */
static inline u32 tx_max(struct dw_spi *dws)
static inline u32 dw_spi_tx_max(struct dw_spi *dws)
{
u32 tx_room, rxtx_gap;
@ -129,14 +130,14 @@ static inline u32 tx_max(struct dw_spi *dws)
}
/* Return the max entries we should read out of rx fifo */
static inline u32 rx_max(struct dw_spi *dws)
static inline u32 dw_spi_rx_max(struct dw_spi *dws)
{
return min_t(u32, dws->rx_len, dw_readl(dws, DW_SPI_RXFLR));
}
static void dw_writer(struct dw_spi *dws)
{
u32 max = tx_max(dws);
u32 max = dw_spi_tx_max(dws);
u32 txw = 0;
while (max--) {
@ -157,7 +158,7 @@ static void dw_writer(struct dw_spi *dws)
static void dw_reader(struct dw_spi *dws)
{
u32 max = rx_max(dws);
u32 max = dw_spi_rx_max(dws);
u32 rxw;
while (max--) {
@ -186,31 +187,31 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw)
else
irq_status = dw_readl(dws, DW_SPI_ISR);
if (irq_status & SPI_INT_RXOI) {
if (irq_status & DW_SPI_INT_RXOI) {
dev_err(&dws->master->dev, "RX FIFO overflow detected\n");
ret = -EIO;
}
if (irq_status & SPI_INT_RXUI) {
if (irq_status & DW_SPI_INT_RXUI) {
dev_err(&dws->master->dev, "RX FIFO underflow detected\n");
ret = -EIO;
}
if (irq_status & SPI_INT_TXOI) {
if (irq_status & DW_SPI_INT_TXOI) {
dev_err(&dws->master->dev, "TX FIFO overflow detected\n");
ret = -EIO;
}
/* Generically handle the erroneous situation */
if (ret) {
spi_reset_chip(dws);
dw_spi_reset_chip(dws);
if (dws->master->cur_msg)
dws->master->cur_msg->status = ret;
}
return ret;
}
EXPORT_SYMBOL_GPL(dw_spi_check_status);
EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, SPI_DW_CORE);
static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
{
@ -230,7 +231,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
*/
dw_reader(dws);
if (!dws->rx_len) {
spi_mask_intr(dws, 0xff);
dw_spi_mask_intr(dws, 0xff);
spi_finalize_current_transfer(dws->master);
} else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
@ -241,10 +242,10 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
* disabled after the data transmission is finished so not to
* have the TXE IRQ flood at the final stage of the transfer.
*/
if (irq_status & SPI_INT_TXEI) {
if (irq_status & DW_SPI_INT_TXEI) {
dw_writer(dws);
if (!dws->tx_len)
spi_mask_intr(dws, SPI_INT_TXEI);
dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
}
return IRQ_HANDLED;
@ -254,13 +255,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
{
struct spi_controller *master = dev_id;
struct dw_spi *dws = spi_controller_get_devdata(master);
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f;
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK;
if (!irq_status)
return IRQ_NONE;
if (!master->cur_msg) {
spi_mask_intr(dws, 0xff);
dw_spi_mask_intr(dws, 0xff);
return IRQ_HANDLED;
}
@ -271,37 +272,43 @@ static u32 dw_spi_prepare_cr0(struct dw_spi *dws, struct spi_device *spi)
{
u32 cr0 = 0;
if (!(dws->caps & DW_SPI_CAP_DWC_SSI)) {
if (dw_spi_ip_is(dws, PSSI)) {
/* CTRLR0[ 5: 4] Frame Format */
cr0 |= SSI_MOTO_SPI << SPI_FRF_OFFSET;
cr0 |= FIELD_PREP(DW_PSSI_CTRLR0_FRF_MASK, DW_SPI_CTRLR0_FRF_MOTO_SPI);
/*
* SPI mode (SCPOL|SCPH)
* CTRLR0[ 6] Serial Clock Phase
* CTRLR0[ 7] Serial Clock Polarity
*/
cr0 |= ((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET;
cr0 |= ((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET;
if (spi->mode & SPI_CPOL)
cr0 |= DW_PSSI_CTRLR0_SCPOL;
if (spi->mode & SPI_CPHA)
cr0 |= DW_PSSI_CTRLR0_SCPHA;
/* CTRLR0[11] Shift Register Loop */
cr0 |= ((spi->mode & SPI_LOOP) ? 1 : 0) << SPI_SRL_OFFSET;
if (spi->mode & SPI_LOOP)
cr0 |= DW_PSSI_CTRLR0_SRL;
} else {
/* CTRLR0[ 7: 6] Frame Format */
cr0 |= SSI_MOTO_SPI << DWC_SSI_CTRLR0_FRF_OFFSET;
cr0 |= FIELD_PREP(DW_HSSI_CTRLR0_FRF_MASK, DW_SPI_CTRLR0_FRF_MOTO_SPI);
/*
* SPI mode (SCPOL|SCPH)
* CTRLR0[ 8] Serial Clock Phase
* CTRLR0[ 9] Serial Clock Polarity
*/
cr0 |= ((spi->mode & SPI_CPOL) ? 1 : 0) << DWC_SSI_CTRLR0_SCPOL_OFFSET;
cr0 |= ((spi->mode & SPI_CPHA) ? 1 : 0) << DWC_SSI_CTRLR0_SCPH_OFFSET;
if (spi->mode & SPI_CPOL)
cr0 |= DW_HSSI_CTRLR0_SCPOL;
if (spi->mode & SPI_CPHA)
cr0 |= DW_HSSI_CTRLR0_SCPHA;
/* CTRLR0[13] Shift Register Loop */
cr0 |= ((spi->mode & SPI_LOOP) ? 1 : 0) << DWC_SSI_CTRLR0_SRL_OFFSET;
if (spi->mode & SPI_LOOP)
cr0 |= DW_HSSI_CTRLR0_SRL;
if (dws->caps & DW_SPI_CAP_KEEMBAY_MST)
cr0 |= DWC_SSI_CTRLR0_KEEMBAY_MST;
cr0 |= DW_HSSI_CTRLR0_KEEMBAY_MST;
}
return cr0;
@ -310,7 +317,7 @@ static u32 dw_spi_prepare_cr0(struct dw_spi *dws, struct spi_device *spi)
void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
struct dw_spi_cfg *cfg)
{
struct chip_data *chip = spi_get_ctldata(spi);
struct dw_spi_chip_data *chip = spi_get_ctldata(spi);
u32 cr0 = chip->cr0;
u32 speed_hz;
u16 clk_div;
@ -318,16 +325,17 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
/* CTRLR0[ 4/3: 0] or CTRLR0[ 20: 16] Data Frame Size */
cr0 |= (cfg->dfs - 1) << dws->dfs_offset;
if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
if (dw_spi_ip_is(dws, PSSI))
/* CTRLR0[ 9:8] Transfer Mode */
cr0 |= cfg->tmode << SPI_TMOD_OFFSET;
cr0 |= FIELD_PREP(DW_PSSI_CTRLR0_TMOD_MASK, cfg->tmode);
else
/* CTRLR0[11:10] Transfer Mode */
cr0 |= cfg->tmode << DWC_SSI_CTRLR0_TMOD_OFFSET;
cr0 |= FIELD_PREP(DW_HSSI_CTRLR0_TMOD_MASK, cfg->tmode);
dw_writel(dws, DW_SPI_CTRLR0, cr0);
if (cfg->tmode == SPI_TMOD_EPROMREAD || cfg->tmode == SPI_TMOD_RO)
if (cfg->tmode == DW_SPI_CTRLR0_TMOD_EPROMREAD ||
cfg->tmode == DW_SPI_CTRLR0_TMOD_RO)
dw_writel(dws, DW_SPI_CTRLR1, cfg->ndf ? cfg->ndf - 1 : 0);
/* Note DW APB SSI clock divider doesn't support odd numbers */
@ -335,7 +343,7 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
speed_hz = dws->max_freq / clk_div;
if (dws->current_freq != speed_hz) {
spi_set_clk(dws, clk_div);
dw_spi_set_clk(dws, clk_div);
dws->current_freq = speed_hz;
}
@ -345,7 +353,7 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
dws->cur_rx_sample_dly = chip->rx_sample_dly;
}
}
EXPORT_SYMBOL_GPL(dw_spi_update_config);
EXPORT_SYMBOL_NS_GPL(dw_spi_update_config, SPI_DW_CORE);
static void dw_spi_irq_setup(struct dw_spi *dws)
{
@ -363,9 +371,9 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
dws->transfer_handler = dw_spi_transfer_handler;
imask = SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI |
SPI_INT_RXFI;
spi_umask_intr(dws, imask);
imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI |
DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
dw_spi_umask_intr(dws, imask);
}
/*
@ -405,11 +413,12 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
}
static int dw_spi_transfer_one(struct spi_controller *master,
struct spi_device *spi, struct spi_transfer *transfer)
struct spi_device *spi,
struct spi_transfer *transfer)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
struct dw_spi_cfg cfg = {
.tmode = SPI_TMOD_TR,
.tmode = DW_SPI_CTRLR0_TMOD_TR,
.dfs = transfer->bits_per_word,
.freq = transfer->speed_hz,
};
@ -425,7 +434,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
/* Ensure the data above is visible for all CPUs */
smp_mb();
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, spi, &cfg);
@ -436,7 +445,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
dws->dma_mapped = master->cur_msg_mapped;
/* For poll mode just disable all interrupts */
spi_mask_intr(dws, 0xff);
dw_spi_mask_intr(dws, 0xff);
if (dws->dma_mapped) {
ret = dws->dma_ops->dma_setup(dws, transfer);
@ -444,7 +453,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
return ret;
}
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
if (dws->dma_mapped)
return dws->dma_ops->dma_transfer(dws, transfer);
@ -457,20 +466,20 @@ static int dw_spi_transfer_one(struct spi_controller *master,
}
static void dw_spi_handle_err(struct spi_controller *master,
struct spi_message *msg)
struct spi_message *msg)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
if (dws->dma_mapped)
dws->dma_ops->dma_stop(dws);
spi_reset_chip(dws);
dw_spi_reset_chip(dws);
}
static int dw_spi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
if (op->data.dir == SPI_MEM_DATA_IN)
op->data.nbytes = clamp_val(op->data.nbytes, 0, SPI_NDF_MASK + 1);
op->data.nbytes = clamp_val(op->data.nbytes, 0, DW_SPI_NDF_MASK + 1);
return 0;
}
@ -498,7 +507,7 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
if (op->data.dir == SPI_MEM_DATA_OUT)
len += op->data.nbytes;
if (len <= SPI_BUF_SIZE) {
if (len <= DW_SPI_BUF_SIZE) {
out = dws->buf;
} else {
out = kzalloc(len, GFP_KERNEL);
@ -512,9 +521,9 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op)
* single buffer in order to speed the data transmission up.
*/
for (i = 0; i < op->cmd.nbytes; ++i)
out[i] = SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1);
out[i] = DW_SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1);
for (j = 0; j < op->addr.nbytes; ++i, ++j)
out[i] = SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1);
for (j = 0; j < op->dummy.nbytes; ++i, ++j)
out[i] = 0x0;
@ -587,7 +596,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
entries = readl_relaxed(dws->regs + DW_SPI_RXFLR);
if (!entries) {
sts = readl_relaxed(dws->regs + DW_SPI_RISR);
if (sts & SPI_INT_RXOI) {
if (sts & DW_SPI_INT_RXOI) {
dev_err(&dws->master->dev, "FIFO overflow on Rx\n");
return -EIO;
}
@ -603,12 +612,12 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
static inline bool dw_spi_ctlr_busy(struct dw_spi *dws)
{
return dw_readl(dws, DW_SPI_SR) & SR_BUSY;
return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY;
}
static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
{
int retry = SPI_WAIT_RETRIES;
int retry = DW_SPI_WAIT_RETRIES;
struct spi_delay delay;
unsigned long ns, us;
u32 nents;
@ -638,9 +647,9 @@ static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
static void dw_spi_stop_mem_op(struct dw_spi *dws, struct spi_device *spi)
{
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_spi_set_cs(spi, true);
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
}
/*
@ -673,19 +682,19 @@ static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
cfg.dfs = 8;
cfg.freq = clamp(mem->spi->max_speed_hz, 0U, dws->max_mem_freq);
if (op->data.dir == SPI_MEM_DATA_IN) {
cfg.tmode = SPI_TMOD_EPROMREAD;
cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;
cfg.ndf = op->data.nbytes;
} else {
cfg.tmode = SPI_TMOD_TO;
cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
}
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_spi_update_config(dws, mem->spi, &cfg);
spi_mask_intr(dws, 0xff);
dw_spi_mask_intr(dws, 0xff);
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
/*
* DW APB SSI controller has very nasty peculiarities. First originally
@ -768,7 +777,7 @@ static void dw_spi_init_mem_ops(struct dw_spi *dws)
static int dw_spi_setup(struct spi_device *spi)
{
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
struct chip_data *chip;
struct dw_spi_chip_data *chip;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
@ -776,7 +785,7 @@ static int dw_spi_setup(struct spi_device *spi)
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
u32 rx_sample_dly_ns;
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
spi_set_ctldata(spi, chip);
@ -803,16 +812,30 @@ static int dw_spi_setup(struct spi_device *spi)
static void dw_spi_cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
struct dw_spi_chip_data *chip = spi_get_ctldata(spi);
kfree(chip);
spi_set_ctldata(spi, NULL);
}
/* Restart the controller, disable all interrupts, clean rx fifo */
static void spi_hw_init(struct device *dev, struct dw_spi *dws)
static void dw_spi_hw_init(struct device *dev, struct dw_spi *dws)
{
spi_reset_chip(dws);
dw_spi_reset_chip(dws);
/*
* Retrieve the Synopsys component version if it hasn't been specified
* by the platform. CoreKit version ID is encoded as a 3-chars ASCII
* code enclosed with '*' (typical for the most of Synopsys IP-cores).
*/
if (!dws->ver) {
dws->ver = dw_readl(dws, DW_SPI_VERSION);
dev_dbg(dev, "Synopsys DWC%sSSI v%c.%c%c\n",
dw_spi_ip_is(dws, PSSI) ? " APB " : " ",
DW_SPI_GET_BYTE(dws->ver, 3), DW_SPI_GET_BYTE(dws->ver, 2),
DW_SPI_GET_BYTE(dws->ver, 1));
}
/*
* Try to detect the FIFO depth if not set by interface driver,
@ -837,18 +860,18 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
* writability. Note DWC SSI controller also has the extended DFS, but
* with zero offset.
*/
if (!(dws->caps & DW_SPI_CAP_DWC_SSI)) {
if (dw_spi_ip_is(dws, PSSI)) {
u32 cr0, tmp = dw_readl(dws, DW_SPI_CTRLR0);
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_writel(dws, DW_SPI_CTRLR0, 0xffffffff);
cr0 = dw_readl(dws, DW_SPI_CTRLR0);
dw_writel(dws, DW_SPI_CTRLR0, tmp);
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
if (!(cr0 & SPI_DFS_MASK)) {
if (!(cr0 & DW_PSSI_CTRLR0_DFS_MASK)) {
dws->caps |= DW_SPI_CAP_DFS32;
dws->dfs_offset = SPI_DFS32_OFFSET;
dws->dfs_offset = __bf_shf(DW_PSSI_CTRLR0_DFS32_MASK);
dev_dbg(dev, "Detected 32-bits max data frame size\n");
}
} else {
@ -872,13 +895,15 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
if (!master)
return -ENOMEM;
device_set_node(&master->dev, dev_fwnode(dev));
dws->master = master;
dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
spi_controller_set_devdata(master, dws);
/* Basic HW init */
spi_hw_init(dev, dws);
dw_spi_hw_init(dev, dws);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
master);
@ -908,8 +933,6 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
if (dws->mem_ops.exec_op)
master->mem_ops = &dws->mem_ops;
master->max_speed_hz = dws->max_freq;
master->dev.of_node = dev->of_node;
master->dev.fwnode = dev->fwnode;
master->flags = SPI_MASTER_GPIO_SS;
master->auto_runtime_pm = true;
@ -939,13 +962,13 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
err_dma_exit:
if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws);
spi_enable_chip(dws, 0);
dw_spi_enable_chip(dws, 0);
free_irq(dws->irq, master);
err_free_master:
spi_controller_put(master);
return ret;
}
EXPORT_SYMBOL_GPL(dw_spi_add_host);
EXPORT_SYMBOL_NS_GPL(dw_spi_add_host, SPI_DW_CORE);
void dw_spi_remove_host(struct dw_spi *dws)
{
@ -956,11 +979,11 @@ void dw_spi_remove_host(struct dw_spi *dws)
if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws);
spi_shutdown_chip(dws);
dw_spi_shutdown_chip(dws);
free_irq(dws->irq, dws->master);
}
EXPORT_SYMBOL_GPL(dw_spi_remove_host);
EXPORT_SYMBOL_NS_GPL(dw_spi_remove_host, SPI_DW_CORE);
int dw_spi_suspend_host(struct dw_spi *dws)
{
@ -970,17 +993,17 @@ int dw_spi_suspend_host(struct dw_spi *dws)
if (ret)
return ret;
spi_shutdown_chip(dws);
dw_spi_shutdown_chip(dws);
return 0;
}
EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
EXPORT_SYMBOL_NS_GPL(dw_spi_suspend_host, SPI_DW_CORE);
int dw_spi_resume_host(struct dw_spi *dws)
{
spi_hw_init(&dws->master->dev, dws);
dw_spi_hw_init(&dws->master->dev, dws);
return spi_controller_resume(dws->master);
}
EXPORT_SYMBOL_GPL(dw_spi_resume_host);
EXPORT_SYMBOL_NS_GPL(dw_spi_resume_host, SPI_DW_CORE);
MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");

View File

@ -10,6 +10,7 @@
#include <linux/dmaengine.h>
#include <linux/irqreturn.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_data/dma-dw.h>
#include <linux/spi/spi.h>
@ -17,10 +18,10 @@
#include "spi-dw.h"
#define RX_BUSY 0
#define RX_BURST_LEVEL 16
#define TX_BUSY 1
#define TX_BURST_LEVEL 16
#define DW_SPI_RX_BUSY 0
#define DW_SPI_RX_BURST_LEVEL 16
#define DW_SPI_TX_BUSY 1
#define DW_SPI_TX_BURST_LEVEL 16
static bool dw_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{
@ -45,7 +46,7 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
if (!ret && caps.max_burst)
max_burst = caps.max_burst;
else
max_burst = RX_BURST_LEVEL;
max_burst = DW_SPI_RX_BURST_LEVEL;
dws->rxburst = min(max_burst, def_burst);
dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1);
@ -54,7 +55,7 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
if (!ret && caps.max_burst)
max_burst = caps.max_burst;
else
max_burst = TX_BURST_LEVEL;
max_burst = DW_SPI_TX_BURST_LEVEL;
/*
* Having a Rx DMA channel serviced with higher priority than a Tx DMA
@ -226,13 +227,13 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
static inline bool dw_spi_dma_tx_busy(struct dw_spi *dws)
{
return !(dw_readl(dws, DW_SPI_SR) & SR_TF_EMPT);
return !(dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_TF_EMPT);
}
static int dw_spi_dma_wait_tx_done(struct dw_spi *dws,
struct spi_transfer *xfer)
{
int retry = SPI_WAIT_RETRIES;
int retry = DW_SPI_WAIT_RETRIES;
struct spi_delay delay;
u32 nents;
@ -259,8 +260,8 @@ static void dw_spi_dma_tx_done(void *arg)
{
struct dw_spi *dws = arg;
clear_bit(TX_BUSY, &dws->dma_chan_busy);
if (test_bit(RX_BUSY, &dws->dma_chan_busy))
clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy);
if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy))
return;
complete(&dws->dma_completion);
@ -304,19 +305,19 @@ static int dw_spi_dma_submit_tx(struct dw_spi *dws, struct scatterlist *sgl,
return ret;
}
set_bit(TX_BUSY, &dws->dma_chan_busy);
set_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy);
return 0;
}
static inline bool dw_spi_dma_rx_busy(struct dw_spi *dws)
{
return !!(dw_readl(dws, DW_SPI_SR) & SR_RF_NOT_EMPT);
return !!(dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_RF_NOT_EMPT);
}
static int dw_spi_dma_wait_rx_done(struct dw_spi *dws)
{
int retry = SPI_WAIT_RETRIES;
int retry = DW_SPI_WAIT_RETRIES;
struct spi_delay delay;
unsigned long ns, us;
u32 nents;
@ -360,8 +361,8 @@ static void dw_spi_dma_rx_done(void *arg)
{
struct dw_spi *dws = arg;
clear_bit(RX_BUSY, &dws->dma_chan_busy);
if (test_bit(TX_BUSY, &dws->dma_chan_busy))
clear_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy);
if (test_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy))
return;
complete(&dws->dma_completion);
@ -405,7 +406,7 @@ static int dw_spi_dma_submit_rx(struct dw_spi *dws, struct scatterlist *sgl,
return ret;
}
set_bit(RX_BUSY, &dws->dma_chan_busy);
set_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy);
return 0;
}
@ -430,16 +431,16 @@ static int dw_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
}
/* Set the DMA handshaking interface */
dma_ctrl = SPI_DMA_TDMAE;
dma_ctrl = DW_SPI_DMACR_TDMAE;
if (xfer->rx_buf)
dma_ctrl |= SPI_DMA_RDMAE;
dma_ctrl |= DW_SPI_DMACR_RDMAE;
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
/* Set the interrupt mask */
imr = SPI_INT_TXOI;
imr = DW_SPI_INT_TXOI;
if (xfer->rx_buf)
imr |= SPI_INT_RXUI | SPI_INT_RXOI;
spi_umask_intr(dws, imr);
imr |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI;
dw_spi_umask_intr(dws, imr);
reinit_completion(&dws->dma_completion);
@ -615,13 +616,13 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
static void dw_spi_dma_stop(struct dw_spi *dws)
{
if (test_bit(TX_BUSY, &dws->dma_chan_busy)) {
if (test_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_sync(dws->txchan);
clear_bit(TX_BUSY, &dws->dma_chan_busy);
clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy);
}
if (test_bit(RX_BUSY, &dws->dma_chan_busy)) {
if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_sync(dws->rxchan);
clear_bit(RX_BUSY, &dws->dma_chan_busy);
clear_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy);
}
}
@ -638,7 +639,7 @@ void dw_spi_dma_setup_mfld(struct dw_spi *dws)
{
dws->dma_ops = &dw_spi_dma_mfld_ops;
}
EXPORT_SYMBOL_GPL(dw_spi_dma_setup_mfld);
EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_mfld, SPI_DW_CORE);
static const struct dw_spi_dma_ops dw_spi_dma_generic_ops = {
.dma_init = dw_spi_dma_init_generic,
@ -653,4 +654,4 @@ void dw_spi_dma_setup_generic(struct dw_spi *dws)
{
dws->dma_ops = &dw_spi_dma_generic_ops;
}
EXPORT_SYMBOL_GPL(dw_spi_dma_setup_generic);
EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_generic, SPI_DW_CORE);

View File

@ -196,18 +196,18 @@ static int dw_spi_alpine_init(struct platform_device *pdev,
return 0;
}
static int dw_spi_dw_apb_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
static int dw_spi_pssi_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
dw_spi_dma_setup_generic(&dwsmmio->dws);
return 0;
}
static int dw_spi_dwc_ssi_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
static int dw_spi_hssi_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
dwsmmio->dws.caps = DW_SPI_CAP_DWC_SSI;
dwsmmio->dws.ip = DW_HSSI_ID;
dw_spi_dma_setup_generic(&dwsmmio->dws);
@ -217,7 +217,8 @@ static int dw_spi_dwc_ssi_init(struct platform_device *pdev,
static int dw_spi_keembay_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
dwsmmio->dws.caps = DW_SPI_CAP_KEEMBAY_MST | DW_SPI_CAP_DWC_SSI;
dwsmmio->dws.ip = DW_HSSI_ID;
dwsmmio->dws.caps = DW_SPI_CAP_KEEMBAY_MST;
return 0;
}
@ -342,12 +343,12 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
}
static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dw-apb-ssi", .data = dw_spi_dw_apb_init},
{ .compatible = "snps,dw-apb-ssi", .data = dw_spi_pssi_init},
{ .compatible = "mscc,ocelot-spi", .data = dw_spi_mscc_ocelot_init},
{ .compatible = "mscc,jaguar2-spi", .data = dw_spi_mscc_jaguar2_init},
{ .compatible = "amazon,alpine-dw-apb-ssi", .data = dw_spi_alpine_init},
{ .compatible = "renesas,rzn1-spi", .data = dw_spi_dw_apb_init},
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
{ .compatible = "renesas,rzn1-spi", .data = dw_spi_pssi_init},
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init},
{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
{ .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
@ -357,7 +358,7 @@ MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id dw_spi_mmio_acpi_match[] = {
{"HISI0173", (kernel_ulong_t)dw_spi_dw_apb_init},
{"HISI0173", (kernel_ulong_t)dw_spi_pssi_init},
{},
};
MODULE_DEVICE_TABLE(acpi, dw_spi_mmio_acpi_match);
@ -377,3 +378,4 @@ module_platform_driver(dw_spi_mmio_driver);
MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SPI_DW_CORE);

View File

@ -24,14 +24,14 @@
#define CLK_SPI_CDIV_MASK 0x00000e00
#define CLK_SPI_DISABLE_OFFSET 8
struct spi_pci_desc {
struct dw_spi_pci_desc {
int (*setup)(struct dw_spi *);
u16 num_cs;
u16 bus_num;
u32 max_freq;
};
static int spi_mid_init(struct dw_spi *dws)
static int dw_spi_pci_mid_init(struct dw_spi *dws)
{
void __iomem *clk_reg;
u32 clk_cdiv;
@ -53,36 +53,36 @@ static int spi_mid_init(struct dw_spi *dws)
return 0;
}
static int spi_generic_init(struct dw_spi *dws)
static int dw_spi_pci_generic_init(struct dw_spi *dws)
{
dw_spi_dma_setup_generic(dws);
return 0;
}
static struct spi_pci_desc spi_pci_mid_desc_1 = {
.setup = spi_mid_init,
static struct dw_spi_pci_desc dw_spi_pci_mid_desc_1 = {
.setup = dw_spi_pci_mid_init,
.num_cs = 5,
.bus_num = 0,
};
static struct spi_pci_desc spi_pci_mid_desc_2 = {
.setup = spi_mid_init,
static struct dw_spi_pci_desc dw_spi_pci_mid_desc_2 = {
.setup = dw_spi_pci_mid_init,
.num_cs = 2,
.bus_num = 1,
};
static struct spi_pci_desc spi_pci_ehl_desc = {
.setup = spi_generic_init,
static struct dw_spi_pci_desc dw_spi_pci_ehl_desc = {
.setup = dw_spi_pci_generic_init,
.num_cs = 2,
.bus_num = -1,
.max_freq = 100000000,
};
static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int dw_spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct dw_spi_pci_desc *desc = (struct dw_spi_pci_desc *)ent->driver_data;
struct dw_spi *dws;
struct spi_pci_desc *desc = (struct spi_pci_desc *)ent->driver_data;
int pci_bar = 0;
int ret;
@ -150,7 +150,7 @@ err_free_irq_vectors:
return ret;
}
static void spi_pci_remove(struct pci_dev *pdev)
static void dw_spi_pci_remove(struct pci_dev *pdev)
{
struct dw_spi *dws = pci_get_drvdata(pdev);
@ -162,14 +162,14 @@ static void spi_pci_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM_SLEEP
static int spi_suspend(struct device *dev)
static int dw_spi_pci_suspend(struct device *dev)
{
struct dw_spi *dws = dev_get_drvdata(dev);
return dw_spi_suspend_host(dws);
}
static int spi_resume(struct device *dev)
static int dw_spi_pci_resume(struct device *dev)
{
struct dw_spi *dws = dev_get_drvdata(dev);
@ -177,39 +177,39 @@ static int spi_resume(struct device *dev)
}
#endif
static SIMPLE_DEV_PM_OPS(dw_spi_pm_ops, spi_suspend, spi_resume);
static SIMPLE_DEV_PM_OPS(dw_spi_pci_pm_ops, dw_spi_pci_suspend, dw_spi_pci_resume);
static const struct pci_device_id pci_ids[] = {
static const struct pci_device_id dw_spi_pci_ids[] = {
/* Intel MID platform SPI controller 0 */
/*
* The access to the device 8086:0801 is disabled by HW, since it's
* exclusively used by SCU to communicate with MSIC.
*/
/* Intel MID platform SPI controller 1 */
{ PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc_1},
{ PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&dw_spi_pci_mid_desc_1},
/* Intel MID platform SPI controller 2 */
{ PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&spi_pci_mid_desc_2},
{ PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&dw_spi_pci_mid_desc_2},
/* Intel Elkhart Lake PSE SPI controllers */
{ PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
{ PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&dw_spi_pci_ehl_desc},
{},
};
MODULE_DEVICE_TABLE(pci, pci_ids);
MODULE_DEVICE_TABLE(pci, dw_spi_pci_ids);
static struct pci_driver dw_spi_driver = {
static struct pci_driver dw_spi_pci_driver = {
.name = DRIVER_NAME,
.id_table = pci_ids,
.probe = spi_pci_probe,
.remove = spi_pci_remove,
.id_table = dw_spi_pci_ids,
.probe = dw_spi_pci_probe,
.remove = dw_spi_pci_remove,
.driver = {
.pm = &dw_spi_pm_ops,
.pm = &dw_spi_pci_pm_ops,
},
};
module_pci_driver(dw_spi_driver);
module_pci_driver(dw_spi_pci_driver);
MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(SPI_DW_CORE);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef DW_SPI_HEADER_H
#define DW_SPI_HEADER_H
#ifndef __SPI_DW_H__
#define __SPI_DW_H__
#include <linux/bits.h>
#include <linux/completion.h>
@ -11,7 +11,30 @@
#include <linux/spi/spi-mem.h>
#include <linux/bitfield.h>
/* Register offsets */
/* Synopsys DW SSI IP-core virtual IDs */
#define DW_PSSI_ID 0
#define DW_HSSI_ID 1
/* Synopsys DW SSI component versions (FourCC sequence) */
#define DW_HSSI_102A 0x3130322a
/* DW SSI IP-core ID and version check helpers */
#define dw_spi_ip_is(_dws, _ip) \
((_dws)->ip == DW_ ## _ip ## _ID)
#define __dw_spi_ver_cmp(_dws, _ip, _ver, _op) \
(dw_spi_ip_is(_dws, _ip) && (_dws)->ver _op DW_ ## _ip ## _ver)
#define dw_spi_ver_is(_dws, _ip, _ver) __dw_spi_ver_cmp(_dws, _ip, _ver, ==)
#define dw_spi_ver_is_ge(_dws, _ip, _ver) __dw_spi_ver_cmp(_dws, _ip, _ver, >=)
/* DW SPI controller capabilities */
#define DW_SPI_CAP_CS_OVERRIDE BIT(0)
#define DW_SPI_CAP_KEEMBAY_MST BIT(1)
#define DW_SPI_CAP_DFS32 BIT(2)
/* Register offsets (Generic for both DWC APB SSI and DWC SSI IP-cores) */
#define DW_SPI_CTRLR0 0x00
#define DW_SPI_CTRLR1 0x04
#define DW_SPI_SSIENR 0x08
@ -40,92 +63,79 @@
#define DW_SPI_RX_SAMPLE_DLY 0xf0
#define DW_SPI_CS_OVERRIDE 0xf4
/* Bit fields in CTRLR0 */
#define SPI_DFS_OFFSET 0
#define SPI_DFS_MASK GENMASK(3, 0)
#define SPI_DFS32_OFFSET 16
/* Bit fields in CTRLR0 (DWC APB SSI) */
#define DW_PSSI_CTRLR0_DFS_MASK GENMASK(3, 0)
#define DW_PSSI_CTRLR0_DFS32_MASK GENMASK(20, 16)
#define SPI_FRF_OFFSET 4
#define SPI_FRF_SPI 0x0
#define SPI_FRF_SSP 0x1
#define SPI_FRF_MICROWIRE 0x2
#define SPI_FRF_RESV 0x3
#define DW_PSSI_CTRLR0_FRF_MASK GENMASK(5, 4)
#define DW_SPI_CTRLR0_FRF_MOTO_SPI 0x0
#define DW_SPI_CTRLR0_FRF_TI_SSP 0x1
#define DW_SPI_CTRLR0_FRF_NS_MICROWIRE 0x2
#define DW_SPI_CTRLR0_FRF_RESV 0x3
#define SPI_MODE_OFFSET 6
#define SPI_SCPH_OFFSET 6
#define SPI_SCOL_OFFSET 7
#define DW_PSSI_CTRLR0_MODE_MASK GENMASK(7, 6)
#define DW_PSSI_CTRLR0_SCPHA BIT(6)
#define DW_PSSI_CTRLR0_SCPOL BIT(7)
#define SPI_TMOD_OFFSET 8
#define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET)
#define SPI_TMOD_TR 0x0 /* xmit & recv */
#define SPI_TMOD_TO 0x1 /* xmit only */
#define SPI_TMOD_RO 0x2 /* recv only */
#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */
#define DW_PSSI_CTRLR0_TMOD_MASK GENMASK(9, 8)
#define DW_SPI_CTRLR0_TMOD_TR 0x0 /* xmit & recv */
#define DW_SPI_CTRLR0_TMOD_TO 0x1 /* xmit only */
#define DW_SPI_CTRLR0_TMOD_RO 0x2 /* recv only */
#define DW_SPI_CTRLR0_TMOD_EPROMREAD 0x3 /* eeprom read mode */
#define SPI_SLVOE_OFFSET 10
#define SPI_SRL_OFFSET 11
#define SPI_CFS_OFFSET 12
#define DW_PSSI_CTRLR0_SLV_OE BIT(10)
#define DW_PSSI_CTRLR0_SRL BIT(11)
#define DW_PSSI_CTRLR0_CFS BIT(12)
/* Bit fields in CTRLR0 based on DWC_ssi_databook.pdf v1.01a */
#define DWC_SSI_CTRLR0_SRL_OFFSET 13
#define DWC_SSI_CTRLR0_TMOD_OFFSET 10
#define DWC_SSI_CTRLR0_TMOD_MASK GENMASK(11, 10)
#define DWC_SSI_CTRLR0_SCPOL_OFFSET 9
#define DWC_SSI_CTRLR0_SCPH_OFFSET 8
#define DWC_SSI_CTRLR0_FRF_OFFSET 6
#define DWC_SSI_CTRLR0_DFS_OFFSET 0
/* Bit fields in CTRLR0 (DWC SSI with AHB interface) */
#define DW_HSSI_CTRLR0_DFS_MASK GENMASK(4, 0)
#define DW_HSSI_CTRLR0_FRF_MASK GENMASK(7, 6)
#define DW_HSSI_CTRLR0_SCPHA BIT(8)
#define DW_HSSI_CTRLR0_SCPOL BIT(9)
#define DW_HSSI_CTRLR0_TMOD_MASK GENMASK(11, 10)
#define DW_HSSI_CTRLR0_SRL BIT(13)
/*
* For Keem Bay, CTRLR0[31] is used to select controller mode.
* 0: SSI is slave
* 1: SSI is master
*/
#define DWC_SSI_CTRLR0_KEEMBAY_MST BIT(31)
#define DW_HSSI_CTRLR0_KEEMBAY_MST BIT(31)
/* Bit fields in CTRLR1 */
#define SPI_NDF_MASK GENMASK(15, 0)
#define DW_SPI_NDF_MASK GENMASK(15, 0)
/* Bit fields in SR, 7 bits */
#define SR_MASK 0x7f /* cover 7 bits */
#define SR_BUSY (1 << 0)
#define SR_TF_NOT_FULL (1 << 1)
#define SR_TF_EMPT (1 << 2)
#define SR_RF_NOT_EMPT (1 << 3)
#define SR_RF_FULL (1 << 4)
#define SR_TX_ERR (1 << 5)
#define SR_DCOL (1 << 6)
#define DW_SPI_SR_MASK GENMASK(6, 0)
#define DW_SPI_SR_BUSY BIT(0)
#define DW_SPI_SR_TF_NOT_FULL BIT(1)
#define DW_SPI_SR_TF_EMPT BIT(2)
#define DW_SPI_SR_RF_NOT_EMPT BIT(3)
#define DW_SPI_SR_RF_FULL BIT(4)
#define DW_SPI_SR_TX_ERR BIT(5)
#define DW_SPI_SR_DCOL BIT(6)
/* Bit fields in ISR, IMR, RISR, 7 bits */
#define SPI_INT_TXEI (1 << 0)
#define SPI_INT_TXOI (1 << 1)
#define SPI_INT_RXUI (1 << 2)
#define SPI_INT_RXOI (1 << 3)
#define SPI_INT_RXFI (1 << 4)
#define SPI_INT_MSTI (1 << 5)
#define DW_SPI_INT_MASK GENMASK(5, 0)
#define DW_SPI_INT_TXEI BIT(0)
#define DW_SPI_INT_TXOI BIT(1)
#define DW_SPI_INT_RXUI BIT(2)
#define DW_SPI_INT_RXOI BIT(3)
#define DW_SPI_INT_RXFI BIT(4)
#define DW_SPI_INT_MSTI BIT(5)
/* Bit fields in DMACR */
#define SPI_DMA_RDMAE (1 << 0)
#define SPI_DMA_TDMAE (1 << 1)
#define DW_SPI_DMACR_RDMAE BIT(0)
#define DW_SPI_DMACR_TDMAE BIT(1)
#define SPI_WAIT_RETRIES 5
#define SPI_BUF_SIZE \
/* Mem/DMA operations helpers */
#define DW_SPI_WAIT_RETRIES 5
#define DW_SPI_BUF_SIZE \
(sizeof_field(struct spi_mem_op, cmd.opcode) + \
sizeof_field(struct spi_mem_op, addr.val) + 256)
#define SPI_GET_BYTE(_val, _idx) \
#define DW_SPI_GET_BYTE(_val, _idx) \
((_val) >> (BITS_PER_BYTE * (_idx)) & 0xff)
enum dw_ssi_type {
SSI_MOTO_SPI = 0,
SSI_TI_SSP,
SSI_NS_MICROWIRE,
};
/* DW SPI capabilities */
#define DW_SPI_CAP_CS_OVERRIDE BIT(0)
#define DW_SPI_CAP_KEEMBAY_MST BIT(1)
#define DW_SPI_CAP_DWC_SSI BIT(2)
#define DW_SPI_CAP_DFS32 BIT(3)
/* Slave spi_transfer/spi_mem_op related */
struct dw_spi_cfg {
u8 tmode;
@ -148,6 +158,10 @@ struct dw_spi_dma_ops {
struct dw_spi {
struct spi_controller *master;
u32 ip; /* Synopsys DW SSI IP-core ID */
u32 ver; /* Synopsys component version */
u32 caps; /* DW SPI capabilities */
void __iomem *regs;
unsigned long paddr;
int irq;
@ -156,8 +170,6 @@ struct dw_spi {
u32 max_mem_freq; /* max mem-ops bus freq */
u32 max_freq; /* max bus freq supported */
u32 caps; /* DW SPI capabilities */
u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num;
u16 num_cs; /* supported slave numbers */
@ -168,7 +180,7 @@ struct dw_spi {
unsigned int tx_len;
void *rx;
unsigned int rx_len;
u8 buf[SPI_BUF_SIZE];
u8 buf[DW_SPI_BUF_SIZE];
int dma_mapped;
u8 n_bytes; /* current is a 1/2 bytes op */
irqreturn_t (*transfer_handler)(struct dw_spi *dws);
@ -230,18 +242,18 @@ static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
}
}
static inline void spi_enable_chip(struct dw_spi *dws, int enable)
static inline void dw_spi_enable_chip(struct dw_spi *dws, int enable)
{
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
}
static inline void spi_set_clk(struct dw_spi *dws, u16 div)
static inline void dw_spi_set_clk(struct dw_spi *dws, u16 div)
{
dw_writel(dws, DW_SPI_BAUDR, div);
}
/* Disable IRQ bits */
static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
static inline void dw_spi_mask_intr(struct dw_spi *dws, u32 mask)
{
u32 new_mask;
@ -250,7 +262,7 @@ static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
}
/* Enable IRQ bits */
static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
static inline void dw_spi_umask_intr(struct dw_spi *dws, u32 mask)
{
u32 new_mask;
@ -263,19 +275,19 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
* and CS, then re-enables the controller back. Transmit and receive FIFO
* buffers are cleared when the device is disabled.
*/
static inline void spi_reset_chip(struct dw_spi *dws)
static inline void dw_spi_reset_chip(struct dw_spi *dws)
{
spi_enable_chip(dws, 0);
spi_mask_intr(dws, 0xff);
dw_spi_enable_chip(dws, 0);
dw_spi_mask_intr(dws, 0xff);
dw_readl(dws, DW_SPI_ICR);
dw_writel(dws, DW_SPI_SER, 0);
spi_enable_chip(dws, 1);
dw_spi_enable_chip(dws, 1);
}
static inline void spi_shutdown_chip(struct dw_spi *dws)
static inline void dw_spi_shutdown_chip(struct dw_spi *dws)
{
spi_enable_chip(dws, 0);
spi_set_clk(dws, 0);
dw_spi_enable_chip(dws, 0);
dw_spi_set_clk(dws, 0);
}
extern void dw_spi_set_cs(struct spi_device *spi, bool enable);
@ -299,4 +311,4 @@ static inline void dw_spi_dma_setup_generic(struct dw_spi *dws) {}
#endif /* !CONFIG_SPI_DW_DMA */
#endif /* DW_SPI_HEADER_H */
#endif /* __SPI_DW_H__ */

View File

@ -913,7 +913,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "spi_register_controller error: %i\n", ret);
goto out_pm_get;
goto free_dma;
}
pm_runtime_mark_last_busy(fsl_lpspi->dev);
@ -921,6 +921,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
return 0;
free_dma:
fsl_lpspi_dma_exit(controller);
out_pm_get:
pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
pm_runtime_put_sync(fsl_lpspi->dev);
@ -937,6 +939,8 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
struct fsl_lpspi_data *fsl_lpspi =
spi_controller_get_devdata(controller);
fsl_lpspi_dma_exit(controller);
pm_runtime_disable(fsl_lpspi->dev);
return 0;
}

View File

@ -71,10 +71,6 @@
#define GSI_CPHA BIT(4)
#define GSI_CPOL BIT(5)
#define MAX_TX_SG 3
#define NUM_SPI_XFER 8
#define SPI_XFER_TIMEOUT_MS 250
struct spi_geni_master {
struct geni_se se;
struct device *dev;
@ -168,6 +164,30 @@ static void handle_fifo_timeout(struct spi_master *spi,
}
}
static void handle_gpi_timeout(struct spi_master *spi, struct spi_message *msg)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
dmaengine_terminate_sync(mas->tx);
dmaengine_terminate_sync(mas->rx);
}
static void spi_geni_handle_err(struct spi_master *spi, struct spi_message *msg)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
switch (mas->cur_xfer_mode) {
case GENI_SE_FIFO:
handle_fifo_timeout(spi, msg);
break;
case GENI_GPI_DMA:
handle_gpi_timeout(spi, msg);
break;
default:
dev_err(mas->dev, "Abort on Mode:%d not supported", mas->cur_xfer_mode);
}
}
static bool spi_geni_is_abort_still_pending(struct spi_geni_master *mas)
{
struct geni_se *se = &mas->se;
@ -350,17 +370,21 @@ spi_gsi_callback_result(void *cb, const struct dmaengine_result *result)
{
struct spi_master *spi = cb;
spi->cur_msg->status = -EIO;
if (result->result != DMA_TRANS_NOERROR) {
dev_err(&spi->dev, "DMA txn failed: %d\n", result->result);
spi_finalize_current_transfer(spi);
return;
}
if (!result->residue) {
spi->cur_msg->status = 0;
dev_dbg(&spi->dev, "DMA txn completed\n");
spi_finalize_current_transfer(spi);
} else {
dev_err(&spi->dev, "DMA xfer has pending: %d\n", result->residue);
}
spi_finalize_current_transfer(spi);
}
static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas,
@ -922,7 +946,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->can_dma = geni_can_dma;
spi->dma_map_dev = dev->parent;
spi->auto_runtime_pm = true;
spi->handle_err = handle_fifo_timeout;
spi->handle_err = spi_geni_handle_err;
spi->use_gpio_descriptors = true;
init_completion(&mas->cs_done);

View File

@ -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))
@ -490,7 +491,7 @@ static int hisi_spi_probe(struct platform_device *pdev)
master->use_gpio_descriptors = true;
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;
@ -506,15 +507,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);

View File

@ -349,6 +349,7 @@ static int meson_spifc_probe(struct platform_device *pdev)
return 0;
out_clk:
clk_disable_unprepare(spifc->clk);
pm_runtime_disable(spifc->dev);
out_err:
spi_master_put(master);
return ret;

View File

@ -427,7 +427,6 @@ static void lpss_ssp_cs_control(struct spi_device *spi, bool enable)
static void cs_assert(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
@ -436,18 +435,12 @@ static void cs_assert(struct spi_device *spi)
return;
}
if (chip->cs_control) {
chip->cs_control(PXA2XX_CS_ASSERT);
return;
}
if (is_lpss_ssp(drv_data))
lpss_ssp_cs_control(spi, true);
}
static void cs_deassert(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
unsigned long timeout;
@ -461,11 +454,6 @@ static void cs_deassert(struct spi_device *spi)
!time_after(jiffies, timeout))
cpu_relax();
if (chip->cs_control) {
chip->cs_control(PXA2XX_CS_DEASSERT);
return;
}
if (is_lpss_ssp(drv_data))
lpss_ssp_cs_control(spi, false);
}
@ -994,13 +982,10 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
dev_err(&spi->dev, "Flush failed\n");
return -EIO;
}
drv_data->n_bytes = chip->n_bytes;
drv_data->tx = (void *)transfer->tx_buf;
drv_data->tx_end = drv_data->tx + transfer->len;
drv_data->rx = transfer->rx_buf;
drv_data->rx_end = drv_data->rx + transfer->len;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
/* Change speed and bit per word on a per transfer */
bits = transfer->bits_per_word;
@ -1010,22 +995,16 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
if (bits <= 8) {
drv_data->n_bytes = 1;
drv_data->read = drv_data->read != null_reader ?
u8_reader : null_reader;
drv_data->write = drv_data->write != null_writer ?
u8_writer : null_writer;
drv_data->read = drv_data->rx ? u8_reader : null_reader;
drv_data->write = drv_data->tx ? u8_writer : null_writer;
} else if (bits <= 16) {
drv_data->n_bytes = 2;
drv_data->read = drv_data->read != null_reader ?
u16_reader : null_reader;
drv_data->write = drv_data->write != null_writer ?
u16_writer : null_writer;
drv_data->read = drv_data->rx ? u16_reader : null_reader;
drv_data->write = drv_data->tx ? u16_writer : null_writer;
} else if (bits <= 32) {
drv_data->n_bytes = 4;
drv_data->read = drv_data->read != null_reader ?
u32_reader : null_reader;
drv_data->write = drv_data->write != null_writer ?
u32_writer : null_writer;
drv_data->read = drv_data->rx ? u32_reader : null_reader;
drv_data->write = drv_data->tx ? u32_writer : null_writer;
}
/*
* If bits per word is changed in DMA mode, then must check
@ -1213,12 +1192,6 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
*/
cleanup_cs(spi);
/* If ->cs_control() is provided, ignore GPIO chip select */
if (chip_info->cs_control) {
chip->cs_control = chip_info->cs_control;
return 0;
}
if (gpio_is_valid(chip_info->gpio_cs)) {
int gpio = chip_info->gpio_cs;
int err;
@ -1316,7 +1289,6 @@ static int setup(struct spi_device *spi)
chip_info = spi->controller_data;
/* chip_info isn't always needed */
chip->cr1 = 0;
if (chip_info) {
if (chip_info->timeout)
chip->timeout = chip_info->timeout;
@ -1327,9 +1299,9 @@ static int setup(struct spi_device *spi)
if (chip_info->rx_threshold)
rx_thres = chip_info->rx_threshold;
chip->dma_threshold = 0;
if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM;
}
chip->cr1 = 0;
if (spi_controller_is_slave(drv_data->controller)) {
chip->cr1 |= SSCR1_SCFR;
chip->cr1 |= SSCR1_SCLKDIR;
@ -1391,20 +1363,6 @@ static int setup(struct spi_device *spi)
if (spi->mode & SPI_LOOP)
chip->cr1 |= SSCR1_LBM;
if (spi->bits_per_word <= 8) {
chip->n_bytes = 1;
chip->read = u8_reader;
chip->write = u8_writer;
} else if (spi->bits_per_word <= 16) {
chip->n_bytes = 2;
chip->read = u16_reader;
chip->write = u16_writer;
} else if (spi->bits_per_word <= 32) {
chip->n_bytes = 4;
chip->read = u32_reader;
chip->write = u32_writer;
}
spi_set_ctldata(spi, chip);
if (drv_data->ssp_type == CE4100_SSP)
@ -1706,8 +1664,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->controller_info = platform_info;
drv_data->ssp = ssp;
controller->dev.of_node = dev->of_node;
controller->dev.fwnode = dev->fwnode;
device_set_node(&controller->dev, dev_fwnode(dev));
/* The spi->mode bits understood by this driver: */
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;

View File

@ -49,7 +49,6 @@ struct driver_data {
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
void __iomem *lpss_base;
@ -61,18 +60,12 @@ struct chip_data {
u32 cr1;
u32 dds_rate;
u32 timeout;
u8 n_bytes;
u8 enable_dma;
u32 dma_burst_size;
u32 dma_threshold;
u32 threshold;
u16 lpss_rx_threshold;
u16 lpss_tx_threshold;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
static inline u32 pxa2xx_spi_read(const struct driver_data *drv_data, u32 reg)

View File

@ -21,6 +21,7 @@
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/sh_dma.h>
#include <linux/spi/spi.h>
#include <linux/spi/rspi.h>
@ -834,7 +835,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
int ret;
if (rspi->ctlr->can_dma && __rspi_can_dma(rspi, xfer)) {
int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
if (ret != -EAGAIN)
return ret;
}
@ -1225,8 +1226,14 @@ static const struct of_device_id rspi_of_match[] = {
MODULE_DEVICE_TABLE(of, rspi_of_match);
static void rspi_reset_control_assert(void *data)
{
reset_control_assert(data);
}
static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
{
struct reset_control *rstc;
u32 num_cs;
int error;
@ -1238,6 +1245,24 @@ static int rspi_parse_dt(struct device *dev, struct spi_controller *ctlr)
}
ctlr->num_chipselect = num_cs;
rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(rstc))
return dev_err_probe(dev, PTR_ERR(rstc),
"failed to get reset ctrl\n");
error = reset_control_deassert(rstc);
if (error) {
dev_err(dev, "failed to deassert reset %d\n", error);
return error;
}
error = devm_add_action_or_reset(dev, rspi_reset_control_assert, rstc);
if (error) {
dev_err(dev, "failed to register assert devm action, %d\n", error);
return error;
}
return 0;
}
#else

View File

@ -877,7 +877,7 @@ static struct tegra_qspi_client_data *tegra_qspi_parse_cdata_dt(struct spi_devic
struct tegra_qspi_client_data *cdata;
struct device_node *slave_np = spi->dev.of_node;
cdata = kzalloc(sizeof(*cdata), GFP_KERNEL);
cdata = devm_kzalloc(&spi->dev, sizeof(*cdata), GFP_KERNEL);
if (!cdata)
return NULL;
@ -888,14 +888,6 @@ static struct tegra_qspi_client_data *tegra_qspi_parse_cdata_dt(struct spi_devic
return cdata;
}
static void tegra_qspi_cleanup(struct spi_device *spi)
{
struct tegra_qspi_client_data *cdata = spi->controller_data;
spi->controller_data = NULL;
kfree(cdata);
}
static int tegra_qspi_setup(struct spi_device *spi)
{
struct tegra_qspi *tqspi = spi_master_get_devdata(spi->master);
@ -1229,7 +1221,6 @@ static int tegra_qspi_probe(struct platform_device *pdev)
SPI_TX_DUAL | SPI_RX_DUAL | SPI_TX_QUAD | SPI_RX_QUAD;
master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
master->setup = tegra_qspi_setup;
master->cleanup = tegra_qspi_cleanup;
master->transfer_one_message = tegra_qspi_transfer_one_message;
master->num_chipselect = 1;
master->auto_runtime_pm = true;

View File

@ -767,12 +767,13 @@ out_master_put:
static int uniphier_spi_remove(struct platform_device *pdev)
{
struct uniphier_spi_priv *priv = platform_get_drvdata(pdev);
struct spi_master *master = platform_get_drvdata(pdev);
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
if (priv->master->dma_tx)
dma_release_channel(priv->master->dma_tx);
if (priv->master->dma_rx)
dma_release_channel(priv->master->dma_rx);
if (master->dma_tx)
dma_release_channel(master->dma_tx);
if (master->dma_rx)
dma_release_channel(master->dma_rx);
clk_disable_unprepare(priv->clk);

View File

@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/interrupt.h>
/* SPI Configuration Register */
@ -436,17 +435,10 @@ static const struct acpi_device_id xlp_spi_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, xlp_spi_acpi_match);
#endif
static const struct of_device_id xlp_spi_dt_id[] = {
{ .compatible = "netlogic,xlp832-spi" },
{ },
};
MODULE_DEVICE_TABLE(of, xlp_spi_dt_id);
static struct platform_driver xlp_spi_driver = {
.probe = xlp_spi_probe,
.driver = {
.name = "xlp-spi",
.of_match_table = xlp_spi_dt_id,
.acpi_match_table = ACPI_PTR(xlp_spi_acpi_match),
},
};

View File

@ -33,6 +33,7 @@
#include <linux/highmem.h>
#include <linux/idr.h>
#include <linux/platform_data/x86/apple.h>
#include <linux/ptp_clock_kernel.h>
#define CREATE_TRACE_POINTS
#include <trace/events/spi.h>
@ -311,15 +312,14 @@ static void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
spin_unlock_irqrestore(&stats->lock, flags);
}
/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
/*
* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
* and the sysfs version makes coldplug work too.
*/
static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,
const struct spi_device *sdev)
static const struct spi_device_id *spi_match_id(const struct spi_device_id *id, const char *name)
{
while (id->name[0]) {
if (!strcmp(sdev->modalias, id->name))
if (!strcmp(name, id->name))
return id;
id++;
}
@ -330,7 +330,7 @@ const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
{
const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver);
return spi_match_id(sdrv->id_table, sdev);
return spi_match_id(sdrv->id_table, sdev->modalias);
}
EXPORT_SYMBOL_GPL(spi_get_device_id);
@ -352,7 +352,7 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
return 1;
if (sdrv->id_table)
return !!spi_match_id(sdrv->id_table, spi);
return !!spi_match_id(sdrv->id_table, spi->modalias);
return strcmp(spi->modalias, drv->name) == 0;
}
@ -474,12 +474,8 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv)
if (sdrv->id_table) {
const struct spi_device_id *spi_id;
for (spi_id = sdrv->id_table; spi_id->name[0];
spi_id++)
if (strcmp(spi_id->name, of_name) == 0)
break;
if (spi_id->name[0])
spi_id = spi_match_id(sdrv->id_table, of_name);
if (spi_id)
continue;
} else {
if (strcmp(sdrv->driver.name, of_name) == 0)
@ -497,7 +493,8 @@ EXPORT_SYMBOL_GPL(__spi_register_driver);
/*-------------------------------------------------------------------------*/
/* SPI devices should normally not be created by SPI device drivers; that
/*
* SPI devices should normally not be created by SPI device drivers; that
* would make them board-specific. Similarly with SPI controller drivers.
* Device registration normally goes into like arch/.../mach.../board-YYY.c
* with other readonly (flashable) information about mainboard devices.
@ -513,8 +510,8 @@ static LIST_HEAD(spi_controller_list);
/*
* Used to protect add/del operation for board_info list and
* spi_controller list, and their matching process
* also used to protect object of type struct idr
* spi_controller list, and their matching process also used
* to protect object of type struct idr.
*/
static DEFINE_MUTEX(board_lock);
@ -621,7 +618,8 @@ static int __spi_add_device(struct spi_device *spi)
else if (ctlr->cs_gpios)
spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
/* Drivers may modify this initial i/o setup, but will
/*
* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
@ -715,7 +713,8 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr,
struct spi_device *proxy;
int status;
/* NOTE: caller did any chip->bus_num checks necessary.
/*
* NOTE: caller did any chip->bus_num checks necessary.
*
* Also, unless we change the return value convention to use
* error-or-pointer (not NULL-or-pointer), troubleshootability
@ -883,7 +882,6 @@ static void *spi_res_alloc(struct spi_device *spi, spi_res_release_t release,
/**
* spi_res_free - free an spi resource
* @res: pointer to the custom data of a resource
*
*/
static void spi_res_free(void *res)
{
@ -947,12 +945,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
spi->controller->last_cs_enable = enable;
spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
!spi->controller->set_cs_timing) {
if (activate)
spi_delay_exec(&spi->cs_setup, NULL);
else
spi_delay_exec(&spi->cs_hold, NULL);
if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
!spi->controller->set_cs_timing) && !activate) {
spi_delay_exec(&spi->cs_hold, NULL);
}
if (spi->mode & SPI_CS_HIGH)
@ -978,7 +973,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
gpiod_set_value_cansleep(spi->cs_gpiod, activate);
} else {
/*
* invert the enable line, as active low is
* Invert the enable line, as active low is
* default for SPI.
*/
gpio_set_value_cansleep(spi->cs_gpio, !enable);
@ -994,7 +989,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
!spi->controller->set_cs_timing) {
if (!activate)
if (activate)
spi_delay_exec(&spi->cs_setup, NULL);
else
spi_delay_exec(&spi->cs_inactive, NULL);
}
}
@ -1227,11 +1224,10 @@ static int spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
if (max_tx) {
tmp = krealloc(ctlr->dummy_tx, max_tx,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | GFP_DMA | __GFP_ZERO);
if (!tmp)
return -ENOMEM;
ctlr->dummy_tx = tmp;
memset(tmp, 0, max_tx);
}
if (max_rx) {
@ -1717,16 +1713,7 @@ static void spi_pump_messages(struct kthread_work *work)
}
/**
* spi_take_timestamp_pre - helper for drivers to collect the beginning of the
* TX timestamp for the requested byte from the SPI
* transfer. The frequency with which this function
* must be called (once per word, once for the whole
* transfer, once per batch of words etc) is arbitrary
* as long as the @tx buffer offset is greater than or
* equal to the requested byte at the time of the
* call. The timestamp is only taken once, at the
* first such call. It is assumed that the driver
* advances its @tx buffer pointer monotonically.
* spi_take_timestamp_pre - helper to collect the beginning of the TX timestamp
* @ctlr: Pointer to the spi_controller structure of the driver
* @xfer: Pointer to the transfer being timestamped
* @progress: How many words (not bytes) have been transferred so far
@ -1736,6 +1723,14 @@ static void spi_pump_messages(struct kthread_work *work)
* spi_take_timestamp_post or otherwise system will crash.
* WARNING: for fully predictable results, the CPU frequency must
* also be under control (governor).
*
* This is a helper for drivers to collect the beginning of the TX timestamp
* for the requested byte from the SPI transfer. The frequency with which this
* function must be called (once per word, once for the whole transfer, once
* per batch of words etc) is arbitrary as long as the @tx buffer offset is
* greater than or equal to the requested byte at the time of the call. The
* timestamp is only taken once, at the first such call. It is assumed that
* the driver advances its @tx buffer pointer monotonically.
*/
void spi_take_timestamp_pre(struct spi_controller *ctlr,
struct spi_transfer *xfer,
@ -1763,16 +1758,16 @@ void spi_take_timestamp_pre(struct spi_controller *ctlr,
EXPORT_SYMBOL_GPL(spi_take_timestamp_pre);
/**
* spi_take_timestamp_post - helper for drivers to collect the end of the
* TX timestamp for the requested byte from the SPI
* transfer. Can be called with an arbitrary
* frequency: only the first call where @tx exceeds
* or is equal to the requested word will be
* timestamped.
* spi_take_timestamp_post - helper to collect the end of the TX timestamp
* @ctlr: Pointer to the spi_controller structure of the driver
* @xfer: Pointer to the transfer being timestamped
* @progress: How many words (not bytes) have been transferred so far
* @irqs_off: If true, will re-enable IRQs and preemption for the local CPU.
*
* This is a helper for drivers to collect the end of the TX timestamp for
* the requested byte from the SPI transfer. Can be called with an arbitrary
* frequency: only the first call where @tx exceeds or is equal to the
* requested word will be timestamped.
*/
void spi_take_timestamp_post(struct spi_controller *ctlr,
struct spi_transfer *xfer,
@ -1905,10 +1900,12 @@ void spi_finalize_current_message(struct spi_controller *ctlr)
spi_unmap_msg(ctlr, mesg);
/* In the prepare_messages callback the spi bus has the opportunity to
* split a transfer to smaller chunks.
* Release splited transfers here since spi_map_msg is done on the
* splited transfers.
/*
* In the prepare_messages callback the SPI bus has the opportunity
* to split a transfer to smaller chunks.
*
* Release the split transfers here since spi_map_msg() is done on
* the split transfers.
*/
spi_res_release(ctlr, mesg);
@ -2950,8 +2947,9 @@ int spi_register_controller(struct spi_controller *ctlr)
if (!ctlr->max_dma_len)
ctlr->max_dma_len = INT_MAX;
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
/*
* Register the device, then userspace will see it.
* Registration fails if the bus ID is in use.
*/
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
@ -3217,16 +3215,18 @@ static struct spi_replaced_transfers *spi_replace_transfers(
/* init the replaced_transfers list */
INIT_LIST_HEAD(&rxfer->replaced_transfers);
/* assign the list_entry after which we should reinsert
/*
* Assign the list_entry after which we should reinsert
* the @replaced_transfers - it may be spi_message.messages!
*/
rxfer->replaced_after = xfer_first->transfer_list.prev;
/* remove the requested number of transfers */
for (i = 0; i < remove; i++) {
/* if the entry after replaced_after it is msg->transfers
/*
* If the entry after replaced_after it is msg->transfers
* then we have been requested to remove more transfers
* than are in the list
* than are in the list.
*/
if (rxfer->replaced_after->next == &msg->transfers) {
dev_err(&msg->spi->dev,
@ -3242,15 +3242,17 @@ static struct spi_replaced_transfers *spi_replace_transfers(
return ERR_PTR(-EINVAL);
}
/* remove the entry after replaced_after from list of
* transfers and add it to list of replaced_transfers
/*
* Remove the entry after replaced_after from list of
* transfers and add it to list of replaced_transfers.
*/
list_move_tail(rxfer->replaced_after->next,
&rxfer->replaced_transfers);
}
/* create copy of the given xfer with identical settings
* based on the first transfer to get removed
/*
* Create copy of the given xfer with identical settings
* based on the first transfer to get removed.
*/
for (i = 0; i < insert; i++) {
/* we need to run in reverse order */
@ -3298,18 +3300,20 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr,
return PTR_ERR(srt);
xfers = srt->inserted_transfers;
/* now handle each of those newly inserted spi_transfers
* note that the replacements spi_transfers all are preset
/*
* Now handle each of those newly inserted spi_transfers.
* Note that the replacements spi_transfers all are preset
* to the same values as *xferp, so tx_buf, rx_buf and len
* are all identical (as well as most others)
* so we just have to fix up len and the pointers.
*
* this also includes support for the depreciated
* spi_message.is_dma_mapped interface
* This also includes support for the depreciated
* spi_message.is_dma_mapped interface.
*/
/* the first transfer just needs the length modified, so we
* run it outside the loop
/*
* The first transfer just needs the length modified, so we
* run it outside the loop.
*/
xfers[0].len = min_t(size_t, maxsize, xfer[0].len);
@ -3329,8 +3333,9 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr,
xfers[i].len = min(maxsize, xfers[i].len - offset);
}
/* we set up xferp to the last entry we have inserted,
* so that we skip those already split transfers
/*
* We set up xferp to the last entry we have inserted,
* so that we skip those already split transfers.
*/
*xferp = &xfers[count - 1];
@ -3362,11 +3367,12 @@ int spi_split_transfers_maxsize(struct spi_controller *ctlr,
struct spi_transfer *xfer;
int ret;
/* iterate over the transfer_list,
/*
* Iterate over the transfer_list,
* but note that xfer is advanced to the last transfer inserted
* to avoid checking sizes again unnecessarily (also xfer does
* potentiall belong to a different list by the time the
* replacement has happened
* potentially belong to a different list by the time the
* replacement has happened).
*/
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (xfer->len > maxsize) {
@ -3427,8 +3433,8 @@ int spi_setup(struct spi_device *spi)
int status;
/*
* check mode to prevent that any two of DUAL, QUAD and NO_MOSI/MISO
* are set at the same time
* Check mode to prevent that any two of DUAL, QUAD and NO_MOSI/MISO
* are set at the same time.
*/
if ((hweight_long(spi->mode &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_NO_TX)) > 1) ||
@ -3438,20 +3444,21 @@ int spi_setup(struct spi_device *spi)
"setup: can not select any two of dual, quad and no-rx/tx at the same time\n");
return -EINVAL;
}
/* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden
*/
/* If it is SPI_3WIRE mode, DUAL and QUAD should be forbidden */
if ((spi->mode & SPI_3WIRE) && (spi->mode &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL |
SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL)))
return -EINVAL;
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current controller
/*
* Help drivers fail *cleanly* when they need options
* that aren't supported with their current controller.
* SPI_CS_WORD has a fallback software implementation,
* so it is ignored here.
*/
bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD |
SPI_NO_TX | SPI_NO_RX);
/* nothing prevents from working with active-high CS in case if it
/*
* Nothing prevents from working with active-high CS in case if it
* is driven by GPIO.
*/
if (gpio_is_valid(spi->cs_gpio))
@ -3573,7 +3580,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
if (list_empty(&message->transfers))
return -EINVAL;
/* If an SPI controller does not support toggling the CS line on each
/*
* If an SPI controller does not support toggling the CS line on each
* transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO
* for the CS line, we can emulate the CS-per-word hardware function by
* splitting transfers into one-word transfers and ensuring that
@ -3603,7 +3611,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
}
}
/* Half-duplex links include original MicroWire, and ones with
/*
* Half-duplex links include original MicroWire, and ones with
* only one data pin like SPI_3WIRE (switches direction) or where
* either MOSI or MISO is missing. They can also be caused by
* software limitations.
@ -3622,7 +3631,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
}
}
/**
/*
* Set transfer bits_per_word and max speed as spi device default if
* it is not set for this transfer.
* Set transfer tx_nbits and rx_nbits as single transfer default
@ -3648,7 +3657,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
/*
* SPI transfer length should be multiple of SPI word size
* where SPI word size should be power-of-two multiple
* where SPI word size should be power-of-two multiple.
*/
if (xfer->bits_per_word <= 8)
w_size = 1;
@ -3669,7 +3678,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
xfer->tx_nbits = SPI_NBITS_SINGLE;
if (xfer->rx_buf && !xfer->rx_nbits)
xfer->rx_nbits = SPI_NBITS_SINGLE;
/* check transfer tx/rx_nbits:
/*
* Check transfer tx/rx_nbits:
* 1. check the value matches one of single, dual and quad
* 2. check tx/rx_nbits match the mode in spi_device
*/
@ -3848,7 +3858,8 @@ static int spi_async_locked(struct spi_device *spi, struct spi_message *message)
/*-------------------------------------------------------------------------*/
/* Utility methods for SPI protocol drivers, layered on
/*
* Utility methods for SPI protocol drivers, layered on
* top of the core. Some other utility methods are defined as
* inline functions.
*/
@ -3876,7 +3887,8 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_sync);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync);
/* If we're not using the legacy transfer method then we will
/*
* If we're not using the legacy transfer method then we will
* try to transfer in the calling context so special case.
* This code would be less tricky if we could remove the
* support for driver implemented message queues.
@ -3894,9 +3906,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
}
if (status == 0) {
/* Push out the messages in the calling context if we
* can.
*/
/* Push out the messages in the calling context if we can */
if (ctlr->transfer == spi_queued_transfer) {
SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics,
spi_sync_immediate);
@ -4057,7 +4067,8 @@ int spi_write_then_read(struct spi_device *spi,
struct spi_transfer x[2];
u8 *local_buf;
/* Use preallocated DMA-safe buffer if we can. We can't avoid
/*
* Use preallocated DMA-safe buffer if we can. We can't avoid
* copying here, (as a pure convenience thing), but we can
* keep heap costs out of the hot path unless someone else is
* using the pre-allocated buffer or the transfer is too large.
@ -4293,11 +4304,12 @@ err0:
return status;
}
/* board_info is normally registered in arch_initcall(),
* but even essential drivers wait till later
/*
* A board_info is normally registered in arch_initcall(),
* but even essential drivers wait till later.
*
* REVISIT only boardinfo really needs static linking. the rest (device and
* driver registration) _could_ be dynamically linked (modular) ... costs
* REVISIT only boardinfo really needs static linking. The rest (device and
* driver registration) _could_ be dynamically linked (modular) ... Costs
* include needing to have boardinfo data structures be much more public.
*/
postcore_initcall(spi_init);

View File

@ -415,7 +415,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
tmp |= SPI_CS_HIGH;
tmp |= spi->mode & ~SPI_MODE_MASK;
spi->mode = (u16)tmp;
spi->mode = tmp & SPI_MODE_USER_MASK;
retval = spi_setup(spi);
if (retval < 0)
spi->mode = save;
@ -751,9 +751,10 @@ static int spidev_probe(struct spi_device *spi)
* compatible string, it is a Linux implementation thing
* rather than a description of the hardware.
*/
WARN(spi->dev.of_node &&
of_device_is_compatible(spi->dev.of_node, "spidev"),
"%pOF: buggy DT: spidev listed directly in DT\n", spi->dev.of_node);
if (spi->dev.of_node && of_device_is_compatible(spi->dev.of_node, "spidev")) {
dev_err(&spi->dev, "spidev listed directly in DT is not supported\n");
return -EINVAL;
}
spidev_probe_acpi(spi);

View File

@ -1,17 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* CLPS711X SPI bus driver definitions
*
* Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
*/
#ifndef ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
#define ____LINUX_PLATFORM_DATA_SPI_CLPS711X_H
/* Board specific platform_data */
struct spi_clps711x_pdata {
int *chipselect; /* Array of GPIO-numbers */
int num_chipselect; /* Total count of GPIOs */
};
#endif

View File

@ -9,9 +9,6 @@
#include <linux/pxa2xx_ssp.h>
#define PXA2XX_CS_ASSERT (0x01)
#define PXA2XX_CS_DEASSERT (0x02)
struct dma_chan;
/*
@ -45,9 +42,7 @@ struct pxa2xx_spi_chip {
u8 rx_threshold;
u8 dma_burst_size;
u32 timeout;
u8 enable_loopback;
int gpio_cs;
void (*cs_control)(u32 command);
};
#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)

View File

@ -14,12 +14,12 @@
#include <linux/completion.h>
#include <linux/scatterlist.h>
#include <linux/gpio/consumer.h>
#include <linux/ptp_clock_kernel.h>
#include <uapi/linux/spi/spi.h>
struct dma_chan;
struct software_node;
struct ptp_system_timestamp;
struct spi_controller;
struct spi_transfer;
struct spi_controller_mem_ops;