spi: Updates for v6.6
There's been quite a lot of generic activity here, but more administrative than featuers. We also have a bunch of new drivers, including one that's part of a MFD so we pulled in the core parts of that: - Lots of work from both Yang Yingliang and Andy Shevchenko on moving to host/device/controller based terminology for devices. - QuadSPI SPI support for Allwinner sun6i. - New device support Cirrus Logic CS43L43, Longsoon, Qualcomm GENI QuPv3 and StarFive JH7110 QSPI. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmTp6KQACgkQJNaLcl1U h9BHMQf+Jtvdx8cIhzVyMRBUfmeEzpi5oGiurPiQVBM5RsO0APULbxdy1kBsQ4FO 5Omv7juG323XiZc1hrtBPNoZfnn83pjjMFZZZYse8Ntd6e5iesHzxRQJaml8NPBA 0ktJQiB6Eh9WTjYT6LgN8T5j4SLT5F2jiDinBPUj1vHGSy0YXGWpYFq9QIkXwMbE 8n0jyf5+Neccs4CIiPR3ap8NjIyPE/b761acRFkOmF+iiHWmnFrQYNS4CSxR2kOC yL0SlzuoG2feYSfiHyCKIPC0MGT5/Vn1tzNqoEam6B6Ecql24W8BMdU0/No3yKPT 22LIfRWR9Wb5usFxjDxIs9YaWD4abA== =oj/i -----END PGP SIGNATURE----- Merge tag 'spi-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi updates from Mark Brown: "There's been quite a lot of generic activity here, but more administrative than featuers. We also have a bunch of new drivers, including one that's part of a MFD so we pulled in the core parts of that: - Lots of work from both Yang Yingliang and Andy Shevchenko on moving to host/device/controller based terminology for devices. - QuadSPI SPI support for Allwinner sun6i. - New device support Cirrus Logic CS43L43, Longsoon, Qualcomm GENI QuPv3 and StarFive JH7110 QSPI" * tag 'spi-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (151 commits) spi: at91-usart: Use PTR_ERR_OR_ZERO() to simplify code spi: spi-sn-f-ospi: switch to use modern name spi: sifive: switch to use modern name spi: sh: switch to use modern name spi: sh-sci: switch to use modern name spi: sh-msiof: switch to use modern name spi: sh-hspi: switch to use modern name spi: sc18is602: switch to use modern name spi: s3c64xx: switch to use modern name spi: rzv2m-csi: switch to use devm_spi_alloc_host() spi: rspi: switch to use spi_alloc_host() spi: rockchip: switch to use modern name spi: rockchip-sfc: switch to use modern name spi: realtek-rtl: switch to use devm_spi_alloc_host() spi: rb4xx: switch to use modern name spi: qup: switch to use modern name spi: spi-qcom-qspi: switch to use modern name spi: pxa2xx: switch to use modern name spi: ppc4xx: switch to use modern name spi: spl022: switch to use modern name ...
This commit is contained in:
Коммит
3b6bf5b1f8
|
@ -0,0 +1,313 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/cirrus,cs42l43.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cirrus Logic CS42L43 Audio CODEC
|
||||
|
||||
maintainers:
|
||||
- patches@opensource.cirrus.com
|
||||
|
||||
description: |
|
||||
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface
|
||||
(Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed
|
||||
for portable applications. It provides a high dynamic range, stereo
|
||||
DAC for headphone output, two integrated Class D amplifiers for
|
||||
loudspeakers, and two ADCs for wired headset microphone input or
|
||||
stereo line input. PDM inputs are provided for digital microphones.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- cirrus,cs42l43
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-p-supply:
|
||||
description:
|
||||
Power supply for the high voltage interface.
|
||||
|
||||
vdd-a-supply:
|
||||
description:
|
||||
Power supply for internal analog circuits.
|
||||
|
||||
vdd-d-supply:
|
||||
description:
|
||||
Power supply for internal digital circuits. Can be internally supplied.
|
||||
|
||||
vdd-io-supply:
|
||||
description:
|
||||
Power supply for external interface and internal digital logic.
|
||||
|
||||
vdd-cp-supply:
|
||||
description:
|
||||
Power supply for the amplifier 3 and 4 charge pump.
|
||||
|
||||
vdd-amp-supply:
|
||||
description:
|
||||
Power supply for amplifier 1 and 2.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Synchronous audio clock provided on mclk_in.
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
cirrus,bias-low:
|
||||
type: boolean
|
||||
description:
|
||||
Select a 1.8V headset micbias rather than 2.8V.
|
||||
|
||||
cirrus,bias-sense-microamp:
|
||||
description:
|
||||
Current at which the headset micbias sense clamp will engage, 0 to
|
||||
disable.
|
||||
enum: [ 0, 14, 23, 41, 50, 60, 68, 86, 95 ]
|
||||
default: 0
|
||||
|
||||
cirrus,bias-ramp-ms:
|
||||
description:
|
||||
Time in milliseconds the hardware allows for the headset micbias to
|
||||
ramp up.
|
||||
enum: [ 10, 40, 90, 170 ]
|
||||
default: 170
|
||||
|
||||
cirrus,detect-us:
|
||||
description:
|
||||
Time in microseconds the type detection will run for. Long values will
|
||||
cause more audible effects, but give more accurate detection.
|
||||
enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ]
|
||||
default: 10000
|
||||
|
||||
cirrus,button-automute:
|
||||
type: boolean
|
||||
description:
|
||||
Enable the hardware automuting of decimator 1 when a headset button is
|
||||
pressed.
|
||||
|
||||
cirrus,buttons-ohms:
|
||||
description:
|
||||
Impedance in Ohms for each headset button, these should be listed in
|
||||
ascending order.
|
||||
minItems: 1
|
||||
maxItems: 6
|
||||
|
||||
cirrus,tip-debounce-ms:
|
||||
description:
|
||||
Software debounce on tip sense triggering in milliseconds.
|
||||
default: 0
|
||||
|
||||
cirrus,tip-invert:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates tip detect polarity, inverted implies open-circuit whilst the
|
||||
jack is inserted.
|
||||
|
||||
cirrus,tip-disable-pullup:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates if the internal pullup on the tip detect should be disabled.
|
||||
|
||||
cirrus,tip-fall-db-ms:
|
||||
description:
|
||||
Time in milliseconds a falling edge on the tip detect should be hardware
|
||||
debounced for. Note the falling edge is considered after the invert.
|
||||
enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ]
|
||||
default: 500
|
||||
|
||||
cirrus,tip-rise-db-ms:
|
||||
description:
|
||||
Time in milliseconds a rising edge on the tip detect should be hardware
|
||||
debounced for. Note the rising edge is considered after the invert.
|
||||
enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ]
|
||||
default: 500
|
||||
|
||||
cirrus,use-ring-sense:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates if the ring sense should be used.
|
||||
|
||||
cirrus,ring-invert:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates ring detect polarity, inverted implies open-circuit whilst the
|
||||
jack is inserted.
|
||||
|
||||
cirrus,ring-disable-pullup:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates if the internal pullup on the ring detect should be disabled.
|
||||
|
||||
cirrus,ring-fall-db-ms:
|
||||
description:
|
||||
Time in milliseconds a falling edge on the ring detect should be hardware
|
||||
debounced for. Note the falling edge is considered after the invert.
|
||||
enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ]
|
||||
default: 500
|
||||
|
||||
cirrus,ring-rise-db-ms:
|
||||
description:
|
||||
Time in milliseconds a rising edge on the ring detect should be hardware
|
||||
debounced for. Note the rising edge is considered after the invert.
|
||||
enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ]
|
||||
default: 500
|
||||
|
||||
pinctrl:
|
||||
type: object
|
||||
$ref: /schemas/pinctrl/pinctrl.yaml#
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
gpio-ranges:
|
||||
items:
|
||||
- description: A phandle to the CODEC pinctrl node
|
||||
minimum: 0
|
||||
- const: 0
|
||||
- const: 0
|
||||
- const: 3
|
||||
|
||||
patternProperties:
|
||||
"-state$":
|
||||
oneOf:
|
||||
- $ref: "#/$defs/cirrus-cs42l43-state"
|
||||
- patternProperties:
|
||||
"-pins$":
|
||||
$ref: "#/$defs/cirrus-cs42l43-state"
|
||||
additionalProperties: false
|
||||
|
||||
spi:
|
||||
type: object
|
||||
$ref: /schemas/spi/spi-controller.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
$defs:
|
||||
cirrus-cs42l43-state:
|
||||
type: object
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pinctrl/pincfg-node.yaml#
|
||||
- $ref: /schemas/pinctrl/pinmux-node.yaml#
|
||||
|
||||
oneOf:
|
||||
- required: [ groups ]
|
||||
- required: [ pins ]
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
groups:
|
||||
enum: [ gpio1, gpio2, gpio3, asp, pdmout2, pdmout1, i2c, spi ]
|
||||
|
||||
pins:
|
||||
enum: [ gpio1, gpio2, gpio3,
|
||||
asp_dout, asp_fsync, asp_bclk,
|
||||
pdmout2_clk, pdmout2_data, pdmout1_clk, pdmout1_data,
|
||||
i2c_sda, i2c_scl,
|
||||
spi_miso, spi_sck, spi_ssb ]
|
||||
|
||||
function:
|
||||
enum: [ gpio, spdif, irq, mic-shutter, spk-shutter ]
|
||||
|
||||
drive-strength:
|
||||
description: Set drive strength in mA
|
||||
enum: [ 1, 2, 4, 8, 9, 10, 12, 16 ]
|
||||
|
||||
input-debounce:
|
||||
description: Set input debounce in uS
|
||||
enum: [ 0, 85 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-p-supply
|
||||
- vdd-a-supply
|
||||
- vdd-io-supply
|
||||
- vdd-cp-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cs42l43: codec@1a {
|
||||
compatible = "cirrus,cs42l43";
|
||||
reg = <0x1a>;
|
||||
|
||||
vdd-p-supply = <&vdd5v0>;
|
||||
vdd-a-supply = <&vdd1v8>;
|
||||
vdd-io-supply = <&vdd1v8>;
|
||||
vdd-cp-supply = <&vdd1v8>;
|
||||
vdd-amp-supply = <&vdd5v0>;
|
||||
|
||||
reset-gpios = <&gpio 0>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
#sound-dai-cells = <1>;
|
||||
|
||||
clocks = <&clks 0>;
|
||||
clock-names = "mclk";
|
||||
|
||||
cs42l43_pins: pinctrl {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&cs42l43_pins 0 0 3>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinsettings>;
|
||||
|
||||
pinsettings: default-state {
|
||||
shutter-pins {
|
||||
groups = "gpio3";
|
||||
function = "mic-shutter";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cs-gpios = <&cs42l43_pins 1 0>;
|
||||
|
||||
sensor@0 {
|
||||
compatible = "bosch,bme680";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1400000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,71 @@
|
|||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/brcm,bcm63xx-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM6348/BCM6358 SPI controller
|
||||
|
||||
maintainers:
|
||||
- Jonas Gorski <jonas.gorski@gmail.com>
|
||||
|
||||
description: |
|
||||
Broadcom "Low Speed" SPI controller found in many older MIPS based Broadband
|
||||
SoCs.
|
||||
|
||||
This controller has a limitation that can not keep the chip select line active
|
||||
between the SPI transfers within the same SPI message. This can terminate the
|
||||
transaction to some SPI devices prematurely. The issue can be worked around by
|
||||
the controller's prepend mode.
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- brcm,bcm6368-spi
|
||||
- brcm,bcm6362-spi
|
||||
- brcm,bcm63268-spi
|
||||
- const: brcm,bcm6358-spi
|
||||
- enum:
|
||||
- brcm,bcm6348-spi
|
||||
- brcm,bcm6358-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SPI master reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: spi
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi@10000800 {
|
||||
compatible = "brcm,bcm6368-spi", "brcm,bcm6358-spi";
|
||||
reg = <0x10000800 0x70c>;
|
||||
interrupts = <1>;
|
||||
clocks = <&clkctl 9>;
|
||||
clock-names = "spi";
|
||||
num-cs = <5>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
|
@ -86,7 +86,17 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: ref
|
||||
- items:
|
||||
- const: ref
|
||||
- const: ahb
|
||||
- const: apb
|
||||
|
||||
cdns,fifo-depth:
|
||||
description:
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/loongson,ls2k-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Loongson SPI controller
|
||||
|
||||
maintainers:
|
||||
- Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- loongson,ls2k1000-spi
|
||||
- items:
|
||||
- enum:
|
||||
- loongson,ls2k0500-spi
|
||||
- const: loongson,ls2k1000-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi0: spi@1fff0220{
|
||||
compatible = "loongson,ls2k1000-spi";
|
||||
reg = <0x1fff0220 0x10>;
|
||||
clocks = <&clk 17>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
|
@ -1,61 +0,0 @@
|
|||
NVIDIA Tegra114 SPI controller.
|
||||
|
||||
Required properties:
|
||||
- compatible : For Tegra114, must contain "nvidia,tegra114-spi".
|
||||
Otherwise, must contain '"nvidia,<chip>-spi", "nvidia,tegra114-spi"' where
|
||||
<chip> is tegra124, tegra132, or tegra210.
|
||||
- reg: Should contain SPI registers location and length.
|
||||
- interrupts: Should contain SPI interrupts.
|
||||
- clock-names : Must include the following entries:
|
||||
- spi
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names : Must include the following entries:
|
||||
- spi
|
||||
- dmas : Must contain an entry for each entry in clock-names.
|
||||
See ../dma/dma.txt for details.
|
||||
- dma-names : Must include the following entries:
|
||||
- rx
|
||||
- tx
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
|
||||
Recommended properties:
|
||||
- spi-max-frequency: Definition as per
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
Optional properties:
|
||||
- nvidia,tx-clk-tap-delay: Delays the clock going out to the external device
|
||||
with this tap value. This property is used to tune the outgoing data from
|
||||
Tegra SPI master with respect to outgoing Tegra SPI master clock.
|
||||
Tap values vary based on the platform design trace lengths from Tegra SPI
|
||||
to corresponding slave devices. Valid tap values are from 0 thru 63.
|
||||
- nvidia,rx-clk-tap-delay: Delays the clock coming in from the external device
|
||||
with this tap value. This property is used to adjust the Tegra SPI master
|
||||
clock with respect to the data from the SPI slave device.
|
||||
Tap values vary based on the platform design trace lengths from Tegra SPI
|
||||
to corresponding slave devices. Valid tap values are from 0 thru 63.
|
||||
|
||||
Example:
|
||||
|
||||
spi@7000d600 {
|
||||
compatible = "nvidia,tegra114-spi";
|
||||
reg = <0x7000d600 0x200>;
|
||||
interrupts = <0 82 0x04>;
|
||||
spi-max-frequency = <25000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car 44>;
|
||||
clock-names = "spi";
|
||||
resets = <&tegra_car 44>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
<spi-client>@<bus_num> {
|
||||
...
|
||||
...
|
||||
nvidia,rx-clk-tap-delay = <0>;
|
||||
nvidia,tx-clk-tap-delay = <16>;
|
||||
...
|
||||
};
|
||||
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/nvidia,tegra114-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra114 SPI controller
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: nvidia,tegra114-spi
|
||||
- items:
|
||||
- enum:
|
||||
- nvidia,tegra210-spi
|
||||
- nvidia,tegra124-spi
|
||||
- const: nvidia,tegra114-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: SPI module clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: spi
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: SPI module reset
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: spi
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: DMA channel for the reception FIFO
|
||||
- description: DMA channel for the transmission FIFO
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
spi-max-frequency:
|
||||
description: Maximum SPI clocking speed of the controller in Hz.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi@7000d600 {
|
||||
compatible = "nvidia,tegra114-spi";
|
||||
reg = <0x7000d600 0x200>;
|
||||
interrupts = <0 82 0x04>;
|
||||
clocks = <&tegra_car 44>;
|
||||
clock-names = "spi";
|
||||
resets = <&tegra_car 44>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
|
||||
spi-max-frequency = <25000000>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <20000000>;
|
||||
nvidia,rx-clk-tap-delay = <0>;
|
||||
nvidia,tx-clk-tap-delay = <16>;
|
||||
};
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
NVIDIA Tegra20 SFLASH controller.
|
||||
|
||||
Required properties:
|
||||
- compatible : should be "nvidia,tegra20-sflash".
|
||||
- reg: Should contain SFLASH registers location and length.
|
||||
- interrupts: Should contain SFLASH interrupts.
|
||||
- clocks : Must contain one entry, for the module clock.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names : Must include the following entries:
|
||||
- spi
|
||||
- dmas : Must contain an entry for each entry in clock-names.
|
||||
See ../dma/dma.txt for details.
|
||||
- dma-names : Must include the following entries:
|
||||
- rx
|
||||
- tx
|
||||
|
||||
Recommended properties:
|
||||
- spi-max-frequency: Definition as per
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Example:
|
||||
|
||||
spi@7000c380 {
|
||||
compatible = "nvidia,tegra20-sflash";
|
||||
reg = <0x7000c380 0x80>;
|
||||
interrupts = <0 39 0x04>;
|
||||
spi-max-frequency = <25000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car 43>;
|
||||
resets = <&tegra_car 43>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 11>, <&apbdma 11>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/nvidia,tegra20-sflash.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra20 SFLASH controller
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nvidia,tegra20-sflash
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: module clock
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: module reset
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: spi
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: DMA channel used for reception
|
||||
- description: DMA channel used for transmission
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
spi-max-frequency:
|
||||
description: Maximum SPI clocking speed of the controller in Hz.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- resets
|
||||
- reset-names
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra20-car.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
spi@7000c380 {
|
||||
compatible = "nvidia,tegra20-sflash";
|
||||
reg = <0x7000c380 0x80>;
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
|
||||
spi-max-frequency = <25000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA20_CLK_SPI>;
|
||||
resets = <&tegra_car 43>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 11>, <&apbdma 11>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
NVIDIA Tegra20/Tegra30 SLINK controller.
|
||||
|
||||
Required properties:
|
||||
- compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
|
||||
- reg: Should contain SLINK registers location and length.
|
||||
- interrupts: Should contain SLINK interrupts.
|
||||
- clocks : Must contain one entry, for the module clock.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names : Must include the following entries:
|
||||
- spi
|
||||
- dmas : Must contain an entry for each entry in clock-names.
|
||||
See ../dma/dma.txt for details.
|
||||
- dma-names : Must include the following entries:
|
||||
- rx
|
||||
- tx
|
||||
|
||||
Recommended properties:
|
||||
- spi-max-frequency: Definition as per
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Example:
|
||||
|
||||
spi@7000d600 {
|
||||
compatible = "nvidia,tegra20-slink";
|
||||
reg = <0x7000d600 0x200>;
|
||||
interrupts = <0 82 0x04>;
|
||||
spi-max-frequency = <25000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car 44>;
|
||||
resets = <&tegra_car 44>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
|
@ -0,0 +1,90 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/nvidia,tegra20-slink.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra20/30 SLINK controller
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nvidia,tegra20-slink
|
||||
- nvidia,tegra30-slink
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: module clock
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: module reset
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: spi
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: DMA channel used for reception
|
||||
- description: DMA channel used for transmission
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
operating-points-v2:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
power-domains:
|
||||
items:
|
||||
- description: phandle to the core power domain
|
||||
|
||||
spi-max-frequency:
|
||||
description: Maximum SPI clocking speed of the controller in Hz.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- resets
|
||||
- reset-names
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra20-car.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
spi@7000d600 {
|
||||
compatible = "nvidia,tegra20-slink";
|
||||
reg = <0x7000d600 0x200>;
|
||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
||||
spi-max-frequency = <25000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA20_CLK_SBC2>;
|
||||
resets = <&tegra_car 44>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
|
@ -1,33 +0,0 @@
|
|||
Binding for Broadcom BCM6348/BCM6358 SPI controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must contain one of "brcm,bcm6348-spi", "brcm,bcm6358-spi".
|
||||
- reg: Base address and size of the controllers memory area.
|
||||
- interrupts: Interrupt for the SPI block.
|
||||
- clocks: phandle of the SPI clock.
|
||||
- clock-names: has to be "spi".
|
||||
- #address-cells: <1>, as required by generic SPI binding.
|
||||
- #size-cells: <0>, also as required by generic SPI binding.
|
||||
|
||||
Optional properties:
|
||||
- num-cs: some controllers have less than 8 cs signals. Defaults to 8
|
||||
if absent.
|
||||
|
||||
Child nodes as per the generic SPI binding.
|
||||
|
||||
Example:
|
||||
|
||||
spi@10000800 {
|
||||
compatible = "brcm,bcm6368-spi", "brcm,bcm6358-spi";
|
||||
reg = <0x10000800 0x70c>;
|
||||
|
||||
interrupts = <1>;
|
||||
|
||||
clocks = <&clkctl 9>;
|
||||
clock-names = "spi";
|
||||
|
||||
num-cs = <5>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
|
@ -49,6 +49,12 @@ properties:
|
|||
enum: [ 0, 1 ]
|
||||
default: 0
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
label:
|
||||
description: Descriptive name of the SPI controller.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -63,6 +63,9 @@ properties:
|
|||
maximum: 2
|
||||
default: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -45,6 +45,9 @@ properties:
|
|||
- const: fspi_en
|
||||
- const: fspi
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -11,6 +11,7 @@ maintainers:
|
|||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
- $ref: /schemas/arm/primecell.yaml#
|
||||
|
||||
# We need a select here so we don't match all nodes with 'arm,primecell'
|
||||
select:
|
||||
|
|
16
MAINTAINERS
16
MAINTAINERS
|
@ -4126,7 +4126,7 @@ BROADCOM BCM6348/BCM6358 SPI controller DRIVER
|
|||
M: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
L: linux-spi@vger.kernel.org
|
||||
S: Odd Fixes
|
||||
F: Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
|
||||
F: Documentation/devicetree/bindings/spi/brcm,bcm63xx-spi.yaml
|
||||
F: drivers/spi/spi-bcm63xx.c
|
||||
|
||||
BROADCOM ETHERNET PHY DRIVERS
|
||||
|
@ -4887,7 +4887,11 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
|||
L: patches@opensource.cirrus.com
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/cirrus,cs*
|
||||
F: drivers/mfd/cs42l43*
|
||||
F: drivers/pinctrl/cirrus/pinctrl-cs42l43*
|
||||
F: drivers/spi/spi-cs42l43*
|
||||
F: include/dt-bindings/sound/cs*
|
||||
F: include/linux/mfd/cs42l43*
|
||||
F: include/sound/cs*
|
||||
F: sound/pci/hda/cs*
|
||||
F: sound/pci/hda/hda_cs_dsp_ctl.*
|
||||
|
@ -12282,6 +12286,16 @@ F: Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml
|
|||
F: drivers/clk/clk-loongson2.c
|
||||
F: include/dt-bindings/clock/loongson,ls2k-clk.h
|
||||
|
||||
LOONGSON SPI DRIVER
|
||||
M: Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||
L: linux-spi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/loongson,ls2k-spi.yaml
|
||||
F: drivers/spi/spi-loongson-core.c
|
||||
F: drivers/spi/spi-loongson-pci.c
|
||||
F: drivers/spi/spi-loongson-plat.c
|
||||
F: drivers/spi/spi-loongson.h
|
||||
|
||||
LOONGSON-2 SOC SERIES GUTS DRIVER
|
||||
M: Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||
L: loongarch@lists.linux.dev
|
||||
|
|
|
@ -237,6 +237,29 @@ config MFD_CROS_EC_DEV
|
|||
To compile this driver as a module, choose M here: the module will be
|
||||
called cros-ec-dev.
|
||||
|
||||
config MFD_CS42L43
|
||||
tristate
|
||||
select MFD_CORE
|
||||
select REGMAP
|
||||
|
||||
config MFD_CS42L43_I2C
|
||||
tristate "Cirrus Logic CS42L43 (I2C)"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
select MFD_CS42L43
|
||||
help
|
||||
Select this to support the Cirrus Logic CS42L43 PC CODEC with
|
||||
headphone and class D speaker drivers over I2C.
|
||||
|
||||
config MFD_CS42L43_SDW
|
||||
tristate "Cirrus Logic CS42L43 (SoundWire)"
|
||||
depends on SOUNDWIRE
|
||||
select REGMAP_SOUNDWIRE
|
||||
select MFD_CS42L43
|
||||
help
|
||||
Select this to support the Cirrus Logic CS42L43 PC CODEC with
|
||||
headphone and class D speaker drivers over SoundWire.
|
||||
|
||||
config MFD_MADERA
|
||||
tristate "Cirrus Logic Madera codecs"
|
||||
select MFD_CORE
|
||||
|
|
|
@ -13,6 +13,9 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
|
|||
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o
|
||||
obj-$(CONFIG_MFD_CS42L43) += cs42l43.o
|
||||
obj-$(CONFIG_MFD_CS42L43_I2C) += cs42l43-i2c.o
|
||||
obj-$(CONFIG_MFD_CS42L43_SDW) += cs42l43-sdw.o
|
||||
obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o
|
||||
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
||||
obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* CS42L43 I2C driver
|
||||
*
|
||||
* Copyright (C) 2022-2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/cs42l43-regs.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "cs42l43.h"
|
||||
|
||||
static const struct regmap_config cs42l43_i2c_regmap = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
.val_format_endian = REGMAP_ENDIAN_BIG,
|
||||
|
||||
.max_register = CS42L43_MCU_RAM_MAX,
|
||||
.readable_reg = cs42l43_readable_register,
|
||||
.volatile_reg = cs42l43_volatile_register,
|
||||
.precious_reg = cs42l43_precious_register,
|
||||
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults = cs42l43_reg_default,
|
||||
.num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default),
|
||||
};
|
||||
|
||||
static int cs42l43_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct cs42l43 *cs42l43;
|
||||
int ret;
|
||||
|
||||
cs42l43 = devm_kzalloc(&i2c->dev, sizeof(*cs42l43), GFP_KERNEL);
|
||||
if (!cs42l43)
|
||||
return -ENOMEM;
|
||||
|
||||
cs42l43->dev = &i2c->dev;
|
||||
cs42l43->irq = i2c->irq;
|
||||
/* A device on an I2C is always attached by definition. */
|
||||
cs42l43->attached = true;
|
||||
|
||||
cs42l43->regmap = devm_regmap_init_i2c(i2c, &cs42l43_i2c_regmap);
|
||||
if (IS_ERR(cs42l43->regmap)) {
|
||||
ret = PTR_ERR(cs42l43->regmap);
|
||||
dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return cs42l43_dev_probe(cs42l43);
|
||||
}
|
||||
|
||||
static void cs42l43_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(&i2c->dev);
|
||||
|
||||
cs42l43_dev_remove(cs42l43);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id cs42l43_of_match[] = {
|
||||
{ .compatible = "cirrus,cs42l43", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs42l43_of_match);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
static const struct acpi_device_id cs42l43_acpi_match[] = {
|
||||
{ "CSC4243", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver cs42l43_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l43",
|
||||
.pm = pm_ptr(&cs42l43_pm_ops),
|
||||
.of_match_table = of_match_ptr(cs42l43_of_match),
|
||||
.acpi_match_table = ACPI_PTR(cs42l43_acpi_match),
|
||||
},
|
||||
|
||||
.probe = cs42l43_i2c_probe,
|
||||
.remove = cs42l43_i2c_remove,
|
||||
};
|
||||
module_i2c_driver(cs42l43_i2c_driver);
|
||||
|
||||
MODULE_IMPORT_NS(MFD_CS42L43);
|
||||
|
||||
MODULE_DESCRIPTION("CS42L43 I2C Driver");
|
||||
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,239 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* CS42L43 SoundWire driver
|
||||
*
|
||||
* Copyright (C) 2022-2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mfd/cs42l43-regs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
|
||||
#include "cs42l43.h"
|
||||
|
||||
enum cs42l43_sdw_ports {
|
||||
CS42L43_DMIC_DEC_ASP_PORT = 1,
|
||||
CS42L43_SPK_TX_PORT,
|
||||
CS42L43_SPDIF_HP_PORT,
|
||||
CS42L43_SPK_RX_PORT,
|
||||
CS42L43_ASP_PORT,
|
||||
};
|
||||
|
||||
static const struct regmap_config cs42l43_sdw_regmap = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
|
||||
.max_register = CS42L43_MCU_RAM_MAX,
|
||||
.readable_reg = cs42l43_readable_register,
|
||||
.volatile_reg = cs42l43_volatile_register,
|
||||
.precious_reg = cs42l43_precious_register,
|
||||
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults = cs42l43_reg_default,
|
||||
.num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default),
|
||||
};
|
||||
|
||||
static int cs42l43_read_prop(struct sdw_slave *sdw)
|
||||
{
|
||||
struct sdw_slave_prop *prop = &sdw->prop;
|
||||
struct device *dev = &sdw->dev;
|
||||
struct sdw_dpn_prop *dpn;
|
||||
unsigned long addr;
|
||||
int nval;
|
||||
int i;
|
||||
u32 bit;
|
||||
|
||||
prop->use_domain_irq = true;
|
||||
prop->paging_support = true;
|
||||
prop->wake_capable = true;
|
||||
prop->source_ports = BIT(CS42L43_DMIC_DEC_ASP_PORT) | BIT(CS42L43_SPK_TX_PORT);
|
||||
prop->sink_ports = BIT(CS42L43_SPDIF_HP_PORT) |
|
||||
BIT(CS42L43_SPK_RX_PORT) | BIT(CS42L43_ASP_PORT);
|
||||
prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
|
||||
prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY |
|
||||
SDW_SCP_INT1_IMPL_DEF;
|
||||
|
||||
nval = hweight32(prop->source_ports);
|
||||
prop->src_dpn_prop = devm_kcalloc(dev, nval, sizeof(*prop->src_dpn_prop),
|
||||
GFP_KERNEL);
|
||||
if (!prop->src_dpn_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
dpn = prop->src_dpn_prop;
|
||||
addr = prop->source_ports;
|
||||
for_each_set_bit(bit, &addr, 32) {
|
||||
dpn[i].num = bit;
|
||||
dpn[i].max_ch = 2;
|
||||
dpn[i].type = SDW_DPN_FULL;
|
||||
dpn[i].max_word = 24;
|
||||
i++;
|
||||
}
|
||||
/*
|
||||
* All ports are 2 channels max, except the first one,
|
||||
* CS42L43_DMIC_DEC_ASP_PORT.
|
||||
*/
|
||||
dpn[CS42L43_DMIC_DEC_ASP_PORT].max_ch = 4;
|
||||
|
||||
nval = hweight32(prop->sink_ports);
|
||||
prop->sink_dpn_prop = devm_kcalloc(dev, nval, sizeof(*prop->sink_dpn_prop),
|
||||
GFP_KERNEL);
|
||||
if (!prop->sink_dpn_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
dpn = prop->sink_dpn_prop;
|
||||
addr = prop->sink_ports;
|
||||
for_each_set_bit(bit, &addr, 32) {
|
||||
dpn[i].num = bit;
|
||||
dpn[i].max_ch = 2;
|
||||
dpn[i].type = SDW_DPN_FULL;
|
||||
dpn[i].max_word = 24;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev);
|
||||
|
||||
switch (status) {
|
||||
case SDW_SLAVE_ATTACHED:
|
||||
dev_dbg(cs42l43->dev, "Device attach\n");
|
||||
|
||||
sdw_write_no_pm(sdw, CS42L43_GEN_INT_MASK_1,
|
||||
CS42L43_INT_STAT_GEN1_MASK);
|
||||
|
||||
cs42l43->attached = true;
|
||||
|
||||
complete(&cs42l43->device_attach);
|
||||
break;
|
||||
case SDW_SLAVE_UNATTACHED:
|
||||
dev_dbg(cs42l43->dev, "Device detach\n");
|
||||
|
||||
cs42l43->attached = false;
|
||||
|
||||
reinit_completion(&cs42l43->device_attach);
|
||||
complete(&cs42l43->device_detach);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_sdw_interrupt(struct sdw_slave *sdw,
|
||||
struct sdw_slave_intr_status *status)
|
||||
{
|
||||
/*
|
||||
* The IRQ itself was handled through the regmap_irq handler, this is
|
||||
* just clearing up the additional Cirrus SoundWire registers that are
|
||||
* not covered by the SoundWire framework or the IRQ handler itself.
|
||||
* There is only a single bit in GEN_INT_STAT_1 and it doesn't clear if
|
||||
* IRQs are still pending so doing a read/write here after handling the
|
||||
* IRQ is fine.
|
||||
*/
|
||||
sdw_read_no_pm(sdw, CS42L43_GEN_INT_STAT_1);
|
||||
sdw_write_no_pm(sdw, CS42L43_GEN_INT_STAT_1, CS42L43_INT_STAT_GEN1_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_sdw_bus_config(struct sdw_slave *sdw,
|
||||
struct sdw_bus_params *params)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&cs42l43->pll_lock);
|
||||
|
||||
if (cs42l43->sdw_freq != params->curr_dr_freq / 2) {
|
||||
if (cs42l43->sdw_pll_active) {
|
||||
dev_err(cs42l43->dev,
|
||||
"PLL active can't change SoundWire bus clock\n");
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
cs42l43->sdw_freq = params->curr_dr_freq / 2;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&cs42l43->pll_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct sdw_slave_ops cs42l43_sdw_ops = {
|
||||
.read_prop = cs42l43_read_prop,
|
||||
.update_status = cs42l43_sdw_update_status,
|
||||
.interrupt_callback = cs42l43_sdw_interrupt,
|
||||
.bus_config = cs42l43_sdw_bus_config,
|
||||
};
|
||||
|
||||
static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id)
|
||||
{
|
||||
struct cs42l43 *cs42l43;
|
||||
struct device *dev = &sdw->dev;
|
||||
int ret;
|
||||
|
||||
cs42l43 = devm_kzalloc(dev, sizeof(*cs42l43), GFP_KERNEL);
|
||||
if (!cs42l43)
|
||||
return -ENOMEM;
|
||||
|
||||
cs42l43->dev = dev;
|
||||
cs42l43->sdw = sdw;
|
||||
|
||||
cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap);
|
||||
if (IS_ERR(cs42l43->regmap)) {
|
||||
ret = PTR_ERR(cs42l43->regmap);
|
||||
dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return cs42l43_dev_probe(cs42l43);
|
||||
}
|
||||
|
||||
static int cs42l43_sdw_remove(struct sdw_slave *sdw)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev);
|
||||
|
||||
cs42l43_dev_remove(cs42l43);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sdw_device_id cs42l43_sdw_id[] = {
|
||||
SDW_SLAVE_ENTRY(0x01FA, 0x4243, 0),
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id);
|
||||
|
||||
static struct sdw_driver cs42l43_sdw_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l43",
|
||||
.pm = pm_ptr(&cs42l43_pm_ops),
|
||||
},
|
||||
|
||||
.probe = cs42l43_sdw_probe,
|
||||
.remove = cs42l43_sdw_remove,
|
||||
.id_table = cs42l43_sdw_id,
|
||||
.ops = &cs42l43_sdw_ops,
|
||||
};
|
||||
module_sdw_driver(cs42l43_sdw_driver);
|
||||
|
||||
MODULE_IMPORT_NS(MFD_CS42L43);
|
||||
|
||||
MODULE_DESCRIPTION("CS42L43 SoundWire Driver");
|
||||
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,28 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* CS42L43 core driver internal data
|
||||
*
|
||||
* Copyright (C) 2022-2023 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/mfd/cs42l43.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#ifndef CS42L43_CORE_INT_H
|
||||
#define CS42L43_CORE_INT_H
|
||||
|
||||
#define CS42L43_N_DEFAULTS 176
|
||||
|
||||
extern const struct dev_pm_ops cs42l43_pm_ops;
|
||||
extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS];
|
||||
|
||||
bool cs42l43_readable_register(struct device *dev, unsigned int reg);
|
||||
bool cs42l43_precious_register(struct device *dev, unsigned int reg);
|
||||
bool cs42l43_volatile_register(struct device *dev, unsigned int reg);
|
||||
|
||||
int cs42l43_dev_probe(struct cs42l43 *cs42l43);
|
||||
void cs42l43_dev_remove(struct cs42l43 *cs42l43);
|
||||
|
||||
#endif /* CS42L43_CORE_INT_H */
|
|
@ -1,4 +1,15 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config PINCTRL_CS42L43
|
||||
tristate "Cirrus Logic CS42L43 Pinctrl Driver"
|
||||
depends on MFD_CS42L43
|
||||
select GPIOLIB
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
Select this to support the GPIO/Pinctrl functions of the Cirrus
|
||||
Logic CS42L43 PC CODEC.
|
||||
|
||||
config PINCTRL_LOCHNAGAR
|
||||
tristate "Cirrus Logic Lochnagar pinctrl driver"
|
||||
depends on MFD_LOCHNAGAR
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Cirrus Logic pinctrl drivers
|
||||
obj-$(CONFIG_PINCTRL_CS42L43) += pinctrl-cs42l43.o
|
||||
|
||||
obj-$(CONFIG_PINCTRL_LOCHNAGAR) += pinctrl-lochnagar.o
|
||||
|
||||
pinctrl-madera-objs := pinctrl-madera-core.o
|
||||
|
|
|
@ -0,0 +1,609 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// CS42L43 Pinctrl and GPIO driver
|
||||
//
|
||||
// Copyright (c) 2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/cs42l43.h>
|
||||
#include <linux/mfd/cs42l43-regs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include "../pinctrl-utils.h"
|
||||
|
||||
#define CS42L43_NUM_GPIOS 3
|
||||
|
||||
struct cs42l43_pin {
|
||||
struct gpio_chip gpio_chip;
|
||||
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
bool shutters_locked;
|
||||
};
|
||||
|
||||
struct cs42l43_pin_data {
|
||||
unsigned int reg;
|
||||
unsigned int shift;
|
||||
unsigned int mask;
|
||||
};
|
||||
|
||||
#define CS42L43_PIN(_number, _name, _reg, _field) { \
|
||||
.number = _number, .name = _name, \
|
||||
.drv_data = &((struct cs42l43_pin_data){ \
|
||||
.reg = CS42L43_##_reg, \
|
||||
.shift = CS42L43_##_field##_DRV_SHIFT, \
|
||||
.mask = CS42L43_##_field##_DRV_MASK, \
|
||||
}), \
|
||||
}
|
||||
|
||||
static const struct pinctrl_pin_desc cs42l43_pin_pins[] = {
|
||||
CS42L43_PIN(0, "gpio1", DRV_CTRL4, GPIO1),
|
||||
CS42L43_PIN(1, "gpio2", DRV_CTRL4, GPIO2),
|
||||
CS42L43_PIN(2, "gpio3", DRV_CTRL4, GPIO3),
|
||||
CS42L43_PIN(3, "asp_dout", DRV_CTRL1, ASP_DOUT),
|
||||
CS42L43_PIN(4, "asp_fsync", DRV_CTRL1, ASP_FSYNC),
|
||||
CS42L43_PIN(5, "asp_bclk", DRV_CTRL1, ASP_BCLK),
|
||||
CS42L43_PIN(6, "pdmout2_clk", DRV_CTRL3, PDMOUT2_CLK),
|
||||
CS42L43_PIN(7, "pdmout2_data", DRV_CTRL3, PDMOUT2_DATA),
|
||||
CS42L43_PIN(8, "pdmout1_clk", DRV_CTRL3, PDMOUT1_CLK),
|
||||
CS42L43_PIN(9, "pdmout1_data", DRV_CTRL3, PDMOUT1_DATA),
|
||||
CS42L43_PIN(10, "i2c_sda", DRV_CTRL3, I2C_SDA),
|
||||
CS42L43_PIN(11, "i2c_scl", DRV_CTRL_5, I2C_SCL),
|
||||
CS42L43_PIN(12, "spi_miso", DRV_CTRL3, SPI_MISO),
|
||||
CS42L43_PIN(13, "spi_sck", DRV_CTRL_5, SPI_SCK),
|
||||
CS42L43_PIN(14, "spi_ssb", DRV_CTRL_5, SPI_SSB),
|
||||
};
|
||||
|
||||
static const unsigned int cs42l43_pin_gpio1_pins[] = { 0 };
|
||||
static const unsigned int cs42l43_pin_gpio2_pins[] = { 1 };
|
||||
static const unsigned int cs42l43_pin_gpio3_pins[] = { 2 };
|
||||
static const unsigned int cs42l43_pin_asp_pins[] = { 3, 4, 5 };
|
||||
static const unsigned int cs42l43_pin_pdmout2_pins[] = { 6, 7 };
|
||||
static const unsigned int cs42l43_pin_pdmout1_pins[] = { 8, 9 };
|
||||
static const unsigned int cs42l43_pin_i2c_pins[] = { 10, 11 };
|
||||
static const unsigned int cs42l43_pin_spi_pins[] = { 12, 13, 14 };
|
||||
|
||||
#define CS42L43_PINGROUP(_name) \
|
||||
PINCTRL_PINGROUP(#_name, cs42l43_pin_##_name##_pins, \
|
||||
ARRAY_SIZE(cs42l43_pin_##_name##_pins))
|
||||
|
||||
static const struct pingroup cs42l43_pin_groups[] = {
|
||||
CS42L43_PINGROUP(gpio1),
|
||||
CS42L43_PINGROUP(gpio2),
|
||||
CS42L43_PINGROUP(gpio3),
|
||||
CS42L43_PINGROUP(asp),
|
||||
CS42L43_PINGROUP(pdmout2),
|
||||
CS42L43_PINGROUP(pdmout1),
|
||||
CS42L43_PINGROUP(i2c),
|
||||
CS42L43_PINGROUP(spi),
|
||||
};
|
||||
|
||||
static int cs42l43_pin_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return ARRAY_SIZE(cs42l43_pin_groups);
|
||||
}
|
||||
|
||||
static const char *cs42l43_pin_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int group_idx)
|
||||
{
|
||||
return cs42l43_pin_groups[group_idx].name;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned int group_idx,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
*pins = cs42l43_pin_groups[group_idx].pins;
|
||||
*num_pins = cs42l43_pin_groups[group_idx].npins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops cs42l43_pin_group_ops = {
|
||||
.get_groups_count = cs42l43_pin_get_groups_count,
|
||||
.get_group_name = cs42l43_pin_get_group_name,
|
||||
.get_group_pins = cs42l43_pin_get_group_pins,
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
|
||||
.dt_free_map = pinconf_generic_dt_free_map,
|
||||
#endif
|
||||
};
|
||||
|
||||
enum cs42l43_pin_funcs {
|
||||
CS42L43_FUNC_GPIO,
|
||||
CS42L43_FUNC_SPDIF,
|
||||
CS42L43_FUNC_IRQ,
|
||||
CS42L43_FUNC_MIC_SHT,
|
||||
CS42L43_FUNC_SPK_SHT,
|
||||
CS42L43_FUNC_MAX
|
||||
};
|
||||
|
||||
static const char * const cs42l43_pin_funcs[] = {
|
||||
"gpio", "spdif", "irq", "mic-shutter", "spk-shutter",
|
||||
};
|
||||
|
||||
static const char * const cs42l43_pin_gpio_groups[] = { "gpio1", "gpio3" };
|
||||
static const char * const cs42l43_pin_spdif_groups[] = { "gpio3" };
|
||||
static const char * const cs42l43_pin_irq_groups[] = { "gpio1" };
|
||||
static const char * const cs42l43_pin_shutter_groups[] = { "gpio1", "gpio2", "gpio3" };
|
||||
|
||||
static const struct pinfunction cs42l43_pin_func_groups[] = {
|
||||
PINCTRL_PINFUNCTION("gpio", cs42l43_pin_gpio_groups,
|
||||
ARRAY_SIZE(cs42l43_pin_gpio_groups)),
|
||||
PINCTRL_PINFUNCTION("spdif", cs42l43_pin_spdif_groups,
|
||||
ARRAY_SIZE(cs42l43_pin_spdif_groups)),
|
||||
PINCTRL_PINFUNCTION("irq", cs42l43_pin_irq_groups,
|
||||
ARRAY_SIZE(cs42l43_pin_irq_groups)),
|
||||
PINCTRL_PINFUNCTION("mic-shutter", cs42l43_pin_shutter_groups,
|
||||
ARRAY_SIZE(cs42l43_pin_shutter_groups)),
|
||||
PINCTRL_PINFUNCTION("spk-shutter", cs42l43_pin_shutter_groups,
|
||||
ARRAY_SIZE(cs42l43_pin_shutter_groups)),
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(cs42l43_pin_funcs) == CS42L43_FUNC_MAX);
|
||||
static_assert(ARRAY_SIZE(cs42l43_pin_func_groups) == CS42L43_FUNC_MAX);
|
||||
|
||||
static int cs42l43_pin_get_func_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return ARRAY_SIZE(cs42l43_pin_funcs);
|
||||
}
|
||||
|
||||
static const char *cs42l43_pin_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int func_idx)
|
||||
{
|
||||
return cs42l43_pin_funcs[func_idx];
|
||||
}
|
||||
|
||||
static int cs42l43_pin_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned int func_idx,
|
||||
const char * const **groups,
|
||||
unsigned int * const num_groups)
|
||||
{
|
||||
*groups = cs42l43_pin_func_groups[func_idx].groups;
|
||||
*num_groups = cs42l43_pin_func_groups[func_idx].ngroups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int func_idx, unsigned int group_idx)
|
||||
{
|
||||
struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int reg, mask, val;
|
||||
|
||||
dev_dbg(priv->dev, "Setting %s to %s\n",
|
||||
cs42l43_pin_groups[group_idx].name, cs42l43_pin_funcs[func_idx]);
|
||||
|
||||
switch (func_idx) {
|
||||
case CS42L43_FUNC_MIC_SHT:
|
||||
reg = CS42L43_SHUTTER_CONTROL;
|
||||
mask = CS42L43_MIC_SHUTTER_CFG_MASK;
|
||||
val = 0x2 << (group_idx + CS42L43_MIC_SHUTTER_CFG_SHIFT);
|
||||
break;
|
||||
case CS42L43_FUNC_SPK_SHT:
|
||||
reg = CS42L43_SHUTTER_CONTROL;
|
||||
mask = CS42L43_SPK_SHUTTER_CFG_MASK;
|
||||
val = 0x2 << (group_idx + CS42L43_SPK_SHUTTER_CFG_SHIFT);
|
||||
break;
|
||||
default:
|
||||
reg = CS42L43_GPIO_FN_SEL;
|
||||
mask = BIT(group_idx + CS42L43_GPIO1_FN_SEL_SHIFT);
|
||||
val = (func_idx == CS42L43_FUNC_GPIO) ?
|
||||
(0x1 << (group_idx + CS42L43_GPIO1_FN_SEL_SHIFT)) : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv->shutters_locked && reg == CS42L43_SHUTTER_CONTROL) {
|
||||
dev_err(priv->dev, "Shutter configuration not available\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return regmap_update_bits(priv->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static int cs42l43_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int offset, bool input)
|
||||
{
|
||||
struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int shift = offset + CS42L43_GPIO1_DIR_SHIFT;
|
||||
int ret;
|
||||
|
||||
dev_dbg(priv->dev, "Setting gpio%d to %s\n",
|
||||
offset + 1, input ? "input" : "output");
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->dev);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to resume for direction: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1,
|
||||
BIT(shift), !!input << shift);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to set gpio%d direction: %d\n",
|
||||
offset + 1, ret);
|
||||
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs42l43_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int offset)
|
||||
{
|
||||
return cs42l43_pin_set_mux(pctldev, 0, offset);
|
||||
}
|
||||
|
||||
static void cs42l43_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int offset)
|
||||
{
|
||||
cs42l43_gpio_set_direction(pctldev, range, offset, true);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops cs42l43_pin_mux_ops = {
|
||||
.get_functions_count = cs42l43_pin_get_func_count,
|
||||
.get_function_name = cs42l43_pin_get_func_name,
|
||||
.get_function_groups = cs42l43_pin_get_func_groups,
|
||||
|
||||
.set_mux = cs42l43_pin_set_mux,
|
||||
|
||||
.gpio_request_enable = cs42l43_gpio_request_enable,
|
||||
.gpio_disable_free = cs42l43_gpio_disable_free,
|
||||
.gpio_set_direction = cs42l43_gpio_set_direction,
|
||||
|
||||
.strict = true,
|
||||
};
|
||||
|
||||
static const unsigned int cs42l43_pin_drv_str_ma[] = { 1, 2, 4, 8, 9, 10, 12, 16 };
|
||||
|
||||
static inline int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin)
|
||||
{
|
||||
const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(priv->regmap, pdat->reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return cs42l43_pin_drv_str_ma[(val & pdat->mask) >> pdat->shift];
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int ma)
|
||||
{
|
||||
const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cs42l43_pin_drv_str_ma); i++) {
|
||||
if (ma == cs42l43_pin_drv_str_ma[i]) {
|
||||
if ((i << pdat->shift) > pdat->mask)
|
||||
goto err;
|
||||
|
||||
dev_dbg(priv->dev, "Set drive strength for %s to %d mA\n",
|
||||
cs42l43_pin_pins[pin].name, ma);
|
||||
|
||||
return regmap_update_bits(priv->regmap, pdat->reg,
|
||||
pdat->mask, i << pdat->shift);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
dev_err(priv->dev, "Invalid drive strength for %s: %d mA\n",
|
||||
cs42l43_pin_pins[pin].name, ma);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (pin >= CS42L43_NUM_GPIOS)
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = regmap_read(priv->regmap, CS42L43_GPIO_CTRL2, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & (CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin))
|
||||
return 0;
|
||||
|
||||
return 85; // Debounce is roughly 85uS
|
||||
}
|
||||
|
||||
static inline int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin,
|
||||
unsigned int us)
|
||||
{
|
||||
if (pin >= CS42L43_NUM_GPIOS)
|
||||
return -ENOTSUPP;
|
||||
|
||||
dev_dbg(priv->dev, "Set debounce %s for %s\n",
|
||||
str_on_off(us), cs42l43_pin_pins[pin].name);
|
||||
|
||||
return regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL2,
|
||||
CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin,
|
||||
!!us << pin);
|
||||
}
|
||||
|
||||
static int cs42l43_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin, unsigned long *config)
|
||||
{
|
||||
struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int param = pinconf_to_config_param(*config);
|
||||
int ret;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
ret = cs42l43_pin_get_drv_str(priv, pin);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
ret = cs42l43_pin_get_db(priv, pin);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
while (num_configs) {
|
||||
val = pinconf_to_config_argument(*configs);
|
||||
|
||||
switch (pinconf_to_config_param(*configs)) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
ret = cs42l43_pin_set_drv_str(priv, pin, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
ret = cs42l43_pin_set_db(priv, pin, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
configs++;
|
||||
num_configs--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_config_group_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector, unsigned long *config)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) {
|
||||
ret = cs42l43_pin_config_get(pctldev,
|
||||
cs42l43_pin_groups[selector].pins[i],
|
||||
config);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_config_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) {
|
||||
ret = cs42l43_pin_config_set(pctldev,
|
||||
cs42l43_pin_groups[selector].pins[i],
|
||||
configs, num_configs);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops cs42l43_pin_conf_ops = {
|
||||
.is_generic = true,
|
||||
|
||||
.pin_config_get = cs42l43_pin_config_get,
|
||||
.pin_config_set = cs42l43_pin_config_set,
|
||||
.pin_config_group_get = cs42l43_pin_config_group_get,
|
||||
.pin_config_group_set = cs42l43_pin_config_group_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc cs42l43_pin_desc = {
|
||||
.name = "cs42l43-pinctrl",
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.pins = cs42l43_pin_pins,
|
||||
.npins = ARRAY_SIZE(cs42l43_pin_pins),
|
||||
|
||||
.pctlops = &cs42l43_pin_group_ops,
|
||||
.pmxops = &cs42l43_pin_mux_ops,
|
||||
.confops = &cs42l43_pin_conf_ops,
|
||||
};
|
||||
|
||||
static int cs42l43_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct cs42l43_pin *priv = gpiochip_get_data(chip);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->dev);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to resume for get: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_read(priv->regmap, CS42L43_GPIO_STS, &val);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to get gpio%d: %d\n", offset + 1, ret);
|
||||
else
|
||||
ret = !!(val & BIT(offset + CS42L43_GPIO1_STS_SHIFT));
|
||||
|
||||
pm_runtime_put(priv->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs42l43_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct cs42l43_pin *priv = gpiochip_get_data(chip);
|
||||
unsigned int shift = offset + CS42L43_GPIO1_LVL_SHIFT;
|
||||
int ret;
|
||||
|
||||
dev_dbg(priv->dev, "Setting gpio%d to %s\n",
|
||||
offset + 1, value ? "high" : "low");
|
||||
|
||||
ret = pm_runtime_resume_and_get(priv->dev);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to resume for set: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1,
|
||||
BIT(shift), value << shift);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to set gpio%d: %d\n", offset + 1, ret);
|
||||
|
||||
pm_runtime_put(priv->dev);
|
||||
}
|
||||
|
||||
static int cs42l43_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + offset);
|
||||
}
|
||||
|
||||
static int cs42l43_gpio_direction_out(struct gpio_chip *chip,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
cs42l43_gpio_set(chip, offset, value);
|
||||
|
||||
return pinctrl_gpio_direction_output(chip->base + offset);
|
||||
}
|
||||
|
||||
static int cs42l43_gpio_add_pin_ranges(struct gpio_chip *chip)
|
||||
{
|
||||
struct cs42l43_pin *priv = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
ret = gpiochip_add_pin_range(&priv->gpio_chip, priv->gpio_chip.label,
|
||||
0, 0, CS42L43_NUM_GPIOS);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to add GPIO pin range: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs42l43_pin_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cs42l43_pin *priv;
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = &pdev->dev;
|
||||
priv->regmap = cs42l43->regmap;
|
||||
|
||||
priv->shutters_locked = cs42l43->hw_lock;
|
||||
|
||||
priv->gpio_chip.request = gpiochip_generic_request;
|
||||
priv->gpio_chip.free = gpiochip_generic_free;
|
||||
priv->gpio_chip.direction_input = cs42l43_gpio_direction_in;
|
||||
priv->gpio_chip.direction_output = cs42l43_gpio_direction_out;
|
||||
priv->gpio_chip.add_pin_ranges = cs42l43_gpio_add_pin_ranges;
|
||||
priv->gpio_chip.get = cs42l43_gpio_get;
|
||||
priv->gpio_chip.set = cs42l43_gpio_set;
|
||||
priv->gpio_chip.label = dev_name(priv->dev);
|
||||
priv->gpio_chip.parent = priv->dev;
|
||||
priv->gpio_chip.can_sleep = true;
|
||||
priv->gpio_chip.base = -1;
|
||||
priv->gpio_chip.ngpio = CS42L43_NUM_GPIOS;
|
||||
|
||||
if (is_of_node(fwnode)) {
|
||||
fwnode = fwnode_get_named_child_node(fwnode, "pinctrl");
|
||||
|
||||
if (fwnode && !fwnode->dev)
|
||||
fwnode->dev = priv->dev;
|
||||
}
|
||||
|
||||
priv->gpio_chip.fwnode = fwnode;
|
||||
|
||||
device_set_node(priv->dev, fwnode);
|
||||
|
||||
devm_pm_runtime_enable(priv->dev);
|
||||
pm_runtime_idle(priv->dev);
|
||||
|
||||
pctldev = devm_pinctrl_register(priv->dev, &cs42l43_pin_desc, priv);
|
||||
if (IS_ERR(pctldev))
|
||||
return dev_err_probe(priv->dev, PTR_ERR(pctldev),
|
||||
"Failed to register pinctrl\n");
|
||||
|
||||
ret = devm_gpiochip_add_data(priv->dev, &priv->gpio_chip, priv);
|
||||
if (ret)
|
||||
return dev_err_probe(priv->dev, ret,
|
||||
"Failed to register gpiochip\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id cs42l43_pin_id_table[] = {
|
||||
{ "cs42l43-pinctrl", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, cs42l43_pin_id_table);
|
||||
|
||||
static struct platform_driver cs42l43_pin_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l43-pinctrl",
|
||||
},
|
||||
.probe = cs42l43_pin_probe,
|
||||
.id_table = cs42l43_pin_id_table,
|
||||
};
|
||||
module_platform_driver(cs42l43_pin_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CS42L43 Pinctrl Driver");
|
||||
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
|
@ -25,6 +26,23 @@ static int sdw_get_id(struct sdw_bus *bus)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sdw_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct sdw_bus *bus = h->host_data;
|
||||
|
||||
irq_set_chip_data(virq, bus);
|
||||
irq_set_chip(virq, &bus->irq_chip);
|
||||
irq_set_nested_thread(virq, 1);
|
||||
irq_set_noprobe(virq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops sdw_domain_ops = {
|
||||
.map = sdw_irq_map,
|
||||
};
|
||||
|
||||
/**
|
||||
* sdw_bus_master_add() - add a bus Master instance
|
||||
* @bus: bus instance
|
||||
|
@ -151,6 +169,14 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
|
|||
bus->params.curr_bank = SDW_BANK0;
|
||||
bus->params.next_bank = SDW_BANK1;
|
||||
|
||||
bus->irq_chip.name = dev_name(bus->dev);
|
||||
bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES,
|
||||
&sdw_domain_ops, bus);
|
||||
if (!bus->domain) {
|
||||
dev_err(bus->dev, "Failed to add IRQ domain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(sdw_bus_master_add);
|
||||
|
@ -187,6 +213,9 @@ static int sdw_delete_slave(struct device *dev, void *data)
|
|||
void sdw_bus_master_delete(struct sdw_bus *bus)
|
||||
{
|
||||
device_for_each_child(bus->dev, NULL, sdw_delete_slave);
|
||||
|
||||
irq_domain_remove(bus->domain);
|
||||
|
||||
sdw_master_device_del(bus);
|
||||
|
||||
sdw_bus_debugfs_exit(bus);
|
||||
|
@ -1725,6 +1754,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
|
|||
struct device *dev = &slave->dev;
|
||||
struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
|
||||
|
||||
if (slave->prop.use_domain_irq && slave->irq)
|
||||
handle_nested_irq(slave->irq);
|
||||
|
||||
if (drv->ops && drv->ops->interrupt_callback) {
|
||||
slave_intr.sdca_cascade = sdca_cascade;
|
||||
slave_intr.control_port = clear;
|
||||
|
|
|
@ -122,6 +122,12 @@ static int sdw_drv_probe(struct device *dev)
|
|||
if (drv->ops && drv->ops->read_prop)
|
||||
drv->ops->read_prop(slave);
|
||||
|
||||
if (slave->prop.use_domain_irq) {
|
||||
slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num);
|
||||
if (!slave->irq)
|
||||
dev_warn(dev, "Failed to map IRQ\n");
|
||||
}
|
||||
|
||||
/* init the sysfs as we have properties now */
|
||||
ret = sdw_slave_sysfs_init(slave);
|
||||
if (ret < 0)
|
||||
|
@ -166,7 +172,13 @@ static int sdw_drv_remove(struct device *dev)
|
|||
int ret = 0;
|
||||
|
||||
mutex_lock(&slave->sdw_dev_lock);
|
||||
|
||||
slave->probed = false;
|
||||
|
||||
if (slave->prop.use_domain_irq)
|
||||
irq_dispose_mapping(irq_find_mapping(slave->bus->domain,
|
||||
slave->dev_num));
|
||||
|
||||
mutex_unlock(&slave->sdw_dev_lock);
|
||||
|
||||
if (drv->remove)
|
||||
|
|
|
@ -281,6 +281,13 @@ config SPI_COLDFIRE_QSPI
|
|||
This enables support for the Coldfire QSPI controller in master
|
||||
mode.
|
||||
|
||||
config SPI_CS42L43
|
||||
tristate "Cirrus Logic CS42L43 SPI controller"
|
||||
depends on MFD_CS42L43 && PINCTRL_CS42L43
|
||||
help
|
||||
This enables support for the SPI controller inside the Cirrus Logic
|
||||
CS42L43 audio codec.
|
||||
|
||||
config SPI_DAVINCI
|
||||
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
|
||||
depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST
|
||||
|
@ -516,6 +523,32 @@ config SPI_LM70_LLP
|
|||
which interfaces to an LM70 temperature sensor using
|
||||
a parallel port.
|
||||
|
||||
config SPI_LOONGSON_CORE
|
||||
tristate
|
||||
depends on LOONGARCH || COMPILE_TEST
|
||||
|
||||
config SPI_LOONGSON_PCI
|
||||
tristate "Loongson SPI Controller PCI Driver Support"
|
||||
select SPI_LOONGSON_CORE
|
||||
depends on PCI && (LOONGARCH || COMPILE_TEST)
|
||||
help
|
||||
This bus driver supports the Loongson SPI hardware controller in
|
||||
the Loongson platforms and supports to use PCI framework to
|
||||
register SPI device resources.
|
||||
Say Y or M here if you want to use the SPI controller on
|
||||
Loongson platform.
|
||||
|
||||
config SPI_LOONGSON_PLATFORM
|
||||
tristate "Loongson SPI Controller Platform Driver Support"
|
||||
select SPI_LOONGSON_CORE
|
||||
depends on OF && (LOONGARCH || COMPILE_TEST)
|
||||
help
|
||||
This bus driver supports the Loongson SPI hardware controller in
|
||||
the Loongson platforms and supports to use DTS framework to
|
||||
register SPI device resources.
|
||||
Say Y or M here if you want to use the SPI controller on
|
||||
Loongson platform.
|
||||
|
||||
config SPI_LP8841_RTC
|
||||
tristate "ICP DAS LP-8841 SPI Controller for RTC"
|
||||
depends on MACH_PXA27X_DT || COMPILE_TEST
|
||||
|
|
|
@ -40,6 +40,7 @@ obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o
|
|||
obj-$(CONFIG_SPI_CADENCE_XSPI) += spi-cadence-xspi.o
|
||||
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
|
||||
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
|
||||
obj-$(CONFIG_SPI_CS42L43) += spi-cs42l43.o
|
||||
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
|
||||
obj-$(CONFIG_SPI_DLN2) += spi-dln2.o
|
||||
obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
|
||||
|
@ -71,6 +72,9 @@ obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o
|
|||
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
|
||||
obj-$(CONFIG_SPI_JCORE) += spi-jcore.o
|
||||
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
|
||||
obj-$(CONFIG_SPI_LOONGSON_CORE) += spi-loongson-core.o
|
||||
obj-$(CONFIG_SPI_LOONGSON_PCI) += spi-loongson-pci.o
|
||||
obj-$(CONFIG_SPI_LOONGSON_PLATFORM) += spi-loongson-plat.o
|
||||
obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
|
||||
obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
|
||||
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
|
||||
|
|
|
@ -215,9 +215,9 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
|
|||
}
|
||||
}
|
||||
|
||||
static int amd_spi_master_setup(struct spi_device *spi)
|
||||
static int amd_spi_host_setup(struct spi_device *spi)
|
||||
{
|
||||
struct amd_spi *amd_spi = spi_master_get_devdata(spi->master);
|
||||
struct amd_spi *amd_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
amd_spi_clear_fifo_ptr(amd_spi);
|
||||
|
||||
|
@ -272,7 +272,7 @@ static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz)
|
|||
}
|
||||
|
||||
static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
|
||||
struct spi_master *master,
|
||||
struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct spi_transfer *xfer = NULL;
|
||||
|
@ -353,15 +353,15 @@ fin_msg:
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return message->status;
|
||||
}
|
||||
|
||||
static int amd_spi_master_transfer(struct spi_master *master,
|
||||
static int amd_spi_host_transfer(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct amd_spi *amd_spi = spi_master_get_devdata(master);
|
||||
struct amd_spi *amd_spi = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = msg->spi;
|
||||
|
||||
amd_spi_select_chip(amd_spi, spi_get_chipselect(spi, 0));
|
||||
|
@ -370,7 +370,7 @@ static int amd_spi_master_transfer(struct spi_master *master,
|
|||
* Extract spi_transfers from the spi message and
|
||||
* program the controller.
|
||||
*/
|
||||
return amd_spi_fifo_xfer(amd_spi, master, msg);
|
||||
return amd_spi_fifo_xfer(amd_spi, host, msg);
|
||||
}
|
||||
|
||||
static size_t amd_spi_max_transfer_size(struct spi_device *spi)
|
||||
|
@ -381,16 +381,16 @@ static size_t amd_spi_max_transfer_size(struct spi_device *spi)
|
|||
static int amd_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct amd_spi *amd_spi;
|
||||
int err;
|
||||
|
||||
/* Allocate storage for spi_master and driver private data */
|
||||
master = devm_spi_alloc_master(dev, sizeof(struct amd_spi));
|
||||
if (!master)
|
||||
return dev_err_probe(dev, -ENOMEM, "Error allocating SPI master\n");
|
||||
/* Allocate storage for host and driver private data */
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct amd_spi));
|
||||
if (!host)
|
||||
return dev_err_probe(dev, -ENOMEM, "Error allocating SPI host\n");
|
||||
|
||||
amd_spi = spi_master_get_devdata(master);
|
||||
amd_spi = spi_controller_get_devdata(host);
|
||||
amd_spi->io_remap_addr = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(amd_spi->io_remap_addr))
|
||||
return dev_err_probe(dev, PTR_ERR(amd_spi->io_remap_addr),
|
||||
|
@ -398,22 +398,22 @@ static int amd_spi_probe(struct platform_device *pdev)
|
|||
|
||||
dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr);
|
||||
|
||||
amd_spi->version = (enum amd_spi_versions) device_get_match_data(dev);
|
||||
amd_spi->version = (uintptr_t) device_get_match_data(dev);
|
||||
|
||||
/* Initialize the spi_master fields */
|
||||
master->bus_num = 0;
|
||||
master->num_chipselect = 4;
|
||||
master->mode_bits = 0;
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->max_speed_hz = AMD_SPI_MAX_HZ;
|
||||
master->min_speed_hz = AMD_SPI_MIN_HZ;
|
||||
master->setup = amd_spi_master_setup;
|
||||
master->transfer_one_message = amd_spi_master_transfer;
|
||||
master->max_transfer_size = amd_spi_max_transfer_size;
|
||||
master->max_message_size = amd_spi_max_transfer_size;
|
||||
/* Initialize the spi_controller fields */
|
||||
host->bus_num = 0;
|
||||
host->num_chipselect = 4;
|
||||
host->mode_bits = 0;
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->max_speed_hz = AMD_SPI_MAX_HZ;
|
||||
host->min_speed_hz = AMD_SPI_MIN_HZ;
|
||||
host->setup = amd_spi_host_setup;
|
||||
host->transfer_one_message = amd_spi_host_transfer;
|
||||
host->max_transfer_size = amd_spi_max_transfer_size;
|
||||
host->max_message_size = amd_spi_max_transfer_size;
|
||||
|
||||
/* Register the controller with SPI framework */
|
||||
err = devm_spi_register_master(dev, master);
|
||||
err = devm_spi_register_controller(dev, host);
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "error registering SPI controller\n");
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
#define SPIFC_A1_USER_DBUF_ADDR_REG 0x248
|
||||
|
||||
#define SPIFC_A1_BUFFER_SIZE 512
|
||||
#define SPIFC_A1_BUFFER_SIZE 512U
|
||||
|
||||
#define SPIFC_A1_MAX_HZ 200000000
|
||||
#define SPIFC_A1_MIN_HZ 1000000
|
||||
|
@ -107,6 +107,7 @@ struct amlogic_spifc_a1 {
|
|||
struct clk *clk;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
u32 curr_speed_hz;
|
||||
};
|
||||
|
||||
static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read)
|
||||
|
@ -235,66 +236,68 @@ static int amlogic_spifc_a1_write(struct amlogic_spifc_a1 *spifc,
|
|||
return amlogic_spifc_a1_request(spifc, false);
|
||||
}
|
||||
|
||||
static int amlogic_spifc_a1_set_freq(struct amlogic_spifc_a1 *spifc, u32 freq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (freq == spifc->curr_speed_hz)
|
||||
return 0;
|
||||
|
||||
ret = clk_set_rate(spifc->clk, freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spifc->curr_speed_hz = freq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amlogic_spifc_a1_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct amlogic_spifc_a1 *spifc =
|
||||
spi_controller_get_devdata(mem->spi->controller);
|
||||
size_t off, nbytes = op->data.nbytes;
|
||||
u32 cmd_cfg, addr_cfg, dummy_cfg, dmode;
|
||||
size_t data_size = op->data.nbytes;
|
||||
int ret;
|
||||
|
||||
ret = amlogic_spifc_a1_set_freq(spifc, mem->spi->max_speed_hz);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
amlogic_spifc_a1_user_init(spifc);
|
||||
amlogic_spifc_a1_set_cmd(spifc, SPIFC_A1_USER_CMD(op));
|
||||
|
||||
cmd_cfg = SPIFC_A1_USER_CMD(op);
|
||||
amlogic_spifc_a1_set_cmd(spifc, cmd_cfg);
|
||||
if (op->addr.nbytes)
|
||||
amlogic_spifc_a1_set_addr(spifc, op->addr.val,
|
||||
SPIFC_A1_USER_ADDR(op));
|
||||
|
||||
if (op->addr.nbytes) {
|
||||
addr_cfg = SPIFC_A1_USER_ADDR(op);
|
||||
amlogic_spifc_a1_set_addr(spifc, op->addr.val, addr_cfg);
|
||||
}
|
||||
if (op->dummy.nbytes)
|
||||
amlogic_spifc_a1_set_dummy(spifc, SPIFC_A1_USER_DUMMY(op));
|
||||
|
||||
if (op->dummy.nbytes) {
|
||||
dummy_cfg = SPIFC_A1_USER_DUMMY(op);
|
||||
amlogic_spifc_a1_set_dummy(spifc, dummy_cfg);
|
||||
}
|
||||
|
||||
if (!op->data.nbytes)
|
||||
return amlogic_spifc_a1_request(spifc, false);
|
||||
|
||||
dmode = ilog2(op->data.buswidth);
|
||||
off = 0;
|
||||
|
||||
do {
|
||||
size_t block_size = min_t(size_t, nbytes, SPIFC_A1_BUFFER_SIZE);
|
||||
|
||||
amlogic_spifc_a1_set_cmd(spifc, cmd_cfg);
|
||||
|
||||
if (op->addr.nbytes)
|
||||
amlogic_spifc_a1_set_addr(spifc, op->addr.val + off,
|
||||
addr_cfg);
|
||||
|
||||
if (op->dummy.nbytes)
|
||||
amlogic_spifc_a1_set_dummy(spifc, dummy_cfg);
|
||||
if (data_size) {
|
||||
u32 mode = ilog2(op->data.buswidth);
|
||||
|
||||
writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG);
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_IN)
|
||||
ret = amlogic_spifc_a1_read(spifc,
|
||||
op->data.buf.in + off,
|
||||
block_size, dmode);
|
||||
ret = amlogic_spifc_a1_read(spifc, op->data.buf.in,
|
||||
data_size, mode);
|
||||
else
|
||||
ret = amlogic_spifc_a1_write(spifc,
|
||||
op->data.buf.out + off,
|
||||
block_size, dmode);
|
||||
|
||||
nbytes -= block_size;
|
||||
off += block_size;
|
||||
} while (nbytes != 0 && !ret);
|
||||
ret = amlogic_spifc_a1_write(spifc, op->data.buf.out,
|
||||
data_size, mode);
|
||||
} else {
|
||||
ret = amlogic_spifc_a1_request(spifc, false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amlogic_spifc_a1_adjust_op_size(struct spi_mem *mem,
|
||||
struct spi_mem_op *op)
|
||||
{
|
||||
op->data.nbytes = min(op->data.nbytes, SPIFC_A1_BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc)
|
||||
{
|
||||
u32 regv;
|
||||
|
@ -314,6 +317,7 @@ static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc)
|
|||
|
||||
static const struct spi_controller_mem_ops amlogic_spifc_a1_mem_ops = {
|
||||
.exec_op = amlogic_spifc_a1_exec_op,
|
||||
.adjust_op_size = amlogic_spifc_a1_adjust_op_size,
|
||||
};
|
||||
|
||||
static int amlogic_spifc_a1_probe(struct platform_device *pdev)
|
||||
|
@ -322,7 +326,7 @@ static int amlogic_spifc_a1_probe(struct platform_device *pdev)
|
|||
struct amlogic_spifc_a1 *spifc;
|
||||
int ret;
|
||||
|
||||
ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*spifc));
|
||||
ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifc));
|
||||
if (!ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define DRIVER_NAME "spi-ar934x"
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ static const struct aspeed_spi_data ast2400_spi_data;
|
|||
|
||||
static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(mem->spi, 0)];
|
||||
u32 addr_mode, addr_mode_backup;
|
||||
u32 ctl_val;
|
||||
|
@ -374,7 +374,7 @@ static int aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
|
||||
static const char *aspeed_spi_get_name(struct spi_mem *mem)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct device *dev = aspi->dev;
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
|
||||
|
@ -553,7 +553,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip);
|
|||
|
||||
static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)];
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
u32 ctl_val;
|
||||
|
@ -620,7 +620,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offset, size_t len, void *buf)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)];
|
||||
|
||||
/* Switch to USER command mode if mapping window is too small */
|
||||
|
@ -669,7 +669,7 @@ static void aspeed_spi_chip_enable(struct aspeed_spi *aspi, unsigned int cs, boo
|
|||
|
||||
static int aspeed_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(spi->controller);
|
||||
const struct aspeed_spi_data *data = aspi->data;
|
||||
unsigned int cs = spi_get_chipselect(spi, 0);
|
||||
struct aspeed_spi_chip *chip = &aspi->chips[cs];
|
||||
|
@ -697,7 +697,7 @@ static int aspeed_spi_setup(struct spi_device *spi)
|
|||
|
||||
static void aspeed_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(spi->master);
|
||||
struct aspeed_spi *aspi = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int cs = spi_get_chipselect(spi, 0);
|
||||
|
||||
aspeed_spi_chip_enable(aspi, cs, false);
|
||||
|
@ -726,7 +726,7 @@ static int aspeed_spi_probe(struct platform_device *pdev)
|
|||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
ctlr = devm_spi_alloc_master(dev, sizeof(*aspi));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(*aspi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -486,10 +485,7 @@ static int at91_usart_gpio_setup(struct platform_device *pdev)
|
|||
|
||||
cs_gpios = devm_gpiod_get_array_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
|
||||
|
||||
if (IS_ERR(cs_gpios))
|
||||
return PTR_ERR(cs_gpios);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(cs_gpios);
|
||||
}
|
||||
|
||||
static int at91_usart_spi_probe(struct platform_device *pdev)
|
||||
|
@ -527,7 +523,7 @@ static int at91_usart_spi_probe(struct platform_device *pdev)
|
|||
controller->dev.of_node = pdev->dev.parent->of_node;
|
||||
controller->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
controller->setup = at91_usart_spi_setup;
|
||||
controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
|
||||
controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
|
||||
controller->transfer_one = at91_usart_spi_transfer_one;
|
||||
controller->prepare_message = at91_usart_spi_prepare_message;
|
||||
controller->unprepare_message = at91_usart_spi_unprepare_message;
|
||||
|
|
|
@ -185,7 +185,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
|
|||
|
||||
host->use_gpio_descriptors = true;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
||||
host->flags = SPI_MASTER_GPIO_SS;
|
||||
host->flags = SPI_CONTROLLER_GPIO_SS;
|
||||
host->num_chipselect = 3;
|
||||
host->mem_ops = &ath79_mem_ops;
|
||||
|
||||
|
|
|
@ -1450,10 +1450,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
/* Select default pin state */
|
||||
pinctrl_pm_select_default_state(&pdev->dev);
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs)
|
||||
return -ENXIO;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
@ -1475,8 +1471,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
host->bus_num = pdev->id;
|
||||
host->num_chipselect = 4;
|
||||
host->setup = atmel_spi_setup;
|
||||
host->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX |
|
||||
SPI_MASTER_GPIO_SS);
|
||||
host->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX |
|
||||
SPI_CONTROLLER_GPIO_SS);
|
||||
host->transfer_one = atmel_spi_one_transfer;
|
||||
host->set_cs = atmel_spi_set_cs;
|
||||
host->cleanup = atmel_spi_cleanup;
|
||||
|
@ -1490,7 +1486,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&as->lock);
|
||||
|
||||
as->pdev = pdev;
|
||||
as->regs = devm_ioremap_resource(&pdev->dev, regs);
|
||||
as->regs = devm_platform_get_and_ioremap_resource(pdev, 0, ®s);
|
||||
if (IS_ERR(as->regs)) {
|
||||
ret = PTR_ERR(as->regs);
|
||||
goto out_unmap_regs;
|
||||
|
|
|
@ -54,7 +54,7 @@ struct au1550_spi {
|
|||
int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
|
||||
irqreturn_t (*irq_callback)(struct au1550_spi *hw);
|
||||
|
||||
struct completion master_done;
|
||||
struct completion host_done;
|
||||
|
||||
unsigned int usedma;
|
||||
u32 dma_tx_id;
|
||||
|
@ -66,7 +66,7 @@ struct au1550_spi {
|
|||
unsigned int dma_rx_tmpbuf_size;
|
||||
u32 dma_rx_tmpbuf_addr;
|
||||
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct device *dev;
|
||||
struct au1550_spi_info *pdata;
|
||||
struct resource *ioarea;
|
||||
|
@ -159,7 +159,7 @@ static void au1550_spi_reset_fifos(struct au1550_spi *hw)
|
|||
*/
|
||||
static void au1550_spi_chipsel(struct spi_device *spi, int value)
|
||||
{
|
||||
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct au1550_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
|
||||
u32 cfg, stat;
|
||||
|
||||
|
@ -219,7 +219,7 @@ static void au1550_spi_chipsel(struct spi_device *spi, int value)
|
|||
|
||||
static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct au1550_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int bpw, hz;
|
||||
u32 cfg, stat;
|
||||
|
||||
|
@ -272,7 +272,7 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
|
|||
* no reliable way how to recognize that spi transfer is done
|
||||
* dma complete callbacks are called before real spi transfer is finished
|
||||
* and if only tx dma channel is set up (and rx fifo overflow event masked)
|
||||
* spi master done event irq is not generated unless rx fifo is empty (emptied)
|
||||
* spi host done event irq is not generated unless rx fifo is empty (emptied)
|
||||
* so we need rx tmp buffer to use for rx dma if user does not provide one
|
||||
*/
|
||||
static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned int size)
|
||||
|
@ -303,7 +303,7 @@ static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw)
|
|||
|
||||
static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct au1550_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
dma_addr_t dma_tx_addr;
|
||||
dma_addr_t dma_rx_addr;
|
||||
u32 res;
|
||||
|
@ -387,7 +387,7 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
|
|||
hw->regs->psc_spipcr = PSC_SPIPCR_MS;
|
||||
wmb(); /* drain writebuffer */
|
||||
|
||||
wait_for_completion(&hw->master_done);
|
||||
wait_for_completion(&hw->host_done);
|
||||
|
||||
au1xxx_dbdma_stop(hw->dma_tx_ch);
|
||||
au1xxx_dbdma_stop(hw->dma_rx_ch);
|
||||
|
@ -449,7 +449,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
|
|||
"dma transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n",
|
||||
evnt, stat);
|
||||
|
||||
complete(&hw->master_done);
|
||||
complete(&hw->host_done);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -458,7 +458,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
|
|||
au1550_spi_mask_ack_all(hw);
|
||||
hw->rx_count = hw->len;
|
||||
hw->tx_count = hw->len;
|
||||
complete(&hw->master_done);
|
||||
complete(&hw->host_done);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ AU1550_SPI_TX_WORD(32, 0xffffff)
|
|||
static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
u32 stat, mask;
|
||||
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct au1550_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
hw->tx = t->tx_buf;
|
||||
hw->rx = t->rx_buf;
|
||||
|
@ -537,7 +537,7 @@ static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
|
|||
hw->regs->psc_spipcr = PSC_SPIPCR_MS;
|
||||
wmb(); /* drain writebuffer */
|
||||
|
||||
wait_for_completion(&hw->master_done);
|
||||
wait_for_completion(&hw->host_done);
|
||||
|
||||
return min(hw->rx_count, hw->tx_count);
|
||||
}
|
||||
|
@ -568,7 +568,7 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
|
|||
dev_err(hw->dev,
|
||||
"pio transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n",
|
||||
evnt, stat);
|
||||
complete(&hw->master_done);
|
||||
complete(&hw->host_done);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -605,11 +605,11 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
|
|||
/*
|
||||
* Restart the SPI transmission in case of a transmit underflow.
|
||||
* This seems to work despite the notes in the Au1550 data book
|
||||
* of Figure 8-4 with flowchart for SPI master operation:
|
||||
* of Figure 8-4 with flowchart for SPI host operation:
|
||||
*
|
||||
* """Note 1: An XFR Error Interrupt occurs, unless masked,
|
||||
* for any of the following events: Tx FIFO Underflow,
|
||||
* Rx FIFO Overflow, or Multiple-master Error
|
||||
* Rx FIFO Overflow, or Multiple-host Error
|
||||
* Note 2: In case of a Tx Underflow Error, all zeroes are
|
||||
* transmitted."""
|
||||
*
|
||||
|
@ -627,14 +627,14 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
|
|||
if (hw->rx_count >= hw->len) {
|
||||
/* transfer completed successfully */
|
||||
au1550_spi_mask_ack_all(hw);
|
||||
complete(&hw->master_done);
|
||||
complete(&hw->host_done);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct au1550_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
return hw->txrx_bufs(spi, t);
|
||||
}
|
||||
|
@ -723,24 +723,24 @@ static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
|
|||
static int au1550_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct au1550_spi *hw;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource *r;
|
||||
int err = 0;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
|
||||
if (master == NULL) {
|
||||
dev_err(&pdev->dev, "No memory for spi_master\n");
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct au1550_spi));
|
||||
if (host == NULL) {
|
||||
dev_err(&pdev->dev, "No memory for spi_controller\n");
|
||||
err = -ENOMEM;
|
||||
goto err_nomem;
|
||||
}
|
||||
|
||||
/* the spi->mode bits understood by this driver: */
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 24);
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 24);
|
||||
|
||||
hw = spi_master_get_devdata(master);
|
||||
hw = spi_controller_get_devdata(host);
|
||||
|
||||
hw->master = master;
|
||||
hw->host = host;
|
||||
hw->pdata = dev_get_platdata(&pdev->dev);
|
||||
hw->dev = &pdev->dev;
|
||||
|
||||
|
@ -798,9 +798,9 @@ static int au1550_spi_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
init_completion(&hw->master_done);
|
||||
init_completion(&hw->host_done);
|
||||
|
||||
hw->bitbang.master = hw->master;
|
||||
hw->bitbang.master = hw->host;
|
||||
hw->bitbang.setup_transfer = au1550_spi_setupxfer;
|
||||
hw->bitbang.chipselect = au1550_spi_chipsel;
|
||||
hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
|
||||
|
@ -858,8 +858,8 @@ static int au1550_spi_probe(struct platform_device *pdev)
|
|||
goto err_no_irq;
|
||||
}
|
||||
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = hw->pdata->num_chipselect;
|
||||
host->bus_num = pdev->id;
|
||||
host->num_chipselect = hw->pdata->num_chipselect;
|
||||
|
||||
/*
|
||||
* precompute valid range for spi freq - from au1550 datasheet:
|
||||
|
@ -874,8 +874,8 @@ static int au1550_spi_probe(struct platform_device *pdev)
|
|||
int min_div = (2 << 0) * (2 * (4 + 1));
|
||||
int max_div = (2 << 3) * (2 * (63 + 1));
|
||||
|
||||
master->max_speed_hz = hw->pdata->mainclk_hz / min_div;
|
||||
master->min_speed_hz =
|
||||
host->max_speed_hz = hw->pdata->mainclk_hz / min_div;
|
||||
host->min_speed_hz =
|
||||
hw->pdata->mainclk_hz / (max_div + 1) + 1;
|
||||
}
|
||||
|
||||
|
@ -883,13 +883,13 @@ static int au1550_spi_probe(struct platform_device *pdev)
|
|||
|
||||
err = spi_bitbang_start(&hw->bitbang);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to register SPI master\n");
|
||||
dev_err(&pdev->dev, "Failed to register SPI host\n");
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"spi master registered: bus_num=%d num_chipselect=%d\n",
|
||||
master->bus_num, master->num_chipselect);
|
||||
"spi host registered: bus_num=%d num_chipselect=%d\n",
|
||||
host->bus_num, host->num_chipselect);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -917,7 +917,7 @@ err_ioremap:
|
|||
|
||||
err_no_iores:
|
||||
err_no_pdata:
|
||||
spi_master_put(hw->master);
|
||||
spi_controller_put(hw->host);
|
||||
|
||||
err_nomem:
|
||||
return err;
|
||||
|
@ -927,8 +927,8 @@ static void au1550_spi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct au1550_spi *hw = platform_get_drvdata(pdev);
|
||||
|
||||
dev_info(&pdev->dev, "spi master remove: bus_num=%d\n",
|
||||
hw->master->bus_num);
|
||||
dev_info(&pdev->dev, "spi host remove: bus_num=%d\n",
|
||||
hw->host->bus_num);
|
||||
|
||||
spi_bitbang_stop(&hw->bitbang);
|
||||
free_irq(hw->irq, hw);
|
||||
|
@ -941,7 +941,7 @@ static void au1550_spi_remove(struct platform_device *pdev)
|
|||
au1xxx_dbdma_chan_free(hw->dma_tx_ch);
|
||||
}
|
||||
|
||||
spi_master_put(hw->master);
|
||||
spi_controller_put(hw->host);
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
|
|
|
@ -356,8 +356,8 @@ static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine)
|
|||
|
||||
static irqreturn_t spi_engine_irq(int irq, void *devid)
|
||||
{
|
||||
struct spi_master *master = devid;
|
||||
struct spi_engine *spi_engine = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = devid;
|
||||
struct spi_engine *spi_engine = spi_controller_get_devdata(host);
|
||||
unsigned int disable_int = 0;
|
||||
unsigned int pending;
|
||||
|
||||
|
@ -396,7 +396,7 @@ static irqreturn_t spi_engine_irq(int irq, void *devid)
|
|||
msg->status = 0;
|
||||
msg->actual_length = msg->frame_length;
|
||||
spi_engine->msg = NULL;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
disable_int |= SPI_ENGINE_INT_SYNC;
|
||||
}
|
||||
}
|
||||
|
@ -412,11 +412,11 @@ static irqreturn_t spi_engine_irq(int irq, void *devid)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int spi_engine_transfer_one_message(struct spi_master *master,
|
||||
static int spi_engine_transfer_one_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct spi_engine_program p_dry, *p;
|
||||
struct spi_engine *spi_engine = spi_master_get_devdata(master);
|
||||
struct spi_engine *spi_engine = spi_controller_get_devdata(host);
|
||||
unsigned int int_enable = 0;
|
||||
unsigned long flags;
|
||||
size_t size;
|
||||
|
@ -464,42 +464,42 @@ static int spi_engine_transfer_one_message(struct spi_master *master,
|
|||
static int spi_engine_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_engine *spi_engine;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
unsigned int version;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0)
|
||||
return -ENXIO;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL);
|
||||
if (!spi_engine)
|
||||
return -ENOMEM;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, 0);
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, 0);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_master_set_devdata(master, spi_engine);
|
||||
spi_controller_set_devdata(host, spi_engine);
|
||||
|
||||
spin_lock_init(&spi_engine->lock);
|
||||
|
||||
spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
|
||||
if (IS_ERR(spi_engine->clk)) {
|
||||
ret = PTR_ERR(spi_engine->clk);
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk");
|
||||
if (IS_ERR(spi_engine->ref_clk)) {
|
||||
ret = PTR_ERR(spi_engine->ref_clk);
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(spi_engine->clk);
|
||||
if (ret)
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
|
||||
ret = clk_prepare_enable(spi_engine->ref_clk);
|
||||
if (ret)
|
||||
|
@ -525,46 +525,46 @@ static int spi_engine_probe(struct platform_device *pdev)
|
|||
writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
|
||||
writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
|
||||
|
||||
ret = request_irq(irq, spi_engine_irq, 0, pdev->name, master);
|
||||
ret = request_irq(irq, spi_engine_irq, 0, pdev->name, host);
|
||||
if (ret)
|
||||
goto err_ref_clk_disable;
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2;
|
||||
master->transfer_one_message = spi_engine_transfer_one_message;
|
||||
master->num_chipselect = 8;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2;
|
||||
host->transfer_one_message = spi_engine_transfer_one_message;
|
||||
host->num_chipselect = 8;
|
||||
|
||||
ret = spi_register_master(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
return 0;
|
||||
err_free_irq:
|
||||
free_irq(irq, master);
|
||||
free_irq(irq, host);
|
||||
err_ref_clk_disable:
|
||||
clk_disable_unprepare(spi_engine->ref_clk);
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(spi_engine->clk);
|
||||
err_put_master:
|
||||
spi_master_put(master);
|
||||
err_put_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void spi_engine_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
|
||||
struct spi_engine *spi_engine = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = spi_controller_get(platform_get_drvdata(pdev));
|
||||
struct spi_engine *spi_engine = spi_controller_get_devdata(host);
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
|
||||
spi_unregister_master(master);
|
||||
spi_unregister_controller(host);
|
||||
|
||||
free_irq(irq, master);
|
||||
free_irq(irq, host);
|
||||
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
|
||||
writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
|
||||
writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
|
||||
|
|
|
@ -220,7 +220,7 @@ struct qspi_trans {
|
|||
|
||||
struct bcm_qspi {
|
||||
struct platform_device *pdev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct clk *clk;
|
||||
u32 base_clk;
|
||||
u32 max_speed_hz;
|
||||
|
@ -732,7 +732,7 @@ static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi,
|
|||
struct qspi_trans *qt)
|
||||
{
|
||||
if (qt->mspi_last_trans &&
|
||||
spi_transfer_is_last(qspi->master, qt->trans))
|
||||
spi_transfer_is_last(qspi->host, qt->trans))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -979,7 +979,7 @@ static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi)
|
|||
mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 :
|
||||
MSPI_CDRAM_BITSE_BIT);
|
||||
|
||||
/* set 3wrire halfduplex mode data from master to slave */
|
||||
/* set 3wrire halfduplex mode data from host to target */
|
||||
if ((spi->mode & SPI_3WIRE) && tp.trans->tx_buf)
|
||||
mspi_cdram |= MSPI_CDRAM_OUTP;
|
||||
|
||||
|
@ -1035,7 +1035,7 @@ done:
|
|||
static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
|
||||
struct bcm_qspi *qspi = spi_controller_get_devdata(spi->controller);
|
||||
u32 addr = 0, len, rdlen, len_words, from = 0;
|
||||
int ret = 0;
|
||||
unsigned long timeo = msecs_to_jiffies(100);
|
||||
|
@ -1118,11 +1118,11 @@ static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int bcm_qspi_transfer_one(struct spi_master *master,
|
||||
static int bcm_qspi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *trans)
|
||||
{
|
||||
struct bcm_qspi *qspi = spi_master_get_devdata(master);
|
||||
struct bcm_qspi *qspi = spi_controller_get_devdata(host);
|
||||
int slots;
|
||||
unsigned long timeo = msecs_to_jiffies(100);
|
||||
|
||||
|
@ -1150,8 +1150,8 @@ static int bcm_qspi_transfer_one(struct spi_master *master,
|
|||
static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
struct bcm_qspi *qspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = spi->controller;
|
||||
struct bcm_qspi *qspi = spi_controller_get_devdata(host);
|
||||
struct spi_transfer t[2];
|
||||
u8 cmd[6] = { };
|
||||
int ret, i;
|
||||
|
@ -1171,7 +1171,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi,
|
|||
t[0].tx_nbits = op->cmd.buswidth;
|
||||
/* lets mspi know that this is not last transfer */
|
||||
qspi->trans_pos.mspi_last_trans = false;
|
||||
ret = bcm_qspi_transfer_one(master, spi, &t[0]);
|
||||
ret = bcm_qspi_transfer_one(host, spi, &t[0]);
|
||||
|
||||
/* rx */
|
||||
qspi->trans_pos.mspi_last_trans = true;
|
||||
|
@ -1181,7 +1181,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi,
|
|||
t[1].len = op->data.nbytes;
|
||||
t[1].rx_nbits = op->data.buswidth;
|
||||
t[1].bits_per_word = spi->bits_per_word;
|
||||
ret = bcm_qspi_transfer_one(master, spi, &t[1]);
|
||||
ret = bcm_qspi_transfer_one(host, spi, &t[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1191,7 +1191,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem,
|
|||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct spi_device *spi = mem->spi;
|
||||
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
|
||||
struct bcm_qspi *qspi = spi_controller_get_devdata(spi->controller);
|
||||
int ret = 0;
|
||||
bool mspi_read = false;
|
||||
u32 addr = 0, len;
|
||||
|
@ -1486,7 +1486,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
const struct bcm_qspi_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm_qspi *qspi;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource *res;
|
||||
int irq, ret = 0, num_ints = 0;
|
||||
u32 val;
|
||||
|
@ -1504,13 +1504,13 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
|
||||
data = of_id->data;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi));
|
||||
if (!master) {
|
||||
dev_err(dev, "error allocating spi_master\n");
|
||||
host = devm_spi_alloc_host(dev, sizeof(struct bcm_qspi));
|
||||
if (!host) {
|
||||
dev_err(dev, "error allocating spi_controller\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
qspi = spi_master_get_devdata(master);
|
||||
qspi = spi_controller_get_devdata(host);
|
||||
|
||||
qspi->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(qspi->clk))
|
||||
|
@ -1520,23 +1520,23 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
qspi->trans_pos.trans = NULL;
|
||||
qspi->trans_pos.byte = 0;
|
||||
qspi->trans_pos.mspi_last_trans = true;
|
||||
qspi->master = master;
|
||||
qspi->host = host;
|
||||
|
||||
master->bus_num = -1;
|
||||
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD |
|
||||
host->bus_num = -1;
|
||||
host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD |
|
||||
SPI_3WIRE;
|
||||
master->setup = bcm_qspi_setup;
|
||||
master->transfer_one = bcm_qspi_transfer_one;
|
||||
master->mem_ops = &bcm_qspi_mem_ops;
|
||||
master->cleanup = bcm_qspi_cleanup;
|
||||
master->dev.of_node = dev->of_node;
|
||||
master->num_chipselect = NUM_CHIPSELECT;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->setup = bcm_qspi_setup;
|
||||
host->transfer_one = bcm_qspi_transfer_one;
|
||||
host->mem_ops = &bcm_qspi_mem_ops;
|
||||
host->cleanup = bcm_qspi_cleanup;
|
||||
host->dev.of_node = dev->of_node;
|
||||
host->num_chipselect = NUM_CHIPSELECT;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
qspi->big_endian = of_device_is_big_endian(dev->of_node);
|
||||
|
||||
if (!of_property_read_u32(dev->of_node, "num-cs", &val))
|
||||
master->num_chipselect = val;
|
||||
host->num_chipselect = val;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hif_mspi");
|
||||
if (!res)
|
||||
|
@ -1659,9 +1659,9 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
qspi->xfer_mode.addrlen = -1;
|
||||
qspi->xfer_mode.hp = -1;
|
||||
|
||||
ret = spi_register_master(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't register master\n");
|
||||
dev_err(dev, "can't register host\n");
|
||||
goto qspi_reg_err;
|
||||
}
|
||||
|
||||
|
@ -1682,7 +1682,7 @@ void bcm_qspi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct bcm_qspi *qspi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_unregister_master(qspi->master);
|
||||
spi_unregister_controller(qspi->host);
|
||||
bcm_qspi_hw_uninit(qspi);
|
||||
clk_disable_unprepare(qspi->clk);
|
||||
kfree(qspi->dev_ids);
|
||||
|
@ -1700,7 +1700,7 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev)
|
|||
qspi->s3_strap_override_ctrl =
|
||||
bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
|
||||
|
||||
spi_master_suspend(qspi->master);
|
||||
spi_controller_suspend(qspi->host);
|
||||
clk_disable_unprepare(qspi->clk);
|
||||
bcm_qspi_hw_uninit(qspi);
|
||||
|
||||
|
@ -1721,7 +1721,7 @@ static int __maybe_unused bcm_qspi_resume(struct device *dev)
|
|||
|
||||
ret = clk_prepare_enable(qspi->clk);
|
||||
if (!ret)
|
||||
spi_master_resume(qspi->master);
|
||||
spi_controller_resume(qspi->host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h> /* FIXME: using chip internals */
|
||||
#include <linux/gpio/driver.h> /* FIXME: using chip internals */
|
||||
|
@ -105,7 +105,7 @@ MODULE_PARM_DESC(polling_limit_us,
|
|||
* These are counted as well in @count_transfer_polling and
|
||||
* @count_transfer_irq
|
||||
* @count_transfer_dma: count how often dma mode is used
|
||||
* @slv: SPI slave currently selected
|
||||
* @target: SPI target currently selected
|
||||
* (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs)
|
||||
* @tx_dma_active: whether a TX DMA descriptor is in progress
|
||||
* @rx_dma_active: whether a RX DMA descriptor is in progress
|
||||
|
@ -135,7 +135,7 @@ struct bcm2835_spi {
|
|||
u64 count_transfer_irq_after_polling;
|
||||
u64 count_transfer_dma;
|
||||
|
||||
struct bcm2835_spidev *slv;
|
||||
struct bcm2835_spidev *target;
|
||||
unsigned int tx_dma_active;
|
||||
unsigned int rx_dma_active;
|
||||
struct dma_async_tx_descriptor *fill_tx_desc;
|
||||
|
@ -143,14 +143,14 @@ struct bcm2835_spi {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct bcm2835_spidev - BCM2835 SPI slave
|
||||
* struct bcm2835_spidev - BCM2835 SPI target
|
||||
* @prepare_cs: precalculated CS register value for ->prepare_message()
|
||||
* (uses slave-specific clock polarity and phase settings)
|
||||
* (uses target-specific clock polarity and phase settings)
|
||||
* @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers
|
||||
* (cyclically clears RX FIFO by writing @clear_rx_cs to CS register)
|
||||
* @clear_rx_addr: bus address of @clear_rx_cs
|
||||
* @clear_rx_cs: precalculated CS register value to clear RX FIFO
|
||||
* (uses slave-specific clock polarity and phase settings)
|
||||
* (uses target-specific clock polarity and phase settings)
|
||||
*/
|
||||
struct bcm2835_spidev {
|
||||
u32 prepare_cs;
|
||||
|
@ -434,7 +434,7 @@ static int bcm2835_spi_transfer_one_irq(struct spi_controller *ctlr,
|
|||
|
||||
/**
|
||||
* bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA
|
||||
* @ctlr: SPI master controller
|
||||
* @ctlr: SPI host controller
|
||||
* @tfr: SPI transfer
|
||||
* @bs: BCM2835 SPI controller
|
||||
* @cs: CS register
|
||||
|
@ -596,7 +596,7 @@ out:
|
|||
|
||||
/**
|
||||
* bcm2835_spi_dma_rx_done() - callback for DMA RX channel
|
||||
* @data: SPI master controller
|
||||
* @data: SPI host controller
|
||||
*
|
||||
* Used for bidirectional and RX-only transfers.
|
||||
*/
|
||||
|
@ -624,7 +624,7 @@ static void bcm2835_spi_dma_rx_done(void *data)
|
|||
|
||||
/**
|
||||
* bcm2835_spi_dma_tx_done() - callback for DMA TX channel
|
||||
* @data: SPI master controller
|
||||
* @data: SPI host controller
|
||||
*
|
||||
* Used for TX-only transfers.
|
||||
*/
|
||||
|
@ -635,7 +635,7 @@ static void bcm2835_spi_dma_tx_done(void *data)
|
|||
|
||||
/* busy-wait for TX FIFO to empty */
|
||||
while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE))
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS, bs->slv->clear_rx_cs);
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS, bs->target->clear_rx_cs);
|
||||
|
||||
bs->tx_dma_active = false;
|
||||
smp_wmb();
|
||||
|
@ -655,10 +655,10 @@ static void bcm2835_spi_dma_tx_done(void *data)
|
|||
|
||||
/**
|
||||
* bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist
|
||||
* @ctlr: SPI master controller
|
||||
* @ctlr: SPI host controller
|
||||
* @tfr: SPI transfer
|
||||
* @bs: BCM2835 SPI controller
|
||||
* @slv: BCM2835 SPI slave
|
||||
* @target: BCM2835 SPI target
|
||||
* @is_tx: whether to submit DMA descriptor for TX or RX sglist
|
||||
*
|
||||
* Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr.
|
||||
|
@ -667,7 +667,7 @@ static void bcm2835_spi_dma_tx_done(void *data)
|
|||
static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
|
||||
struct spi_transfer *tfr,
|
||||
struct bcm2835_spi *bs,
|
||||
struct bcm2835_spidev *slv,
|
||||
struct bcm2835_spidev *target,
|
||||
bool is_tx)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
|
@ -707,7 +707,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
|
|||
} else if (!tfr->rx_buf) {
|
||||
desc->callback = bcm2835_spi_dma_tx_done;
|
||||
desc->callback_param = ctlr;
|
||||
bs->slv = slv;
|
||||
bs->target = target;
|
||||
}
|
||||
|
||||
/* submit it to DMA-engine */
|
||||
|
@ -718,9 +718,9 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
|
|||
|
||||
/**
|
||||
* bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine
|
||||
* @ctlr: SPI master controller
|
||||
* @ctlr: SPI host controller
|
||||
* @tfr: SPI transfer
|
||||
* @slv: BCM2835 SPI slave
|
||||
* @target: BCM2835 SPI target
|
||||
* @cs: CS register
|
||||
*
|
||||
* For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up
|
||||
|
@ -732,7 +732,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
|
|||
* clear the RX FIFO by setting the CLEAR_RX bit in the CS register.
|
||||
*
|
||||
* The CS register value is precalculated in bcm2835_spi_setup(). Normally
|
||||
* this is called only once, on slave registration. A DMA descriptor to write
|
||||
* this is called only once, on target registration. A DMA descriptor to write
|
||||
* this value is preallocated in bcm2835_dma_init(). All that's left to do
|
||||
* when performing a TX-only transfer is to submit this descriptor to the RX
|
||||
* DMA channel. Latency is thereby minimized. The descriptor does not
|
||||
|
@ -765,7 +765,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr,
|
|||
*/
|
||||
static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
|
||||
struct spi_transfer *tfr,
|
||||
struct bcm2835_spidev *slv,
|
||||
struct bcm2835_spidev *target,
|
||||
u32 cs)
|
||||
{
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
|
@ -783,7 +783,7 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
|
|||
|
||||
/* setup tx-DMA */
|
||||
if (bs->tx_buf) {
|
||||
ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, slv, true);
|
||||
ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, true);
|
||||
} else {
|
||||
cookie = dmaengine_submit(bs->fill_tx_desc);
|
||||
ret = dma_submit_error(cookie);
|
||||
|
@ -809,9 +809,9 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
|
|||
* this saves 10us or more.
|
||||
*/
|
||||
if (bs->rx_buf) {
|
||||
ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, slv, false);
|
||||
ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, false);
|
||||
} else {
|
||||
cookie = dmaengine_submit(slv->clear_rx_desc);
|
||||
cookie = dmaengine_submit(target->clear_rx_desc);
|
||||
ret = dma_submit_error(cookie);
|
||||
}
|
||||
if (ret) {
|
||||
|
@ -903,15 +903,15 @@ static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
|
|||
/* get tx/rx dma */
|
||||
ctlr->dma_tx = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(ctlr->dma_tx)) {
|
||||
dev_err(dev, "no tx-dma configuration found - not using dma mode\n");
|
||||
ret = PTR_ERR(ctlr->dma_tx);
|
||||
ret = dev_err_probe(dev, PTR_ERR(ctlr->dma_tx),
|
||||
"no tx-dma configuration found - not using dma mode\n");
|
||||
ctlr->dma_tx = NULL;
|
||||
goto err;
|
||||
}
|
||||
ctlr->dma_rx = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(ctlr->dma_rx)) {
|
||||
dev_err(dev, "no rx-dma configuration found - not using dma mode\n");
|
||||
ret = PTR_ERR(ctlr->dma_rx);
|
||||
ret = dev_err_probe(dev, PTR_ERR(ctlr->dma_rx),
|
||||
"no rx-dma configuration found - not using dma mode\n");
|
||||
ctlr->dma_rx = NULL;
|
||||
goto err_release;
|
||||
}
|
||||
|
@ -1050,10 +1050,10 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
|
|||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
struct bcm2835_spidev *slv = spi_get_ctldata(spi);
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
unsigned long spi_hz, cdiv;
|
||||
unsigned long hz_per_byte, byte_limit;
|
||||
u32 cs = slv->prepare_cs;
|
||||
u32 cs = target->prepare_cs;
|
||||
|
||||
/* set clock */
|
||||
spi_hz = tfr->speed_hz;
|
||||
|
@ -1101,7 +1101,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
|
|||
* this 1 idle clock cycle pattern but runs the spi clock without gaps
|
||||
*/
|
||||
if (ctlr->can_dma && bcm2835_spi_can_dma(ctlr, spi, tfr))
|
||||
return bcm2835_spi_transfer_one_dma(ctlr, tfr, slv, cs);
|
||||
return bcm2835_spi_transfer_one_dma(ctlr, tfr, target, cs);
|
||||
|
||||
/* run in interrupt-mode */
|
||||
return bcm2835_spi_transfer_one_irq(ctlr, spi, tfr, cs, true);
|
||||
|
@ -1112,7 +1112,7 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
|
|||
{
|
||||
struct spi_device *spi = msg->spi;
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
struct bcm2835_spidev *slv = spi_get_ctldata(spi);
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
int ret;
|
||||
|
||||
if (ctlr->can_dma) {
|
||||
|
@ -1131,7 +1131,7 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr,
|
|||
* Set up clock polarity before spi_transfer_one_message() asserts
|
||||
* chip select to avoid a gratuitous clock signal edge.
|
||||
*/
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS, slv->prepare_cs);
|
||||
bcm2835_wr(bs, BCM2835_SPI_CS, target->prepare_cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1163,51 +1163,51 @@ static int chip_match_name(struct gpio_chip *chip, void *data)
|
|||
|
||||
static void bcm2835_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct bcm2835_spidev *slv = spi_get_ctldata(spi);
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
|
||||
if (slv->clear_rx_desc)
|
||||
dmaengine_desc_free(slv->clear_rx_desc);
|
||||
if (target->clear_rx_desc)
|
||||
dmaengine_desc_free(target->clear_rx_desc);
|
||||
|
||||
if (slv->clear_rx_addr)
|
||||
if (target->clear_rx_addr)
|
||||
dma_unmap_single(ctlr->dma_rx->device->dev,
|
||||
slv->clear_rx_addr,
|
||||
target->clear_rx_addr,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
kfree(slv);
|
||||
kfree(target);
|
||||
}
|
||||
|
||||
static int bcm2835_spi_setup_dma(struct spi_controller *ctlr,
|
||||
struct spi_device *spi,
|
||||
struct bcm2835_spi *bs,
|
||||
struct bcm2835_spidev *slv)
|
||||
struct bcm2835_spidev *target)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ctlr->dma_rx)
|
||||
return 0;
|
||||
|
||||
slv->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev,
|
||||
&slv->clear_rx_cs,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(ctlr->dma_rx->device->dev, slv->clear_rx_addr)) {
|
||||
target->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev,
|
||||
&target->clear_rx_cs,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(ctlr->dma_rx->device->dev, target->clear_rx_addr)) {
|
||||
dev_err(&spi->dev, "cannot map clear_rx_cs\n");
|
||||
slv->clear_rx_addr = 0;
|
||||
target->clear_rx_addr = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
slv->clear_rx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_rx,
|
||||
slv->clear_rx_addr,
|
||||
sizeof(u32), 0,
|
||||
DMA_MEM_TO_DEV, 0);
|
||||
if (!slv->clear_rx_desc) {
|
||||
target->clear_rx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_rx,
|
||||
target->clear_rx_addr,
|
||||
sizeof(u32), 0,
|
||||
DMA_MEM_TO_DEV, 0);
|
||||
if (!target->clear_rx_desc) {
|
||||
dev_err(&spi->dev, "cannot prepare clear_rx_desc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = dmaengine_desc_set_reuse(slv->clear_rx_desc);
|
||||
ret = dmaengine_desc_set_reuse(target->clear_rx_desc);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "cannot reuse clear_rx_desc\n");
|
||||
return ret;
|
||||
|
@ -1220,26 +1220,26 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
|||
{
|
||||
struct spi_controller *ctlr = spi->controller;
|
||||
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
|
||||
struct bcm2835_spidev *slv = spi_get_ctldata(spi);
|
||||
struct bcm2835_spidev *target = spi_get_ctldata(spi);
|
||||
struct gpio_chip *chip;
|
||||
int ret;
|
||||
u32 cs;
|
||||
|
||||
if (!slv) {
|
||||
slv = kzalloc(ALIGN(sizeof(*slv), dma_get_cache_alignment()),
|
||||
if (!target) {
|
||||
target = kzalloc(ALIGN(sizeof(*target), dma_get_cache_alignment()),
|
||||
GFP_KERNEL);
|
||||
if (!slv)
|
||||
if (!target)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_ctldata(spi, slv);
|
||||
spi_set_ctldata(spi, target);
|
||||
|
||||
ret = bcm2835_spi_setup_dma(ctlr, spi, bs, slv);
|
||||
ret = bcm2835_spi_setup_dma(ctlr, spi, bs, target);
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Precalculate SPI slave's CS register value for ->prepare_message():
|
||||
* Precalculate SPI target's CS register value for ->prepare_message():
|
||||
* The driver always uses software-controlled GPIO chip select, hence
|
||||
* set the hardware-controlled native chip select to an invalid value
|
||||
* to prevent it from interfering.
|
||||
|
@ -1249,18 +1249,18 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
|||
cs |= BCM2835_SPI_CS_CPOL;
|
||||
if (spi->mode & SPI_CPHA)
|
||||
cs |= BCM2835_SPI_CS_CPHA;
|
||||
slv->prepare_cs = cs;
|
||||
target->prepare_cs = cs;
|
||||
|
||||
/*
|
||||
* Precalculate SPI slave's CS register value to clear RX FIFO
|
||||
* Precalculate SPI target's CS register value to clear RX FIFO
|
||||
* in case of a TX-only DMA transfer.
|
||||
*/
|
||||
if (ctlr->dma_rx) {
|
||||
slv->clear_rx_cs = cs | BCM2835_SPI_CS_TA |
|
||||
target->clear_rx_cs = cs | BCM2835_SPI_CS_TA |
|
||||
BCM2835_SPI_CS_DMAEN |
|
||||
BCM2835_SPI_CS_CLEAR_RX;
|
||||
dma_sync_single_for_device(ctlr->dma_rx->device->dev,
|
||||
slv->clear_rx_addr,
|
||||
target->clear_rx_addr,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
@ -1328,7 +1328,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
|||
struct bcm2835_spi *bs;
|
||||
int err;
|
||||
|
||||
ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
|
||||
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1360,10 +1360,12 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
|
|||
ctlr->max_speed_hz = clk_get_rate(bs->clk) / 2;
|
||||
|
||||
bs->irq = platform_get_irq(pdev, 0);
|
||||
if (bs->irq <= 0)
|
||||
return bs->irq ? bs->irq : -ENODEV;
|
||||
if (bs->irq < 0)
|
||||
return bs->irq;
|
||||
|
||||
clk_prepare_enable(bs->clk);
|
||||
err = clk_prepare_enable(bs->clk);
|
||||
if (err)
|
||||
return err;
|
||||
bs->clk_hz = clk_get_rate(bs->clk);
|
||||
|
||||
err = bcm2835_dma_init(ctlr, &pdev->dev, bs);
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -233,8 +231,8 @@ static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
|
|||
|
||||
static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = dev_id;
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* IRQ may be shared, so return if our interrupts are disabled */
|
||||
if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
|
||||
|
@ -253,17 +251,17 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
|
|||
/* and if rx_len is 0 then disable interrupts and wake up completion */
|
||||
if (!bs->rx_len) {
|
||||
bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
|
||||
static int __bcm2835aux_spi_transfer_one_irq(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* enable interrupts */
|
||||
bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
|
||||
|
@ -274,11 +272,11 @@ static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
|
||||
static int bcm2835aux_spi_transfer_one_irq(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* update statistics */
|
||||
bs->count_transfer_irq++;
|
||||
|
@ -296,14 +294,14 @@ static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
|
|||
}
|
||||
|
||||
/* now run the interrupt mode */
|
||||
return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
|
||||
return __bcm2835aux_spi_transfer_one_irq(host, spi, tfr);
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
|
||||
static int bcm2835aux_spi_transfer_one_poll(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
unsigned long timeout;
|
||||
|
||||
/* update statistics */
|
||||
|
@ -330,7 +328,7 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
|
|||
bs->tx_len, bs->rx_len);
|
||||
/* forward to interrupt handler */
|
||||
bs->count_transfer_irq_after_poll++;
|
||||
return __bcm2835aux_spi_transfer_one_irq(master,
|
||||
return __bcm2835aux_spi_transfer_one_irq(host,
|
||||
spi, tfr);
|
||||
}
|
||||
}
|
||||
|
@ -339,11 +337,11 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_transfer_one(struct spi_master *master,
|
||||
static int bcm2835aux_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
unsigned long spi_hz, clk_hz, speed;
|
||||
unsigned long hz_per_byte, byte_limit;
|
||||
|
||||
|
@ -394,17 +392,17 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
|
|||
|
||||
/* run in polling mode for short transfers */
|
||||
if (tfr->len < byte_limit)
|
||||
return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
|
||||
return bcm2835aux_spi_transfer_one_poll(host, spi, tfr);
|
||||
|
||||
/* run in interrupt mode for all others */
|
||||
return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
|
||||
return bcm2835aux_spi_transfer_one_irq(host, spi, tfr);
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_prepare_message(struct spi_master *master,
|
||||
static int bcm2835aux_spi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct spi_device *spi = msg->spi;
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
|
||||
BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
|
||||
|
@ -424,20 +422,20 @@ static int bcm2835aux_spi_prepare_message(struct spi_master *master,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
|
||||
static int bcm2835aux_spi_unprepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
bcm2835aux_spi_reset_hw(bs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm2835aux_spi_handle_err(struct spi_master *master,
|
||||
static void bcm2835aux_spi_handle_err(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
bcm2835aux_spi_reset_hw(bs);
|
||||
}
|
||||
|
@ -475,18 +473,18 @@ static int bcm2835aux_spi_setup(struct spi_device *spi)
|
|||
|
||||
static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct bcm2835aux_spi *bs;
|
||||
unsigned long clk_hz;
|
||||
int err;
|
||||
|
||||
master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
platform_set_drvdata(pdev, host);
|
||||
host->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
/* even though the driver never officially supported native CS
|
||||
* allow a single native CS for legacy DT support purposes when
|
||||
* no cs-gpio is configured.
|
||||
|
@ -498,16 +496,16 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
|||
* * cs_delay_usec: cs is always deasserted one SCK cycle after
|
||||
* a spi_transfer
|
||||
*/
|
||||
master->num_chipselect = 1;
|
||||
master->setup = bcm2835aux_spi_setup;
|
||||
master->transfer_one = bcm2835aux_spi_transfer_one;
|
||||
master->handle_err = bcm2835aux_spi_handle_err;
|
||||
master->prepare_message = bcm2835aux_spi_prepare_message;
|
||||
master->unprepare_message = bcm2835aux_spi_unprepare_message;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->num_chipselect = 1;
|
||||
host->setup = bcm2835aux_spi_setup;
|
||||
host->transfer_one = bcm2835aux_spi_transfer_one;
|
||||
host->handle_err = bcm2835aux_spi_handle_err;
|
||||
host->prepare_message = bcm2835aux_spi_prepare_message;
|
||||
host->unprepare_message = bcm2835aux_spi_unprepare_message;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* the main area */
|
||||
bs->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
@ -522,8 +520,8 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
bs->irq = platform_get_irq(pdev, 0);
|
||||
if (bs->irq <= 0)
|
||||
return bs->irq ? bs->irq : -ENODEV;
|
||||
if (bs->irq < 0)
|
||||
return bs->irq;
|
||||
|
||||
/* this also enables the HW block */
|
||||
err = clk_prepare_enable(bs->clk);
|
||||
|
@ -546,15 +544,15 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
|
|||
err = devm_request_irq(&pdev->dev, bs->irq,
|
||||
bcm2835aux_spi_interrupt,
|
||||
IRQF_SHARED,
|
||||
dev_name(&pdev->dev), master);
|
||||
dev_name(&pdev->dev), host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
err = spi_register_master(master);
|
||||
err = spi_register_controller(host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
|
||||
dev_err(&pdev->dev, "could not register SPI host: %d\n", err);
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
|
@ -569,12 +567,12 @@ out_clk_disable:
|
|||
|
||||
static void bcm2835aux_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcm2835aux_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
bcm2835aux_debugfs_remove(bs);
|
||||
|
||||
spi_unregister_master(master);
|
||||
spi_unregister_controller(host);
|
||||
|
||||
bcm2835aux_spi_reset_hw(bs);
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ static ssize_t wait_mode_show(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
|
||||
return sprintf(buf, "%d\n", bs->wait_mode);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ static ssize_t wait_mode_store(struct device *dev, struct device_attribute *attr
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
u32 val;
|
||||
|
||||
if (kstrtou32(buf, 10, &val))
|
||||
|
@ -185,7 +185,7 @@ static ssize_t xfer_mode_show(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
|
||||
return sprintf(buf, "%d\n", bs->xfer_mode);
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ static ssize_t xfer_mode_store(struct device *dev, struct device_attribute *attr
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
u32 val;
|
||||
|
||||
if (kstrtou32(buf, 10, &val))
|
||||
|
@ -262,12 +262,12 @@ static int bcm63xx_hsspi_wait_cmd(struct bcm63xx_hsspi *bs)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static bool bcm63xx_prepare_prepend_transfer(struct spi_master *master,
|
||||
static bool bcm63xx_prepare_prepend_transfer(struct spi_controller *host,
|
||||
struct spi_message *msg,
|
||||
struct spi_transfer *t_prepend)
|
||||
{
|
||||
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
bool tx_only = false;
|
||||
struct spi_transfer *t;
|
||||
|
||||
|
@ -348,7 +348,7 @@ static bool bcm63xx_prepare_prepend_transfer(struct spi_master *master,
|
|||
static int bcm63xx_hsspi_do_prepend_txrx(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int chip_select = spi_get_chipselect(spi, 0);
|
||||
u16 opcode = 0, val;
|
||||
const u8 *tx = t->tx_buf;
|
||||
|
@ -467,7 +467,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
|
|||
|
||||
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int chip_select = spi_get_chipselect(spi, 0);
|
||||
u16 opcode = 0, val;
|
||||
int pending = t->len;
|
||||
|
@ -541,7 +541,7 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
|
|||
|
||||
static int bcm63xx_hsspi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
u32 reg;
|
||||
|
||||
reg = __raw_readl(bs->regs +
|
||||
|
@ -579,7 +579,7 @@ static int bcm63xx_hsspi_setup(struct spi_device *spi)
|
|||
static int bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device *spi,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
int status = -EINVAL;
|
||||
int dummy_cs;
|
||||
bool keep_cs = false;
|
||||
|
@ -653,10 +653,10 @@ static int bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device *spi,
|
|||
return status;
|
||||
}
|
||||
|
||||
static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
|
||||
static int bcm63xx_hsspi_transfer_one(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = msg->spi;
|
||||
int status = -EINVAL;
|
||||
bool prependable = false;
|
||||
|
@ -665,7 +665,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
|
|||
mutex_lock(&bs->msg_mutex);
|
||||
|
||||
if (bs->xfer_mode != HSSPI_XFER_MODE_DUMMYCS)
|
||||
prependable = bcm63xx_prepare_prepend_transfer(master, msg, &t_prepend);
|
||||
prependable = bcm63xx_prepare_prepend_transfer(host, msg, &t_prepend);
|
||||
|
||||
if (prependable) {
|
||||
status = bcm63xx_hsspi_do_prepend_txrx(spi, &t_prepend);
|
||||
|
@ -681,7 +681,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
|
|||
|
||||
mutex_unlock(&bs->msg_mutex);
|
||||
msg->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -723,7 +723,7 @@ static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
|
|||
|
||||
static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct bcm63xx_hsspi *bs;
|
||||
void __iomem *regs;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -779,13 +779,13 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*bs));
|
||||
if (!master) {
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto out_disable_pll_clk;
|
||||
}
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
bs = spi_controller_get_devdata(host);
|
||||
bs->pdev = pdev;
|
||||
bs->clk = clk;
|
||||
bs->pll_clk = pll_clk;
|
||||
|
@ -796,17 +796,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
bs->prepend_buf = devm_kzalloc(dev, HSSPI_BUFFER_LEN, GFP_KERNEL);
|
||||
if (!bs->prepend_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_put_master;
|
||||
goto out_put_host;
|
||||
}
|
||||
|
||||
mutex_init(&bs->bus_mutex);
|
||||
mutex_init(&bs->msg_mutex);
|
||||
init_completion(&bs->done);
|
||||
|
||||
master->mem_ops = &bcm63xx_hsspi_mem_ops;
|
||||
master->dev.of_node = dev->of_node;
|
||||
host->mem_ops = &bcm63xx_hsspi_mem_ops;
|
||||
host->dev.of_node = dev->of_node;
|
||||
if (!dev->of_node)
|
||||
master->bus_num = HSSPI_BUS_NUM;
|
||||
host->bus_num = HSSPI_BUS_NUM;
|
||||
|
||||
of_property_read_u32(dev->of_node, "num-cs", &num_cs);
|
||||
if (num_cs > 8) {
|
||||
|
@ -814,18 +814,18 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
num_cs);
|
||||
num_cs = HSSPI_SPI_MAX_CS;
|
||||
}
|
||||
master->num_chipselect = num_cs;
|
||||
master->setup = bcm63xx_hsspi_setup;
|
||||
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
|
||||
master->max_transfer_size = bcm63xx_hsspi_max_message_size;
|
||||
master->max_message_size = bcm63xx_hsspi_max_message_size;
|
||||
host->num_chipselect = num_cs;
|
||||
host->setup = bcm63xx_hsspi_setup;
|
||||
host->transfer_one_message = bcm63xx_hsspi_transfer_one;
|
||||
host->max_transfer_size = bcm63xx_hsspi_max_message_size;
|
||||
host->max_message_size = bcm63xx_hsspi_max_message_size;
|
||||
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
SPI_RX_DUAL | SPI_TX_DUAL;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->auto_runtime_pm = true;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
/* Initialize the hardware */
|
||||
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
|
||||
|
@ -844,7 +844,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
pdev->name, bs);
|
||||
|
||||
if (ret)
|
||||
goto out_put_master;
|
||||
goto out_put_host;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
@ -856,7 +856,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* register and we are done */
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret)
|
||||
goto out_sysgroup_disable;
|
||||
|
||||
|
@ -868,8 +868,8 @@ out_sysgroup_disable:
|
|||
sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
|
||||
out_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
out_put_master:
|
||||
spi_master_put(master);
|
||||
out_put_host:
|
||||
spi_controller_put(host);
|
||||
out_disable_pll_clk:
|
||||
clk_disable_unprepare(pll_clk);
|
||||
out_disable_clk:
|
||||
|
@ -880,8 +880,8 @@ out_disable_clk:
|
|||
|
||||
static void bcm63xx_hsspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* reset the hardware and block queue progress */
|
||||
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
|
||||
|
@ -893,10 +893,10 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bcm63xx_hsspi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
spi_master_suspend(master);
|
||||
spi_controller_suspend(host);
|
||||
clk_disable_unprepare(bs->pll_clk);
|
||||
clk_disable_unprepare(bs->clk);
|
||||
|
||||
|
@ -905,8 +905,8 @@ static int bcm63xx_hsspi_suspend(struct device *dev)
|
|||
|
||||
static int bcm63xx_hsspi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(bs->clk);
|
||||
|
@ -921,7 +921,7 @@ static int bcm63xx_hsspi_resume(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
spi_master_resume(master);
|
||||
spi_controller_resume(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ static const unsigned int bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
|
|||
static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller);
|
||||
u8 clk_cfg, reg;
|
||||
int i;
|
||||
|
||||
|
@ -217,7 +217,7 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
|
|||
static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
|
||||
unsigned int num_transfers)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller);
|
||||
u16 msg_ctl;
|
||||
u16 cmd;
|
||||
unsigned int i, timeout = 0, prepend_len = 0, len = 0;
|
||||
|
@ -312,10 +312,10 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcm63xx_spi_transfer_one(struct spi_master *master,
|
||||
static int bcm63xx_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *t, *first = NULL;
|
||||
struct spi_device *spi = m->spi;
|
||||
int status = 0;
|
||||
|
@ -385,18 +385,18 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master,
|
|||
}
|
||||
exit:
|
||||
m->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This driver supports single master mode only. Hence
|
||||
/* This driver supports single host mode only. Hence
|
||||
* CMD_DONE is the only interrupt we care about
|
||||
*/
|
||||
static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = (struct spi_master *)dev_id;
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = (struct spi_controller *)dev_id;
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
u8 intr;
|
||||
|
||||
/* Read interupts and clear them immediately */
|
||||
|
@ -413,7 +413,7 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
|
|||
|
||||
static size_t bcm63xx_spi_max_length(struct spi_device *spi)
|
||||
{
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
return bs->fifo_size;
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
const unsigned long *bcm63xx_spireg;
|
||||
struct device *dev = &pdev->dev;
|
||||
int irq, bus_num;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct clk *clk;
|
||||
struct bcm63xx_spi *bs;
|
||||
int ret;
|
||||
|
@ -525,16 +525,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(reset))
|
||||
return PTR_ERR(reset);
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(*bs));
|
||||
if (!master) {
|
||||
host = spi_alloc_host(dev, sizeof(*bs));
|
||||
if (!host) {
|
||||
dev_err(dev, "out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
bs = spi_controller_get_devdata(host);
|
||||
init_completion(&bs->done);
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
bs->pdev = pdev;
|
||||
|
||||
bs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
|
@ -549,21 +549,21 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
|
||||
pdev->name, master);
|
||||
pdev->name, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to request irq\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
master->dev.of_node = dev->of_node;
|
||||
master->bus_num = bus_num;
|
||||
master->num_chipselect = num_cs;
|
||||
master->transfer_one_message = bcm63xx_spi_transfer_one;
|
||||
master->mode_bits = MODEBITS;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->max_transfer_size = bcm63xx_spi_max_length;
|
||||
master->max_message_size = bcm63xx_spi_max_length;
|
||||
master->auto_runtime_pm = true;
|
||||
host->dev.of_node = dev->of_node;
|
||||
host->bus_num = bus_num;
|
||||
host->num_chipselect = num_cs;
|
||||
host->transfer_one_message = bcm63xx_spi_transfer_one;
|
||||
host->mode_bits = MODEBITS;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->max_transfer_size = bcm63xx_spi_max_length;
|
||||
host->max_message_size = bcm63xx_spi_max_length;
|
||||
host->auto_runtime_pm = true;
|
||||
bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
|
||||
bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
|
||||
bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
|
||||
|
@ -585,7 +585,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/* register and we are done */
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "spi register failed\n");
|
||||
goto out_pm_disable;
|
||||
|
@ -601,14 +601,14 @@ out_pm_disable:
|
|||
out_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
out_err:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bcm63xx_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* reset spi block */
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
|
@ -619,10 +619,10 @@ static void bcm63xx_spi_remove(struct platform_device *pdev)
|
|||
|
||||
static int bcm63xx_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
spi_master_suspend(master);
|
||||
spi_controller_suspend(host);
|
||||
|
||||
clk_disable_unprepare(bs->clk);
|
||||
|
||||
|
@ -631,15 +631,15 @@ static int bcm63xx_spi_suspend(struct device *dev)
|
|||
|
||||
static int bcm63xx_spi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(bs->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spi_master_resume(master);
|
||||
spi_controller_resume(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ static ssize_t wait_mode_show(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
|
||||
return sprintf(buf, "%d\n", bs->wait_mode);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ static ssize_t wait_mode_store(struct device *dev, struct device_attribute *attr
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct spi_controller *ctrl = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(ctrl);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl);
|
||||
u32 val;
|
||||
|
||||
if (kstrtou32(buf, 10, &val))
|
||||
|
@ -250,7 +250,7 @@ static int bcmbca_hsspi_wait_cmd(struct bcmbca_hsspi *bs, unsigned int cs)
|
|||
static int bcmbca_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int chip_select = spi_get_chipselect(spi, 0);
|
||||
u16 opcode = 0, val;
|
||||
int pending = t->len;
|
||||
|
@ -328,7 +328,7 @@ static int bcmbca_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t,
|
|||
|
||||
static int bcmbca_hsspi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(spi->master);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller);
|
||||
u32 reg;
|
||||
|
||||
reg = __raw_readl(bs->regs +
|
||||
|
@ -366,10 +366,10 @@ static int bcmbca_hsspi_setup(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcmbca_hsspi_transfer_one(struct spi_master *master,
|
||||
static int bcmbca_hsspi_transfer_one(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *t;
|
||||
struct spi_device *spi = msg->spi;
|
||||
int status = -EINVAL;
|
||||
|
@ -409,7 +409,7 @@ static int bcmbca_hsspi_transfer_one(struct spi_master *master,
|
|||
bcmbca_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), false);
|
||||
|
||||
msg->status = status;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ static irqreturn_t bcmbca_hsspi_interrupt(int irq, void *dev_id)
|
|||
|
||||
static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct bcmbca_hsspi *bs;
|
||||
struct resource *res_mem;
|
||||
void __iomem *spim_ctrl;
|
||||
|
@ -487,13 +487,13 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*bs));
|
||||
if (!master) {
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*bs));
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto out_disable_pll_clk;
|
||||
}
|
||||
|
||||
bs = spi_master_get_devdata(master);
|
||||
bs = spi_controller_get_devdata(host);
|
||||
bs->pdev = pdev;
|
||||
bs->clk = clk;
|
||||
bs->pll_clk = pll_clk;
|
||||
|
@ -507,9 +507,9 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
|||
mutex_init(&bs->msg_mutex);
|
||||
init_completion(&bs->done);
|
||||
|
||||
master->dev.of_node = dev->of_node;
|
||||
host->dev.of_node = dev->of_node;
|
||||
if (!dev->of_node)
|
||||
master->bus_num = HSSPI_BUS_NUM;
|
||||
host->bus_num = HSSPI_BUS_NUM;
|
||||
|
||||
of_property_read_u32(dev->of_node, "num-cs", &num_cs);
|
||||
if (num_cs > 8) {
|
||||
|
@ -517,15 +517,15 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
|||
num_cs);
|
||||
num_cs = HSSPI_SPI_MAX_CS;
|
||||
}
|
||||
master->num_chipselect = num_cs;
|
||||
master->setup = bcmbca_hsspi_setup;
|
||||
master->transfer_one_message = bcmbca_hsspi_transfer_one;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
SPI_RX_DUAL | SPI_TX_DUAL;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->auto_runtime_pm = true;
|
||||
host->num_chipselect = num_cs;
|
||||
host->setup = bcmbca_hsspi_setup;
|
||||
host->transfer_one_message = bcmbca_hsspi_transfer_one;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
SPI_RX_DUAL | SPI_TX_DUAL;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
/* Initialize the hardware */
|
||||
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
|
||||
|
@ -543,7 +543,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(dev, irq, bcmbca_hsspi_interrupt, IRQF_SHARED,
|
||||
pdev->name, bs);
|
||||
if (ret)
|
||||
goto out_put_master;
|
||||
goto out_put_host;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
@ -555,7 +555,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* register and we are done */
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret)
|
||||
goto out_sysgroup_disable;
|
||||
|
||||
|
@ -567,8 +567,8 @@ out_sysgroup_disable:
|
|||
sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group);
|
||||
out_pm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
out_put_master:
|
||||
spi_master_put(master);
|
||||
out_put_host:
|
||||
spi_controller_put(host);
|
||||
out_disable_pll_clk:
|
||||
clk_disable_unprepare(pll_clk);
|
||||
out_disable_clk:
|
||||
|
@ -578,8 +578,8 @@ out_disable_clk:
|
|||
|
||||
static void bcmbca_hsspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
/* reset the hardware and block queue progress */
|
||||
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
|
||||
|
@ -591,10 +591,10 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bcmbca_hsspi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
|
||||
|
||||
spi_master_suspend(master);
|
||||
spi_controller_suspend(host);
|
||||
clk_disable_unprepare(bs->pll_clk);
|
||||
clk_disable_unprepare(bs->clk);
|
||||
|
||||
|
@ -603,8 +603,8 @@ static int bcmbca_hsspi_suspend(struct device *dev)
|
|||
|
||||
static int bcmbca_hsspi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct bcmbca_hsspi *bs = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(bs->clk);
|
||||
|
@ -619,7 +619,7 @@ static int bcmbca_hsspi_resume(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
spi_master_resume(master);
|
||||
spi_controller_resume(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
|
|||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* setup MSB (to slave) on trailing edge */
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0) {
|
||||
if ((word & (1 << 31)) != oldbit) {
|
||||
setmosi(spi, word & (1 << 31));
|
||||
oldbit = word & (1 << 31);
|
||||
|
@ -70,7 +70,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
|
|||
|
||||
/* sample MSB (from slave) on leading edge */
|
||||
word <<= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
setsck(spi, cpol);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
|
|||
|
||||
/* setup MSB (to slave) on leading edge */
|
||||
setsck(spi, !cpol);
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0) {
|
||||
if ((word & (1 << 31)) != oldbit) {
|
||||
setmosi(spi, word & (1 << 31));
|
||||
oldbit = word & (1 << 31);
|
||||
|
@ -103,7 +103,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
|
|||
|
||||
/* sample MSB (from slave) on trailing edge */
|
||||
word <<= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
}
|
||||
return word;
|
||||
|
@ -122,7 +122,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
|
|||
for (; likely(bits); bits--) {
|
||||
|
||||
/* setup LSB (to slave) on trailing edge */
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0) {
|
||||
if ((word & 1) != oldbit) {
|
||||
setmosi(spi, word & 1);
|
||||
oldbit = word & 1;
|
||||
|
@ -135,7 +135,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
|
|||
|
||||
/* sample LSB (from slave) on leading edge */
|
||||
word >>= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= getmiso(spi) << rxbit;
|
||||
setsck(spi, cpol);
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
|
|||
|
||||
/* setup LSB (to slave) on leading edge */
|
||||
setsck(spi, !cpol);
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0) {
|
||||
if ((word & 1) != oldbit) {
|
||||
setmosi(spi, word & 1);
|
||||
oldbit = word & 1;
|
||||
|
@ -169,7 +169,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
|
|||
|
||||
/* sample LSB (from slave) on trailing edge */
|
||||
word >>= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= getmiso(spi) << rxbit;
|
||||
}
|
||||
return word;
|
||||
|
|
|
@ -248,7 +248,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
if (spi->mode & SPI_3WIRE) {
|
||||
unsigned flags;
|
||||
|
||||
flags = t->tx_buf ? SPI_MASTER_NO_RX : SPI_MASTER_NO_TX;
|
||||
flags = t->tx_buf ? SPI_CONTROLLER_NO_RX : SPI_CONTROLLER_NO_TX;
|
||||
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags);
|
||||
}
|
||||
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, 0);
|
||||
|
@ -349,11 +349,11 @@ int spi_bitbang_init(struct spi_bitbang *bitbang)
|
|||
/*
|
||||
* We only need the chipselect callback if we are actually using it.
|
||||
* If we just use GPIO descriptors, it is surplus. If the
|
||||
* SPI_MASTER_GPIO_SS flag is set, we always need to call the
|
||||
* SPI_CONTROLLER_GPIO_SS flag is set, we always need to call the
|
||||
* driver-specific chipselect routine.
|
||||
*/
|
||||
custom_cs = (!master->use_gpio_descriptors ||
|
||||
(master->flags & SPI_MASTER_GPIO_SS));
|
||||
(master->flags & SPI_CONTROLLER_GPIO_SS));
|
||||
|
||||
if (custom_cs && !bitbang->chipselect)
|
||||
return -EINVAL;
|
||||
|
@ -371,7 +371,7 @@ int spi_bitbang_init(struct spi_bitbang *bitbang)
|
|||
master->transfer_one = spi_bitbang_transfer_one;
|
||||
/*
|
||||
* When using GPIO descriptors, the ->set_cs() callback doesn't even
|
||||
* get called unless SPI_MASTER_GPIO_SS is set.
|
||||
* get called unless SPI_CONTROLLER_GPIO_SS is set.
|
||||
*/
|
||||
if (custom_cs)
|
||||
master->set_cs = spi_bitbang_set_cs;
|
||||
|
|
|
@ -178,7 +178,7 @@ static void butterfly_attach(struct parport *p)
|
|||
struct pardevice *pd;
|
||||
int status;
|
||||
struct butterfly *pp;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct device *dev = p->physport->dev;
|
||||
struct pardev_cb butterfly_cb;
|
||||
|
||||
|
@ -189,12 +189,12 @@ static void butterfly_attach(struct parport *p)
|
|||
* and no way to be selective about what it binds to.
|
||||
*/
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(*pp));
|
||||
if (!master) {
|
||||
host = spi_alloc_host(dev, sizeof(*pp));
|
||||
if (!host) {
|
||||
status = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
pp = spi_master_get_devdata(master);
|
||||
pp = spi_controller_get_devdata(host);
|
||||
|
||||
/*
|
||||
* SPI and bitbang hookup
|
||||
|
@ -202,10 +202,10 @@ static void butterfly_attach(struct parport *p)
|
|||
* use default setup(), cleanup(), and transfer() methods; and
|
||||
* only bother implementing mode 0. Start it later.
|
||||
*/
|
||||
master->bus_num = 42;
|
||||
master->num_chipselect = 2;
|
||||
host->bus_num = 42;
|
||||
host->num_chipselect = 2;
|
||||
|
||||
pp->bitbang.master = master;
|
||||
pp->bitbang.master = host;
|
||||
pp->bitbang.chipselect = butterfly_chipselect;
|
||||
pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
|
||||
|
||||
|
@ -280,7 +280,7 @@ clean2:
|
|||
clean1:
|
||||
parport_unregister_device(pd);
|
||||
clean0:
|
||||
spi_master_put(pp->bitbang.master);
|
||||
spi_controller_put(host);
|
||||
done:
|
||||
pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ static void butterfly_detach(struct parport *p)
|
|||
parport_release(pp->pd);
|
||||
parport_unregister_device(pp->pd);
|
||||
|
||||
spi_master_put(pp->bitbang.master);
|
||||
spi_controller_put(pp->bitbang.master);
|
||||
}
|
||||
|
||||
static struct parport_driver butterfly_driver = {
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -47,6 +46,12 @@
|
|||
|
||||
#define CQSPI_OP_WIDTH(part) ((part).nbytes ? ilog2((part).buswidth) : 0)
|
||||
|
||||
enum {
|
||||
CLK_QSPI_APB = 0,
|
||||
CLK_QSPI_AHB,
|
||||
CLK_QSPI_NUM,
|
||||
};
|
||||
|
||||
struct cqspi_st;
|
||||
|
||||
struct cqspi_flash_pdata {
|
||||
|
@ -62,8 +67,9 @@ struct cqspi_flash_pdata {
|
|||
|
||||
struct cqspi_st {
|
||||
struct platform_device *pdev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct clk *clk;
|
||||
struct clk *clks[CLK_QSPI_NUM];
|
||||
unsigned int sclk;
|
||||
|
||||
void __iomem *iobase;
|
||||
|
@ -92,6 +98,8 @@ struct cqspi_st {
|
|||
bool wr_completion;
|
||||
bool slow_sram;
|
||||
bool apb_ahb_hazard;
|
||||
|
||||
bool is_jh7110; /* Flag for StarFive JH7110 SoC */
|
||||
};
|
||||
|
||||
struct cqspi_driver_platdata {
|
||||
|
@ -100,6 +108,8 @@ struct cqspi_driver_platdata {
|
|||
int (*indirect_read_dma)(struct cqspi_flash_pdata *f_pdata,
|
||||
u_char *rxbuf, loff_t from_addr, size_t n_rx);
|
||||
u32 (*get_dma_status)(struct cqspi_st *cqspi);
|
||||
int (*jh7110_clk_init)(struct platform_device *pdev,
|
||||
struct cqspi_st *cqspi);
|
||||
};
|
||||
|
||||
/* Operation timeout value */
|
||||
|
@ -1369,7 +1379,7 @@ static ssize_t cqspi_read(struct cqspi_flash_pdata *f_pdata,
|
|||
|
||||
static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
|
||||
struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct cqspi_flash_pdata *f_pdata;
|
||||
|
||||
f_pdata = &cqspi->f_pdata[spi_get_chipselect(mem->spi, 0)];
|
||||
|
@ -1575,7 +1585,7 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
|
|||
|
||||
static const char *cqspi_get_name(struct spi_mem *mem)
|
||||
{
|
||||
struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
|
||||
struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct device *dev = &cqspi->pdev->dev;
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
|
||||
|
@ -1630,31 +1640,77 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cqspi_jh7110_clk_init(struct platform_device *pdev, struct cqspi_st *cqspi)
|
||||
{
|
||||
static struct clk_bulk_data qspiclk[] = {
|
||||
{ .id = "apb" },
|
||||
{ .id = "ahb" },
|
||||
};
|
||||
|
||||
int ret = 0;
|
||||
|
||||
ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(qspiclk), qspiclk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: failed to get qspi clocks\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cqspi->clks[CLK_QSPI_APB] = qspiclk[0].clk;
|
||||
cqspi->clks[CLK_QSPI_AHB] = qspiclk[1].clk;
|
||||
|
||||
ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_APB]);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_APB\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_AHB]);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_AHB\n", __func__);
|
||||
goto disable_apb_clk;
|
||||
}
|
||||
|
||||
cqspi->is_jh7110 = true;
|
||||
|
||||
return 0;
|
||||
|
||||
disable_apb_clk:
|
||||
clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cqspi_jh7110_disable_clk(struct platform_device *pdev, struct cqspi_st *cqspi)
|
||||
{
|
||||
clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]);
|
||||
clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]);
|
||||
}
|
||||
static int cqspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct cqspi_driver_platdata *ddata;
|
||||
struct reset_control *rstc, *rstc_ocp, *rstc_ref;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource *res_ahb;
|
||||
struct cqspi_st *cqspi;
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
master = devm_spi_alloc_master(&pdev->dev, sizeof(*cqspi));
|
||||
if (!master) {
|
||||
dev_err(&pdev->dev, "spi_alloc_master failed\n");
|
||||
host = devm_spi_alloc_host(&pdev->dev, sizeof(*cqspi));
|
||||
if (!host) {
|
||||
dev_err(&pdev->dev, "devm_spi_alloc_host failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
master->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL;
|
||||
master->mem_ops = &cqspi_mem_ops;
|
||||
master->mem_caps = &cqspi_mem_caps;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL;
|
||||
host->mem_ops = &cqspi_mem_ops;
|
||||
host->mem_caps = &cqspi_mem_caps;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
cqspi = spi_master_get_devdata(master);
|
||||
cqspi = spi_controller_get_devdata(host);
|
||||
|
||||
cqspi->pdev = pdev;
|
||||
cqspi->master = master;
|
||||
cqspi->host = host;
|
||||
cqspi->is_jh7110 = false;
|
||||
platform_set_drvdata(pdev, cqspi);
|
||||
|
||||
/* Obtain configuration from OF. */
|
||||
|
@ -1741,7 +1797,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
reset_control_deassert(rstc_ocp);
|
||||
|
||||
cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
|
||||
master->max_speed_hz = cqspi->master_ref_clk_hz;
|
||||
host->max_speed_hz = cqspi->master_ref_clk_hz;
|
||||
|
||||
/* write completion is supported by default */
|
||||
cqspi->wr_completion = true;
|
||||
|
@ -1752,7 +1808,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC,
|
||||
cqspi->master_ref_clk_hz);
|
||||
if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL)
|
||||
master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
|
||||
host->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
|
||||
if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) {
|
||||
cqspi->use_direct_mode = true;
|
||||
cqspi->use_direct_mode_wr = true;
|
||||
|
@ -1766,6 +1822,12 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR)
|
||||
cqspi->apb_ahb_hazard = true;
|
||||
|
||||
if (ddata->jh7110_clk_init) {
|
||||
ret = cqspi_jh7110_clk_init(pdev, cqspi);
|
||||
if (ret)
|
||||
goto probe_clk_failed;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"xlnx,versal-ospi-1.0")) {
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
|
||||
|
@ -1786,7 +1848,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
cqspi->current_cs = -1;
|
||||
cqspi->sclk = 0;
|
||||
|
||||
master->num_chipselect = cqspi->num_chipselect;
|
||||
host->num_chipselect = cqspi->num_chipselect;
|
||||
|
||||
ret = cqspi_setup_flash(cqspi);
|
||||
if (ret) {
|
||||
|
@ -1800,7 +1862,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
|||
goto probe_setup_failed;
|
||||
}
|
||||
|
||||
ret = spi_register_master(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret);
|
||||
goto probe_setup_failed;
|
||||
|
@ -1822,7 +1884,7 @@ static void cqspi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct cqspi_st *cqspi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_unregister_master(cqspi->master);
|
||||
spi_unregister_controller(cqspi->host);
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
|
||||
if (cqspi->rx_chan)
|
||||
|
@ -1830,6 +1892,9 @@ static void cqspi_remove(struct platform_device *pdev)
|
|||
|
||||
clk_disable_unprepare(cqspi->clk);
|
||||
|
||||
if (cqspi->is_jh7110)
|
||||
cqspi_jh7110_disable_clk(pdev, cqspi);
|
||||
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
@ -1837,10 +1902,10 @@ static void cqspi_remove(struct platform_device *pdev)
|
|||
static int cqspi_suspend(struct device *dev)
|
||||
{
|
||||
struct cqspi_st *cqspi = dev_get_drvdata(dev);
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
|
||||
clk_disable_unprepare(cqspi->clk);
|
||||
|
@ -1851,7 +1916,7 @@ static int cqspi_suspend(struct device *dev)
|
|||
static int cqspi_resume(struct device *dev)
|
||||
{
|
||||
struct cqspi_st *cqspi = dev_get_drvdata(dev);
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
|
||||
clk_prepare_enable(cqspi->clk);
|
||||
cqspi_wait_idle(cqspi);
|
||||
|
@ -1860,7 +1925,7 @@ static int cqspi_resume(struct device *dev)
|
|||
cqspi->current_cs = -1;
|
||||
cqspi->sclk = 0;
|
||||
|
||||
return spi_master_resume(master);
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume);
|
||||
|
@ -1897,6 +1962,7 @@ static const struct cqspi_driver_platdata versal_ospi = {
|
|||
|
||||
static const struct cqspi_driver_platdata jh7110_qspi = {
|
||||
.quirks = CQSPI_DISABLE_DAC_MODE,
|
||||
.jh7110_clk_init = cqspi_jh7110_clk_init,
|
||||
};
|
||||
|
||||
static const struct cqspi_driver_platdata pensando_cdns_qspi = {
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -420,7 +419,7 @@ static int cdns_xspi_mem_op_execute(struct spi_mem *mem,
|
|||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct cdns_xspi_dev *cdns_xspi =
|
||||
spi_master_get_devdata(mem->spi->master);
|
||||
spi_controller_get_devdata(mem->spi->controller);
|
||||
int ret = 0;
|
||||
|
||||
ret = cdns_xspi_mem_op(cdns_xspi, mem, op);
|
||||
|
@ -431,7 +430,7 @@ static int cdns_xspi_mem_op_execute(struct spi_mem *mem,
|
|||
static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
{
|
||||
struct cdns_xspi_dev *cdns_xspi =
|
||||
spi_master_get_devdata(mem->spi->master);
|
||||
spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
op->data.nbytes = clamp_val(op->data.nbytes, 0, cdns_xspi->sdmasize);
|
||||
|
||||
|
@ -528,26 +527,26 @@ static void cdns_xspi_print_phy_config(struct cdns_xspi_dev *cdns_xspi)
|
|||
static int cdns_xspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master = NULL;
|
||||
struct spi_controller *host = NULL;
|
||||
struct cdns_xspi_dev *cdns_xspi = NULL;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*cdns_xspi));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*cdns_xspi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
master->mode_bits = SPI_3WIRE | SPI_TX_DUAL | SPI_TX_QUAD |
|
||||
host->mode_bits = SPI_3WIRE | SPI_TX_DUAL | SPI_TX_QUAD |
|
||||
SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL | SPI_RX_OCTAL |
|
||||
SPI_MODE_0 | SPI_MODE_3;
|
||||
|
||||
master->mem_ops = &cadence_xspi_mem_ops;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bus_num = -1;
|
||||
host->mem_ops = &cadence_xspi_mem_ops;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->bus_num = -1;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
cdns_xspi = spi_master_get_devdata(master);
|
||||
cdns_xspi = spi_controller_get_devdata(host);
|
||||
cdns_xspi->pdev = pdev;
|
||||
cdns_xspi->dev = &pdev->dev;
|
||||
cdns_xspi->cur_cs = 0;
|
||||
|
@ -597,15 +596,15 @@ static int cdns_xspi_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
master->num_chipselect = 1 << cdns_xspi->hw_num_banks;
|
||||
host->num_chipselect = 1 << cdns_xspi->hw_num_banks;
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register SPI master\n");
|
||||
dev_err(dev, "Failed to register SPI host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "Successfully registered SPI master\n");
|
||||
dev_info(dev, "Successfully registered SPI host\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Cadence SPI controller driver (master and slave mode)
|
||||
* Cadence SPI controller driver (host and target mode)
|
||||
*
|
||||
* Copyright (C) 2008 - 2014 Xilinx, Inc.
|
||||
*
|
||||
|
@ -59,10 +59,10 @@
|
|||
CDNS_SPI_CR_BAUD_DIV_4)
|
||||
|
||||
/*
|
||||
* SPI Configuration Register - Baud rate and slave select
|
||||
* SPI Configuration Register - Baud rate and target select
|
||||
*
|
||||
* These are the values used in the calculation of baud rate divisor and
|
||||
* setting the slave select.
|
||||
* setting the target select.
|
||||
*/
|
||||
|
||||
#define CDNS_SPI_BAUD_DIV_MAX 7 /* Baud rate divisor maximum */
|
||||
|
@ -141,20 +141,20 @@ static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val)
|
|||
/**
|
||||
* cdns_spi_init_hw - Initialize the hardware and configure the SPI controller
|
||||
* @xspi: Pointer to the cdns_spi structure
|
||||
* @is_slave: Flag to indicate slave or master mode
|
||||
* * On reset the SPI controller is configured to slave or master mode.
|
||||
* In master mode baud rate divisor is set to 4, threshold value for TX FIFO
|
||||
* @is_target: Flag to indicate target or host mode
|
||||
* * On reset the SPI controller is configured to target or host mode.
|
||||
* In host mode baud rate divisor is set to 4, threshold value for TX FIFO
|
||||
* not full interrupt is set to 1 and size of the word to be transferred as 8 bit.
|
||||
*
|
||||
* This function initializes the SPI controller to disable and clear all the
|
||||
* interrupts, enable manual slave select and manual start, deselect all the
|
||||
* interrupts, enable manual target select and manual start, deselect all the
|
||||
* chip select lines, and enable the SPI controller.
|
||||
*/
|
||||
static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_slave)
|
||||
static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_target)
|
||||
{
|
||||
u32 ctrl_reg = 0;
|
||||
|
||||
if (!is_slave)
|
||||
if (!is_target)
|
||||
ctrl_reg |= CDNS_SPI_CR_DEFAULT;
|
||||
|
||||
if (xspi->is_decoded_cs)
|
||||
|
@ -185,10 +185,10 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
|
|||
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
|
||||
|
||||
if (is_high) {
|
||||
/* Deselect the slave */
|
||||
/* Deselect the target */
|
||||
ctrl_reg |= CDNS_SPI_CR_SSCTRL;
|
||||
} else {
|
||||
/* Select the slave */
|
||||
/* Select the target */
|
||||
ctrl_reg &= ~CDNS_SPI_CR_SSCTRL;
|
||||
if (!(xspi->is_decoded_cs))
|
||||
ctrl_reg |= ((~(CDNS_SPI_SS0 << spi_get_chipselect(spi, 0))) <<
|
||||
|
@ -227,7 +227,7 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi)
|
|||
/*
|
||||
* Just writing the CR register does not seem to apply the clock
|
||||
* setting changes. This is problematic when changing the clock
|
||||
* polarity as it will cause the SPI slave to see spurious clock
|
||||
* polarity as it will cause the SPI target to see spurious clock
|
||||
* transitions. To workaround the issue toggle the ER register.
|
||||
*/
|
||||
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
|
||||
|
@ -405,7 +405,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
|
|||
static int cdns_prepare_message(struct spi_controller *ctlr,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
if (!spi_controller_is_slave(ctlr))
|
||||
if (!spi_controller_is_target(ctlr))
|
||||
cdns_spi_config_clock_mode(msg->spi);
|
||||
return 0;
|
||||
}
|
||||
|
@ -417,9 +417,9 @@ static int cdns_prepare_message(struct spi_controller *ctlr,
|
|||
* @transfer: Pointer to the spi_transfer structure which provides
|
||||
* information about next transfer parameters
|
||||
*
|
||||
* This function in master mode fills the TX FIFO, starts the SPI transfer and
|
||||
* This function in host mode fills the TX FIFO, starts the SPI transfer and
|
||||
* returns a positive transfer count so that core will wait for completion.
|
||||
* This function in slave mode fills the TX FIFO and wait for transfer trigger.
|
||||
* This function in target mode fills the TX FIFO and wait for transfer trigger.
|
||||
*
|
||||
* Return: Number of bytes transferred in the last transfer
|
||||
*/
|
||||
|
@ -434,7 +434,7 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
|
|||
xspi->tx_bytes = transfer->len;
|
||||
xspi->rx_bytes = transfer->len;
|
||||
|
||||
if (!spi_controller_is_slave(ctlr)) {
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
cdns_spi_setup_transfer(spi, transfer);
|
||||
} else {
|
||||
/* Set TX empty threshold to half of FIFO depth
|
||||
|
@ -462,7 +462,7 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
|
|||
* @ctlr: Pointer to the spi_controller structure which provides
|
||||
* information about the controller.
|
||||
*
|
||||
* This function enables SPI master controller.
|
||||
* This function enables SPI host controller.
|
||||
*
|
||||
* Return: 0 always
|
||||
*/
|
||||
|
@ -480,7 +480,7 @@ static int cdns_prepare_transfer_hardware(struct spi_controller *ctlr)
|
|||
* @ctlr: Pointer to the spi_controller structure which provides
|
||||
* information about the controller.
|
||||
*
|
||||
* This function disables the SPI master controller when no slave selected.
|
||||
* This function disables the SPI host controller when no target selected.
|
||||
* This function flush out if any pending data in FIFO.
|
||||
*
|
||||
* Return: 0 always
|
||||
|
@ -491,15 +491,15 @@ static int cdns_unprepare_transfer_hardware(struct spi_controller *ctlr)
|
|||
u32 ctrl_reg;
|
||||
unsigned int cnt = xspi->tx_fifo_depth;
|
||||
|
||||
if (spi_controller_is_slave(ctlr)) {
|
||||
if (spi_controller_is_target(ctlr)) {
|
||||
while (cnt--)
|
||||
cdns_spi_read(xspi, CDNS_SPI_RXD);
|
||||
}
|
||||
|
||||
/* Disable the SPI if slave is deselected */
|
||||
/* Disable the SPI if target is deselected */
|
||||
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
|
||||
ctrl_reg = (ctrl_reg & CDNS_SPI_CR_SSCTRL) >> CDNS_SPI_SS_SHIFT;
|
||||
if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_slave(ctlr))
|
||||
if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_target(ctlr))
|
||||
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
|
||||
|
||||
/* Reset to default */
|
||||
|
@ -526,14 +526,14 @@ static void cdns_spi_detect_fifo_depth(struct cdns_spi *xspi)
|
|||
}
|
||||
|
||||
/**
|
||||
* cdns_slave_abort - Abort slave transfer
|
||||
* cdns_target_abort - Abort target transfer
|
||||
* @ctlr: Pointer to the spi_controller structure
|
||||
*
|
||||
* This function abort slave transfer if there any transfer timeout.
|
||||
* This function abort target transfer if there any transfer timeout.
|
||||
*
|
||||
* Return: 0 always
|
||||
*/
|
||||
static int cdns_slave_abort(struct spi_controller *ctlr)
|
||||
static int cdns_target_abort(struct spi_controller *ctlr)
|
||||
{
|
||||
struct cdns_spi *xspi = spi_controller_get_devdata(ctlr);
|
||||
u32 intr_status;
|
||||
|
@ -560,13 +560,13 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
struct spi_controller *ctlr;
|
||||
struct cdns_spi *xspi;
|
||||
u32 num_cs;
|
||||
bool slave;
|
||||
bool target;
|
||||
|
||||
slave = of_property_read_bool(pdev->dev.of_node, "spi-slave");
|
||||
if (slave)
|
||||
ctlr = spi_alloc_slave(&pdev->dev, sizeof(*xspi));
|
||||
target = of_property_read_bool(pdev->dev.of_node, "spi-slave");
|
||||
if (target)
|
||||
ctlr = spi_alloc_target(&pdev->dev, sizeof(*xspi));
|
||||
else
|
||||
ctlr = spi_alloc_master(&pdev->dev, sizeof(*xspi));
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*xspi));
|
||||
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
@ -594,7 +594,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
goto remove_ctlr;
|
||||
}
|
||||
|
||||
if (!spi_controller_is_slave(ctlr)) {
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
|
||||
if (IS_ERR(xspi->ref_clk)) {
|
||||
dev_err(&pdev->dev, "ref_clk clock not found.\n");
|
||||
|
@ -629,11 +629,11 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
cdns_spi_detect_fifo_depth(xspi);
|
||||
|
||||
/* SPI controller initializations */
|
||||
cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr));
|
||||
cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr));
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
ret = -ENXIO;
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto clk_dis_all;
|
||||
}
|
||||
|
||||
|
@ -653,7 +653,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
|
||||
if (!spi_controller_is_slave(ctlr)) {
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
ctlr->mode_bits |= SPI_CS_HIGH;
|
||||
ctlr->set_cs = cdns_spi_chipselect;
|
||||
ctlr->auto_runtime_pm = true;
|
||||
|
@ -665,7 +665,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
} else {
|
||||
ctlr->mode_bits |= SPI_NO_CS;
|
||||
ctlr->slave_abort = cdns_slave_abort;
|
||||
ctlr->target_abort = cdns_target_abort;
|
||||
}
|
||||
ret = spi_register_controller(ctlr);
|
||||
if (ret) {
|
||||
|
@ -676,7 +676,7 @@ static int cdns_spi_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
clk_dis_all:
|
||||
if (!spi_controller_is_slave(ctlr)) {
|
||||
if (!spi_controller_is_target(ctlr)) {
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable_unprepare(xspi->ref_clk);
|
||||
|
@ -695,8 +695,6 @@ remove_ctlr:
|
|||
* This function is called if a device is physically removed from the system or
|
||||
* if the driver module is being unloaded. It frees all resources allocated to
|
||||
* the device.
|
||||
*
|
||||
* Return: 0 on success and error value on error
|
||||
*/
|
||||
static void cdns_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -742,7 +740,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
|
|||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct cdns_spi *xspi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr));
|
||||
cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr));
|
||||
return spi_controller_resume(ctlr);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
static int octeon_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct octeon_spi *p;
|
||||
int err = -ENOENT;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct octeon_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
p = spi_master_get_devdata(master);
|
||||
platform_set_drvdata(pdev, master);
|
||||
p = spi_controller_get_devdata(host);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(reg_base)) {
|
||||
|
@ -43,21 +43,21 @@ static int octeon_spi_probe(struct platform_device *pdev)
|
|||
p->regs.tx = 0x10;
|
||||
p->regs.data = 0x80;
|
||||
|
||||
master->num_chipselect = 4;
|
||||
master->mode_bits = SPI_CPHA |
|
||||
host->num_chipselect = 4;
|
||||
host->mode_bits = SPI_CPHA |
|
||||
SPI_CPOL |
|
||||
SPI_CS_HIGH |
|
||||
SPI_LSB_FIRST |
|
||||
SPI_3WIRE;
|
||||
|
||||
master->transfer_one_message = octeon_spi_transfer_one_message;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
|
||||
host->transfer_one_message = octeon_spi_transfer_one_message;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
err = devm_spi_register_master(&pdev->dev, master);
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
err = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "register master failed: %d\n", err);
|
||||
dev_err(&pdev->dev, "register host failed: %d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -65,14 +65,14 @@ static int octeon_spi_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
fail:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void octeon_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct octeon_spi *p = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct octeon_spi *p = spi_controller_get_devdata(host);
|
||||
|
||||
/* Clear the CSENA* and put everything in a known state. */
|
||||
writeq(0, p->register_base + OCTEON_SPI_CFG(p));
|
||||
|
|
|
@ -20,15 +20,15 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct octeon_spi *p;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(struct octeon_spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(dev, sizeof(struct octeon_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
p = spi_master_get_devdata(master);
|
||||
p = spi_controller_get_devdata(host);
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
|
@ -64,18 +64,18 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
p->sys_freq = SYS_FREQ_DEFAULT;
|
||||
dev_info(dev, "Set system clock to %u\n", p->sys_freq);
|
||||
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->num_chipselect = 4;
|
||||
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH |
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->num_chipselect = 4;
|
||||
host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH |
|
||||
SPI_LSB_FIRST | SPI_3WIRE;
|
||||
master->transfer_one_message = octeon_spi_transfer_one_message;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->transfer_one_message = octeon_spi_transfer_one_message;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
pci_set_drvdata(pdev, master);
|
||||
pci_set_drvdata(pdev, host);
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
@ -84,16 +84,16 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
|
|||
error:
|
||||
clk_disable_unprepare(p->clk);
|
||||
pci_release_regions(pdev);
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void thunderx_spi_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct spi_master *master = pci_get_drvdata(pdev);
|
||||
struct spi_controller *host = pci_get_drvdata(pdev);
|
||||
struct octeon_spi *p;
|
||||
|
||||
p = spi_master_get_devdata(master);
|
||||
p = spi_controller_get_devdata(host);
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
|
|
|
@ -33,10 +33,10 @@ struct spi_clps711x_data {
|
|||
int len;
|
||||
};
|
||||
|
||||
static int spi_clps711x_prepare_message(struct spi_master *master,
|
||||
static int spi_clps711x_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct spi_clps711x_data *hw = spi_master_get_devdata(master);
|
||||
struct spi_clps711x_data *hw = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = msg->spi;
|
||||
|
||||
/* Setup mode for transfer */
|
||||
|
@ -45,11 +45,11 @@ static int spi_clps711x_prepare_message(struct spi_master *master,
|
|||
SYSCON3_ADCCKNSEN : 0);
|
||||
}
|
||||
|
||||
static int spi_clps711x_transfer_one(struct spi_master *master,
|
||||
static int spi_clps711x_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct spi_clps711x_data *hw = spi_master_get_devdata(master);
|
||||
struct spi_clps711x_data *hw = spi_controller_get_devdata(host);
|
||||
u8 data;
|
||||
|
||||
clk_set_rate(hw->spi_clk, xfer->speed_hz ? : spi->max_speed_hz);
|
||||
|
@ -68,8 +68,8 @@ static int spi_clps711x_transfer_one(struct spi_master *master,
|
|||
|
||||
static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = dev_id;
|
||||
struct spi_clps711x_data *hw = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct spi_clps711x_data *hw = spi_controller_get_devdata(host);
|
||||
u8 data;
|
||||
|
||||
/* Handle RX */
|
||||
|
@ -83,7 +83,7 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
|
|||
writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
|
||||
hw->syncio);
|
||||
} else
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -92,26 +92,26 @@ static int spi_clps711x_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct spi_clps711x_data *hw;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
int irq, ret;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*hw));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*hw));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
master->use_gpio_descriptors = true;
|
||||
master->bus_num = -1;
|
||||
master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->prepare_message = spi_clps711x_prepare_message;
|
||||
master->transfer_one = spi_clps711x_transfer_one;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->bus_num = -1;
|
||||
host->mode_bits = SPI_CPHA | SPI_CS_HIGH;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->prepare_message = spi_clps711x_prepare_message;
|
||||
host->transfer_one = spi_clps711x_transfer_one;
|
||||
|
||||
hw = spi_master_get_devdata(master);
|
||||
hw = spi_controller_get_devdata(host);
|
||||
|
||||
hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(hw->spi_clk)) {
|
||||
|
@ -138,16 +138,16 @@ static int spi_clps711x_probe(struct platform_device *pdev)
|
|||
readl(hw->syncio);
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0,
|
||||
dev_name(&pdev->dev), master);
|
||||
dev_name(&pdev->dev), host);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
|
|||
|
||||
static void mcfqspi_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(spi->master);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(spi->controller);
|
||||
bool cs_high = spi->mode & SPI_CS_HIGH;
|
||||
|
||||
if (enable)
|
||||
|
@ -295,11 +295,11 @@ static void mcfqspi_set_cs(struct spi_device *spi, bool enable)
|
|||
mcfqspi_cs_deselect(mcfqspi, spi_get_chipselect(spi, 0), cs_high);
|
||||
}
|
||||
|
||||
static int mcfqspi_transfer_one(struct spi_master *master,
|
||||
static int mcfqspi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
u16 qmr = MCFQSPI_QMR_MSTR;
|
||||
|
||||
qmr |= t->bits_per_word << 10;
|
||||
|
@ -323,7 +323,7 @@ static int mcfqspi_transfer_one(struct spi_master *master,
|
|||
|
||||
static int mcfqspi_setup(struct spi_device *spi)
|
||||
{
|
||||
mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
|
||||
mcfqspi_cs_deselect(spi_controller_get_devdata(spi->controller),
|
||||
spi_get_chipselect(spi, 0), spi->mode & SPI_CS_HIGH);
|
||||
|
||||
dev_dbg(&spi->dev,
|
||||
|
@ -337,7 +337,7 @@ static int mcfqspi_setup(struct spi_device *spi)
|
|||
|
||||
static int mcfqspi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mcfqspi *mcfqspi;
|
||||
struct mcfqspi_platform_data *pdata;
|
||||
int status;
|
||||
|
@ -353,13 +353,13 @@ static int mcfqspi_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi));
|
||||
if (master == NULL) {
|
||||
dev_dbg(&pdev->dev, "spi_alloc_master failed\n");
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*mcfqspi));
|
||||
if (host == NULL) {
|
||||
dev_dbg(&pdev->dev, "spi_alloc_host failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mcfqspi = spi_master_get_devdata(master);
|
||||
mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mcfqspi->iobase)) {
|
||||
|
@ -381,53 +381,50 @@ static int mcfqspi_probe(struct platform_device *pdev)
|
|||
goto fail0;
|
||||
}
|
||||
|
||||
mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk");
|
||||
mcfqspi->clk = devm_clk_get_enabled(&pdev->dev, "qspi_clk");
|
||||
if (IS_ERR(mcfqspi->clk)) {
|
||||
dev_dbg(&pdev->dev, "clk_get failed\n");
|
||||
status = PTR_ERR(mcfqspi->clk);
|
||||
goto fail0;
|
||||
}
|
||||
clk_prepare_enable(mcfqspi->clk);
|
||||
|
||||
master->bus_num = pdata->bus_num;
|
||||
master->num_chipselect = pdata->num_chipselect;
|
||||
host->bus_num = pdata->bus_num;
|
||||
host->num_chipselect = pdata->num_chipselect;
|
||||
|
||||
mcfqspi->cs_control = pdata->cs_control;
|
||||
status = mcfqspi_cs_setup(mcfqspi);
|
||||
if (status) {
|
||||
dev_dbg(&pdev->dev, "error initializing cs_control\n");
|
||||
goto fail1;
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&mcfqspi->waitq);
|
||||
|
||||
master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
|
||||
master->setup = mcfqspi_setup;
|
||||
master->set_cs = mcfqspi_set_cs;
|
||||
master->transfer_one = mcfqspi_transfer_one;
|
||||
master->auto_runtime_pm = true;
|
||||
host->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
|
||||
host->setup = mcfqspi_setup;
|
||||
host->set_cs = mcfqspi_set_cs;
|
||||
host->transfer_one = mcfqspi_transfer_one;
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
status = devm_spi_register_master(&pdev->dev, master);
|
||||
status = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (status) {
|
||||
dev_dbg(&pdev->dev, "spi_register_master failed\n");
|
||||
goto fail2;
|
||||
dev_dbg(&pdev->dev, "devm_spi_register_controller failed\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
fail1:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
mcfqspi_cs_teardown(mcfqspi);
|
||||
fail1:
|
||||
clk_disable_unprepare(mcfqspi->clk);
|
||||
fail0:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
|
||||
dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
|
||||
|
||||
|
@ -436,8 +433,8 @@ fail0:
|
|||
|
||||
static void mcfqspi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
/* disable the hardware (set the baud rate to 0) */
|
||||
|
@ -450,11 +447,11 @@ static void mcfqspi_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mcfqspi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -465,20 +462,20 @@ static int mcfqspi_suspend(struct device *dev)
|
|||
|
||||
static int mcfqspi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
clk_enable(mcfqspi->clk);
|
||||
|
||||
return spi_master_resume(master);
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mcfqspi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
clk_disable(mcfqspi->clk);
|
||||
|
||||
|
@ -487,8 +484,8 @@ static int mcfqspi_runtime_suspend(struct device *dev)
|
|||
|
||||
static int mcfqspi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mcfqspi *mcfqspi = spi_controller_get_devdata(host);
|
||||
|
||||
clk_enable(mcfqspi->clk);
|
||||
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// CS42L43 SPI Controller Driver
|
||||
//
|
||||
// Copyright (C) 2022-2023 Cirrus Logic, Inc. and
|
||||
// Cirrus Logic International Semiconductor Ltd.
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mfd/cs42l43.h>
|
||||
#include <linux/mfd/cs42l43-regs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define CS42L43_FIFO_SIZE 16
|
||||
#define CS42L43_SPI_ROOT_HZ (40 * HZ_PER_MHZ)
|
||||
#define CS42L43_SPI_MAX_LENGTH 65532
|
||||
|
||||
enum cs42l43_spi_cmd {
|
||||
CS42L43_WRITE,
|
||||
CS42L43_READ
|
||||
};
|
||||
|
||||
struct cs42l43_spi {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct spi_controller *ctlr;
|
||||
};
|
||||
|
||||
static const unsigned int cs42l43_clock_divs[] = {
|
||||
2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
|
||||
};
|
||||
|
||||
static int cs42l43_spi_tx(struct regmap *regmap, const u8 *buf, unsigned int len)
|
||||
{
|
||||
const u8 *end = buf + len;
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
while (buf < end) {
|
||||
const u8 *block = min(buf + CS42L43_FIFO_SIZE, end);
|
||||
|
||||
while (buf < block) {
|
||||
const u8 *word = min(buf + sizeof(u32), block);
|
||||
int pad = (buf + sizeof(u32)) - word;
|
||||
|
||||
while (buf < word) {
|
||||
val >>= BITS_PER_BYTE;
|
||||
val |= FIELD_PREP(GENMASK(31, 24), *buf);
|
||||
|
||||
buf++;
|
||||
}
|
||||
|
||||
val >>= pad * BITS_PER_BYTE;
|
||||
|
||||
regmap_write(regmap, CS42L43_TX_DATA, val);
|
||||
}
|
||||
|
||||
regmap_write(regmap, CS42L43_TRAN_CONFIG8, CS42L43_SPI_TX_DONE_MASK);
|
||||
|
||||
ret = regmap_read_poll_timeout(regmap, CS42L43_TRAN_STATUS1,
|
||||
val, (val & CS42L43_SPI_TX_REQUEST_MASK),
|
||||
1000, 5000);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_spi_rx(struct regmap *regmap, u8 *buf, unsigned int len)
|
||||
{
|
||||
u8 *end = buf + len;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
while (buf < end) {
|
||||
u8 *block = min(buf + CS42L43_FIFO_SIZE, end);
|
||||
|
||||
ret = regmap_read_poll_timeout(regmap, CS42L43_TRAN_STATUS1,
|
||||
val, (val & CS42L43_SPI_RX_REQUEST_MASK),
|
||||
1000, 5000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
while (buf < block) {
|
||||
u8 *word = min(buf + sizeof(u32), block);
|
||||
|
||||
ret = regmap_read(regmap, CS42L43_RX_DATA, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
while (buf < word) {
|
||||
*buf = FIELD_GET(GENMASK(7, 0), val);
|
||||
|
||||
val >>= BITS_PER_BYTE;
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
|
||||
regmap_write(regmap, CS42L43_TRAN_CONFIG8, CS42L43_SPI_RX_DONE_MASK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_transfer_one(struct spi_controller *ctlr, struct spi_device *spi,
|
||||
struct spi_transfer *tfr)
|
||||
{
|
||||
struct cs42l43_spi *priv = spi_controller_get_devdata(spi->controller);
|
||||
int i, ret = -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cs42l43_clock_divs); i++) {
|
||||
if (CS42L43_SPI_ROOT_HZ / cs42l43_clock_divs[i] <= tfr->speed_hz)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(cs42l43_clock_divs))
|
||||
return -EINVAL;
|
||||
|
||||
regmap_write(priv->regmap, CS42L43_SPI_CLK_CONFIG1, i);
|
||||
|
||||
if (tfr->tx_buf) {
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG3, CS42L43_WRITE);
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG4, tfr->len - 1);
|
||||
} else if (tfr->rx_buf) {
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG3, CS42L43_READ);
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG5, tfr->len - 1);
|
||||
}
|
||||
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG1, CS42L43_SPI_START_MASK);
|
||||
|
||||
if (tfr->tx_buf)
|
||||
ret = cs42l43_spi_tx(priv->regmap, (const u8 *)tfr->tx_buf, tfr->len);
|
||||
else if (tfr->rx_buf)
|
||||
ret = cs42l43_spi_rx(priv->regmap, (u8 *)tfr->rx_buf, tfr->len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs42l43_set_cs(struct spi_device *spi, bool is_high)
|
||||
{
|
||||
struct cs42l43_spi *priv = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (spi_get_chipselect(spi, 0) == 0)
|
||||
regmap_write(priv->regmap, CS42L43_SPI_CONFIG2, !is_high);
|
||||
}
|
||||
|
||||
static int cs42l43_prepare_message(struct spi_controller *ctlr, struct spi_message *msg)
|
||||
{
|
||||
struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr);
|
||||
struct spi_device *spi = msg->spi;
|
||||
unsigned int spi_config1 = 0;
|
||||
|
||||
/* select another internal CS, which doesn't exist, so CS 0 is not used */
|
||||
if (spi_get_csgpiod(spi, 0))
|
||||
spi_config1 |= 1 << CS42L43_SPI_SS_SEL_SHIFT;
|
||||
if (spi->mode & SPI_CPOL)
|
||||
spi_config1 |= CS42L43_SPI_CPOL_MASK;
|
||||
if (spi->mode & SPI_CPHA)
|
||||
spi_config1 |= CS42L43_SPI_CPHA_MASK;
|
||||
if (spi->mode & SPI_3WIRE)
|
||||
spi_config1 |= CS42L43_SPI_THREE_WIRE_MASK;
|
||||
|
||||
regmap_write(priv->regmap, CS42L43_SPI_CONFIG1, spi_config1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l43_prepare_transfer_hardware(struct spi_controller *ctlr)
|
||||
{
|
||||
struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr);
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(priv->regmap, CS42L43_BLOCK_EN2, CS42L43_SPI_MSTR_EN_MASK);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to enable SPI controller: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs42l43_unprepare_transfer_hardware(struct spi_controller *ctlr)
|
||||
{
|
||||
struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr);
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(priv->regmap, CS42L43_BLOCK_EN2, 0);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to disable SPI controller: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t cs42l43_spi_max_length(struct spi_device *spi)
|
||||
{
|
||||
return CS42L43_SPI_MAX_LENGTH;
|
||||
}
|
||||
|
||||
static int cs42l43_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct cs42l43_spi *priv;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*priv->ctlr));
|
||||
if (!priv->ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_controller_set_devdata(priv->ctlr, priv);
|
||||
|
||||
priv->dev = &pdev->dev;
|
||||
priv->regmap = cs42l43->regmap;
|
||||
|
||||
priv->ctlr->prepare_message = cs42l43_prepare_message;
|
||||
priv->ctlr->prepare_transfer_hardware = cs42l43_prepare_transfer_hardware;
|
||||
priv->ctlr->unprepare_transfer_hardware = cs42l43_unprepare_transfer_hardware;
|
||||
priv->ctlr->transfer_one = cs42l43_transfer_one;
|
||||
priv->ctlr->set_cs = cs42l43_set_cs;
|
||||
priv->ctlr->max_transfer_size = cs42l43_spi_max_length;
|
||||
|
||||
if (is_of_node(fwnode))
|
||||
fwnode = fwnode_get_named_child_node(fwnode, "spi");
|
||||
|
||||
device_set_node(&priv->ctlr->dev, fwnode);
|
||||
|
||||
priv->ctlr->mode_bits = SPI_3WIRE | SPI_MODE_X_MASK;
|
||||
priv->ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
priv->ctlr->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) |
|
||||
SPI_BPW_MASK(32);
|
||||
priv->ctlr->min_speed_hz = CS42L43_SPI_ROOT_HZ /
|
||||
cs42l43_clock_divs[ARRAY_SIZE(cs42l43_clock_divs) - 1];
|
||||
priv->ctlr->max_speed_hz = CS42L43_SPI_ROOT_HZ / cs42l43_clock_divs[0];
|
||||
priv->ctlr->use_gpio_descriptors = true;
|
||||
priv->ctlr->auto_runtime_pm = true;
|
||||
|
||||
devm_pm_runtime_enable(priv->dev);
|
||||
pm_runtime_idle(priv->dev);
|
||||
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG6, CS42L43_FIFO_SIZE - 1);
|
||||
regmap_write(priv->regmap, CS42L43_TRAN_CONFIG7, CS42L43_FIFO_SIZE - 1);
|
||||
|
||||
// Disable Watchdog timer and enable stall
|
||||
regmap_write(priv->regmap, CS42L43_SPI_CONFIG3, 0);
|
||||
regmap_write(priv->regmap, CS42L43_SPI_CONFIG4, CS42L43_SPI_STALL_ENA_MASK);
|
||||
|
||||
ret = devm_spi_register_controller(priv->dev, priv->ctlr);
|
||||
if (ret) {
|
||||
pm_runtime_disable(priv->dev);
|
||||
dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_device_id cs42l43_spi_id_table[] = {
|
||||
{ "cs42l43-spi", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, cs42l43_spi_id_table);
|
||||
|
||||
static struct platform_driver cs42l43_spi_driver = {
|
||||
.driver = {
|
||||
.name = "cs42l43-spi",
|
||||
},
|
||||
.probe = cs42l43_spi_probe,
|
||||
.id_table = cs42l43_spi_id_table,
|
||||
};
|
||||
module_platform_driver(cs42l43_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CS42L43 SPI Driver");
|
||||
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Maciej Strozek <mstrozek@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -15,7 +15,6 @@
|
|||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -202,7 +201,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
|
|||
u8 chip_sel = spi_get_chipselect(spi, 0);
|
||||
u16 spidat1 = CS_DEFAULT;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
dspi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
/* program delay transfers if tx_delay is non zero */
|
||||
if (spicfg && spicfg->wdelay)
|
||||
|
@ -272,7 +271,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
|
|||
u32 hz = 0, spifmt = 0;
|
||||
int prescale;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
dspi = spi_controller_get_devdata(spi->controller);
|
||||
spicfg = spi->controller_data;
|
||||
if (!spicfg)
|
||||
spicfg = &davinci_spi_default_cfg;
|
||||
|
@ -380,7 +379,7 @@ static int davinci_spi_of_setup(struct spi_device *spi)
|
|||
{
|
||||
struct davinci_spi_config *spicfg = spi->controller_data;
|
||||
struct device_node *np = spi->dev.of_node;
|
||||
struct davinci_spi *dspi = spi_master_get_devdata(spi->master);
|
||||
struct davinci_spi *dspi = spi_controller_get_devdata(spi->controller);
|
||||
u32 prop;
|
||||
|
||||
if (spicfg == NULL && np) {
|
||||
|
@ -412,7 +411,7 @@ static int davinci_spi_setup(struct spi_device *spi)
|
|||
struct device_node *np = spi->dev.of_node;
|
||||
bool internal_cs = true;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
dspi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (!(spi->mode & SPI_NO_CS)) {
|
||||
if (np && spi_get_csgpiod(spi, 0))
|
||||
|
@ -442,7 +441,7 @@ static void davinci_spi_cleanup(struct spi_device *spi)
|
|||
kfree(spicfg);
|
||||
}
|
||||
|
||||
static bool davinci_spi_can_dma(struct spi_master *master,
|
||||
static bool davinci_spi_can_dma(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
|
@ -572,7 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
struct davinci_spi_config *spicfg;
|
||||
struct davinci_spi_platform_data *pdata;
|
||||
|
||||
dspi = spi_master_get_devdata(spi->master);
|
||||
dspi = spi_controller_get_devdata(spi->controller);
|
||||
pdata = &dspi->pdata;
|
||||
spicfg = (struct davinci_spi_config *)spi->controller_data;
|
||||
if (!spicfg)
|
||||
|
@ -593,7 +592,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
|
||||
reinit_completion(&dspi->done);
|
||||
|
||||
if (!davinci_spi_can_dma(spi->master, spi, t)) {
|
||||
if (!davinci_spi_can_dma(spi->controller, spi, t)) {
|
||||
if (spicfg->io_type != SPI_IO_TYPE_POLL)
|
||||
set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
|
||||
/* start the transfer */
|
||||
|
@ -674,7 +673,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
}
|
||||
|
||||
clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
|
||||
if (davinci_spi_can_dma(spi->master, spi, t))
|
||||
if (davinci_spi_can_dma(spi->controller, spi, t))
|
||||
clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
|
||||
|
||||
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
|
||||
|
@ -856,22 +855,22 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
|
|||
*/
|
||||
static int davinci_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct davinci_spi *dspi;
|
||||
struct davinci_spi_platform_data *pdata;
|
||||
struct resource *r;
|
||||
int ret = 0;
|
||||
u32 spipc0;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
|
||||
if (master == NULL) {
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct davinci_spi));
|
||||
if (host == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
dspi = spi_master_get_devdata(master);
|
||||
dspi = spi_controller_get_devdata(host);
|
||||
|
||||
if (dev_get_platdata(&pdev->dev)) {
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
|
@ -880,7 +879,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
|||
/* update dspi pdata with that from the DT */
|
||||
ret = spi_davinci_get_pdata(pdev, dspi);
|
||||
if (ret < 0)
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
}
|
||||
|
||||
/* pdata in dspi is now updated and point pdata to that */
|
||||
|
@ -892,57 +891,48 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
|||
GFP_KERNEL);
|
||||
if (dspi->bytes_per_word == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
}
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (r == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto free_master;
|
||||
}
|
||||
|
||||
dspi->pbase = r->start;
|
||||
|
||||
dspi->base = devm_ioremap_resource(&pdev->dev, r);
|
||||
dspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
|
||||
if (IS_ERR(dspi->base)) {
|
||||
ret = PTR_ERR(dspi->base);
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
}
|
||||
dspi->pbase = r->start;
|
||||
|
||||
init_completion(&dspi->done);
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
if (ret < 0)
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
dspi->irq = ret;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq,
|
||||
dummy_thread_fn, 0, dev_name(&pdev->dev), dspi);
|
||||
if (ret)
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
|
||||
dspi->bitbang.master = master;
|
||||
dspi->bitbang.master = host;
|
||||
|
||||
dspi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(dspi->clk)) {
|
||||
ret = -ENODEV;
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
}
|
||||
ret = clk_prepare_enable(dspi->clk);
|
||||
if (ret)
|
||||
goto free_master;
|
||||
goto free_host;
|
||||
|
||||
master->use_gpio_descriptors = true;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = pdata->num_chipselect;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
|
||||
master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_GPIO_SS;
|
||||
master->setup = davinci_spi_setup;
|
||||
master->cleanup = davinci_spi_cleanup;
|
||||
master->can_dma = davinci_spi_can_dma;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->bus_num = pdev->id;
|
||||
host->num_chipselect = pdata->num_chipselect;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
|
||||
host->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_GPIO_SS;
|
||||
host->setup = davinci_spi_setup;
|
||||
host->cleanup = davinci_spi_cleanup;
|
||||
host->can_dma = davinci_spi_can_dma;
|
||||
|
||||
dspi->bitbang.chipselect = davinci_spi_chipselect;
|
||||
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
|
||||
|
@ -983,7 +973,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
|
|||
|
||||
iowrite32(CS_DEFAULT, dspi->base + SPIDEF);
|
||||
|
||||
/* master mode default */
|
||||
/* host mode default */
|
||||
set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
|
||||
set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
|
||||
set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
|
||||
|
@ -1003,8 +993,8 @@ free_dma:
|
|||
}
|
||||
free_clk:
|
||||
clk_disable_unprepare(dspi->clk);
|
||||
free_master:
|
||||
spi_master_put(master);
|
||||
free_host:
|
||||
spi_controller_put(host);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1021,10 +1011,10 @@ err:
|
|||
static void davinci_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct davinci_spi *dspi;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
|
||||
master = platform_get_drvdata(pdev);
|
||||
dspi = spi_master_get_devdata(master);
|
||||
host = platform_get_drvdata(pdev);
|
||||
dspi = spi_controller_get_devdata(host);
|
||||
|
||||
spi_bitbang_stop(&dspi->bitbang);
|
||||
|
||||
|
@ -1035,7 +1025,7 @@ static void davinci_spi_remove(struct platform_device *pdev)
|
|||
dma_release_channel(dspi->dma_tx);
|
||||
}
|
||||
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
}
|
||||
|
||||
static struct platform_driver davinci_spi_driver = {
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
struct dln2_spi {
|
||||
struct platform_device *pdev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
u8 port;
|
||||
|
||||
/*
|
||||
|
@ -176,7 +176,7 @@ static int dln2_spi_cs_enable(struct dln2_spi *dln2, u8 cs_mask, bool enable)
|
|||
|
||||
static int dln2_spi_cs_enable_all(struct dln2_spi *dln2, bool enable)
|
||||
{
|
||||
u8 cs_mask = GENMASK(dln2->master->num_chipselect - 1, 0);
|
||||
u8 cs_mask = GENMASK(dln2->host->num_chipselect - 1, 0);
|
||||
|
||||
return dln2_spi_cs_enable(dln2, cs_mask, enable);
|
||||
}
|
||||
|
@ -589,11 +589,11 @@ static int dln2_spi_rdwr(struct dln2_spi *dln2, const u8 *tx_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dln2_spi_prepare_message(struct spi_master *master,
|
||||
static int dln2_spi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
int ret;
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
struct spi_device *spi = message->spi;
|
||||
|
||||
if (dln2->cs != spi_get_chipselect(spi, 0)) {
|
||||
|
@ -650,11 +650,11 @@ static int dln2_spi_transfer_setup(struct dln2_spi *dln2, u32 speed,
|
|||
return dln2_spi_enable(dln2, true);
|
||||
}
|
||||
|
||||
static int dln2_spi_transfer_one(struct spi_master *master,
|
||||
static int dln2_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
int status;
|
||||
u8 attr = 0;
|
||||
|
||||
|
@ -666,7 +666,7 @@ static int dln2_spi_transfer_one(struct spi_master *master,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (!xfer->cs_change && !spi_transfer_is_last(master, xfer))
|
||||
if (!xfer->cs_change && !spi_transfer_is_last(host, xfer))
|
||||
attr = DLN2_SPI_ATTR_LEAVE_SS_LOW;
|
||||
|
||||
status = dln2_spi_rdwr(dln2, xfer->tx_buf, xfer->rx_buf,
|
||||
|
@ -679,29 +679,29 @@ static int dln2_spi_transfer_one(struct spi_master *master,
|
|||
|
||||
static int dln2_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct dln2_spi *dln2;
|
||||
struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*dln2));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*dln2));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
device_set_node(&master->dev, dev_fwnode(dev));
|
||||
device_set_node(&host->dev, dev_fwnode(dev));
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
dln2 = spi_master_get_devdata(master);
|
||||
dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
dln2->buf = devm_kmalloc(&pdev->dev, DLN2_SPI_BUF_SIZE, GFP_KERNEL);
|
||||
if (!dln2->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
dln2->master = master;
|
||||
dln2->host = host;
|
||||
dln2->pdev = pdev;
|
||||
dln2->port = pdata->port;
|
||||
/* cs/mode can never be 0xff, so the first transfer will set them */
|
||||
|
@ -712,47 +712,47 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
ret = dln2_spi_enable(dln2, false);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to disable SPI module\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_cs_num(dln2, &master->num_chipselect);
|
||||
ret = dln2_spi_get_cs_num(dln2, &host->num_chipselect);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get number of CS pins\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_speed_range(dln2,
|
||||
&master->min_speed_hz,
|
||||
&master->max_speed_hz);
|
||||
&host->min_speed_hz,
|
||||
&host->max_speed_hz);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to read bus min/max freqs\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
ret = dln2_spi_get_supported_frame_sizes(dln2,
|
||||
&master->bits_per_word_mask);
|
||||
&host->bits_per_word_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to read supported frame sizes\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
ret = dln2_spi_cs_enable_all(dln2, true);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable CS pins\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
master->bus_num = -1;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
master->prepare_message = dln2_spi_prepare_message;
|
||||
master->transfer_one = dln2_spi_transfer_one;
|
||||
master->auto_runtime_pm = true;
|
||||
host->bus_num = -1;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
host->prepare_message = dln2_spi_prepare_message;
|
||||
host->transfer_one = dln2_spi_transfer_one;
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
/* enable SPI module, we're good to go */
|
||||
ret = dln2_spi_enable(dln2, true);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable SPI module\n");
|
||||
goto exit_free_master;
|
||||
goto exit_free_host;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev,
|
||||
|
@ -761,9 +761,9 @@ static int dln2_spi_probe(struct platform_device *pdev)
|
|||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register master\n");
|
||||
dev_err(&pdev->dev, "Failed to register host\n");
|
||||
goto exit_register;
|
||||
}
|
||||
|
||||
|
@ -775,16 +775,16 @@ exit_register:
|
|||
|
||||
if (dln2_spi_enable(dln2, false) < 0)
|
||||
dev_err(&pdev->dev, "Failed to disable SPI module\n");
|
||||
exit_free_master:
|
||||
spi_master_put(master);
|
||||
exit_free_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dln2_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
|
@ -796,10 +796,10 @@ static void dln2_spi_remove(struct platform_device *pdev)
|
|||
static int dln2_spi_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -824,8 +824,8 @@ static int dln2_spi_suspend(struct device *dev)
|
|||
static int dln2_spi_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
ret = dln2_spi_cs_enable_all(dln2, true);
|
||||
|
@ -837,23 +837,23 @@ static int dln2_spi_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return spi_master_resume(master);
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int dln2_spi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
return dln2_spi_enable(dln2, false);
|
||||
}
|
||||
|
||||
static int dln2_spi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct dln2_spi *dln2 = spi_controller_get_devdata(host);
|
||||
|
||||
return dln2_spi_enable(dln2, true);
|
||||
}
|
||||
|
@ -875,7 +875,7 @@ static struct platform_driver spi_dln2_driver = {
|
|||
};
|
||||
module_platform_driver(spi_dln2_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for the Diolan DLN2 SPI master interface");
|
||||
MODULE_DESCRIPTION("Driver for the Diolan DLN2 SPI host interface");
|
||||
MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:dln2-spi");
|
||||
|
|
|
@ -61,7 +61,7 @@ static void dw_spi_debugfs_init(struct dw_spi *dws)
|
|||
{
|
||||
char name[32];
|
||||
|
||||
snprintf(name, 32, "dw_spi%d", dws->master->bus_num);
|
||||
snprintf(name, 32, "dw_spi%d", dws->host->bus_num);
|
||||
dws->debugfs = debugfs_create_dir(name, NULL);
|
||||
|
||||
dws->regset.regs = dw_spi_dbgfs_regs;
|
||||
|
@ -183,25 +183,25 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw)
|
|||
irq_status = dw_readl(dws, DW_SPI_ISR);
|
||||
|
||||
if (irq_status & DW_SPI_INT_RXOI) {
|
||||
dev_err(&dws->master->dev, "RX FIFO overflow detected\n");
|
||||
dev_err(&dws->host->dev, "RX FIFO overflow detected\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (irq_status & DW_SPI_INT_RXUI) {
|
||||
dev_err(&dws->master->dev, "RX FIFO underflow detected\n");
|
||||
dev_err(&dws->host->dev, "RX FIFO underflow detected\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (irq_status & DW_SPI_INT_TXOI) {
|
||||
dev_err(&dws->master->dev, "TX FIFO overflow detected\n");
|
||||
dev_err(&dws->host->dev, "TX FIFO overflow detected\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
/* Generically handle the erroneous situation */
|
||||
if (ret) {
|
||||
dw_spi_reset_chip(dws);
|
||||
if (dws->master->cur_msg)
|
||||
dws->master->cur_msg->status = ret;
|
||||
if (dws->host->cur_msg)
|
||||
dws->host->cur_msg->status = ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -213,7 +213,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
|
|||
u16 irq_status = dw_readl(dws, DW_SPI_ISR);
|
||||
|
||||
if (dw_spi_check_status(dws, false)) {
|
||||
spi_finalize_current_transfer(dws->master);
|
||||
spi_finalize_current_transfer(dws->host);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
|
|||
dw_reader(dws);
|
||||
if (!dws->rx_len) {
|
||||
dw_spi_mask_intr(dws, 0xff);
|
||||
spi_finalize_current_transfer(dws->master);
|
||||
spi_finalize_current_transfer(dws->host);
|
||||
} else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
|
||||
dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
|
||||
}
|
||||
|
@ -248,14 +248,14 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
|
|||
|
||||
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);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct dw_spi *dws = spi_controller_get_devdata(host);
|
||||
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK;
|
||||
|
||||
if (!irq_status)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!master->cur_msg) {
|
||||
if (!host->cur_msg) {
|
||||
dw_spi_mask_intr(dws, 0xff);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -408,11 +408,11 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dw_spi_transfer_one(struct spi_controller *master,
|
||||
static int dw_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(host);
|
||||
struct dw_spi_cfg cfg = {
|
||||
.tmode = DW_SPI_CTRLR0_TMOD_TR,
|
||||
.dfs = transfer->bits_per_word,
|
||||
|
@ -440,8 +440,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
|
|||
transfer->effective_speed_hz = dws->current_freq;
|
||||
|
||||
/* Check if current transfer is a DMA transaction */
|
||||
if (master->can_dma && master->can_dma(master, spi, transfer))
|
||||
dws->dma_mapped = master->cur_msg_mapped;
|
||||
if (host->can_dma && host->can_dma(host, spi, transfer))
|
||||
dws->dma_mapped = host->cur_msg_mapped;
|
||||
|
||||
/* For poll mode just disable all interrupts */
|
||||
dw_spi_mask_intr(dws, 0xff);
|
||||
|
@ -464,10 +464,10 @@ static int dw_spi_transfer_one(struct spi_controller *master,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void dw_spi_handle_err(struct spi_controller *master,
|
||||
static void dw_spi_handle_err(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(host);
|
||||
|
||||
if (dws->dma_mapped)
|
||||
dws->dma_ops->dma_stop(dws);
|
||||
|
@ -576,7 +576,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
|
|||
while (len) {
|
||||
entries = readl_relaxed(dws->regs + DW_SPI_TXFLR);
|
||||
if (!entries) {
|
||||
dev_err(&dws->master->dev, "CS de-assertion on Tx\n");
|
||||
dev_err(&dws->host->dev, "CS de-assertion on Tx\n");
|
||||
return -EIO;
|
||||
}
|
||||
room = min(dws->fifo_len - entries, len);
|
||||
|
@ -596,7 +596,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi)
|
|||
if (!entries) {
|
||||
sts = readl_relaxed(dws->regs + DW_SPI_RISR);
|
||||
if (sts & DW_SPI_INT_RXOI) {
|
||||
dev_err(&dws->master->dev, "FIFO overflow on Rx\n");
|
||||
dev_err(&dws->host->dev, "FIFO overflow on Rx\n");
|
||||
return -EIO;
|
||||
}
|
||||
continue;
|
||||
|
@ -637,7 +637,7 @@ static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
|
|||
spi_delay_exec(&delay, NULL);
|
||||
|
||||
if (retry < 0) {
|
||||
dev_err(&dws->master->dev, "Mem op hanged up\n");
|
||||
dev_err(&dws->host->dev, "Mem op hanged up\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -884,56 +884,56 @@ static void dw_spi_hw_init(struct device *dev, struct dw_spi *dws)
|
|||
|
||||
int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
||||
{
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
int ret;
|
||||
|
||||
if (!dws)
|
||||
return -EINVAL;
|
||||
|
||||
master = spi_alloc_master(dev, 0);
|
||||
if (!master)
|
||||
host = spi_alloc_host(dev, 0);
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
device_set_node(&master->dev, dev_fwnode(dev));
|
||||
device_set_node(&host->dev, dev_fwnode(dev));
|
||||
|
||||
dws->master = master;
|
||||
dws->host = host;
|
||||
dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
|
||||
|
||||
spi_controller_set_devdata(master, dws);
|
||||
spi_controller_set_devdata(host, dws);
|
||||
|
||||
/* Basic HW init */
|
||||
dw_spi_hw_init(dev, dws);
|
||||
|
||||
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
|
||||
master);
|
||||
host);
|
||||
if (ret < 0 && ret != -ENOTCONN) {
|
||||
dev_err(dev, "can not get IRQ\n");
|
||||
goto err_free_master;
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
dw_spi_init_mem_ops(dws);
|
||||
|
||||
master->use_gpio_descriptors = true;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
|
||||
if (dws->caps & DW_SPI_CAP_DFS32)
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
else
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
master->bus_num = dws->bus_num;
|
||||
master->num_chipselect = dws->num_cs;
|
||||
master->setup = dw_spi_setup;
|
||||
master->cleanup = dw_spi_cleanup;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
host->bus_num = dws->bus_num;
|
||||
host->num_chipselect = dws->num_cs;
|
||||
host->setup = dw_spi_setup;
|
||||
host->cleanup = dw_spi_cleanup;
|
||||
if (dws->set_cs)
|
||||
master->set_cs = dws->set_cs;
|
||||
host->set_cs = dws->set_cs;
|
||||
else
|
||||
master->set_cs = dw_spi_set_cs;
|
||||
master->transfer_one = dw_spi_transfer_one;
|
||||
master->handle_err = dw_spi_handle_err;
|
||||
host->set_cs = dw_spi_set_cs;
|
||||
host->transfer_one = dw_spi_transfer_one;
|
||||
host->handle_err = dw_spi_handle_err;
|
||||
if (dws->mem_ops.exec_op)
|
||||
master->mem_ops = &dws->mem_ops;
|
||||
master->max_speed_hz = dws->max_freq;
|
||||
master->flags = SPI_MASTER_GPIO_SS;
|
||||
master->auto_runtime_pm = true;
|
||||
host->mem_ops = &dws->mem_ops;
|
||||
host->max_speed_hz = dws->max_freq;
|
||||
host->flags = SPI_CONTROLLER_GPIO_SS;
|
||||
host->auto_runtime_pm = true;
|
||||
|
||||
/* Get default rx sample delay */
|
||||
device_property_read_u32(dev, "rx-sample-delay-ns",
|
||||
|
@ -946,14 +946,14 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
|||
} else if (ret) {
|
||||
dev_warn(dev, "DMA init failed\n");
|
||||
} else {
|
||||
master->can_dma = dws->dma_ops->can_dma;
|
||||
master->flags |= SPI_CONTROLLER_MUST_TX;
|
||||
host->can_dma = dws->dma_ops->can_dma;
|
||||
host->flags |= SPI_CONTROLLER_MUST_TX;
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_register_controller(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "problem registering spi master\n");
|
||||
dev_err_probe(dev, ret, "problem registering spi host\n");
|
||||
goto err_dma_exit;
|
||||
}
|
||||
|
||||
|
@ -965,9 +965,9 @@ err_dma_exit:
|
|||
dws->dma_ops->dma_exit(dws);
|
||||
dw_spi_enable_chip(dws, 0);
|
||||
err_free_irq:
|
||||
free_irq(dws->irq, master);
|
||||
err_free_master:
|
||||
spi_controller_put(master);
|
||||
free_irq(dws->irq, host);
|
||||
err_free_host:
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dw_spi_add_host, SPI_DW_CORE);
|
||||
|
@ -976,14 +976,14 @@ void dw_spi_remove_host(struct dw_spi *dws)
|
|||
{
|
||||
dw_spi_debugfs_remove(dws);
|
||||
|
||||
spi_unregister_controller(dws->master);
|
||||
spi_unregister_controller(dws->host);
|
||||
|
||||
if (dws->dma_ops && dws->dma_ops->dma_exit)
|
||||
dws->dma_ops->dma_exit(dws);
|
||||
|
||||
dw_spi_shutdown_chip(dws);
|
||||
|
||||
free_irq(dws->irq, dws->master);
|
||||
free_irq(dws->irq, dws->host);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dw_spi_remove_host, SPI_DW_CORE);
|
||||
|
||||
|
@ -991,7 +991,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = spi_controller_suspend(dws->master);
|
||||
ret = spi_controller_suspend(dws->host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1002,8 +1002,8 @@ EXPORT_SYMBOL_NS_GPL(dw_spi_suspend_host, SPI_DW_CORE);
|
|||
|
||||
int dw_spi_resume_host(struct dw_spi *dws)
|
||||
{
|
||||
dw_spi_hw_init(&dws->master->dev, dws);
|
||||
return spi_controller_resume(dws->master);
|
||||
dw_spi_hw_init(&dws->host->dev, dws);
|
||||
return spi_controller_resume(dws->host);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dw_spi_resume_host, SPI_DW_CORE);
|
||||
|
||||
|
|
|
@ -139,8 +139,8 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
|
|||
if (!dws->txchan)
|
||||
goto free_rxchan;
|
||||
|
||||
dws->master->dma_rx = dws->rxchan;
|
||||
dws->master->dma_tx = dws->txchan;
|
||||
dws->host->dma_rx = dws->rxchan;
|
||||
dws->host->dma_tx = dws->txchan;
|
||||
|
||||
init_completion(&dws->dma_completion);
|
||||
|
||||
|
@ -183,8 +183,8 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
|
|||
goto free_rxchan;
|
||||
}
|
||||
|
||||
dws->master->dma_rx = dws->rxchan;
|
||||
dws->master->dma_tx = dws->txchan;
|
||||
dws->host->dma_rx = dws->rxchan;
|
||||
dws->host->dma_tx = dws->txchan;
|
||||
|
||||
init_completion(&dws->dma_completion);
|
||||
|
||||
|
@ -242,10 +242,10 @@ static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
|
|||
}
|
||||
}
|
||||
|
||||
static bool dw_spi_can_dma(struct spi_controller *master,
|
||||
static bool dw_spi_can_dma(struct spi_controller *host,
|
||||
struct spi_device *spi, struct spi_transfer *xfer)
|
||||
{
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(host);
|
||||
enum dma_slave_buswidth dma_bus_width;
|
||||
|
||||
if (xfer->len <= dws->fifo_len)
|
||||
|
@ -271,7 +271,7 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
|
|||
msecs_to_jiffies(ms));
|
||||
|
||||
if (ms == 0) {
|
||||
dev_err(&dws->master->cur_msg->spi->dev,
|
||||
dev_err(&dws->host->cur_msg->spi->dev,
|
||||
"DMA transaction timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ static int dw_spi_dma_wait_tx_done(struct dw_spi *dws,
|
|||
spi_delay_exec(&delay, xfer);
|
||||
|
||||
if (retry < 0) {
|
||||
dev_err(&dws->master->dev, "Tx hanged up\n");
|
||||
dev_err(&dws->host->dev, "Tx hanged up\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ static int dw_spi_dma_wait_rx_done(struct dw_spi *dws)
|
|||
spi_delay_exec(&delay, NULL);
|
||||
|
||||
if (retry < 0) {
|
||||
dev_err(&dws->master->dev, "Rx hanged up\n");
|
||||
dev_err(&dws->host->dev, "Rx hanged up\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -656,13 +656,13 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dws->master->cur_msg->status == -EINPROGRESS) {
|
||||
if (dws->host->cur_msg->status == -EINPROGRESS) {
|
||||
ret = dw_spi_dma_wait_tx_done(dws, xfer);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (xfer->rx_buf && dws->master->cur_msg->status == -EINPROGRESS)
|
||||
if (xfer->rx_buf && dws->host->cur_msg->status == -EINPROGRESS)
|
||||
ret = dw_spi_dma_wait_rx_done(dws);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -76,7 +76,7 @@ struct dw_spi_mscc {
|
|||
*/
|
||||
static void dw_spi_mscc_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(spi->master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
|
||||
struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
|
||||
struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
|
||||
u32 cs = spi_get_chipselect(spi, 0);
|
||||
|
@ -149,7 +149,7 @@ static int dw_spi_mscc_jaguar2_init(struct platform_device *pdev,
|
|||
*/
|
||||
static void dw_spi_sparx5_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(spi->master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
|
||||
struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
|
||||
struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
|
||||
u8 cs = spi_get_chipselect(spi, 0);
|
||||
|
@ -277,7 +277,7 @@ static void dw_spi_elba_override_cs(struct regmap *syscon, int cs, int enable)
|
|||
|
||||
static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(spi->master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
|
||||
struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
|
||||
struct regmap *syscon = dwsmmio->priv;
|
||||
u8 cs;
|
||||
|
@ -369,7 +369,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
|
|||
|
||||
dws->max_freq = clk_get_rate(dwsmmio->clk);
|
||||
|
||||
device_property_read_u32(&pdev->dev, "reg-io-width", &dws->reg_io_width);
|
||||
if (device_property_read_u32(&pdev->dev, "reg-io-width",
|
||||
&dws->reg_io_width))
|
||||
dws->reg_io_width = 4;
|
||||
|
||||
num_cs = 4;
|
||||
|
||||
|
|
|
@ -142,14 +142,14 @@ struct dw_spi_dma_ops {
|
|||
int (*dma_init)(struct device *dev, struct dw_spi *dws);
|
||||
void (*dma_exit)(struct dw_spi *dws);
|
||||
int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
|
||||
bool (*can_dma)(struct spi_controller *master, struct spi_device *spi,
|
||||
bool (*can_dma)(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *xfer);
|
||||
int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
|
||||
void (*dma_stop)(struct dw_spi *dws);
|
||||
};
|
||||
|
||||
struct dw_spi {
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
|
||||
u32 ip; /* Synopsys DW SSI IP-core ID */
|
||||
u32 ver; /* Synopsys component version */
|
||||
|
|
|
@ -104,15 +104,15 @@ struct ep93xx_spi {
|
|||
|
||||
/**
|
||||
* ep93xx_spi_calc_divisors() - calculates SPI clock divisors
|
||||
* @master: SPI master
|
||||
* @host: SPI host
|
||||
* @rate: desired SPI output clock rate
|
||||
* @div_cpsr: pointer to return the cpsr (pre-scaler) divider
|
||||
* @div_scr: pointer to return the scr divider
|
||||
*/
|
||||
static int ep93xx_spi_calc_divisors(struct spi_master *master,
|
||||
static int ep93xx_spi_calc_divisors(struct spi_controller *host,
|
||||
u32 rate, u8 *div_cpsr, u8 *div_scr)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
unsigned long spi_clk_rate = clk_get_rate(espi->clk);
|
||||
int cpsr, scr;
|
||||
|
||||
|
@ -120,7 +120,7 @@ static int ep93xx_spi_calc_divisors(struct spi_master *master,
|
|||
* Make sure that max value is between values supported by the
|
||||
* controller.
|
||||
*/
|
||||
rate = clamp(rate, master->min_speed_hz, master->max_speed_hz);
|
||||
rate = clamp(rate, host->min_speed_hz, host->max_speed_hz);
|
||||
|
||||
/*
|
||||
* Calculate divisors so that we can get speed according the
|
||||
|
@ -143,18 +143,18 @@ static int ep93xx_spi_calc_divisors(struct spi_master *master,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ep93xx_spi_chip_setup(struct spi_master *master,
|
||||
static int ep93xx_spi_chip_setup(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
u8 dss = bits_per_word_to_dss(xfer->bits_per_word);
|
||||
u8 div_cpsr = 0;
|
||||
u8 div_scr = 0;
|
||||
u16 cr0;
|
||||
int err;
|
||||
|
||||
err = ep93xx_spi_calc_divisors(master, xfer->speed_hz,
|
||||
err = ep93xx_spi_calc_divisors(host, xfer->speed_hz,
|
||||
&div_cpsr, &div_scr);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -166,9 +166,9 @@ static int ep93xx_spi_chip_setup(struct spi_master *master,
|
|||
cr0 |= SSPCR0_SPH;
|
||||
cr0 |= dss;
|
||||
|
||||
dev_dbg(&master->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
|
||||
dev_dbg(&host->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
|
||||
spi->mode, div_cpsr, div_scr, dss);
|
||||
dev_dbg(&master->dev, "setup: cr0 %#x\n", cr0);
|
||||
dev_dbg(&host->dev, "setup: cr0 %#x\n", cr0);
|
||||
|
||||
writel(div_cpsr, espi->mmio + SSPCPSR);
|
||||
writel(cr0, espi->mmio + SSPCR0);
|
||||
|
@ -176,10 +176,10 @@ static int ep93xx_spi_chip_setup(struct spi_master *master,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ep93xx_do_write(struct spi_master *master)
|
||||
static void ep93xx_do_write(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_transfer *xfer = master->cur_msg->state;
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *xfer = host->cur_msg->state;
|
||||
u32 val = 0;
|
||||
|
||||
if (xfer->bits_per_word > 8) {
|
||||
|
@ -194,10 +194,10 @@ static void ep93xx_do_write(struct spi_master *master)
|
|||
writel(val, espi->mmio + SSPDR);
|
||||
}
|
||||
|
||||
static void ep93xx_do_read(struct spi_master *master)
|
||||
static void ep93xx_do_read(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_transfer *xfer = master->cur_msg->state;
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *xfer = host->cur_msg->state;
|
||||
u32 val;
|
||||
|
||||
val = readl(espi->mmio + SSPDR);
|
||||
|
@ -214,7 +214,7 @@ static void ep93xx_do_read(struct spi_master *master)
|
|||
|
||||
/**
|
||||
* ep93xx_spi_read_write() - perform next RX/TX transfer
|
||||
* @master: SPI master
|
||||
* @host: SPI host
|
||||
*
|
||||
* This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
|
||||
* called several times, the whole transfer will be completed. Returns
|
||||
|
@ -223,20 +223,20 @@ static void ep93xx_do_read(struct spi_master *master)
|
|||
* When this function is finished, RX FIFO should be empty and TX FIFO should be
|
||||
* full.
|
||||
*/
|
||||
static int ep93xx_spi_read_write(struct spi_master *master)
|
||||
static int ep93xx_spi_read_write(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_transfer *xfer = master->cur_msg->state;
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *xfer = host->cur_msg->state;
|
||||
|
||||
/* read as long as RX FIFO has frames in it */
|
||||
while ((readl(espi->mmio + SSPSR) & SSPSR_RNE)) {
|
||||
ep93xx_do_read(master);
|
||||
ep93xx_do_read(host);
|
||||
espi->fifo_level--;
|
||||
}
|
||||
|
||||
/* write as long as TX FIFO has room */
|
||||
while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < xfer->len) {
|
||||
ep93xx_do_write(master);
|
||||
ep93xx_do_write(host);
|
||||
espi->fifo_level++;
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ ep93xx_dma_data_to_trans_dir(enum dma_data_direction dir)
|
|||
|
||||
/**
|
||||
* ep93xx_spi_dma_prepare() - prepares a DMA transfer
|
||||
* @master: SPI master
|
||||
* @host: SPI host
|
||||
* @dir: DMA transfer direction
|
||||
*
|
||||
* Function configures the DMA, maps the buffer and prepares the DMA
|
||||
|
@ -269,11 +269,11 @@ ep93xx_dma_data_to_trans_dir(enum dma_data_direction dir)
|
|||
* in case of failure.
|
||||
*/
|
||||
static struct dma_async_tx_descriptor *
|
||||
ep93xx_spi_dma_prepare(struct spi_master *master,
|
||||
ep93xx_spi_dma_prepare(struct spi_controller *host,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_transfer *xfer = master->cur_msg->state;
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *xfer = host->cur_msg->state;
|
||||
struct dma_async_tx_descriptor *txd;
|
||||
enum dma_slave_buswidth buswidth;
|
||||
struct dma_slave_config conf;
|
||||
|
@ -348,7 +348,7 @@ ep93xx_spi_dma_prepare(struct spi_master *master,
|
|||
}
|
||||
|
||||
if (WARN_ON(len)) {
|
||||
dev_warn(&master->dev, "len = %zu expected 0!\n", len);
|
||||
dev_warn(&host->dev, "len = %zu expected 0!\n", len);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
|
@ -367,16 +367,16 @@ ep93xx_spi_dma_prepare(struct spi_master *master,
|
|||
|
||||
/**
|
||||
* ep93xx_spi_dma_finish() - finishes with a DMA transfer
|
||||
* @master: SPI master
|
||||
* @host: SPI host
|
||||
* @dir: DMA transfer direction
|
||||
*
|
||||
* Function finishes with the DMA transfer. After this, the DMA buffer is
|
||||
* unmapped.
|
||||
*/
|
||||
static void ep93xx_spi_dma_finish(struct spi_master *master,
|
||||
static void ep93xx_spi_dma_finish(struct spi_controller *host,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct dma_chan *chan;
|
||||
struct sg_table *sgt;
|
||||
|
||||
|
@ -393,35 +393,35 @@ static void ep93xx_spi_dma_finish(struct spi_master *master,
|
|||
|
||||
static void ep93xx_spi_dma_callback(void *callback_param)
|
||||
{
|
||||
struct spi_master *master = callback_param;
|
||||
struct spi_controller *host = callback_param;
|
||||
|
||||
ep93xx_spi_dma_finish(master, DMA_TO_DEVICE);
|
||||
ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE);
|
||||
ep93xx_spi_dma_finish(host, DMA_TO_DEVICE);
|
||||
ep93xx_spi_dma_finish(host, DMA_FROM_DEVICE);
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
}
|
||||
|
||||
static int ep93xx_spi_dma_transfer(struct spi_master *master)
|
||||
static int ep93xx_spi_dma_transfer(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
struct dma_async_tx_descriptor *rxd, *txd;
|
||||
|
||||
rxd = ep93xx_spi_dma_prepare(master, DMA_FROM_DEVICE);
|
||||
rxd = ep93xx_spi_dma_prepare(host, DMA_FROM_DEVICE);
|
||||
if (IS_ERR(rxd)) {
|
||||
dev_err(&master->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
|
||||
dev_err(&host->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
|
||||
return PTR_ERR(rxd);
|
||||
}
|
||||
|
||||
txd = ep93xx_spi_dma_prepare(master, DMA_TO_DEVICE);
|
||||
txd = ep93xx_spi_dma_prepare(host, DMA_TO_DEVICE);
|
||||
if (IS_ERR(txd)) {
|
||||
ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE);
|
||||
dev_err(&master->dev, "DMA TX failed: %ld\n", PTR_ERR(txd));
|
||||
ep93xx_spi_dma_finish(host, DMA_FROM_DEVICE);
|
||||
dev_err(&host->dev, "DMA TX failed: %ld\n", PTR_ERR(txd));
|
||||
return PTR_ERR(txd);
|
||||
}
|
||||
|
||||
/* We are ready when RX is done */
|
||||
rxd->callback = ep93xx_spi_dma_callback;
|
||||
rxd->callback_param = master;
|
||||
rxd->callback_param = host;
|
||||
|
||||
/* Now submit both descriptors and start DMA */
|
||||
dmaengine_submit(rxd);
|
||||
|
@ -436,8 +436,8 @@ static int ep93xx_spi_dma_transfer(struct spi_master *master)
|
|||
|
||||
static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = dev_id;
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
|
@ -447,15 +447,15 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
|
|||
if (readl(espi->mmio + SSPIIR) & SSPIIR_RORIS) {
|
||||
/* clear the overrun interrupt */
|
||||
writel(0, espi->mmio + SSPICR);
|
||||
dev_warn(&master->dev,
|
||||
dev_warn(&host->dev,
|
||||
"receive overrun, aborting the message\n");
|
||||
master->cur_msg->status = -EIO;
|
||||
host->cur_msg->status = -EIO;
|
||||
} else {
|
||||
/*
|
||||
* Interrupt is either RX (RIS) or TX (TIS). For both cases we
|
||||
* simply execute next data transfer.
|
||||
*/
|
||||
if (ep93xx_spi_read_write(master)) {
|
||||
if (ep93xx_spi_read_write(host)) {
|
||||
/*
|
||||
* In normal case, there still is some processing left
|
||||
* for current transfer. Let's wait for the next
|
||||
|
@ -474,26 +474,26 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
|
|||
val &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
|
||||
writel(val, espi->mmio + SSPCR1);
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ep93xx_spi_transfer_one(struct spi_master *master,
|
||||
static int ep93xx_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = ep93xx_spi_chip_setup(master, spi, xfer);
|
||||
ret = ep93xx_spi_chip_setup(host, spi, xfer);
|
||||
if (ret) {
|
||||
dev_err(&master->dev, "failed to setup chip for transfer\n");
|
||||
dev_err(&host->dev, "failed to setup chip for transfer\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
master->cur_msg->state = xfer;
|
||||
host->cur_msg->state = xfer;
|
||||
espi->rx = 0;
|
||||
espi->tx = 0;
|
||||
|
||||
|
@ -503,10 +503,10 @@ static int ep93xx_spi_transfer_one(struct spi_master *master,
|
|||
* So in these cases we will be using PIO and don't bother for DMA.
|
||||
*/
|
||||
if (espi->dma_rx && xfer->len > SPI_FIFO_SIZE)
|
||||
return ep93xx_spi_dma_transfer(master);
|
||||
return ep93xx_spi_dma_transfer(host);
|
||||
|
||||
/* Using PIO so prime the TX FIFO and enable interrupts */
|
||||
ep93xx_spi_read_write(master);
|
||||
ep93xx_spi_read_write(host);
|
||||
|
||||
val = readl(espi->mmio + SSPCR1);
|
||||
val |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
|
||||
|
@ -516,10 +516,10 @@ static int ep93xx_spi_transfer_one(struct spi_master *master,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ep93xx_spi_prepare_message(struct spi_master *master,
|
||||
static int ep93xx_spi_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
|
@ -528,7 +528,7 @@ static int ep93xx_spi_prepare_message(struct spi_master *master,
|
|||
timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT);
|
||||
while (readl(espi->mmio + SSPSR) & SSPSR_RNE) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_warn(&master->dev,
|
||||
dev_warn(&host->dev,
|
||||
"timeout while flushing RX FIFO\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -544,9 +544,9 @@ static int ep93xx_spi_prepare_message(struct spi_master *master,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ep93xx_spi_prepare_hardware(struct spi_master *master)
|
||||
static int ep93xx_spi_prepare_hardware(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
|
@ -561,9 +561,9 @@ static int ep93xx_spi_prepare_hardware(struct spi_master *master)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ep93xx_spi_unprepare_hardware(struct spi_master *master)
|
||||
static int ep93xx_spi_unprepare_hardware(struct spi_controller *host)
|
||||
{
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
u32 val;
|
||||
|
||||
val = readl(espi->mmio + SSPCR1);
|
||||
|
@ -646,7 +646,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
|
|||
|
||||
static int ep93xx_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct ep93xx_spi_info *info;
|
||||
struct ep93xx_spi *espi;
|
||||
struct resource *res;
|
||||
|
@ -661,63 +661,56 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return -EBUSY;
|
||||
return irq;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "unable to get iomem resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*espi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*espi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
master->use_gpio_descriptors = true;
|
||||
master->prepare_transfer_hardware = ep93xx_spi_prepare_hardware;
|
||||
master->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware;
|
||||
master->prepare_message = ep93xx_spi_prepare_message;
|
||||
master->transfer_one = ep93xx_spi_transfer_one;
|
||||
master->bus_num = pdev->id;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
host->use_gpio_descriptors = true;
|
||||
host->prepare_transfer_hardware = ep93xx_spi_prepare_hardware;
|
||||
host->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware;
|
||||
host->prepare_message = ep93xx_spi_prepare_message;
|
||||
host->transfer_one = ep93xx_spi_transfer_one;
|
||||
host->bus_num = pdev->id;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
/*
|
||||
* The SPI core will count the number of GPIO descriptors to figure
|
||||
* out the number of chip selects available on the platform.
|
||||
*/
|
||||
master->num_chipselect = 0;
|
||||
host->num_chipselect = 0;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
espi = spi_master_get_devdata(master);
|
||||
espi = spi_controller_get_devdata(host);
|
||||
|
||||
espi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(espi->clk)) {
|
||||
dev_err(&pdev->dev, "unable to get spi clock\n");
|
||||
error = PTR_ERR(espi->clk);
|
||||
goto fail_release_master;
|
||||
goto fail_release_host;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate maximum and minimum supported clock rates
|
||||
* for the controller.
|
||||
*/
|
||||
master->max_speed_hz = clk_get_rate(espi->clk) / 2;
|
||||
master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
|
||||
host->max_speed_hz = clk_get_rate(espi->clk) / 2;
|
||||
host->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
|
||||
|
||||
espi->sspdr_phys = res->start + SSPDR;
|
||||
|
||||
espi->mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||
espi->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(espi->mmio)) {
|
||||
error = PTR_ERR(espi->mmio);
|
||||
goto fail_release_master;
|
||||
goto fail_release_host;
|
||||
}
|
||||
espi->sspdr_phys = res->start + SSPDR;
|
||||
|
||||
error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
|
||||
0, "ep93xx-spi", master);
|
||||
0, "ep93xx-spi", host);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
goto fail_release_master;
|
||||
goto fail_release_host;
|
||||
}
|
||||
|
||||
if (info->use_dma && ep93xx_spi_setup_dma(espi))
|
||||
|
@ -726,9 +719,9 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
/* make sure that the hardware is disabled */
|
||||
writel(0, espi->mmio + SSPCR1);
|
||||
|
||||
error = devm_spi_register_master(&pdev->dev, master);
|
||||
error = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register SPI master\n");
|
||||
dev_err(&pdev->dev, "failed to register SPI host\n");
|
||||
goto fail_free_dma;
|
||||
}
|
||||
|
||||
|
@ -739,16 +732,16 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
|
|||
|
||||
fail_free_dma:
|
||||
ep93xx_spi_release_dma(espi);
|
||||
fail_release_master:
|
||||
spi_master_put(master);
|
||||
fail_release_host:
|
||||
spi_controller_put(host);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void ep93xx_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct ep93xx_spi *espi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
|
||||
|
||||
ep93xx_spi_release_dma(espi);
|
||||
}
|
||||
|
|
|
@ -91,14 +91,14 @@
|
|||
|
||||
struct falcon_sflash {
|
||||
u32 sfcmd; /* for caching of opcode, direction, ... */
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
};
|
||||
|
||||
int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct falcon_sflash *priv = spi_master_get_devdata(spi->master);
|
||||
struct falcon_sflash *priv = spi_controller_get_devdata(spi->controller);
|
||||
const u8 *txp = t->tx_buf;
|
||||
u8 *rxp = t->rx_buf;
|
||||
unsigned int bytelen = ((8 * t->len + 7) / 8);
|
||||
|
@ -351,10 +351,10 @@ static int falcon_sflash_setup(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int falcon_sflash_xfer_one(struct spi_master *master,
|
||||
static int falcon_sflash_xfer_one(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
struct falcon_sflash *priv = spi_master_get_devdata(master);
|
||||
struct falcon_sflash *priv = spi_controller_get_devdata(host);
|
||||
struct spi_transfer *t;
|
||||
unsigned long spi_flags;
|
||||
unsigned long flags;
|
||||
|
@ -382,7 +382,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
|
|||
}
|
||||
|
||||
m->status = ret;
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -390,25 +390,25 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
|
|||
static int falcon_sflash_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct falcon_sflash *priv;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*priv));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*priv));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
priv = spi_master_get_devdata(master);
|
||||
priv->master = master;
|
||||
priv = spi_controller_get_devdata(host);
|
||||
priv->host = host;
|
||||
|
||||
master->mode_bits = SPI_MODE_3;
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->setup = falcon_sflash_setup;
|
||||
master->transfer_one_message = falcon_sflash_xfer_one;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
host->mode_bits = SPI_MODE_3;
|
||||
host->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
host->setup = falcon_sflash_setup;
|
||||
host->transfer_one_message = falcon_sflash_xfer_one;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
ret = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (ret)
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -542,7 +542,7 @@ static int fsi_spi_probe(struct device *dev)
|
|||
if (of_property_read_u32(np, "reg", &base))
|
||||
continue;
|
||||
|
||||
ctlr = spi_alloc_master(dev, sizeof(*ctx));
|
||||
ctlr = spi_alloc_host(dev, sizeof(*ctx));
|
||||
if (!ctlr) {
|
||||
of_node_put(np);
|
||||
break;
|
||||
|
|
|
@ -56,12 +56,12 @@ void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
|
|||
QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
} else {
|
||||
if (mspi->flags & SPI_CPM1) {
|
||||
out_be32(&mspi->pram->rstate, 0);
|
||||
out_be16(&mspi->pram->rbptr,
|
||||
in_be16(&mspi->pram->rbase));
|
||||
out_be32(&mspi->pram->tstate, 0);
|
||||
out_be16(&mspi->pram->tbptr,
|
||||
in_be16(&mspi->pram->tbase));
|
||||
iowrite32be(0, &mspi->pram->rstate);
|
||||
iowrite16be(ioread16be(&mspi->pram->rbase),
|
||||
&mspi->pram->rbptr);
|
||||
iowrite32be(0, &mspi->pram->tstate);
|
||||
iowrite16be(ioread16be(&mspi->pram->tbase),
|
||||
&mspi->pram->tbptr);
|
||||
} else {
|
||||
cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
|
||||
}
|
||||
|
@ -75,24 +75,24 @@ static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
|
|||
struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
|
||||
unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
|
||||
unsigned int xfer_ofs;
|
||||
struct fsl_spi_reg *reg_base = mspi->reg_base;
|
||||
struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
|
||||
|
||||
xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
|
||||
|
||||
if (mspi->rx_dma == mspi->dma_dummy_rx)
|
||||
out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
|
||||
iowrite32be(mspi->rx_dma, &rx_bd->cbd_bufaddr);
|
||||
else
|
||||
out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
|
||||
out_be16(&rx_bd->cbd_datlen, 0);
|
||||
out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
|
||||
iowrite32be(mspi->rx_dma + xfer_ofs, &rx_bd->cbd_bufaddr);
|
||||
iowrite16be(0, &rx_bd->cbd_datlen);
|
||||
iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP, &rx_bd->cbd_sc);
|
||||
|
||||
if (mspi->tx_dma == mspi->dma_dummy_tx)
|
||||
out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
|
||||
iowrite32be(mspi->tx_dma, &tx_bd->cbd_bufaddr);
|
||||
else
|
||||
out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
|
||||
out_be16(&tx_bd->cbd_datlen, xfer_len);
|
||||
out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
|
||||
BD_SC_LAST);
|
||||
iowrite32be(mspi->tx_dma + xfer_ofs, &tx_bd->cbd_bufaddr);
|
||||
iowrite16be(xfer_len, &tx_bd->cbd_datlen);
|
||||
iowrite16be(BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST,
|
||||
&tx_bd->cbd_sc);
|
||||
|
||||
/* start transfer */
|
||||
mpc8xxx_spi_write_reg(®_base->command, SPCOM_STR);
|
||||
|
@ -102,7 +102,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
|
|||
struct spi_transfer *t, bool is_dma_mapped)
|
||||
{
|
||||
struct device *dev = mspi->dev;
|
||||
struct fsl_spi_reg *reg_base = mspi->reg_base;
|
||||
struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
|
||||
|
||||
if (is_dma_mapped) {
|
||||
mspi->map_tx_dma = 0;
|
||||
|
@ -123,7 +123,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
|
|||
}
|
||||
if (t->bits_per_word == 16 && t->tx_buf) {
|
||||
const u16 *src = t->tx_buf;
|
||||
u16 *dst;
|
||||
__le16 *dst;
|
||||
int i;
|
||||
|
||||
dst = kmalloc(t->len, GFP_KERNEL);
|
||||
|
@ -202,12 +202,12 @@ EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
|
|||
void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
|
||||
{
|
||||
u16 len;
|
||||
struct fsl_spi_reg *reg_base = mspi->reg_base;
|
||||
struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
|
||||
|
||||
dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
|
||||
in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
|
||||
ioread16be(&mspi->rx_bd->cbd_datlen), mspi->count);
|
||||
|
||||
len = in_be16(&mspi->rx_bd->cbd_datlen);
|
||||
len = ioread16be(&mspi->rx_bd->cbd_datlen);
|
||||
if (len > mspi->count) {
|
||||
WARN_ON(1);
|
||||
len = mspi->count;
|
||||
|
@ -328,7 +328,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
|||
}
|
||||
|
||||
if (mspi->flags & SPI_CPM1) {
|
||||
void *pram;
|
||||
void __iomem *pram;
|
||||
|
||||
pram = devm_platform_ioremap_resource(to_platform_device(dev),
|
||||
1);
|
||||
|
@ -374,21 +374,21 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
|
|||
mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
|
||||
|
||||
/* Initialize parameter ram. */
|
||||
out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
|
||||
out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
|
||||
out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
|
||||
out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
|
||||
out_be16(&mspi->pram->mrblr, SPI_MRBLR);
|
||||
out_be32(&mspi->pram->rstate, 0);
|
||||
out_be32(&mspi->pram->rdp, 0);
|
||||
out_be16(&mspi->pram->rbptr, 0);
|
||||
out_be16(&mspi->pram->rbc, 0);
|
||||
out_be32(&mspi->pram->rxtmp, 0);
|
||||
out_be32(&mspi->pram->tstate, 0);
|
||||
out_be32(&mspi->pram->tdp, 0);
|
||||
out_be16(&mspi->pram->tbptr, 0);
|
||||
out_be16(&mspi->pram->tbc, 0);
|
||||
out_be32(&mspi->pram->txtmp, 0);
|
||||
iowrite16be(cpm_muram_offset(mspi->tx_bd), &mspi->pram->tbase);
|
||||
iowrite16be(cpm_muram_offset(mspi->rx_bd), &mspi->pram->rbase);
|
||||
iowrite8(CPMFCR_EB | CPMFCR_GBL, &mspi->pram->tfcr);
|
||||
iowrite8(CPMFCR_EB | CPMFCR_GBL, &mspi->pram->rfcr);
|
||||
iowrite16be(SPI_MRBLR, &mspi->pram->mrblr);
|
||||
iowrite32be(0, &mspi->pram->rstate);
|
||||
iowrite32be(0, &mspi->pram->rdp);
|
||||
iowrite16be(0, &mspi->pram->rbptr);
|
||||
iowrite16be(0, &mspi->pram->rbc);
|
||||
iowrite32be(0, &mspi->pram->rxtmp);
|
||||
iowrite32be(0, &mspi->pram->tstate);
|
||||
iowrite32be(0, &mspi->pram->tdp);
|
||||
iowrite16be(0, &mspi->pram->tbptr);
|
||||
iowrite16be(0, &mspi->pram->tbc);
|
||||
iowrite32be(0, &mspi->pram->txtmp);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
@ -22,7 +23,7 @@
|
|||
#define DRIVER_NAME "fsl-dspi"
|
||||
|
||||
#define SPI_MCR 0x00
|
||||
#define SPI_MCR_MASTER BIT(31)
|
||||
#define SPI_MCR_HOST BIT(31)
|
||||
#define SPI_MCR_PCSIS(x) ((x) << 16)
|
||||
#define SPI_MCR_CLR_TXF BIT(11)
|
||||
#define SPI_MCR_CLR_RXF BIT(10)
|
||||
|
@ -339,7 +340,7 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
|
|||
{
|
||||
u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi);
|
||||
|
||||
if (spi_controller_is_slave(dspi->ctlr))
|
||||
if (spi_controller_is_target(dspi->ctlr))
|
||||
return data;
|
||||
|
||||
if (dspi->len > 0)
|
||||
|
@ -429,7 +430,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
|
|||
dma_async_issue_pending(dma->chan_rx);
|
||||
dma_async_issue_pending(dma->chan_tx);
|
||||
|
||||
if (spi_controller_is_slave(dspi->ctlr)) {
|
||||
if (spi_controller_is_target(dspi->ctlr)) {
|
||||
wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete);
|
||||
return 0;
|
||||
}
|
||||
|
@ -502,15 +503,14 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
|
|||
|
||||
dma->chan_rx = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(dma->chan_rx)) {
|
||||
dev_err(dev, "rx dma channel not available\n");
|
||||
ret = PTR_ERR(dma->chan_rx);
|
||||
return ret;
|
||||
return dev_err_probe(dev, PTR_ERR(dma->chan_rx),
|
||||
"rx dma channel not available\n");
|
||||
}
|
||||
|
||||
dma->chan_tx = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(dma->chan_tx)) {
|
||||
dev_err(dev, "tx dma channel not available\n");
|
||||
ret = PTR_ERR(dma->chan_tx);
|
||||
dev_err_probe(dev, ret, "tx dma channel not available\n");
|
||||
goto err_tx_channel;
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1061,7 @@ static int dspi_setup(struct spi_device *spi)
|
|||
if (spi->mode & SPI_CPHA)
|
||||
chip->ctar_val |= SPI_CTAR_CPHA;
|
||||
|
||||
if (!spi_controller_is_slave(dspi->ctlr)) {
|
||||
if (!spi_controller_is_target(dspi->ctlr)) {
|
||||
chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) |
|
||||
SPI_CTAR_CSSCK(cssck) |
|
||||
SPI_CTAR_PASC(pasc) |
|
||||
|
@ -1216,8 +1216,8 @@ static int dspi_init(struct fsl_dspi *dspi)
|
|||
|
||||
if (dspi->devtype_data->trans_mode == DSPI_XSPI_MODE)
|
||||
mcr |= SPI_MCR_XSPI;
|
||||
if (!spi_controller_is_slave(dspi->ctlr))
|
||||
mcr |= SPI_MCR_MASTER;
|
||||
if (!spi_controller_is_target(dspi->ctlr))
|
||||
mcr |= SPI_MCR_HOST;
|
||||
|
||||
regmap_write(dspi->regmap, SPI_MCR, mcr);
|
||||
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
|
||||
|
@ -1240,13 +1240,13 @@ static int dspi_init(struct fsl_dspi *dspi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dspi_slave_abort(struct spi_master *master)
|
||||
static int dspi_target_abort(struct spi_controller *host)
|
||||
{
|
||||
struct fsl_dspi *dspi = spi_master_get_devdata(master);
|
||||
struct fsl_dspi *dspi = spi_controller_get_devdata(host);
|
||||
|
||||
/*
|
||||
* Terminate all pending DMA transactions for the SPI working
|
||||
* in SLAVE mode.
|
||||
* in TARGET mode.
|
||||
*/
|
||||
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
|
||||
dmaengine_terminate_sync(dspi->dma->chan_rx);
|
||||
|
@ -1277,7 +1277,7 @@ static int dspi_probe(struct platform_device *pdev)
|
|||
if (!dspi)
|
||||
return -ENOMEM;
|
||||
|
||||
ctlr = spi_alloc_master(&pdev->dev, 0);
|
||||
ctlr = spi_alloc_host(&pdev->dev, 0);
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1292,7 +1292,7 @@ static int dspi_probe(struct platform_device *pdev)
|
|||
ctlr->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
ctlr->cleanup = dspi_cleanup;
|
||||
ctlr->slave_abort = dspi_slave_abort;
|
||||
ctlr->target_abort = dspi_target_abort;
|
||||
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
|
||||
ctlr->use_gpio_descriptors = true;
|
||||
|
||||
|
@ -1317,7 +1317,7 @@ static int dspi_probe(struct platform_device *pdev)
|
|||
ctlr->bus_num = bus_num;
|
||||
|
||||
if (of_property_read_bool(np, "spi-slave"))
|
||||
ctlr->slave = true;
|
||||
ctlr->target = true;
|
||||
|
||||
dspi->devtype_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!dspi->devtype_data) {
|
||||
|
|
|
@ -148,7 +148,7 @@ static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
|
|||
|
||||
static int fsl_espi_check_message(struct spi_message *m)
|
||||
{
|
||||
struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(m->spi->controller);
|
||||
struct spi_transfer *t, *first;
|
||||
|
||||
if (m->frame_length > SPCOM_TRANLEN_MAX) {
|
||||
|
@ -323,7 +323,7 @@ start:
|
|||
static void fsl_espi_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct fsl_espi *espi = spi_master_get_devdata(spi->master);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(spi->controller);
|
||||
int bits_per_word = t ? t->bits_per_word : spi->bits_per_word;
|
||||
u32 pm, hz = t ? t->speed_hz : spi->max_speed_hz;
|
||||
struct fsl_espi_cs *cs = spi_get_ctldata(spi);
|
||||
|
@ -351,7 +351,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi,
|
|||
|
||||
static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct fsl_espi *espi = spi_master_get_devdata(spi->master);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int rx_len = t->len;
|
||||
u32 mask, spcom;
|
||||
int ret;
|
||||
|
@ -396,7 +396,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
|
|||
|
||||
static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
|
||||
{
|
||||
struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(m->spi->controller);
|
||||
struct spi_device *spi = m->spi;
|
||||
int ret;
|
||||
|
||||
|
@ -432,7 +432,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int fsl_espi_do_one_msg(struct spi_master *master,
|
||||
static int fsl_espi_do_one_msg(struct spi_controller *host,
|
||||
struct spi_message *m)
|
||||
{
|
||||
unsigned int rx_nbits = 0, delay_nsecs = 0;
|
||||
|
@ -470,7 +470,7 @@ out:
|
|||
if (m->status == -EINPROGRESS)
|
||||
m->status = ret;
|
||||
|
||||
spi_finalize_current_message(master);
|
||||
spi_finalize_current_message(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -488,7 +488,7 @@ static int fsl_espi_setup(struct spi_device *spi)
|
|||
spi_set_ctldata(spi, cs);
|
||||
}
|
||||
|
||||
espi = spi_master_get_devdata(spi->master);
|
||||
espi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
pm_runtime_get_sync(espi->dev);
|
||||
|
||||
|
@ -584,8 +584,8 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
|
|||
#ifdef CONFIG_PM
|
||||
static int fsl_espi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(host);
|
||||
u32 regval;
|
||||
|
||||
regval = fsl_espi_read_reg(espi, ESPI_SPMODE);
|
||||
|
@ -597,8 +597,8 @@ static int fsl_espi_runtime_suspend(struct device *dev)
|
|||
|
||||
static int fsl_espi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(host);
|
||||
u32 regval;
|
||||
|
||||
regval = fsl_espi_read_reg(espi, ESPI_SPMODE);
|
||||
|
@ -616,8 +616,8 @@ static size_t fsl_espi_max_message_size(struct spi_device *spi)
|
|||
|
||||
static void fsl_espi_init_regs(struct device *dev, bool initial)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct fsl_espi *espi = spi_controller_get_devdata(host);
|
||||
struct device_node *nc;
|
||||
u32 csmode, cs, prop;
|
||||
int ret;
|
||||
|
@ -629,10 +629,10 @@ static void fsl_espi_init_regs(struct device *dev, bool initial)
|
|||
fsl_espi_write_reg(espi, ESPI_SPIE, 0xffffffff);
|
||||
|
||||
/* Init eSPI CS mode register */
|
||||
for_each_available_child_of_node(master->dev.of_node, nc) {
|
||||
for_each_available_child_of_node(host->dev.of_node, nc) {
|
||||
/* get chip select */
|
||||
ret = of_property_read_u32(nc, "reg", &cs);
|
||||
if (ret || cs >= master->num_chipselect)
|
||||
if (ret || cs >= host->num_chipselect)
|
||||
continue;
|
||||
|
||||
csmode = CSMODE_INIT_VAL;
|
||||
|
@ -664,28 +664,28 @@ static void fsl_espi_init_regs(struct device *dev, bool initial)
|
|||
static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
||||
unsigned int irq, unsigned int num_cs)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct fsl_espi *espi;
|
||||
int ret;
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(struct fsl_espi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(dev, sizeof(struct fsl_espi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, master);
|
||||
dev_set_drvdata(dev, host);
|
||||
|
||||
master->mode_bits = SPI_RX_DUAL | SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
SPI_LSB_FIRST | SPI_LOOP;
|
||||
master->dev.of_node = dev->of_node;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
master->setup = fsl_espi_setup;
|
||||
master->cleanup = fsl_espi_cleanup;
|
||||
master->transfer_one_message = fsl_espi_do_one_msg;
|
||||
master->auto_runtime_pm = true;
|
||||
master->max_message_size = fsl_espi_max_message_size;
|
||||
master->num_chipselect = num_cs;
|
||||
host->mode_bits = SPI_RX_DUAL | SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
|
||||
SPI_LSB_FIRST | SPI_LOOP;
|
||||
host->dev.of_node = dev->of_node;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
|
||||
host->setup = fsl_espi_setup;
|
||||
host->cleanup = fsl_espi_cleanup;
|
||||
host->transfer_one_message = fsl_espi_do_one_msg;
|
||||
host->auto_runtime_pm = true;
|
||||
host->max_message_size = fsl_espi_max_message_size;
|
||||
host->num_chipselect = num_cs;
|
||||
|
||||
espi = spi_master_get_devdata(master);
|
||||
espi = spi_controller_get_devdata(host);
|
||||
spin_lock_init(&espi->lock);
|
||||
|
||||
espi->dev = dev;
|
||||
|
@ -696,8 +696,8 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
goto err_probe;
|
||||
}
|
||||
/* determined by clock divider fields DIV16/PM in register SPMODEx */
|
||||
master->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16);
|
||||
master->max_speed_hz = DIV_ROUND_UP(espi->spibrg, 4);
|
||||
host->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16);
|
||||
host->max_speed_hz = DIV_ROUND_UP(espi->spibrg, 4);
|
||||
|
||||
init_completion(&espi->done);
|
||||
|
||||
|
@ -720,7 +720,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
|
|||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret < 0)
|
||||
goto err_pm;
|
||||
|
||||
|
@ -736,7 +736,7 @@ err_pm:
|
|||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
err_probe:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -791,10 +791,10 @@ static void of_fsl_espi_remove(struct platform_device *dev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int of_fsl_espi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(master);
|
||||
ret = spi_controller_suspend(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -803,7 +803,7 @@ static int of_fsl_espi_suspend(struct device *dev)
|
|||
|
||||
static int of_fsl_espi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
fsl_espi_init_regs(dev, false);
|
||||
|
@ -812,7 +812,7 @@ static int of_fsl_espi_resume(struct device *dev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return spi_master_resume(master);
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#ifdef CONFIG_FSL_SOC
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
|
|
@ -103,12 +103,9 @@ extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
|
|||
|
||||
extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
|
||||
struct fsl_spi_platform_data *pdata);
|
||||
extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
|
||||
struct spi_transfer *t, unsigned int len);
|
||||
extern const char *mpc8xxx_spi_strmode(unsigned int flags);
|
||||
extern void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
|
||||
unsigned int irq);
|
||||
extern int mpc8xxx_spi_remove(struct device *dev);
|
||||
extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
|
||||
|
||||
#endif /* __SPI_FSL_LIB_H__ */
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma/imx-dma.h>
|
||||
|
@ -73,7 +72,7 @@
|
|||
#define CFGR1_PINCFG (BIT(24)|BIT(25))
|
||||
#define CFGR1_PCSPOL BIT(8)
|
||||
#define CFGR1_NOSTALL BIT(3)
|
||||
#define CFGR1_MASTER BIT(0)
|
||||
#define CFGR1_HOST BIT(0)
|
||||
#define FSR_TXCOUNT (0xFF)
|
||||
#define RSR_RXEMPTY BIT(1)
|
||||
#define TCR_CPOL BIT(31)
|
||||
|
@ -97,8 +96,7 @@ struct fsl_lpspi_data {
|
|||
unsigned long base_phys;
|
||||
struct clk *clk_ipg;
|
||||
struct clk *clk_per;
|
||||
bool is_slave;
|
||||
u32 num_cs;
|
||||
bool is_target;
|
||||
bool is_only_cs1;
|
||||
bool is_first_byte;
|
||||
|
||||
|
@ -115,7 +113,7 @@ struct fsl_lpspi_data {
|
|||
struct lpspi_config config;
|
||||
struct completion xfer_done;
|
||||
|
||||
bool slave_aborted;
|
||||
bool target_aborted;
|
||||
|
||||
/* DMA */
|
||||
bool usedma;
|
||||
|
@ -236,7 +234,7 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
|
|||
}
|
||||
|
||||
if (txfifo_cnt < fsl_lpspi->txfifosize) {
|
||||
if (!fsl_lpspi->is_slave) {
|
||||
if (!fsl_lpspi->is_target) {
|
||||
temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
|
||||
temp &= ~TCR_CONTC;
|
||||
writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
|
||||
|
@ -260,7 +258,7 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi)
|
|||
temp |= fsl_lpspi->config.bpw - 1;
|
||||
temp |= (fsl_lpspi->config.mode & 0x3) << 30;
|
||||
temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
|
||||
if (!fsl_lpspi->is_slave) {
|
||||
if (!fsl_lpspi->is_target) {
|
||||
temp |= fsl_lpspi->config.prescale << 27;
|
||||
/*
|
||||
* Set TCR_CONT will keep SS asserted after current transfer.
|
||||
|
@ -387,7 +385,7 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
|
|||
u32 temp;
|
||||
int ret;
|
||||
|
||||
if (!fsl_lpspi->is_slave) {
|
||||
if (!fsl_lpspi->is_target) {
|
||||
ret = fsl_lpspi_set_bitrate(fsl_lpspi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -395,8 +393,8 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
|
|||
|
||||
fsl_lpspi_set_watermark(fsl_lpspi);
|
||||
|
||||
if (!fsl_lpspi->is_slave)
|
||||
temp = CFGR1_MASTER;
|
||||
if (!fsl_lpspi->is_target)
|
||||
temp = CFGR1_HOST;
|
||||
else
|
||||
temp = CFGR1_PINCFG;
|
||||
if (fsl_lpspi->config.mode & SPI_CS_HIGH)
|
||||
|
@ -463,12 +461,12 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller,
|
|||
return fsl_lpspi_config(fsl_lpspi);
|
||||
}
|
||||
|
||||
static int fsl_lpspi_slave_abort(struct spi_controller *controller)
|
||||
static int fsl_lpspi_target_abort(struct spi_controller *controller)
|
||||
{
|
||||
struct fsl_lpspi_data *fsl_lpspi =
|
||||
spi_controller_get_devdata(controller);
|
||||
|
||||
fsl_lpspi->slave_aborted = true;
|
||||
fsl_lpspi->target_aborted = true;
|
||||
if (!fsl_lpspi->usedma)
|
||||
complete(&fsl_lpspi->xfer_done);
|
||||
else {
|
||||
|
@ -484,9 +482,9 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller)
|
|||
struct fsl_lpspi_data *fsl_lpspi =
|
||||
spi_controller_get_devdata(controller);
|
||||
|
||||
if (fsl_lpspi->is_slave) {
|
||||
if (fsl_lpspi->is_target) {
|
||||
if (wait_for_completion_interruptible(&fsl_lpspi->xfer_done) ||
|
||||
fsl_lpspi->slave_aborted) {
|
||||
fsl_lpspi->target_aborted) {
|
||||
dev_dbg(fsl_lpspi->dev, "interrupted\n");
|
||||
return -EINTR;
|
||||
}
|
||||
|
@ -589,9 +587,9 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
reinit_completion(&fsl_lpspi->dma_tx_completion);
|
||||
dma_async_issue_pending(controller->dma_tx);
|
||||
|
||||
fsl_lpspi->slave_aborted = false;
|
||||
fsl_lpspi->target_aborted = false;
|
||||
|
||||
if (!fsl_lpspi->is_slave) {
|
||||
if (!fsl_lpspi->is_target) {
|
||||
transfer_timeout = fsl_lpspi_calculate_timeout(fsl_lpspi,
|
||||
transfer->len);
|
||||
|
||||
|
@ -617,7 +615,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
}
|
||||
} else {
|
||||
if (wait_for_completion_interruptible(&fsl_lpspi->dma_tx_completion) ||
|
||||
fsl_lpspi->slave_aborted) {
|
||||
fsl_lpspi->target_aborted) {
|
||||
dev_dbg(fsl_lpspi->dev,
|
||||
"I/O Error in DMA TX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
|
@ -627,7 +625,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
|
|||
}
|
||||
|
||||
if (wait_for_completion_interruptible(&fsl_lpspi->dma_rx_completion) ||
|
||||
fsl_lpspi->slave_aborted) {
|
||||
fsl_lpspi->target_aborted) {
|
||||
dev_dbg(fsl_lpspi->dev,
|
||||
"I/O Error in DMA RX interrupted\n");
|
||||
dmaengine_terminate_all(controller->dma_tx);
|
||||
|
@ -702,7 +700,7 @@ static int fsl_lpspi_pio_transfer(struct spi_controller *controller,
|
|||
fsl_lpspi->remain = t->len;
|
||||
|
||||
reinit_completion(&fsl_lpspi->xfer_done);
|
||||
fsl_lpspi->slave_aborted = false;
|
||||
fsl_lpspi->target_aborted = false;
|
||||
|
||||
fsl_lpspi_write_tx_fifo(fsl_lpspi);
|
||||
|
||||
|
@ -826,16 +824,17 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|||
struct spi_controller *controller;
|
||||
struct resource *res;
|
||||
int ret, irq;
|
||||
u32 num_cs;
|
||||
u32 temp;
|
||||
bool is_slave;
|
||||
bool is_target;
|
||||
|
||||
is_slave = of_property_read_bool((&pdev->dev)->of_node, "spi-slave");
|
||||
if (is_slave)
|
||||
controller = spi_alloc_slave(&pdev->dev,
|
||||
sizeof(struct fsl_lpspi_data));
|
||||
is_target = of_property_read_bool((&pdev->dev)->of_node, "spi-slave");
|
||||
if (is_target)
|
||||
controller = spi_alloc_target(&pdev->dev,
|
||||
sizeof(struct fsl_lpspi_data));
|
||||
else
|
||||
controller = spi_alloc_master(&pdev->dev,
|
||||
sizeof(struct fsl_lpspi_data));
|
||||
controller = spi_alloc_host(&pdev->dev,
|
||||
sizeof(struct fsl_lpspi_data));
|
||||
|
||||
if (!controller)
|
||||
return -ENOMEM;
|
||||
|
@ -844,25 +843,9 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|||
|
||||
fsl_lpspi = spi_controller_get_devdata(controller);
|
||||
fsl_lpspi->dev = &pdev->dev;
|
||||
fsl_lpspi->is_slave = is_slave;
|
||||
fsl_lpspi->is_target = is_target;
|
||||
fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node,
|
||||
"fsl,spi-only-use-cs1-sel");
|
||||
if (of_property_read_u32((&pdev->dev)->of_node, "num-cs",
|
||||
&fsl_lpspi->num_cs))
|
||||
fsl_lpspi->num_cs = 1;
|
||||
|
||||
controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
|
||||
controller->transfer_one = fsl_lpspi_transfer_one;
|
||||
controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
|
||||
controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware;
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
|
||||
controller->dev.of_node = pdev->dev.of_node;
|
||||
controller->bus_num = pdev->id;
|
||||
controller->num_chipselect = fsl_lpspi->num_cs;
|
||||
controller->slave_abort = fsl_lpspi_slave_abort;
|
||||
if (!fsl_lpspi->is_slave)
|
||||
controller->use_gpio_descriptors = true;
|
||||
|
||||
init_completion(&fsl_lpspi->xfer_done);
|
||||
|
||||
|
@ -912,6 +895,26 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|||
temp = readl(fsl_lpspi->base + IMX7ULP_PARAM);
|
||||
fsl_lpspi->txfifosize = 1 << (temp & 0x0f);
|
||||
fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f);
|
||||
if (of_property_read_u32((&pdev->dev)->of_node, "num-cs",
|
||||
&num_cs)) {
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx93-spi"))
|
||||
num_cs = ((temp >> 16) & 0xf);
|
||||
else
|
||||
num_cs = 1;
|
||||
}
|
||||
|
||||
controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
|
||||
controller->transfer_one = fsl_lpspi_transfer_one;
|
||||
controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
|
||||
controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware;
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
|
||||
controller->dev.of_node = pdev->dev.of_node;
|
||||
controller->bus_num = pdev->id;
|
||||
controller->num_chipselect = num_cs;
|
||||
controller->target_abort = fsl_lpspi_target_abort;
|
||||
if (!fsl_lpspi->is_target)
|
||||
controller->use_gpio_descriptors = true;
|
||||
|
||||
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/sizes.h>
|
||||
|
@ -368,7 +367,7 @@ static int fsl_qspi_check_buswidth(struct fsl_qspi *q, u8 width)
|
|||
static bool fsl_qspi_supports_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller);
|
||||
int ret;
|
||||
|
||||
ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth);
|
||||
|
@ -641,7 +640,7 @@ static int fsl_qspi_readl_poll_tout(struct fsl_qspi *q, void __iomem *base,
|
|||
|
||||
static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller);
|
||||
void __iomem *base = q->iobase;
|
||||
u32 addr_offset = 0;
|
||||
int err = 0;
|
||||
|
@ -703,7 +702,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
|
||||
static int fsl_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
|
||||
{
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_OUT) {
|
||||
if (op->data.nbytes > q->devtype_data->txfifo)
|
||||
|
@ -809,7 +808,7 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
|
|||
|
||||
static const char *fsl_qspi_get_name(struct spi_mem *mem)
|
||||
{
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master);
|
||||
struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct device *dev = &mem->spi->dev;
|
||||
const char *name;
|
||||
|
||||
|
@ -849,7 +848,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
|
|||
struct fsl_qspi *q;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_master(&pdev->dev, sizeof(*q));
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*q));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static int fsl_spi_get_type(struct device *dev)
|
|||
|
||||
static void fsl_spi_change_mode(struct spi_device *spi)
|
||||
{
|
||||
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
|
||||
struct mpc8xxx_spi *mspi = spi_controller_get_devdata(spi->controller);
|
||||
struct spi_mpc8xxx_cs *cs = spi->controller_state;
|
||||
struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
|
||||
__be32 __iomem *mode = ®_base->mode;
|
||||
|
@ -183,7 +183,7 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
|
|||
u32 hz = 0;
|
||||
struct spi_mpc8xxx_cs *cs = spi->controller_state;
|
||||
|
||||
mpc8xxx_spi = spi_master_get_devdata(spi->master);
|
||||
mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (t) {
|
||||
bits_per_word = t->bits_per_word;
|
||||
|
@ -252,7 +252,7 @@ static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
|
|||
static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
|
||||
bool is_dma_mapped)
|
||||
{
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
|
||||
struct fsl_spi_reg __iomem *reg_base;
|
||||
unsigned int len = t->len;
|
||||
u8 bits_per_word;
|
||||
|
@ -385,7 +385,7 @@ static int fsl_spi_setup(struct spi_device *spi)
|
|||
spi_set_ctldata(spi, cs);
|
||||
initial_setup = true;
|
||||
}
|
||||
mpc8xxx_spi = spi_master_get_devdata(spi->master);
|
||||
mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
reg_base = mpc8xxx_spi->reg_base;
|
||||
|
||||
|
@ -479,7 +479,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
|
|||
|
||||
static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
|
||||
{
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller);
|
||||
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
|
||||
u32 slvsel;
|
||||
u16 cs = spi_get_chipselect(spi, 0);
|
||||
|
@ -493,8 +493,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
|
|||
|
||||
static void fsl_spi_grlib_probe(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
|
||||
int mbits;
|
||||
u32 capabilities;
|
||||
|
@ -511,8 +511,8 @@ static void fsl_spi_grlib_probe(struct device *dev)
|
|||
mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities);
|
||||
mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff);
|
||||
}
|
||||
master->num_chipselect = mpc8xxx_spi->native_chipselects;
|
||||
master->set_cs = fsl_spi_grlib_cs_control;
|
||||
host->num_chipselect = mpc8xxx_spi->native_chipselects;
|
||||
host->set_cs = fsl_spi_grlib_cs_control;
|
||||
}
|
||||
|
||||
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
|
||||
|
@ -526,35 +526,35 @@ static void fsl_spi_cs_control(struct spi_device *spi, bool on)
|
|||
iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
|
||||
}
|
||||
|
||||
static struct spi_master *fsl_spi_probe(struct device *dev,
|
||||
static struct spi_controller *fsl_spi_probe(struct device *dev,
|
||||
struct resource *mem, unsigned int irq)
|
||||
{
|
||||
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct mpc8xxx_spi *mpc8xxx_spi;
|
||||
struct fsl_spi_reg __iomem *reg_base;
|
||||
u32 regval;
|
||||
int ret = 0;
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
|
||||
if (master == NULL) {
|
||||
host = spi_alloc_host(dev, sizeof(struct mpc8xxx_spi));
|
||||
if (host == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, master);
|
||||
dev_set_drvdata(dev, host);
|
||||
|
||||
mpc8xxx_spi_probe(dev, mem, irq);
|
||||
|
||||
master->setup = fsl_spi_setup;
|
||||
master->cleanup = fsl_spi_cleanup;
|
||||
master->prepare_message = fsl_spi_prepare_message;
|
||||
master->transfer_one = fsl_spi_transfer_one;
|
||||
master->unprepare_message = fsl_spi_unprepare_message;
|
||||
master->use_gpio_descriptors = true;
|
||||
master->set_cs = fsl_spi_cs_control;
|
||||
host->setup = fsl_spi_setup;
|
||||
host->cleanup = fsl_spi_cleanup;
|
||||
host->prepare_message = fsl_spi_prepare_message;
|
||||
host->transfer_one = fsl_spi_transfer_one;
|
||||
host->unprepare_message = fsl_spi_unprepare_message;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->set_cs = fsl_spi_cs_control;
|
||||
|
||||
mpc8xxx_spi = spi_master_get_devdata(master);
|
||||
mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
mpc8xxx_spi->max_bits_per_word = 32;
|
||||
mpc8xxx_spi->type = fsl_spi_get_type(dev);
|
||||
|
||||
|
@ -572,13 +572,13 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
|
|||
fsl_spi_grlib_probe(dev);
|
||||
|
||||
if (mpc8xxx_spi->flags & SPI_CPM_MODE)
|
||||
master->bits_per_word_mask =
|
||||
host->bits_per_word_mask =
|
||||
(SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32));
|
||||
else
|
||||
master->bits_per_word_mask =
|
||||
host->bits_per_word_mask =
|
||||
(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32));
|
||||
|
||||
master->bits_per_word_mask &=
|
||||
host->bits_per_word_mask &=
|
||||
SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
|
||||
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
|
||||
|
@ -615,19 +615,19 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
|
|||
|
||||
mpc8xxx_spi_write_reg(®_base->mode, regval);
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret < 0)
|
||||
goto err_probe;
|
||||
|
||||
dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
|
||||
mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
|
||||
|
||||
return master;
|
||||
return host;
|
||||
|
||||
err_probe:
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
err_cpm_init:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
err:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -636,7 +636,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
|
|||
{
|
||||
struct device *dev = &ofdev->dev;
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource mem;
|
||||
int irq, type;
|
||||
int ret;
|
||||
|
@ -689,9 +689,9 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
|
|||
goto unmap_out;
|
||||
}
|
||||
|
||||
master = fsl_spi_probe(dev, &mem, irq);
|
||||
host = fsl_spi_probe(dev, &mem, irq);
|
||||
|
||||
return PTR_ERR_OR_ZERO(master);
|
||||
return PTR_ERR_OR_ZERO(host);
|
||||
|
||||
unmap_out:
|
||||
#if IS_ENABLED(CONFIG_FSL_SOC)
|
||||
|
@ -703,8 +703,8 @@ unmap_out:
|
|||
|
||||
static void of_fsl_spi_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(ofdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(ofdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
}
|
||||
|
@ -730,7 +730,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
|
||||
if (!dev_get_platdata(&pdev->dev))
|
||||
return -EINVAL;
|
||||
|
@ -740,17 +740,17 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0)
|
||||
return -EINVAL;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
master = fsl_spi_probe(&pdev->dev, mem, irq);
|
||||
return PTR_ERR_OR_ZERO(master);
|
||||
host = fsl_spi_probe(&pdev->dev, mem, irq);
|
||||
return PTR_ERR_OR_ZERO(host);
|
||||
}
|
||||
|
||||
static void plat_mpc8xxx_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host);
|
||||
|
||||
fsl_spi_cpm_free(mpc8xxx_spi);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/soc/qcom/geni-se.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -52,6 +53,9 @@
|
|||
#define SPI_CS_CLK_DELAY_MSK GENMASK(19, 10)
|
||||
#define SPI_CS_CLK_DELAY_SHFT 10
|
||||
|
||||
#define SE_SPI_SLAVE_EN (0x2BC)
|
||||
#define SPI_SLAVE_EN BIT(0)
|
||||
|
||||
/* M_CMD OP codes for SPI */
|
||||
#define SPI_TX_ONLY 1
|
||||
#define SPI_RX_ONLY 2
|
||||
|
@ -99,6 +103,16 @@ struct spi_geni_master {
|
|||
int cur_xfer_mode;
|
||||
};
|
||||
|
||||
static void spi_slv_setup(struct spi_geni_master *mas)
|
||||
{
|
||||
struct geni_se *se = &mas->se;
|
||||
|
||||
writel(SPI_SLAVE_EN, se->base + SE_SPI_SLAVE_EN);
|
||||
writel(GENI_IO_MUX_0_EN, se->base + GENI_OUTPUT_CTRL);
|
||||
writel(START_TRIGGER, se->base + SE_GENI_CFG_SEQ_START);
|
||||
dev_dbg(mas->dev, "spi slave setup done\n");
|
||||
}
|
||||
|
||||
static int get_spi_clk_cfg(unsigned int speed_hz,
|
||||
struct spi_geni_master *mas,
|
||||
unsigned int *clk_idx,
|
||||
|
@ -140,12 +154,22 @@ static void handle_se_timeout(struct spi_master *spi,
|
|||
const struct spi_transfer *xfer;
|
||||
|
||||
spin_lock_irq(&mas->lock);
|
||||
reinit_completion(&mas->cancel_done);
|
||||
if (mas->cur_xfer_mode == GENI_SE_FIFO)
|
||||
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
|
||||
|
||||
xfer = mas->cur_xfer;
|
||||
mas->cur_xfer = NULL;
|
||||
|
||||
if (spi->slave) {
|
||||
/*
|
||||
* skip CMD Cancel sequnece since spi slave
|
||||
* doesn`t support CMD Cancel sequnece
|
||||
*/
|
||||
spin_unlock_irq(&mas->lock);
|
||||
goto unmap_if_dma;
|
||||
}
|
||||
|
||||
reinit_completion(&mas->cancel_done);
|
||||
geni_se_cancel_m_cmd(se);
|
||||
spin_unlock_irq(&mas->lock);
|
||||
|
||||
|
@ -542,6 +566,10 @@ static bool geni_can_dma(struct spi_controller *ctlr,
|
|||
if (mas->cur_xfer_mode == GENI_GPI_DMA)
|
||||
return true;
|
||||
|
||||
/* Set SE DMA mode for SPI slave. */
|
||||
if (ctlr->slave)
|
||||
return true;
|
||||
|
||||
len = get_xfer_len_in_words(xfer, mas);
|
||||
fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
|
||||
|
||||
|
@ -619,6 +647,7 @@ static void spi_geni_release_dma_chan(struct spi_geni_master *mas)
|
|||
|
||||
static int spi_geni_init(struct spi_geni_master *mas)
|
||||
{
|
||||
struct spi_master *spi = dev_get_drvdata(mas->dev);
|
||||
struct geni_se *se = &mas->se;
|
||||
unsigned int proto, major, minor, ver;
|
||||
u32 spi_tx_cfg, fifo_disable;
|
||||
|
@ -627,7 +656,14 @@ static int spi_geni_init(struct spi_geni_master *mas)
|
|||
pm_runtime_get_sync(mas->dev);
|
||||
|
||||
proto = geni_se_read_proto(se);
|
||||
if (proto != GENI_SE_SPI) {
|
||||
|
||||
if (spi->slave) {
|
||||
if (proto != GENI_SE_SPI_SLAVE) {
|
||||
dev_err(mas->dev, "Invalid proto %d\n", proto);
|
||||
goto out_pm;
|
||||
}
|
||||
spi_slv_setup(mas);
|
||||
} else if (proto != GENI_SE_SPI) {
|
||||
dev_err(mas->dev, "Invalid proto %d\n", proto);
|
||||
goto out_pm;
|
||||
}
|
||||
|
@ -679,9 +715,11 @@ static int spi_geni_init(struct spi_geni_master *mas)
|
|||
}
|
||||
|
||||
/* We always control CS manually */
|
||||
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
|
||||
spi_tx_cfg &= ~CS_TOGGLE;
|
||||
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
|
||||
if (!spi->slave) {
|
||||
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
|
||||
spi_tx_cfg &= ~CS_TOGGLE;
|
||||
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
|
||||
}
|
||||
|
||||
out_pm:
|
||||
pm_runtime_put(mas->dev);
|
||||
|
@ -1074,6 +1112,9 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
if (device_property_read_bool(&pdev->dev, "spi-slave"))
|
||||
spi->slave = true;
|
||||
|
||||
ret = geni_icc_get(&mas->se, NULL);
|
||||
if (ret)
|
||||
goto spi_geni_probe_runtime_disable;
|
||||
|
@ -1094,7 +1135,7 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
* for dma (gsi) mode, the gsi will set cs based on params passed in
|
||||
* TRE
|
||||
*/
|
||||
if (mas->cur_xfer_mode == GENI_SE_FIFO)
|
||||
if (!spi->slave && mas->cur_xfer_mode == GENI_SE_FIFO)
|
||||
spi->set_cs = spi_geni_set_cs;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* SPI master driver using generic bitbanged GPIO
|
||||
* SPI host driver using generic bitbanged GPIO
|
||||
*
|
||||
* Copyright (C) 2006,2008 David Brownell
|
||||
* Copyright (C) 2017 Linus Walleij
|
||||
|
@ -10,7 +10,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
@ -18,7 +17,7 @@
|
|||
|
||||
|
||||
/*
|
||||
* This bitbanging SPI master driver should help make systems usable
|
||||
* This bitbanging SPI host driver should help make systems usable
|
||||
* when a native hardware SPI engine is not available, perhaps because
|
||||
* its driver isn't yet working or because the I/O pins it requires
|
||||
* are used for other purposes.
|
||||
|
@ -27,7 +26,7 @@
|
|||
*
|
||||
* spi->controller_state ... reserved for bitbang framework code
|
||||
*
|
||||
* spi->master->dev.driver_data ... points to spi_gpio->bitbang
|
||||
* spi->controller->dev.driver_data ... points to spi_gpio->bitbang
|
||||
*/
|
||||
|
||||
struct spi_gpio {
|
||||
|
@ -78,7 +77,7 @@ spi_to_spi_gpio(const struct spi_device *spi)
|
|||
const struct spi_bitbang *bang;
|
||||
struct spi_gpio *spi_gpio;
|
||||
|
||||
bang = spi_master_get_devdata(spi->master);
|
||||
bang = spi_controller_get_devdata(spi->controller);
|
||||
spi_gpio = container_of(bang, struct spi_gpio, bitbang);
|
||||
return spi_gpio;
|
||||
}
|
||||
|
@ -170,7 +169,7 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
|
|||
|
||||
/*
|
||||
* These functions do not call setmosi or getmiso if respective flag
|
||||
* (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
|
||||
* (SPI_CONTROLLER_NO_RX or SPI_CONTROLLER_NO_TX) is set, so they are safe to
|
||||
* call when such pin is not present or defined in the controller.
|
||||
* A separate set of callbacks is defined to get highest possible
|
||||
* speed in the generic case (when both MISO and MOSI lines are
|
||||
|
@ -181,7 +180,7 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
|
|||
static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits, unsigned flags)
|
||||
{
|
||||
flags = spi->master->flags;
|
||||
flags = spi->controller->flags;
|
||||
if (unlikely(spi->mode & SPI_LSB_FIRST))
|
||||
return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits);
|
||||
else
|
||||
|
@ -191,7 +190,7 @@ static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
|
|||
static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits, unsigned flags)
|
||||
{
|
||||
flags = spi->master->flags;
|
||||
flags = spi->controller->flags;
|
||||
if (unlikely(spi->mode & SPI_LSB_FIRST))
|
||||
return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits);
|
||||
else
|
||||
|
@ -201,7 +200,7 @@ static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
|
|||
static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits, unsigned flags)
|
||||
{
|
||||
flags = spi->master->flags;
|
||||
flags = spi->controller->flags;
|
||||
if (unlikely(spi->mode & SPI_LSB_FIRST))
|
||||
return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits);
|
||||
else
|
||||
|
@ -211,7 +210,7 @@ static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
|
|||
static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits, unsigned flags)
|
||||
{
|
||||
flags = spi->master->flags;
|
||||
flags = spi->controller->flags;
|
||||
if (unlikely(spi->mode & SPI_LSB_FIRST))
|
||||
return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits);
|
||||
else
|
||||
|
@ -311,7 +310,7 @@ static void spi_gpio_cleanup(struct spi_device *spi)
|
|||
* On platforms which can do so, configure MISO with a weak pullup unless
|
||||
* there's an external pullup on that signal. That saves power by avoiding
|
||||
* floating signals. (A weak pulldown would save power too, but many
|
||||
* drivers expect to see all-ones data as the no slave "response".)
|
||||
* drivers expect to see all-ones data as the no target "response".)
|
||||
*/
|
||||
static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio)
|
||||
{
|
||||
|
@ -335,27 +334,27 @@ static const struct of_device_id spi_gpio_dt_ids[] = {
|
|||
MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids);
|
||||
|
||||
static int spi_gpio_probe_dt(struct platform_device *pdev,
|
||||
struct spi_master *master)
|
||||
struct spi_controller *host)
|
||||
{
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int spi_gpio_probe_dt(struct platform_device *pdev,
|
||||
struct spi_master *master)
|
||||
struct spi_controller *host)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int spi_gpio_probe_pdata(struct platform_device *pdev,
|
||||
struct spi_master *master)
|
||||
struct spi_controller *host)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_gpio_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
|
||||
struct spi_gpio *spi_gpio = spi_controller_get_devdata(host);
|
||||
int i;
|
||||
|
||||
#ifdef GENERIC_BITBANG
|
||||
|
@ -363,18 +362,18 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev,
|
|||
return -ENODEV;
|
||||
#endif
|
||||
/*
|
||||
* The master needs to think there is a chipselect even if not
|
||||
* The host needs to think there is a chipselect even if not
|
||||
* connected
|
||||
*/
|
||||
master->num_chipselect = pdata->num_chipselect ?: 1;
|
||||
host->num_chipselect = pdata->num_chipselect ?: 1;
|
||||
|
||||
spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
|
||||
spi_gpio->cs_gpios = devm_kcalloc(dev, host->num_chipselect,
|
||||
sizeof(*spi_gpio->cs_gpios),
|
||||
GFP_KERNEL);
|
||||
if (!spi_gpio->cs_gpios)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < master->num_chipselect; i++) {
|
||||
for (i = 0; i < host->num_chipselect; i++) {
|
||||
spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i,
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(spi_gpio->cs_gpios[i]))
|
||||
|
@ -387,58 +386,58 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev,
|
|||
static int spi_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int status;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct spi_gpio *spi_gpio;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_bitbang *bb;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*spi_gpio));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*spi_gpio));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
status = spi_gpio_probe_dt(pdev, master);
|
||||
status = spi_gpio_probe_dt(pdev, host);
|
||||
else
|
||||
status = spi_gpio_probe_pdata(pdev, master);
|
||||
status = spi_gpio_probe_pdata(pdev, host);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
spi_gpio = spi_master_get_devdata(master);
|
||||
spi_gpio = spi_controller_get_devdata(host);
|
||||
|
||||
status = spi_gpio_request(dev, spi_gpio);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
||||
master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
||||
host->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
|
||||
SPI_CS_HIGH | SPI_LSB_FIRST;
|
||||
if (!spi_gpio->mosi) {
|
||||
/* HW configuration without MOSI pin
|
||||
*
|
||||
* No setting SPI_MASTER_NO_RX here - if there is only
|
||||
* No setting SPI_CONTROLLER_NO_RX here - if there is only
|
||||
* a MOSI pin connected the host can still do RX by
|
||||
* changing the direction of the line.
|
||||
*/
|
||||
master->flags = SPI_MASTER_NO_TX;
|
||||
host->flags = SPI_CONTROLLER_NO_TX;
|
||||
}
|
||||
|
||||
master->bus_num = pdev->id;
|
||||
master->setup = spi_gpio_setup;
|
||||
master->cleanup = spi_gpio_cleanup;
|
||||
host->bus_num = pdev->id;
|
||||
host->setup = spi_gpio_setup;
|
||||
host->cleanup = spi_gpio_cleanup;
|
||||
|
||||
bb = &spi_gpio->bitbang;
|
||||
bb->master = master;
|
||||
bb->master = host;
|
||||
/*
|
||||
* There is some additional business, apart from driving the CS GPIO
|
||||
* line, that we need to do on selection. This makes the local
|
||||
* callback for chipselect always get called.
|
||||
*/
|
||||
master->flags |= SPI_MASTER_GPIO_SS;
|
||||
host->flags |= SPI_CONTROLLER_GPIO_SS;
|
||||
bb->chipselect = spi_gpio_chipselect;
|
||||
bb->set_line_direction = spi_gpio_set_direction;
|
||||
|
||||
if (master->flags & SPI_MASTER_NO_TX) {
|
||||
if (host->flags & SPI_CONTROLLER_NO_TX) {
|
||||
bb->txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
|
||||
bb->txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
|
||||
bb->txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
|
||||
|
@ -455,7 +454,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
return devm_spi_register_master(&pdev->dev, master);
|
||||
return devm_spi_register_controller(&pdev->dev, host);
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
@ -469,6 +468,6 @@ static struct platform_driver spi_gpio_driver = {
|
|||
};
|
||||
module_platform_driver(spi_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
|
||||
MODULE_DESCRIPTION("SPI host driver using generic bitbanged GPIO ");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
|
@ -200,7 +199,7 @@ static ssize_t gxp_spi_write(struct gxp_spi_chip *chip, const struct spi_mem_op
|
|||
|
||||
static int do_gxp_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct gxp_spi *spifi = spi_controller_get_devdata(mem->spi->master);
|
||||
struct gxp_spi *spifi = spi_controller_get_devdata(mem->spi->controller);
|
||||
struct gxp_spi_chip *chip = &spifi->chips[spi_get_chipselect(mem->spi, 0)];
|
||||
int ret;
|
||||
|
||||
|
@ -236,7 +235,7 @@ static const struct spi_controller_mem_ops gxp_spi_mem_ops = {
|
|||
|
||||
static int gxp_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct gxp_spi *spifi = spi_controller_get_devdata(spi->master);
|
||||
struct gxp_spi *spifi = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int cs = spi_get_chipselect(spi, 0);
|
||||
struct gxp_spi_chip *chip = &spifi->chips[cs];
|
||||
|
||||
|
@ -258,7 +257,7 @@ static int gxp_spifi_probe(struct platform_device *pdev)
|
|||
|
||||
data = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
ctlr = devm_spi_alloc_master(dev, sizeof(*spifi));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(*spifi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -164,10 +164,10 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs)
|
|||
{
|
||||
char name[32];
|
||||
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
|
||||
master = container_of(hs->dev, struct spi_controller, dev);
|
||||
snprintf(name, 32, "hisi_spi%d", master->bus_num);
|
||||
host = container_of(hs->dev, struct spi_controller, dev);
|
||||
snprintf(name, 32, "hisi_spi%d", host->bus_num);
|
||||
hs->debugfs = debugfs_create_dir(name, NULL);
|
||||
if (IS_ERR(hs->debugfs))
|
||||
return -ENOMEM;
|
||||
|
@ -291,18 +291,18 @@ static void __hisi_calc_div_reg(struct hisi_chip_data *chip)
|
|||
chip->div_post = (chip->clk_div / chip->div_pre) - 1;
|
||||
}
|
||||
|
||||
static u32 hisi_calc_effective_speed(struct spi_controller *master,
|
||||
static u32 hisi_calc_effective_speed(struct spi_controller *host,
|
||||
struct hisi_chip_data *chip, u32 speed_hz)
|
||||
{
|
||||
u32 effective_speed;
|
||||
|
||||
/* Note clock divider doesn't support odd numbers */
|
||||
chip->clk_div = DIV_ROUND_UP(master->max_speed_hz, speed_hz) + 1;
|
||||
chip->clk_div = DIV_ROUND_UP(host->max_speed_hz, speed_hz) + 1;
|
||||
chip->clk_div &= 0xfffe;
|
||||
if (chip->clk_div > CLK_DIV_MAX)
|
||||
chip->clk_div = CLK_DIV_MAX;
|
||||
|
||||
effective_speed = master->max_speed_hz / chip->clk_div;
|
||||
effective_speed = host->max_speed_hz / chip->clk_div;
|
||||
if (chip->speed_hz != effective_speed) {
|
||||
__hisi_calc_div_reg(chip);
|
||||
chip->speed_hz = effective_speed;
|
||||
|
@ -336,20 +336,20 @@ static void hisi_spi_hw_init(struct hisi_spi *hs)
|
|||
|
||||
static irqreturn_t hisi_spi_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_controller *master = dev_id;
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
struct spi_controller *host = dev_id;
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(host);
|
||||
u32 irq_status = readl(hs->regs + HISI_SPI_ISR) & ISR_MASK;
|
||||
|
||||
if (!irq_status)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!master->cur_msg)
|
||||
if (!host->cur_msg)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Error handling */
|
||||
if (irq_status & ISR_RXOF) {
|
||||
dev_err(hs->dev, "interrupt_transfer: fifo overflow\n");
|
||||
master->cur_msg->status = -EIO;
|
||||
host->cur_msg->status = -EIO;
|
||||
goto finalize_transfer;
|
||||
}
|
||||
|
||||
|
@ -369,20 +369,20 @@ static irqreturn_t hisi_spi_irq(int irq, void *dev_id)
|
|||
|
||||
finalize_transfer:
|
||||
hisi_spi_disable(hs);
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hisi_spi_transfer_one(struct spi_controller *master,
|
||||
static int hisi_spi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi, struct spi_transfer *transfer)
|
||||
{
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(host);
|
||||
struct hisi_chip_data *chip = spi_get_ctldata(spi);
|
||||
u32 cr = chip->cr;
|
||||
|
||||
/* Update per transfer options for speed and bpw */
|
||||
transfer->effective_speed_hz =
|
||||
hisi_calc_effective_speed(master, chip, transfer->speed_hz);
|
||||
hisi_calc_effective_speed(host, chip, transfer->speed_hz);
|
||||
cr |= FIELD_PREP(CR_DIV_PRE_MASK, chip->div_pre);
|
||||
cr |= FIELD_PREP(CR_DIV_POST_MASK, chip->div_post);
|
||||
cr |= FIELD_PREP(CR_BPW_MASK, transfer->bits_per_word - 1);
|
||||
|
@ -409,10 +409,10 @@ static int hisi_spi_transfer_one(struct spi_controller *master,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void hisi_spi_handle_err(struct spi_controller *master,
|
||||
static void hisi_spi_handle_err(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(host);
|
||||
|
||||
hisi_spi_disable(hs);
|
||||
|
||||
|
@ -452,7 +452,7 @@ static void hisi_spi_cleanup(struct spi_device *spi)
|
|||
static int hisi_spi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
struct hisi_spi *hs;
|
||||
int ret, irq;
|
||||
|
||||
|
@ -460,13 +460,13 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*hs));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*hs));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
hs = spi_controller_get_devdata(master);
|
||||
hs = spi_controller_get_devdata(host);
|
||||
hs->dev = dev;
|
||||
hs->irq = irq;
|
||||
|
||||
|
@ -474,9 +474,9 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(hs->regs))
|
||||
return PTR_ERR(hs->regs);
|
||||
|
||||
/* Specify maximum SPI clocking speed (master only) by firmware */
|
||||
/* Specify maximum SPI clocking speed (host only) by firmware */
|
||||
ret = device_property_read_u32(dev, "spi-max-frequency",
|
||||
&master->max_speed_hz);
|
||||
&host->max_speed_hz);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get max SPI clocking speed, ret=%d\n",
|
||||
ret);
|
||||
|
@ -484,32 +484,32 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ret = device_property_read_u16(dev, "num-cs",
|
||||
&master->num_chipselect);
|
||||
&host->num_chipselect);
|
||||
if (ret)
|
||||
master->num_chipselect = DEFAULT_NUM_CS;
|
||||
host->num_chipselect = DEFAULT_NUM_CS;
|
||||
|
||||
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 = pdev->id;
|
||||
master->setup = hisi_spi_setup;
|
||||
master->cleanup = hisi_spi_cleanup;
|
||||
master->transfer_one = hisi_spi_transfer_one;
|
||||
master->handle_err = hisi_spi_handle_err;
|
||||
master->dev.fwnode = dev->fwnode;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
|
||||
host->bus_num = pdev->id;
|
||||
host->setup = hisi_spi_setup;
|
||||
host->cleanup = hisi_spi_cleanup;
|
||||
host->transfer_one = hisi_spi_transfer_one;
|
||||
host->handle_err = hisi_spi_handle_err;
|
||||
host->dev.fwnode = dev->fwnode;
|
||||
|
||||
hisi_spi_hw_init(hs);
|
||||
|
||||
ret = devm_request_irq(dev, hs->irq, hisi_spi_irq, 0, dev_name(dev),
|
||||
master);
|
||||
host);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get IRQ=%d, ret=%d\n", hs->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_register_controller(master);
|
||||
ret = spi_register_controller(host);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register spi master, ret=%d\n", ret);
|
||||
dev_err(dev, "failed to register spi host, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -518,18 +518,18 @@ static int hisi_spi_probe(struct platform_device *pdev)
|
|||
|
||||
dev_info(dev, "hw version:0x%x max-freq:%u kHz\n",
|
||||
readl(hs->regs + HISI_SPI_VERSION),
|
||||
master->max_speed_hz / 1000);
|
||||
host->max_speed_hz / 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hisi_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *master = platform_get_drvdata(pdev);
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct hisi_spi *hs = spi_controller_get_devdata(host);
|
||||
|
||||
debugfs_remove_recursive(hs->debugfs);
|
||||
spi_unregister_controller(master);
|
||||
spi_unregister_controller(host);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id hisi_spi_acpi_match[] = {
|
||||
|
|
|
@ -152,7 +152,7 @@ static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem,
|
|||
uintptr_t addr = (uintptr_t)op->data.buf.in;
|
||||
int max_byte_count;
|
||||
|
||||
host = spi_controller_get_devdata(spi->master);
|
||||
host = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
max_byte_count = host->max_cmd_dword * 4;
|
||||
|
||||
|
@ -174,7 +174,7 @@ static bool hisi_sfc_v3xx_supports_op(struct spi_mem *mem,
|
|||
struct spi_device *spi = mem->spi;
|
||||
struct hisi_sfc_v3xx_host *host;
|
||||
|
||||
host = spi_controller_get_devdata(spi->master);
|
||||
host = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (op->data.buswidth > 4 || op->dummy.buswidth > 4 ||
|
||||
op->addr.buswidth > 4 || op->cmd.buswidth > 4)
|
||||
|
@ -363,7 +363,7 @@ static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem,
|
|||
struct spi_device *spi = mem->spi;
|
||||
u8 chip_select = spi_get_chipselect(spi, 0);
|
||||
|
||||
host = spi_controller_get_devdata(spi->master);
|
||||
host = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select);
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
u32 version, glb_config;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_master(&pdev->dev, sizeof(*host));
|
||||
ctlr = spi_alloc_host(&pdev->dev, sizeof(*host));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -448,13 +448,13 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
host->regbase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(host->regbase)) {
|
||||
ret = PTR_ERR(host->regbase);
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
host->irq = platform_get_irq_optional(pdev, 0);
|
||||
if (host->irq == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
}
|
||||
|
||||
hisi_sfc_v3xx_disable_int(host);
|
||||
|
@ -496,15 +496,15 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
|
|||
|
||||
ret = devm_spi_register_controller(dev, ctlr);
|
||||
if (ret)
|
||||
goto err_put_master;
|
||||
goto err_put_host;
|
||||
|
||||
dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n",
|
||||
version, host->irq ? "irq" : "polling");
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_master:
|
||||
spi_master_put(ctlr);
|
||||
err_put_host:
|
||||
spi_controller_put(ctlr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
|
||||
struct img_spfi {
|
||||
struct device *dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
spinlock_t lock;
|
||||
|
||||
void __iomem *regs;
|
||||
|
@ -221,11 +221,11 @@ static unsigned int spfi_pio_read8(struct img_spfi *spfi, u8 *buf,
|
|||
return count;
|
||||
}
|
||||
|
||||
static int img_spfi_start_pio(struct spi_master *master,
|
||||
static int img_spfi_start_pio(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(spi->controller);
|
||||
unsigned int tx_bytes = 0, rx_bytes = 0;
|
||||
const void *tx_buf = xfer->tx_buf;
|
||||
void *rx_buf = xfer->rx_buf;
|
||||
|
@ -285,7 +285,7 @@ static void img_spfi_dma_rx_cb(void *data)
|
|||
spin_lock_irqsave(&spfi->lock, flags);
|
||||
spfi->rx_dma_busy = false;
|
||||
if (!spfi->tx_dma_busy)
|
||||
spi_finalize_current_transfer(spfi->master);
|
||||
spi_finalize_current_transfer(spfi->host);
|
||||
spin_unlock_irqrestore(&spfi->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -299,15 +299,15 @@ static void img_spfi_dma_tx_cb(void *data)
|
|||
spin_lock_irqsave(&spfi->lock, flags);
|
||||
spfi->tx_dma_busy = false;
|
||||
if (!spfi->rx_dma_busy)
|
||||
spi_finalize_current_transfer(spfi->master);
|
||||
spi_finalize_current_transfer(spfi->host);
|
||||
spin_unlock_irqrestore(&spfi->lock, flags);
|
||||
}
|
||||
|
||||
static int img_spfi_start_dma(struct spi_master *master,
|
||||
static int img_spfi_start_dma(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(spi->controller);
|
||||
struct dma_async_tx_descriptor *rxdesc = NULL, *txdesc = NULL;
|
||||
struct dma_slave_config rxconf, txconf;
|
||||
|
||||
|
@ -384,10 +384,10 @@ stop_dma:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static void img_spfi_handle_err(struct spi_master *master,
|
||||
static void img_spfi_handle_err(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
|
@ -405,9 +405,9 @@ static void img_spfi_handle_err(struct spi_master *master,
|
|||
spin_unlock_irqrestore(&spfi->lock, flags);
|
||||
}
|
||||
|
||||
static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
|
||||
static int img_spfi_prepare(struct spi_controller *host, struct spi_message *msg)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
u32 val;
|
||||
|
||||
val = spfi_readl(spfi, SPFI_PORT_STATE);
|
||||
|
@ -427,20 +427,20 @@ static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int img_spfi_unprepare(struct spi_master *master,
|
||||
static int img_spfi_unprepare(struct spi_controller *host,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
|
||||
spfi_reset(spfi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
|
||||
static void img_spfi_config(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(spi->controller);
|
||||
u32 val, div;
|
||||
|
||||
/*
|
||||
|
@ -476,11 +476,11 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
|
|||
spfi_writel(spfi, val, SPFI_CONTROL);
|
||||
}
|
||||
|
||||
static int img_spfi_transfer_one(struct spi_master *master,
|
||||
static int img_spfi_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(spi->controller);
|
||||
int ret;
|
||||
|
||||
if (xfer->len > SPFI_TRANSACTION_TSIZE_MASK) {
|
||||
|
@ -490,16 +490,16 @@ static int img_spfi_transfer_one(struct spi_master *master,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
img_spfi_config(master, spi, xfer);
|
||||
if (master->can_dma && master->can_dma(master, spi, xfer))
|
||||
ret = img_spfi_start_dma(master, spi, xfer);
|
||||
img_spfi_config(host, spi, xfer);
|
||||
if (host->can_dma && host->can_dma(host, spi, xfer))
|
||||
ret = img_spfi_start_dma(host, spi, xfer);
|
||||
else
|
||||
ret = img_spfi_start_pio(master, spi, xfer);
|
||||
ret = img_spfi_start_pio(host, spi, xfer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool img_spfi_can_dma(struct spi_master *master, struct spi_device *spi,
|
||||
static bool img_spfi_can_dma(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
if (xfer->len > SPFI_32BIT_FIFO_SIZE)
|
||||
|
@ -524,20 +524,20 @@ static irqreturn_t img_spfi_irq(int irq, void *dev_id)
|
|||
|
||||
static int img_spfi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct img_spfi *spfi;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
u32 max_speed_hz;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spfi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(*spfi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, master);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
spfi = spi_master_get_devdata(master);
|
||||
spfi = spi_controller_get_devdata(host);
|
||||
spfi->dev = &pdev->dev;
|
||||
spfi->master = master;
|
||||
spfi->host = host;
|
||||
spin_lock_init(&spfi->lock);
|
||||
|
||||
spfi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
|
@ -582,15 +582,15 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
*/
|
||||
spfi_writel(spfi, SPFI_INTERRUPT_IACCESS, SPFI_INTERRUPT_ENABLE);
|
||||
|
||||
master->auto_runtime_pm = true;
|
||||
master->bus_num = pdev->id;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL;
|
||||
host->auto_runtime_pm = true;
|
||||
host->bus_num = pdev->id;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL;
|
||||
if (of_property_read_bool(spfi->dev->of_node, "img,supports-quad-mode"))
|
||||
master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8);
|
||||
master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
|
||||
master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
|
||||
host->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8);
|
||||
host->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
|
||||
host->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
|
||||
|
||||
/*
|
||||
* Maximum speed supported by spfi is limited to the lower value
|
||||
|
@ -601,15 +601,15 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
*/
|
||||
if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency",
|
||||
&max_speed_hz)) {
|
||||
if (master->max_speed_hz > max_speed_hz)
|
||||
master->max_speed_hz = max_speed_hz;
|
||||
if (host->max_speed_hz > max_speed_hz)
|
||||
host->max_speed_hz = max_speed_hz;
|
||||
}
|
||||
|
||||
master->transfer_one = img_spfi_transfer_one;
|
||||
master->prepare_message = img_spfi_prepare;
|
||||
master->unprepare_message = img_spfi_unprepare;
|
||||
master->handle_err = img_spfi_handle_err;
|
||||
master->use_gpio_descriptors = true;
|
||||
host->transfer_one = img_spfi_transfer_one;
|
||||
host->prepare_message = img_spfi_prepare;
|
||||
host->unprepare_message = img_spfi_unprepare;
|
||||
host->handle_err = img_spfi_handle_err;
|
||||
host->use_gpio_descriptors = true;
|
||||
|
||||
spfi->tx_ch = dma_request_chan(spfi->dev, "tx");
|
||||
if (IS_ERR(spfi->tx_ch)) {
|
||||
|
@ -636,15 +636,15 @@ static int img_spfi_probe(struct platform_device *pdev)
|
|||
spfi->rx_ch = NULL;
|
||||
dev_warn(spfi->dev, "Failed to get DMA channels, falling back to PIO mode\n");
|
||||
} else {
|
||||
master->dma_tx = spfi->tx_ch;
|
||||
master->dma_rx = spfi->rx_ch;
|
||||
master->can_dma = img_spfi_can_dma;
|
||||
host->dma_tx = spfi->tx_ch;
|
||||
host->dma_rx = spfi->rx_ch;
|
||||
host->can_dma = img_spfi_can_dma;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(spfi->dev);
|
||||
pm_runtime_enable(spfi->dev);
|
||||
|
||||
ret = devm_spi_register_master(spfi->dev, master);
|
||||
ret = devm_spi_register_controller(spfi->dev, host);
|
||||
if (ret)
|
||||
goto disable_pm;
|
||||
|
||||
|
@ -660,15 +660,15 @@ disable_pm:
|
|||
disable_pclk:
|
||||
clk_disable_unprepare(spfi->sys_clk);
|
||||
put_spi:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void img_spfi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_master *master = platform_get_drvdata(pdev);
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = platform_get_drvdata(pdev);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
|
||||
if (spfi->tx_ch)
|
||||
dma_release_channel(spfi->tx_ch);
|
||||
|
@ -685,8 +685,8 @@ static void img_spfi_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM
|
||||
static int img_spfi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
|
||||
clk_disable_unprepare(spfi->spfi_clk);
|
||||
clk_disable_unprepare(spfi->sys_clk);
|
||||
|
@ -696,8 +696,8 @@ static int img_spfi_runtime_suspend(struct device *dev)
|
|||
|
||||
static int img_spfi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(spfi->sys_clk);
|
||||
|
@ -716,15 +716,15 @@ static int img_spfi_runtime_resume(struct device *dev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int img_spfi_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
|
||||
return spi_master_suspend(master);
|
||||
return spi_controller_suspend(host);
|
||||
}
|
||||
|
||||
static int img_spfi_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = dev_get_drvdata(dev);
|
||||
struct img_spfi *spfi = spi_controller_get_devdata(host);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
|
@ -733,7 +733,7 @@ static int img_spfi_resume(struct device *dev)
|
|||
spfi_reset(spfi);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return spi_master_resume(master);
|
||||
return spi_controller_resume(host);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#include <linux/dma/imx-dma.h>
|
||||
|
@ -53,7 +52,7 @@ MODULE_PARM_DESC(polling_limit_us,
|
|||
/* The maximum bytes that a sdma BD can transfer. */
|
||||
#define MAX_SDMA_BD_BYTES (1 << 15)
|
||||
#define MX51_ECSPI_CTRL_MAX_BURST 512
|
||||
/* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/
|
||||
/* The maximum bytes that IMX53_ECSPI can transfer in target mode.*/
|
||||
#define MX53_MAX_TRANSFER_BYTES 512
|
||||
|
||||
enum spi_imx_devtype {
|
||||
|
@ -78,7 +77,7 @@ struct spi_imx_devtype_data {
|
|||
void (*setup_wml)(struct spi_imx_data *spi_imx);
|
||||
void (*disable)(struct spi_imx_data *spi_imx);
|
||||
bool has_dmamode;
|
||||
bool has_slavemode;
|
||||
bool has_targetmode;
|
||||
unsigned int fifo_size;
|
||||
bool dynamic_burst;
|
||||
/*
|
||||
|
@ -114,10 +113,10 @@ struct spi_imx_data {
|
|||
unsigned int dynamic_burst;
|
||||
bool rx_only;
|
||||
|
||||
/* Slave mode */
|
||||
bool slave_mode;
|
||||
bool slave_aborted;
|
||||
unsigned int slave_burst;
|
||||
/* Target mode */
|
||||
bool target_mode;
|
||||
bool target_aborted;
|
||||
unsigned int target_burst;
|
||||
|
||||
/* DMA */
|
||||
bool usedma;
|
||||
|
@ -241,7 +240,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device
|
|||
if (!controller->dma_rx)
|
||||
return false;
|
||||
|
||||
if (spi_imx->slave_mode)
|
||||
if (spi_imx->target_mode)
|
||||
return false;
|
||||
|
||||
if (transfer->len < spi_imx->devtype_data->fifo_size)
|
||||
|
@ -405,12 +404,12 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
|
|||
writel(val, spi_imx->base + MXC_CSPITXDATA);
|
||||
}
|
||||
|
||||
static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
|
||||
static void mx53_ecspi_rx_target(struct spi_imx_data *spi_imx)
|
||||
{
|
||||
u32 val = be32_to_cpu(readl(spi_imx->base + MXC_CSPIRXDATA));
|
||||
|
||||
if (spi_imx->rx_buf) {
|
||||
int n_bytes = spi_imx->slave_burst % sizeof(val);
|
||||
int n_bytes = spi_imx->target_burst % sizeof(val);
|
||||
|
||||
if (!n_bytes)
|
||||
n_bytes = sizeof(val);
|
||||
|
@ -419,13 +418,13 @@ static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
|
|||
((u8 *)&val) + sizeof(val) - n_bytes, n_bytes);
|
||||
|
||||
spi_imx->rx_buf += n_bytes;
|
||||
spi_imx->slave_burst -= n_bytes;
|
||||
spi_imx->target_burst -= n_bytes;
|
||||
}
|
||||
|
||||
spi_imx->remainder -= sizeof(u32);
|
||||
}
|
||||
|
||||
static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx)
|
||||
static void mx53_ecspi_tx_target(struct spi_imx_data *spi_imx)
|
||||
{
|
||||
u32 val = 0;
|
||||
int n_bytes = spi_imx->count % sizeof(val);
|
||||
|
@ -536,8 +535,8 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
|
|||
u32 current_cfg = cfg;
|
||||
int channel = mx51_ecspi_channel(spi);
|
||||
|
||||
/* set Master or Slave mode */
|
||||
if (spi_imx->slave_mode)
|
||||
/* set Host or Target mode */
|
||||
if (spi_imx->target_mode)
|
||||
ctrl &= ~MX51_ECSPI_CTRL_MODE_MASK;
|
||||
else
|
||||
ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
|
||||
|
@ -565,11 +564,11 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
|
|||
writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG);
|
||||
|
||||
/*
|
||||
* eCSPI burst completion by Chip Select signal in Slave mode
|
||||
* eCSPI burst completion by Chip Select signal in Target mode
|
||||
* is not functional for imx53 Soc, config SPI burst completed when
|
||||
* BURST_LENGTH + 1 bits are received
|
||||
*/
|
||||
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
|
||||
if (spi_imx->target_mode && is_imx53_ecspi(spi_imx))
|
||||
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel);
|
||||
else
|
||||
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel);
|
||||
|
@ -656,12 +655,16 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
|
|||
|
||||
/* Clear BL field and set the right value */
|
||||
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
|
||||
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
|
||||
ctrl |= (spi_imx->slave_burst * 8 - 1)
|
||||
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
||||
else
|
||||
ctrl |= (spi_imx->bits_per_word - 1)
|
||||
if (spi_imx->target_mode && is_imx53_ecspi(spi_imx))
|
||||
ctrl |= (spi_imx->target_burst * 8 - 1)
|
||||
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
||||
else {
|
||||
if (spi_imx->count >= 512)
|
||||
ctrl |= 0xFFF << MX51_ECSPI_CTRL_BL_OFFSET;
|
||||
else
|
||||
ctrl |= (spi_imx->count*8 - 1)
|
||||
<< MX51_ECSPI_CTRL_BL_OFFSET;
|
||||
}
|
||||
|
||||
/* set clock speed */
|
||||
ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET |
|
||||
|
@ -718,7 +721,7 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx)
|
|||
#define MX31_INTREG_RREN (1 << 3)
|
||||
|
||||
#define MX31_CSPICTRL_ENABLE (1 << 0)
|
||||
#define MX31_CSPICTRL_MASTER (1 << 1)
|
||||
#define MX31_CSPICTRL_HOST (1 << 1)
|
||||
#define MX31_CSPICTRL_XCH (1 << 2)
|
||||
#define MX31_CSPICTRL_SMC (1 << 3)
|
||||
#define MX31_CSPICTRL_POL (1 << 4)
|
||||
|
@ -775,7 +778,7 @@ static int mx31_prepare_message(struct spi_imx_data *spi_imx,
|
|||
static int mx31_prepare_transfer(struct spi_imx_data *spi_imx,
|
||||
struct spi_device *spi)
|
||||
{
|
||||
unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
|
||||
unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_HOST;
|
||||
unsigned int clk;
|
||||
|
||||
reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) <<
|
||||
|
@ -845,7 +848,7 @@ static void mx31_reset(struct spi_imx_data *spi_imx)
|
|||
#define MX21_CSPICTRL_SSPOL (1 << 8)
|
||||
#define MX21_CSPICTRL_XCH (1 << 9)
|
||||
#define MX21_CSPICTRL_ENABLE (1 << 10)
|
||||
#define MX21_CSPICTRL_MASTER (1 << 11)
|
||||
#define MX21_CSPICTRL_HOST (1 << 11)
|
||||
#define MX21_CSPICTRL_DR_SHIFT 14
|
||||
#define MX21_CSPICTRL_CS_SHIFT 19
|
||||
|
||||
|
@ -879,7 +882,7 @@ static int mx21_prepare_message(struct spi_imx_data *spi_imx,
|
|||
static int mx21_prepare_transfer(struct spi_imx_data *spi_imx,
|
||||
struct spi_device *spi)
|
||||
{
|
||||
unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
|
||||
unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_HOST;
|
||||
unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
|
||||
unsigned int clk;
|
||||
|
||||
|
@ -921,7 +924,7 @@ static void mx21_reset(struct spi_imx_data *spi_imx)
|
|||
#define MX1_CSPICTRL_PHA (1 << 5)
|
||||
#define MX1_CSPICTRL_XCH (1 << 8)
|
||||
#define MX1_CSPICTRL_ENABLE (1 << 9)
|
||||
#define MX1_CSPICTRL_MASTER (1 << 10)
|
||||
#define MX1_CSPICTRL_HOST (1 << 10)
|
||||
#define MX1_CSPICTRL_DR_SHIFT 13
|
||||
|
||||
static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
|
||||
|
@ -954,7 +957,7 @@ static int mx1_prepare_message(struct spi_imx_data *spi_imx,
|
|||
static int mx1_prepare_transfer(struct spi_imx_data *spi_imx,
|
||||
struct spi_device *spi)
|
||||
{
|
||||
unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
|
||||
unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_HOST;
|
||||
unsigned int clk;
|
||||
|
||||
reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) <<
|
||||
|
@ -993,7 +996,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
|
|||
.fifo_size = 8,
|
||||
.has_dmamode = false,
|
||||
.dynamic_burst = false,
|
||||
.has_slavemode = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX1_CSPI,
|
||||
};
|
||||
|
||||
|
@ -1007,7 +1010,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
|
|||
.fifo_size = 8,
|
||||
.has_dmamode = false,
|
||||
.dynamic_burst = false,
|
||||
.has_slavemode = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX21_CSPI,
|
||||
};
|
||||
|
||||
|
@ -1022,7 +1025,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
|
|||
.fifo_size = 8,
|
||||
.has_dmamode = false,
|
||||
.dynamic_burst = false,
|
||||
.has_slavemode = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX27_CSPI,
|
||||
};
|
||||
|
||||
|
@ -1036,7 +1039,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
|
|||
.fifo_size = 8,
|
||||
.has_dmamode = false,
|
||||
.dynamic_burst = false,
|
||||
.has_slavemode = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX31_CSPI,
|
||||
};
|
||||
|
||||
|
@ -1051,7 +1054,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
|
|||
.fifo_size = 8,
|
||||
.has_dmamode = true,
|
||||
.dynamic_burst = false,
|
||||
.has_slavemode = false,
|
||||
.has_targetmode = false,
|
||||
.devtype = IMX35_CSPI,
|
||||
};
|
||||
|
||||
|
@ -1066,7 +1069,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
|
|||
.fifo_size = 64,
|
||||
.has_dmamode = true,
|
||||
.dynamic_burst = true,
|
||||
.has_slavemode = true,
|
||||
.has_targetmode = true,
|
||||
.disable = mx51_ecspi_disable,
|
||||
.devtype = IMX51_ECSPI,
|
||||
};
|
||||
|
@ -1080,7 +1083,7 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
|
|||
.reset = mx51_ecspi_reset,
|
||||
.fifo_size = 64,
|
||||
.has_dmamode = true,
|
||||
.has_slavemode = true,
|
||||
.has_targetmode = true,
|
||||
.disable = mx51_ecspi_disable,
|
||||
.devtype = IMX53_ECSPI,
|
||||
};
|
||||
|
@ -1096,7 +1099,7 @@ static struct spi_imx_devtype_data imx6ul_ecspi_devtype_data = {
|
|||
.fifo_size = 64,
|
||||
.has_dmamode = true,
|
||||
.dynamic_burst = true,
|
||||
.has_slavemode = true,
|
||||
.has_targetmode = true,
|
||||
.tx_glitch_fixed = true,
|
||||
.disable = mx51_ecspi_disable,
|
||||
.devtype = IMX51_ECSPI,
|
||||
|
@ -1161,7 +1164,7 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
|
|||
spi_imx->txfifo++;
|
||||
}
|
||||
|
||||
if (!spi_imx->slave_mode)
|
||||
if (!spi_imx->target_mode)
|
||||
spi_imx->devtype_data->trigger(spi_imx);
|
||||
}
|
||||
|
||||
|
@ -1258,13 +1261,14 @@ static int spi_imx_setupxfer(struct spi_device *spi,
|
|||
spi_imx->spi_bus_clk = t->speed_hz;
|
||||
|
||||
spi_imx->bits_per_word = t->bits_per_word;
|
||||
spi_imx->count = t->len;
|
||||
|
||||
/*
|
||||
* Initialize the functions for transfer. To transfer non byte-aligned
|
||||
* words, we have to use multiple word-size bursts, we can't use
|
||||
* dynamic_burst in that case.
|
||||
*/
|
||||
if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode &&
|
||||
if (spi_imx->devtype_data->dynamic_burst && !spi_imx->target_mode &&
|
||||
!(spi->mode & SPI_CS_WORD) &&
|
||||
(spi_imx->bits_per_word == 8 ||
|
||||
spi_imx->bits_per_word == 16 ||
|
||||
|
@ -1296,10 +1300,10 @@ static int spi_imx_setupxfer(struct spi_device *spi,
|
|||
spi_imx->rx_only = ((t->tx_buf == NULL)
|
||||
|| (t->tx_buf == spi->controller->dummy_tx));
|
||||
|
||||
if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
|
||||
spi_imx->rx = mx53_ecspi_rx_slave;
|
||||
spi_imx->tx = mx53_ecspi_tx_slave;
|
||||
spi_imx->slave_burst = t->len;
|
||||
if (is_imx53_ecspi(spi_imx) && spi_imx->target_mode) {
|
||||
spi_imx->rx = mx53_ecspi_rx_target;
|
||||
spi_imx->tx = mx53_ecspi_tx_target;
|
||||
spi_imx->target_burst = t->len;
|
||||
}
|
||||
|
||||
spi_imx->devtype_data->prepare_transfer(spi_imx, spi);
|
||||
|
@ -1564,8 +1568,8 @@ static int spi_imx_poll_transfer(struct spi_device *spi,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int spi_imx_pio_transfer_slave(struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
static int spi_imx_pio_transfer_target(struct spi_device *spi,
|
||||
struct spi_transfer *transfer)
|
||||
{
|
||||
struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
|
||||
int ret = 0;
|
||||
|
@ -1584,22 +1588,22 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
|
|||
spi_imx->remainder = 0;
|
||||
|
||||
reinit_completion(&spi_imx->xfer_done);
|
||||
spi_imx->slave_aborted = false;
|
||||
spi_imx->target_aborted = false;
|
||||
|
||||
spi_imx_push(spi_imx);
|
||||
|
||||
spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE | MXC_INT_RDR);
|
||||
|
||||
if (wait_for_completion_interruptible(&spi_imx->xfer_done) ||
|
||||
spi_imx->slave_aborted) {
|
||||
spi_imx->target_aborted) {
|
||||
dev_dbg(&spi->dev, "interrupted\n");
|
||||
ret = -EINTR;
|
||||
}
|
||||
|
||||
/* ecspi has a HW issue when works in Slave mode,
|
||||
/* ecspi has a HW issue when works in Target mode,
|
||||
* after 64 words writtern to TXFIFO, even TXFIFO becomes empty,
|
||||
* ECSPI_TXDATA keeps shift out the last word data,
|
||||
* so we have to disable ECSPI when in slave mode after the
|
||||
* so we have to disable ECSPI when in target mode after the
|
||||
* transfer completes
|
||||
*/
|
||||
if (spi_imx->devtype_data->disable)
|
||||
|
@ -1622,8 +1626,8 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
|
|||
while (spi_imx->devtype_data->rx_available(spi_imx))
|
||||
readl(spi_imx->base + MXC_CSPIRXDATA);
|
||||
|
||||
if (spi_imx->slave_mode)
|
||||
return spi_imx_pio_transfer_slave(spi, transfer);
|
||||
if (spi_imx->target_mode)
|
||||
return spi_imx_pio_transfer_target(spi, transfer);
|
||||
|
||||
/*
|
||||
* If we decided in spi_imx_can_dma() that we want to do a DMA
|
||||
|
@ -1689,11 +1693,11 @@ spi_imx_unprepare_message(struct spi_controller *controller, struct spi_message
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int spi_imx_slave_abort(struct spi_controller *controller)
|
||||
static int spi_imx_target_abort(struct spi_controller *controller)
|
||||
{
|
||||
struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
|
||||
|
||||
spi_imx->slave_aborted = true;
|
||||
spi_imx->target_aborted = true;
|
||||
complete(&spi_imx->xfer_done);
|
||||
|
||||
return 0;
|
||||
|
@ -1708,17 +1712,17 @@ static int spi_imx_probe(struct platform_device *pdev)
|
|||
int ret, irq, spi_drctl;
|
||||
const struct spi_imx_devtype_data *devtype_data =
|
||||
of_device_get_match_data(&pdev->dev);
|
||||
bool slave_mode;
|
||||
bool target_mode;
|
||||
u32 val;
|
||||
|
||||
slave_mode = devtype_data->has_slavemode &&
|
||||
of_property_read_bool(np, "spi-slave");
|
||||
if (slave_mode)
|
||||
controller = spi_alloc_slave(&pdev->dev,
|
||||
sizeof(struct spi_imx_data));
|
||||
else
|
||||
controller = spi_alloc_master(&pdev->dev,
|
||||
target_mode = devtype_data->has_targetmode &&
|
||||
of_property_read_bool(np, "spi-slave");
|
||||
if (target_mode)
|
||||
controller = spi_alloc_target(&pdev->dev,
|
||||
sizeof(struct spi_imx_data));
|
||||
else
|
||||
controller = spi_alloc_host(&pdev->dev,
|
||||
sizeof(struct spi_imx_data));
|
||||
if (!controller)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1737,7 +1741,7 @@ static int spi_imx_probe(struct platform_device *pdev)
|
|||
spi_imx = spi_controller_get_devdata(controller);
|
||||
spi_imx->controller = controller;
|
||||
spi_imx->dev = &pdev->dev;
|
||||
spi_imx->slave_mode = slave_mode;
|
||||
spi_imx->target_mode = target_mode;
|
||||
|
||||
spi_imx->devtype_data = devtype_data;
|
||||
|
||||
|
@ -1757,7 +1761,7 @@ static int spi_imx_probe(struct platform_device *pdev)
|
|||
controller->cleanup = spi_imx_cleanup;
|
||||
controller->prepare_message = spi_imx_prepare_message;
|
||||
controller->unprepare_message = spi_imx_unprepare_message;
|
||||
controller->slave_abort = spi_imx_slave_abort;
|
||||
controller->target_abort = spi_imx_target_abort;
|
||||
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS |
|
||||
SPI_MOSI_IDLE_LOW;
|
||||
|
||||
|
@ -1779,7 +1783,7 @@ static int spi_imx_probe(struct platform_device *pdev)
|
|||
|
||||
if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) {
|
||||
controller->max_native_cs = 4;
|
||||
controller->flags |= SPI_MASTER_GPIO_SS;
|
||||
controller->flags |= SPI_CONTROLLER_GPIO_SS;
|
||||
}
|
||||
|
||||
spi_imx->spi_drctl = spi_drctl;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
@ -392,7 +392,7 @@ static int spi_ingenic_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctlr = devm_spi_alloc_master(dev, sizeof(*priv));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(*priv));
|
||||
if (!ctlr) {
|
||||
dev_err(dev, "Unable to allocate SPI controller.\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
* @base: Beginning of MMIO space
|
||||
* @pregs: Start of protection registers
|
||||
* @sregs: Start of software sequencer registers
|
||||
* @master: Pointer to the SPI controller structure
|
||||
* @host: Pointer to the SPI controller structure
|
||||
* @nregions: Maximum number of regions
|
||||
* @pr_num: Maximum number of protected range registers
|
||||
* @chip0_size: Size of the first flash chip in bytes
|
||||
|
@ -161,7 +161,7 @@ struct intel_spi {
|
|||
void __iomem *base;
|
||||
void __iomem *pregs;
|
||||
void __iomem *sregs;
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
size_t nregions;
|
||||
size_t pr_num;
|
||||
size_t chip0_size;
|
||||
|
@ -747,7 +747,7 @@ intel_spi_match_mem_op(struct intel_spi *ispi, const struct spi_mem_op *op)
|
|||
static bool intel_spi_supports_mem_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop;
|
||||
|
||||
iop = intel_spi_match_mem_op(ispi, op);
|
||||
|
@ -778,7 +778,7 @@ static bool intel_spi_supports_mem_op(struct spi_mem *mem,
|
|||
|
||||
static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop;
|
||||
|
||||
iop = intel_spi_match_mem_op(ispi, op);
|
||||
|
@ -790,7 +790,7 @@ static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *o
|
|||
|
||||
static const char *intel_spi_get_name(struct spi_mem *mem)
|
||||
{
|
||||
const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
|
||||
const struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
/*
|
||||
* Return name of the flash controller device to be compatible
|
||||
|
@ -801,7 +801,7 @@ static const char *intel_spi_get_name(struct spi_mem *mem)
|
|||
|
||||
static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop;
|
||||
|
||||
iop = intel_spi_match_mem_op(ispi, &desc->info.op_tmpl);
|
||||
|
@ -815,7 +815,7 @@ static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
|||
static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
|
||||
size_t len, void *buf)
|
||||
{
|
||||
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop = desc->priv;
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
@ -832,7 +832,7 @@ static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
|
|||
static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs,
|
||||
size_t len, const void *buf)
|
||||
{
|
||||
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
|
||||
struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller);
|
||||
const struct intel_spi_mem_op *iop = desc->priv;
|
||||
struct spi_mem_op op = desc->info.op_tmpl;
|
||||
int ret;
|
||||
|
@ -1332,14 +1332,14 @@ static int intel_spi_read_desc(struct intel_spi *ispi)
|
|||
|
||||
nc = (buf[1] & FLMAP0_NC_MASK) >> FLMAP0_NC_SHIFT;
|
||||
if (!nc)
|
||||
ispi->master->num_chipselect = 1;
|
||||
ispi->host->num_chipselect = 1;
|
||||
else if (nc == 1)
|
||||
ispi->master->num_chipselect = 2;
|
||||
ispi->host->num_chipselect = 2;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(ispi->dev, "%u flash components found\n",
|
||||
ispi->master->num_chipselect);
|
||||
ispi->host->num_chipselect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1365,7 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
|
|||
snprintf(chip.modalias, 8, "spi-nor");
|
||||
chip.platform_data = pdata;
|
||||
|
||||
if (!spi_new_device(ispi->master, &chip))
|
||||
if (!spi_new_device(ispi->host, &chip))
|
||||
return -ENODEV;
|
||||
|
||||
ret = intel_spi_read_desc(ispi);
|
||||
|
@ -1373,13 +1373,13 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
|
|||
return ret;
|
||||
|
||||
/* Add the second chip if present */
|
||||
if (ispi->master->num_chipselect < 2)
|
||||
if (ispi->host->num_chipselect < 2)
|
||||
return 0;
|
||||
|
||||
chip.platform_data = NULL;
|
||||
chip.chip_select = 1;
|
||||
|
||||
if (!spi_new_device(ispi->master, &chip))
|
||||
if (!spi_new_device(ispi->host, &chip))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1396,31 +1396,31 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
|
|||
int intel_spi_probe(struct device *dev, struct resource *mem,
|
||||
const struct intel_spi_boardinfo *info)
|
||||
{
|
||||
struct spi_controller *master;
|
||||
struct spi_controller *host;
|
||||
struct intel_spi *ispi;
|
||||
int ret;
|
||||
|
||||
master = devm_spi_alloc_master(dev, sizeof(*ispi));
|
||||
if (!master)
|
||||
host = devm_spi_alloc_host(dev, sizeof(*ispi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
master->mem_ops = &intel_spi_mem_ops;
|
||||
host->mem_ops = &intel_spi_mem_ops;
|
||||
|
||||
ispi = spi_master_get_devdata(master);
|
||||
ispi = spi_controller_get_devdata(host);
|
||||
|
||||
ispi->base = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(ispi->base))
|
||||
return PTR_ERR(ispi->base);
|
||||
|
||||
ispi->dev = dev;
|
||||
ispi->master = master;
|
||||
ispi->host = host;
|
||||
ispi->info = info;
|
||||
|
||||
ret = intel_spi_init(ispi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ static int bcm_iproc_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct bcm_iproc_intc *priv;
|
||||
struct bcm_qspi_soc_intc *soc_intc;
|
||||
struct resource *res;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -104,14 +103,12 @@ static int bcm_iproc_probe(struct platform_device *pdev)
|
|||
|
||||
spin_lock_init(&priv->soclock);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr_regs");
|
||||
priv->int_reg = devm_ioremap_resource(dev, res);
|
||||
priv->int_reg = devm_platform_ioremap_resource_byname(pdev, "intr_regs");
|
||||
if (IS_ERR(priv->int_reg))
|
||||
return PTR_ERR(priv->int_reg);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"intr_status_reg");
|
||||
priv->int_status_reg = devm_ioremap_resource(dev, res);
|
||||
priv->int_status_reg = devm_platform_ioremap_resource_byname(pdev,
|
||||
"intr_status_reg");
|
||||
if (IS_ERR(priv->int_status_reg))
|
||||
return PTR_ERR(priv->int_status_reg);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#define JCORE_SPI_WAIT_RDY_MAX_LOOP 2000000
|
||||
|
||||
struct jcore_spi {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
void __iomem *base;
|
||||
unsigned int cs_reg;
|
||||
unsigned int speed_reg;
|
||||
|
@ -59,7 +59,7 @@ static void jcore_spi_program(struct jcore_spi *hw)
|
|||
void __iomem *ctrl_reg = hw->base + CTRL_REG;
|
||||
|
||||
if (jcore_spi_wait(ctrl_reg))
|
||||
dev_err(hw->master->dev.parent,
|
||||
dev_err(hw->host->dev.parent,
|
||||
"timeout waiting to program ctrl reg.\n");
|
||||
|
||||
writel(hw->cs_reg | hw->speed_reg, ctrl_reg);
|
||||
|
@ -67,10 +67,10 @@ static void jcore_spi_program(struct jcore_spi *hw)
|
|||
|
||||
static void jcore_spi_chipsel(struct spi_device *spi, bool value)
|
||||
{
|
||||
struct jcore_spi *hw = spi_master_get_devdata(spi->master);
|
||||
struct jcore_spi *hw = spi_controller_get_devdata(spi->controller);
|
||||
u32 csbit = 1U << (2 * spi_get_chipselect(spi, 0));
|
||||
|
||||
dev_dbg(hw->master->dev.parent, "chipselect %d\n", spi_get_chipselect(spi, 0));
|
||||
dev_dbg(hw->host->dev.parent, "chipselect %d\n", spi_get_chipselect(spi, 0));
|
||||
|
||||
if (value)
|
||||
hw->cs_reg |= csbit;
|
||||
|
@ -90,14 +90,14 @@ static void jcore_spi_baudrate(struct jcore_spi *hw, int speed)
|
|||
else
|
||||
hw->speed_reg = ((hw->clock_freq / 2 / speed) - 1) << 27;
|
||||
jcore_spi_program(hw);
|
||||
dev_dbg(hw->master->dev.parent, "speed=%d reg=0x%x\n",
|
||||
dev_dbg(hw->host->dev.parent, "speed=%d reg=0x%x\n",
|
||||
speed, hw->speed_reg);
|
||||
}
|
||||
|
||||
static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi,
|
||||
static int jcore_spi_txrx(struct spi_controller *host, struct spi_device *spi,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct jcore_spi *hw = spi_master_get_devdata(master);
|
||||
struct jcore_spi *hw = spi_controller_get_devdata(host);
|
||||
|
||||
void __iomem *ctrl_reg = hw->base + CTRL_REG;
|
||||
void __iomem *data_reg = hw->base + DATA_REG;
|
||||
|
@ -130,7 +130,7 @@ static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi,
|
|||
*rx++ = readl(data_reg);
|
||||
}
|
||||
|
||||
spi_finalize_current_transfer(master);
|
||||
spi_finalize_current_transfer(host);
|
||||
|
||||
if (count < len)
|
||||
return -EREMOTEIO;
|
||||
|
@ -142,26 +142,26 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct jcore_spi *hw;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct resource *res;
|
||||
u32 clock_freq;
|
||||
struct clk *clk;
|
||||
int err = -ENODEV;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(struct jcore_spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(&pdev->dev, sizeof(struct jcore_spi));
|
||||
if (!host)
|
||||
return err;
|
||||
|
||||
/* Setup the master state. */
|
||||
master->num_chipselect = 3;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
master->transfer_one = jcore_spi_txrx;
|
||||
master->set_cs = jcore_spi_chipsel;
|
||||
master->dev.of_node = node;
|
||||
master->bus_num = pdev->id;
|
||||
/* Setup the host state. */
|
||||
host->num_chipselect = 3;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
|
||||
host->transfer_one = jcore_spi_txrx;
|
||||
host->set_cs = jcore_spi_chipsel;
|
||||
host->dev.of_node = node;
|
||||
host->bus_num = pdev->id;
|
||||
|
||||
hw = spi_master_get_devdata(master);
|
||||
hw->master = master;
|
||||
hw = spi_controller_get_devdata(host);
|
||||
hw->host = host;
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
/* Find and map our resources */
|
||||
|
@ -200,7 +200,7 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
jcore_spi_baudrate(hw, 400000);
|
||||
|
||||
/* Register our spi controller */
|
||||
err = devm_spi_register_master(&pdev->dev, master);
|
||||
err = devm_spi_register_controller(&pdev->dev, host);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
|
@ -209,7 +209,7 @@ static int jcore_spi_probe(struct platform_device *pdev)
|
|||
exit_busy:
|
||||
err = -EBUSY;
|
||||
exit:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -91,7 +92,7 @@
|
|||
#define LTQ_SPI_STAT_RE BIT(9) /* Receive error flag */
|
||||
#define LTQ_SPI_STAT_TE BIT(8) /* Transmit error flag */
|
||||
#define LTQ_SPI_STAT_ME BIT(7) /* Mode error flag */
|
||||
#define LTQ_SPI_STAT_MS BIT(1) /* Master/slave select bit */
|
||||
#define LTQ_SPI_STAT_MS BIT(1) /* Host/target select bit */
|
||||
#define LTQ_SPI_STAT_EN BIT(0) /* Enable bit */
|
||||
#define LTQ_SPI_STAT_ERRORS (LTQ_SPI_STAT_ME | LTQ_SPI_STAT_TE | \
|
||||
LTQ_SPI_STAT_RE | LTQ_SPI_STAT_AE | \
|
||||
|
@ -109,8 +110,8 @@
|
|||
#define LTQ_SPI_WHBSTATE_CLRME BIT(6) /* Clear mode error flag */
|
||||
#define LTQ_SPI_WHBSTATE_SETRUE BIT(5) /* Set receive underflow error flag */
|
||||
#define LTQ_SPI_WHBSTATE_CLRRUE BIT(4) /* Clear receive underflow error flag */
|
||||
#define LTQ_SPI_WHBSTATE_SETMS BIT(3) /* Set master select bit */
|
||||
#define LTQ_SPI_WHBSTATE_CLRMS BIT(2) /* Clear master select bit */
|
||||
#define LTQ_SPI_WHBSTATE_SETMS BIT(3) /* Set host select bit */
|
||||
#define LTQ_SPI_WHBSTATE_CLRMS BIT(2) /* Clear host select bit */
|
||||
#define LTQ_SPI_WHBSTATE_SETEN BIT(1) /* Set enable bit (operational mode) */
|
||||
#define LTQ_SPI_WHBSTATE_CLREN BIT(0) /* Clear enable bit (config mode */
|
||||
#define LTQ_SPI_WHBSTATE_CLR_ERRORS (LTQ_SPI_WHBSTATE_CLRRUE | \
|
||||
|
@ -162,7 +163,7 @@ struct lantiq_ssc_hwcfg {
|
|||
};
|
||||
|
||||
struct lantiq_ssc_spi {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct device *dev;
|
||||
void __iomem *regbase;
|
||||
struct clk *spi_clk;
|
||||
|
@ -366,7 +367,7 @@ static void lantiq_ssc_hw_init(const struct lantiq_ssc_spi *spi)
|
|||
hw_setup_bits_per_word(spi, spi->bits_per_word);
|
||||
hw_setup_clock_mode(spi, SPI_MODE_0);
|
||||
|
||||
/* Enable master mode and clear error flags */
|
||||
/* Enable host mode and clear error flags */
|
||||
lantiq_ssc_writel(spi, LTQ_SPI_WHBSTATE_SETMS |
|
||||
LTQ_SPI_WHBSTATE_CLR_ERRORS,
|
||||
LTQ_SPI_WHBSTATE);
|
||||
|
@ -386,8 +387,8 @@ static void lantiq_ssc_hw_init(const struct lantiq_ssc_spi *spi)
|
|||
|
||||
static int lantiq_ssc_setup(struct spi_device *spidev)
|
||||
{
|
||||
struct spi_master *master = spidev->master;
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
|
||||
struct spi_controller *host = spidev->controller;
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host);
|
||||
unsigned int cs = spi_get_chipselect(spidev, 0);
|
||||
u32 gpocon;
|
||||
|
||||
|
@ -415,10 +416,10 @@ static int lantiq_ssc_setup(struct spi_device *spidev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lantiq_ssc_prepare_message(struct spi_master *master,
|
||||
static int lantiq_ssc_prepare_message(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
hw_enter_config_mode(spi);
|
||||
hw_setup_clock_mode(spi, message->spi->mode);
|
||||
|
@ -460,10 +461,10 @@ static void hw_setup_transfer(struct lantiq_ssc_spi *spi,
|
|||
lantiq_ssc_writel(spi, con, LTQ_SPI_CON);
|
||||
}
|
||||
|
||||
static int lantiq_ssc_unprepare_message(struct spi_master *master,
|
||||
static int lantiq_ssc_unprepare_message(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
flush_workqueue(spi->wq);
|
||||
|
||||
|
@ -692,8 +693,8 @@ static irqreturn_t lantiq_ssc_err_interrupt(int irq, void *data)
|
|||
lantiq_ssc_maskl(spi, 0, LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
|
||||
|
||||
/* set bad status so it can be retried */
|
||||
if (spi->master->cur_msg)
|
||||
spi->master->cur_msg->status = -EIO;
|
||||
if (spi->host->cur_msg)
|
||||
spi->host->cur_msg->status = -EIO;
|
||||
queue_work(spi->wq, &spi->work);
|
||||
spin_unlock(&spi->lock);
|
||||
|
||||
|
@ -771,22 +772,22 @@ static void lantiq_ssc_bussy_work(struct work_struct *work)
|
|||
u32 stat = lantiq_ssc_readl(spi, LTQ_SPI_STAT);
|
||||
|
||||
if (!(stat & LTQ_SPI_STAT_BSY)) {
|
||||
spi_finalize_current_transfer(spi->master);
|
||||
spi_finalize_current_transfer(spi->host);
|
||||
return;
|
||||
}
|
||||
|
||||
cond_resched();
|
||||
} while (!time_after_eq(jiffies, end));
|
||||
|
||||
if (spi->master->cur_msg)
|
||||
spi->master->cur_msg->status = -EIO;
|
||||
spi_finalize_current_transfer(spi->master);
|
||||
if (spi->host->cur_msg)
|
||||
spi->host->cur_msg->status = -EIO;
|
||||
spi_finalize_current_transfer(spi->host);
|
||||
}
|
||||
|
||||
static void lantiq_ssc_handle_err(struct spi_master *master,
|
||||
static void lantiq_ssc_handle_err(struct spi_controller *host,
|
||||
struct spi_message *message)
|
||||
{
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
/* flush FIFOs on timeout */
|
||||
rx_fifo_flush(spi);
|
||||
|
@ -795,7 +796,7 @@ static void lantiq_ssc_handle_err(struct spi_master *master,
|
|||
|
||||
static void lantiq_ssc_set_cs(struct spi_device *spidev, bool enable)
|
||||
{
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(spidev->master);
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(spidev->controller);
|
||||
unsigned int cs = spi_get_chipselect(spidev, 0);
|
||||
u32 fgpo;
|
||||
|
||||
|
@ -807,11 +808,11 @@ static void lantiq_ssc_set_cs(struct spi_device *spidev, bool enable)
|
|||
lantiq_ssc_writel(spi, fgpo, LTQ_SPI_FPGO);
|
||||
}
|
||||
|
||||
static int lantiq_ssc_transfer_one(struct spi_master *master,
|
||||
static int lantiq_ssc_transfer_one(struct spi_controller *host,
|
||||
struct spi_device *spidev,
|
||||
struct spi_transfer *t)
|
||||
{
|
||||
struct lantiq_ssc_spi *spi = spi_master_get_devdata(master);
|
||||
struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host);
|
||||
|
||||
hw_setup_transfer(spi, spidev, t);
|
||||
|
||||
|
@ -903,7 +904,7 @@ MODULE_DEVICE_TABLE(of, lantiq_ssc_match);
|
|||
static int lantiq_ssc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_master *master;
|
||||
struct spi_controller *host;
|
||||
struct lantiq_ssc_spi *spi;
|
||||
const struct lantiq_ssc_hwcfg *hwcfg;
|
||||
u32 id, supports_dma, revision;
|
||||
|
@ -912,33 +913,33 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
|
||||
hwcfg = of_device_get_match_data(dev);
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));
|
||||
if (!master)
|
||||
host = spi_alloc_host(dev, sizeof(struct lantiq_ssc_spi));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
spi = spi_master_get_devdata(master);
|
||||
spi->master = master;
|
||||
spi = spi_controller_get_devdata(host);
|
||||
spi->host = host;
|
||||
spi->dev = dev;
|
||||
spi->hwcfg = hwcfg;
|
||||
platform_set_drvdata(pdev, spi);
|
||||
spi->regbase = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(spi->regbase)) {
|
||||
err = PTR_ERR(spi->regbase);
|
||||
goto err_master_put;
|
||||
goto err_host_put;
|
||||
}
|
||||
|
||||
err = hwcfg->cfg_irq(pdev, spi);
|
||||
if (err)
|
||||
goto err_master_put;
|
||||
goto err_host_put;
|
||||
|
||||
spi->spi_clk = devm_clk_get(dev, "gate");
|
||||
if (IS_ERR(spi->spi_clk)) {
|
||||
err = PTR_ERR(spi->spi_clk);
|
||||
goto err_master_put;
|
||||
goto err_host_put;
|
||||
}
|
||||
err = clk_prepare_enable(spi->spi_clk);
|
||||
if (err)
|
||||
goto err_master_put;
|
||||
goto err_host_put;
|
||||
|
||||
/*
|
||||
* Use the old clk_get_fpi() function on Lantiq platform, till it
|
||||
|
@ -964,19 +965,19 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
spi->bits_per_word = 8;
|
||||
spi->speed_hz = 0;
|
||||
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
master->num_chipselect = num_cs;
|
||||
master->use_gpio_descriptors = true;
|
||||
master->setup = lantiq_ssc_setup;
|
||||
master->set_cs = lantiq_ssc_set_cs;
|
||||
master->handle_err = lantiq_ssc_handle_err;
|
||||
master->prepare_message = lantiq_ssc_prepare_message;
|
||||
master->unprepare_message = lantiq_ssc_unprepare_message;
|
||||
master->transfer_one = lantiq_ssc_transfer_one;
|
||||
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH |
|
||||
SPI_LOOP;
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) |
|
||||
SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
|
||||
host->dev.of_node = pdev->dev.of_node;
|
||||
host->num_chipselect = num_cs;
|
||||
host->use_gpio_descriptors = true;
|
||||
host->setup = lantiq_ssc_setup;
|
||||
host->set_cs = lantiq_ssc_set_cs;
|
||||
host->handle_err = lantiq_ssc_handle_err;
|
||||
host->prepare_message = lantiq_ssc_prepare_message;
|
||||
host->unprepare_message = lantiq_ssc_unprepare_message;
|
||||
host->transfer_one = lantiq_ssc_transfer_one;
|
||||
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH |
|
||||
SPI_LOOP;
|
||||
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) |
|
||||
SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
|
||||
|
||||
spi->wq = alloc_ordered_workqueue(dev_name(dev), WQ_MEM_RECLAIM);
|
||||
if (!spi->wq) {
|
||||
|
@ -997,9 +998,9 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
|
|||
"Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n",
|
||||
revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma);
|
||||
|
||||
err = devm_spi_register_master(dev, master);
|
||||
err = devm_spi_register_controller(dev, host);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to register spi_master\n");
|
||||
dev_err(dev, "failed to register spi host\n");
|
||||
goto err_wq_destroy;
|
||||
}
|
||||
|
||||
|
@ -1011,8 +1012,8 @@ err_clk_put:
|
|||
clk_put(spi->fpi_clk);
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(spi->spi_clk);
|
||||
err_master_put:
|
||||
spi_master_put(master);
|
||||
err_host_put:
|
||||
spi_controller_put(host);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
// Loongson SPI Support
|
||||
// Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "spi-loongson.h"
|
||||
|
||||
static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg,
|
||||
unsigned char data)
|
||||
{
|
||||
writeb(data, spi->base + reg);
|
||||
}
|
||||
|
||||
static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg)
|
||||
{
|
||||
return readb(spi->base + reg);
|
||||
}
|
||||
|
||||
static void loongson_spi_set_cs(struct spi_device *spi, bool en)
|
||||
{
|
||||
int cs;
|
||||
unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0);
|
||||
unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0));
|
||||
struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG) & ~mask;
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, val | cs);
|
||||
}
|
||||
|
||||
static void loongson_spi_set_clk(struct loongson_spi *loongson_spi, unsigned int hz)
|
||||
{
|
||||
unsigned char val;
|
||||
unsigned int div, div_tmp;
|
||||
static const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11};
|
||||
|
||||
div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096);
|
||||
div_tmp = rdiv[fls(div - 1)];
|
||||
loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0;
|
||||
loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2;
|
||||
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
|
||||
val &= ~GENMASK(1, 0);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val |
|
||||
loongson_spi->spcr);
|
||||
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
|
||||
val &= ~GENMASK(1, 0);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, val |
|
||||
loongson_spi->sper);
|
||||
loongson_spi->hz = hz;
|
||||
}
|
||||
|
||||
static void loongson_spi_set_mode(struct loongson_spi *loongson_spi,
|
||||
struct spi_device *spi)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
|
||||
val &= ~(LOONGSON_SPI_SPCR_CPOL | LOONGSON_SPI_SPCR_CPHA);
|
||||
if (spi->mode & SPI_CPOL)
|
||||
val |= LOONGSON_SPI_SPCR_CPOL;
|
||||
if (spi->mode & SPI_CPHA)
|
||||
val |= LOONGSON_SPI_SPCR_CPHA;
|
||||
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val);
|
||||
loongson_spi->mode |= spi->mode;
|
||||
}
|
||||
|
||||
static int loongson_spi_update_state(struct loongson_spi *loongson_spi,
|
||||
struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
if (t && loongson_spi->hz != t->speed_hz)
|
||||
loongson_spi_set_clk(loongson_spi, t->speed_hz);
|
||||
|
||||
if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK)
|
||||
loongson_spi_set_mode(loongson_spi, spi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loongson_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct loongson_spi *loongson_spi;
|
||||
|
||||
loongson_spi = spi_controller_get_devdata(spi->controller);
|
||||
if (spi->bits_per_word % 8)
|
||||
return -EINVAL;
|
||||
|
||||
if (spi_get_chipselect(spi, 0) >= spi->controller->num_chipselect)
|
||||
return -EINVAL;
|
||||
|
||||
loongson_spi->hz = 0;
|
||||
loongson_spi_set_cs(spi, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loongson_spi_write_read_8bit(struct spi_device *spi, const u8 **tx_buf,
|
||||
u8 **rx_buf, unsigned int num)
|
||||
{
|
||||
int ret;
|
||||
struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
if (tx_buf && *tx_buf)
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, *((*tx_buf)++));
|
||||
else
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, 0);
|
||||
|
||||
ret = readb_poll_timeout(loongson_spi->base + LOONGSON_SPI_SPSR_REG,
|
||||
loongson_spi->spsr, (loongson_spi->spsr &
|
||||
LOONGSON_SPI_SPSR_RFEMPTY) != LOONGSON_SPI_SPSR_RFEMPTY,
|
||||
1, USEC_PER_MSEC);
|
||||
|
||||
if (rx_buf && *rx_buf)
|
||||
*(*rx_buf)++ = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
|
||||
else
|
||||
loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int loongson_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
{
|
||||
int ret;
|
||||
unsigned int count;
|
||||
const u8 *tx = xfer->tx_buf;
|
||||
u8 *rx = xfer->rx_buf;
|
||||
|
||||
count = xfer->len;
|
||||
do {
|
||||
ret = loongson_spi_write_read_8bit(spi, &tx, &rx, count);
|
||||
if (ret)
|
||||
break;
|
||||
} while (--count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int loongson_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *m)
|
||||
{
|
||||
struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctlr);
|
||||
|
||||
loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para &
|
||||
~LOONGSON_SPI_PARA_MEM_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loongson_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
{
|
||||
struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
|
||||
|
||||
loongson_spi_update_state(loongson_spi, spi, xfer);
|
||||
if (xfer->len)
|
||||
return loongson_spi_write_read(spi, xfer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loongson_spi_unprepare_message(struct spi_controller *ctrl, struct spi_message *m)
|
||||
{
|
||||
struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctrl);
|
||||
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void loongson_spi_reginit(struct loongson_spi *loongson_spi_dev)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
|
||||
val &= ~LOONGSON_SPI_SPCR_SPE;
|
||||
loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
|
||||
|
||||
loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPSR_REG,
|
||||
(LOONGSON_SPI_SPSR_SPIF | LOONGSON_SPI_SPSR_WCOL));
|
||||
|
||||
val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG);
|
||||
val |= LOONGSON_SPI_SPCR_SPE;
|
||||
loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val);
|
||||
}
|
||||
|
||||
int loongson_spi_init_controller(struct device *dev, void __iomem *regs)
|
||||
{
|
||||
struct spi_controller *controller;
|
||||
struct loongson_spi *spi;
|
||||
struct clk *clk;
|
||||
|
||||
controller = devm_spi_alloc_host(dev, sizeof(struct loongson_spi));
|
||||
if (controller == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
controller->mode_bits = SPI_MODE_X_MASK | SPI_CS_HIGH;
|
||||
controller->setup = loongson_spi_setup;
|
||||
controller->prepare_message = loongson_spi_prepare_message;
|
||||
controller->transfer_one = loongson_spi_transfer_one;
|
||||
controller->unprepare_message = loongson_spi_unprepare_message;
|
||||
controller->set_cs = loongson_spi_set_cs;
|
||||
controller->num_chipselect = 4;
|
||||
device_set_node(&controller->dev, dev_fwnode(dev));
|
||||
dev_set_drvdata(dev, controller);
|
||||
|
||||
spi = spi_controller_get_devdata(controller);
|
||||
spi->base = regs;
|
||||
spi->controller = controller;
|
||||
|
||||
clk = devm_clk_get_optional(dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return dev_err_probe(dev, PTR_ERR(clk), "unable to get clock\n");
|
||||
|
||||
spi->clk_rate = clk_get_rate(clk);
|
||||
loongson_spi_reginit(spi);
|
||||
|
||||
spi->mode = 0;
|
||||
|
||||
return devm_spi_register_controller(dev, controller);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, SPI_LOONGSON_CORE);
|
||||
|
||||
static int __maybe_unused loongson_spi_suspend(struct device *dev)
|
||||
{
|
||||
struct loongson_spi *loongson_spi;
|
||||
struct spi_controller *controller;
|
||||
|
||||
controller = dev_get_drvdata(dev);
|
||||
spi_controller_suspend(controller);
|
||||
|
||||
loongson_spi = spi_controller_get_devdata(controller);
|
||||
|
||||
loongson_spi->spcr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
|
||||
loongson_spi->sper = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
|
||||
loongson_spi->spsr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG);
|
||||
loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG);
|
||||
loongson_spi->sfcs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG);
|
||||
loongson_spi->timi = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_TIMI_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused loongson_spi_resume(struct device *dev)
|
||||
{
|
||||
struct loongson_spi *loongson_spi;
|
||||
struct spi_controller *controller;
|
||||
|
||||
controller = dev_get_drvdata(dev);
|
||||
loongson_spi = spi_controller_get_devdata(controller);
|
||||
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, loongson_spi->spcr);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, loongson_spi->sper);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPSR_REG, loongson_spi->spsr);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, loongson_spi->sfcs);
|
||||
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_TIMI_REG, loongson_spi->timi);
|
||||
|
||||
spi_controller_resume(controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops loongson_spi_dev_pm_ops = {
|
||||
.suspend = loongson_spi_suspend,
|
||||
.resume = loongson_spi_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, SPI_LOONGSON_CORE);
|
||||
|
||||
MODULE_DESCRIPTION("Loongson SPI core driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,55 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
// PCI interface driver for Loongson SPI Support
|
||||
// Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "spi-loongson.h"
|
||||
|
||||
static int loongson_spi_pci_register(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
int ret;
|
||||
void __iomem *reg_base;
|
||||
struct device *dev = &pdev->dev;
|
||||
int pci_bar = 0;
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "cannot enable pci device\n");
|
||||
|
||||
ret = pcim_iomap_regions(pdev, BIT(pci_bar), pci_name(pdev));
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to request and remap memory\n");
|
||||
|
||||
reg_base = pcim_iomap_table(pdev)[pci_bar];
|
||||
|
||||
ret = loongson_spi_init_controller(dev, reg_base);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to initialize controller\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_device_id loongson_spi_devices[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a0b) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a1b) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, loongson_spi_devices);
|
||||
|
||||
static struct pci_driver loongson_spi_pci_driver = {
|
||||
.name = "loongson-spi-pci",
|
||||
.id_table = loongson_spi_devices,
|
||||
.probe = loongson_spi_pci_register,
|
||||
.driver = {
|
||||
.bus = &pci_bus_type,
|
||||
.pm = &loongson_spi_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
module_pci_driver(loongson_spi_pci_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Loongson spi pci driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
|
|
@ -0,0 +1,47 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
// Platform driver for Loongson SPI Support
|
||||
// Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "spi-loongson.h"
|
||||
|
||||
static int loongson_spi_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
void __iomem *reg_base;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(reg_base))
|
||||
return PTR_ERR(reg_base);
|
||||
|
||||
ret = loongson_spi_init_controller(dev, reg_base);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to initialize controller\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id loongson_spi_id_table[] = {
|
||||
{ .compatible = "loongson,ls2k1000-spi" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, loongson_spi_id_table);
|
||||
|
||||
static struct platform_driver loongson_spi_plat_driver = {
|
||||
.probe = loongson_spi_platform_probe,
|
||||
.driver = {
|
||||
.name = "loongson-spi",
|
||||
.bus = &platform_bus_type,
|
||||
.pm = &loongson_spi_dev_pm_ops,
|
||||
.of_match_table = loongson_spi_id_table,
|
||||
},
|
||||
};
|
||||
module_platform_driver(loongson_spi_plat_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Loongson spi platform driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
|
|
@ -0,0 +1,49 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/* Header File for Loongson SPI Driver. */
|
||||
/* Copyright (C) 2023 Loongson Technology Corporation Limited */
|
||||
|
||||
#ifndef __LINUX_SPI_LOONGSON_H
|
||||
#define __LINUX_SPI_LOONGSON_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define LOONGSON_SPI_SPCR_REG 0x00
|
||||
#define LOONGSON_SPI_SPSR_REG 0x01
|
||||
#define LOONGSON_SPI_FIFO_REG 0x02
|
||||
#define LOONGSON_SPI_SPER_REG 0x03
|
||||
#define LOONGSON_SPI_PARA_REG 0x04
|
||||
#define LOONGSON_SPI_SFCS_REG 0x05
|
||||
#define LOONGSON_SPI_TIMI_REG 0x06
|
||||
|
||||
/* Bits definition for Loongson SPI register */
|
||||
#define LOONGSON_SPI_PARA_MEM_EN BIT(0)
|
||||
#define LOONGSON_SPI_SPCR_CPHA BIT(2)
|
||||
#define LOONGSON_SPI_SPCR_CPOL BIT(3)
|
||||
#define LOONGSON_SPI_SPCR_SPE BIT(6)
|
||||
#define LOONGSON_SPI_SPSR_RFEMPTY BIT(0)
|
||||
#define LOONGSON_SPI_SPSR_WCOL BIT(6)
|
||||
#define LOONGSON_SPI_SPSR_SPIF BIT(7)
|
||||
|
||||
struct device;
|
||||
struct spi_controller;
|
||||
|
||||
struct loongson_spi {
|
||||
struct spi_controller *controller;
|
||||
void __iomem *base;
|
||||
int cs_active;
|
||||
unsigned int hz;
|
||||
unsigned char spcr;
|
||||
unsigned char sper;
|
||||
unsigned char spsr;
|
||||
unsigned char para;
|
||||
unsigned char sfcs;
|
||||
unsigned char timi;
|
||||
unsigned int mode;
|
||||
u64 clk_rate;
|
||||
};
|
||||
|
||||
int loongson_spi_init_controller(struct device *dev, void __iomem *reg);
|
||||
extern const struct dev_pm_ops loongson_spi_dev_pm_ops;
|
||||
#endif /* __LINUX_SPI_LOONGSON_H */
|
|
@ -14,8 +14,8 @@
|
|||
#include <linux/ktime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/list_sort.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define DRIVER_NAME "spi_lp8841_rtc"
|
||||
|
@ -75,14 +74,14 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data,
|
|||
for (; likely(bits); bits--) {
|
||||
|
||||
/* setup LSB (to slave) on leading edge */
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_TX) == 0)
|
||||
setmosi(data, (word & 1));
|
||||
|
||||
usleep_range(usecs, usecs + 1); /* T(setup) */
|
||||
|
||||
/* sample LSB (from slave) on trailing edge */
|
||||
word >>= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
if ((flags & SPI_CONTROLLER_NO_RX) == 0)
|
||||
word |= (getmiso(data) << 31);
|
||||
|
||||
setsck(data, !cpol);
|
||||
|
@ -113,7 +112,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master,
|
|||
while (likely(count > 0)) {
|
||||
word = *tx++;
|
||||
bitbang_txrx_be_cpha0_lsb(data, 1, 0,
|
||||
SPI_MASTER_NO_RX, word, 8);
|
||||
SPI_CONTROLLER_NO_RX, word, 8);
|
||||
count--;
|
||||
}
|
||||
} else if (rx) {
|
||||
|
@ -121,7 +120,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master,
|
|||
writeb(data->state, data->iomem);
|
||||
while (likely(count > 0)) {
|
||||
word = bitbang_txrx_be_cpha0_lsb(data, 1, 0,
|
||||
SPI_MASTER_NO_TX, word, 8);
|
||||
SPI_CONTROLLER_NO_TX, word, 8);
|
||||
*rx++ = word;
|
||||
count--;
|
||||
}
|
||||
|
@ -191,7 +190,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, master);
|
||||
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST;
|
||||
|
||||
master->bus_num = pdev->id;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -864,7 +863,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|||
SPI_BPW_MASK(24) |
|
||||
SPI_BPW_MASK(16) |
|
||||
SPI_BPW_MASK(8);
|
||||
master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
|
||||
master->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX);
|
||||
master->min_speed_hz = spicc->data->min_speed_hz;
|
||||
master->max_speed_hz = spicc->data->max_speed_hz;
|
||||
master->setup = meson_spicc_setup;
|
||||
|
|
|
@ -530,10 +530,8 @@ static int mchp_corespi_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(spi->regs);
|
||||
|
||||
spi->irq = platform_get_irq(pdev, 0);
|
||||
if (spi->irq <= 0)
|
||||
return dev_err_probe(&pdev->dev, -ENXIO,
|
||||
"invalid IRQ %d for SPI controller\n",
|
||||
spi->irq);
|
||||
if (spi->irq < 0)
|
||||
return spi->irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt,
|
||||
IRQF_SHARED, dev_name(&pdev->dev), master);
|
||||
|
|
|
@ -53,7 +53,7 @@ struct mpc512x_psc_spi {
|
|||
int type;
|
||||
void __iomem *psc;
|
||||
struct mpc512x_psc_fifo __iomem *fifo;
|
||||
unsigned int irq;
|
||||
int irq;
|
||||
u8 bits_per_word;
|
||||
u32 mclk_rate;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ struct mpc52xx_psc_spi {
|
|||
/* driver internal data */
|
||||
struct mpc52xx_psc __iomem *psc;
|
||||
struct mpc52xx_psc_fifo __iomem *fifo;
|
||||
unsigned int irq;
|
||||
int irq;
|
||||
u8 bits_per_word;
|
||||
|
||||
struct completion done;
|
||||
|
|
|
@ -1142,7 +1142,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
|
|||
master->mode_bits |= SPI_CS_HIGH;
|
||||
|
||||
if (mdata->dev_comp->must_tx)
|
||||
master->flags = SPI_MASTER_MUST_TX;
|
||||
master->flags = SPI_CONTROLLER_MUST_TX;
|
||||
if (mdata->dev_comp->ipm_design)
|
||||
master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL |
|
||||
SPI_RX_QUAD | SPI_TX_QUAD;
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
|
|
|
@ -76,7 +76,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/nand-ecc-mtk.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
|
|
|
@ -572,7 +572,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
|
|||
master->mode_bits = SPI_CPOL | SPI_CPHA;
|
||||
master->num_chipselect = 3;
|
||||
master->dev.of_node = np;
|
||||
master->flags = SPI_MASTER_HALF_DUPLEX;
|
||||
master->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
master->auto_runtime_pm = true;
|
||||
|
||||
spi = spi_master_get_devdata(master);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче