Commit 1ba0b52e authored by Mark Brown's avatar Mark Brown

Merge branch 'spi-5.7' into spi-next

parents 16fbf79b ebb3b9a9
# SPDX-License-Identifier: (GPL-2.0-or-later)
%YAML 1.2
---
$id: http://devicetree.org/schemas/fsi/ibm,fsi2spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: IBM FSI-attached SPI controllers
maintainers:
- Eddie James <eajames@linux.ibm.com>
description: |
This binding describes an FSI CFAM engine called the FSI2SPI. Therefore this
node will always be a child of an FSI CFAM node; see fsi.txt for details on
FSI slave and CFAM nodes. This FSI2SPI engine provides access to a number of
SPI controllers.
properties:
compatible:
enum:
- ibm,fsi2spi
reg:
items:
- description: FSI slave address
required:
- compatible
- reg
examples:
- |
fsi2spi@1c00 {
compatible = "ibm,fsi2spi";
reg = <0x1c00 0x400>;
};
......@@ -61,6 +61,7 @@ Regulator nodes are identified by their compatible:
"qcom,rpm-pm8901-regulators"
"qcom,rpm-pm8921-regulators"
"qcom,rpm-pm8018-regulators"
"qcom,rpm-smb208-regulators"
- vdd_l0_l1_lvs-supply:
- vdd_l2_l11_l12-supply:
......@@ -171,6 +172,9 @@ pm8018:
s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
l12, l14, lvs1
smb208:
s1a, s1b, s2a, s2b
The content of each sub-node is defined by the standard binding for regulators -
see regulator.txt - with additional custom properties described below:
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/mps,mp5416.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Monolithic Power System MP5416 PMIC
maintainers:
- Saravanan Sekar <sravanhome@gmail.com>
properties:
$nodename:
pattern: "^pmic@[0-9a-f]{1,2}$"
compatible:
enum:
- mps,mp5416
reg:
maxItems: 1
regulators:
type: object
description: |
list of regulators provided by this controller, must be named
after their hardware counterparts BUCK[1-4] and LDO[1-4]
patternProperties:
"^buck[1-4]$":
allOf:
- $ref: "regulator.yaml#"
type: object
"^ldo[1-4]$":
allOf:
- $ref: "regulator.yaml#"
type: object
additionalProperties: false
additionalProperties: false
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@69 {
compatible = "mps,mp5416";
reg = <0x69>;
regulators {
buck1 {
regulator-name = "buck1";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <2187500>;
regulator-min-microamp = <3800000>;
regulator-max-microamp = <6800000>;
regulator-boot-on;
};
ldo2 {
regulator-name = "ldo2";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <3975000>;
};
};
};
};
...
......@@ -22,6 +22,7 @@ properties:
enum:
- amlogic,meson-gx-spicc # SPICC controller on Amlogic GX and compatible SoCs
- amlogic,meson-axg-spicc # SPICC controller on Amlogic AXG and compatible SoCs
- amlogic,meson-g12a-spicc # SPICC controller on Amlogic G12A and compatible SoCs
interrupts:
maxItems: 1
......@@ -40,6 +41,27 @@ properties:
items:
- const: core
if:
properties:
compatible:
contains:
enum:
- amlogic,meson-g12a-spicc
then:
properties:
clocks:
contains:
items:
- description: controller register bus clock
- description: baud rate generator and delay control clock
clock-names:
minItems: 2
items:
- const: core
- const: pclk
required:
- compatible
- reg
......
......@@ -10,7 +10,10 @@ Required properties:
- "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
- "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
- "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
- "fsl,imx8mq-ecspi" for SPI compatible with the one integrated on i.MX8M
- "fsl,imx8mq-ecspi" for SPI compatible with the one integrated on i.MX8MQ
- "fsl,imx8mm-ecspi" for SPI compatible with the one integrated on i.MX8MM
- "fsl,imx8mn-ecspi" for SPI compatible with the one integrated on i.MX8MN
- "fsl,imx8mp-ecspi" for SPI compatible with the one integrated on i.MX8MP
- reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt
- clocks : Clock specifiers for both ipg and per clocks.
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/qca,ar934x-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Atheros AR934x/QCA95xx SoC SPI controller
maintainers:
- Chuanhong Guo <gch981213@gmail.com>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
const: qca,ar934x-spi
reg:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- clocks
- '#address-cells'
- '#size-cells'
examples:
- |
#include <dt-bindings/clock/ath79-clk.h>
spi: spi@1f000000 {
compatible = "qca,ar934x-spi";
reg = <0x1f000000 0x1c>;
clocks = <&pll ATH79_CLK_AHB>;
#address-cells = <1>;
#size-cells = <0>;
};
......@@ -52,6 +52,12 @@ properties:
description:
The SPI controller acts as a slave, instead of a master.
oneOf:
- required:
- "#address-cells"
- required:
- spi-slave
patternProperties:
"^slave$":
type: object
......@@ -114,7 +120,7 @@ patternProperties:
- enum: [ 1, 2, 4, 8 ]
- default: 1
description:
Bus width to the SPI bus used for MISO.
Bus width to the SPI bus used for read transfers.
spi-rx-delay-us:
description:
......@@ -126,7 +132,7 @@ patternProperties:
- enum: [ 1, 2, 4, 8 ]
- default: 1
description:
Bus width to the SPI bus used for MOSI.
Bus width to the SPI bus used for write transfers.
spi-tx-delay-us:
description:
......
ARM Freescale DSPI controller
Required properties:
- compatible : "fsl,vf610-dspi", "fsl,ls1021a-v1.0-dspi",
"fsl,ls2085a-dspi"
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
"fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
"fsl,ls1088a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
- compatible : must be one of:
"fsl,vf610-dspi",
"fsl,ls1021a-v1.0-dspi",
"fsl,ls1012a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
"fsl,ls1028a-dspi",
"fsl,ls1043a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
"fsl,ls1046a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
"fsl,ls1088a-dspi" (optionally followed by "fsl,ls1021a-v1.0-dspi"),
"fsl,ls2080a-dspi" (optionally followed by "fsl,ls2085a-dspi"),
"fsl,ls2085a-dspi",
"fsl,lx2160a-dspi",
- reg : Offset and length of the register set for the device
- interrupts : Should contain SPI controller interrupt
- clocks: from common clock binding: handle to dspi clock.
......@@ -14,11 +19,11 @@ Required properties:
- pinctrl-0: pin control group to be used for this controller.
- pinctrl-names: must contain a "default" entry.
- spi-num-chipselects : the number of the chipselect signals.
- bus-num : the slave chip chipselect signal number.
Optional property:
- big-endian: If present the dspi device's registers are implemented
in big endian mode.
- bus-num : the slave chip chipselect signal number.
Optional SPI slave node properties:
- fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
......
* Serial NOR flash controller for MediaTek SoCs
* Serial NOR flash controller for MediaTek ARM SoCs
Required properties:
- compatible: For mt8173, compatible should be "mediatek,mt8173-nor",
......@@ -13,6 +13,7 @@ Required properties:
"mediatek,mt7629-nor", "mediatek,mt8173-nor"
"mediatek,mt8173-nor"
- reg: physical base address and length of the controller's register
- interrupts: Interrupt number used by the controller.
- clocks: the phandle of the clocks needed by the nor controller
- clock-names: the names of the clocks
the clocks should be named "spi" and "sf". "spi" is used for spi bus,
......@@ -22,20 +23,16 @@ Required properties:
- #address-cells: should be <1>
- #size-cells: should be <0>
The SPI flash must be a child of the nor_flash node and must have a
compatible property. Also see jedec,spi-nor.txt.
Required properties:
- compatible: May include a device-specific string consisting of the manufacturer
and name of the chip. Must also include "jedec,spi-nor" for any
SPI NOR flash that can be identified by the JEDEC READ ID opcode (0x9F).
- reg : Chip-Select number
There should be only one spi slave device following generic spi bindings.
It's not recommended to use this controller for devices other than SPI NOR
flash due to limited transfer capability of this controller.
Example:
nor_flash: spi@1100d000 {
compatible = "mediatek,mt8173-nor";
reg = <0 0x1100d000 0 0xe0>;
interrupts = <&spi_flash_irq>;
clocks = <&pericfg CLK_PERI_SPI>,
<&topckgen CLK_TOP_SPINFI_IFR_SEL>;
clock-names = "spi", "sf";
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/spi-mux.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic SPI Multiplexer
description: |
This binding describes a SPI bus multiplexer to route the SPI chip select
signals. This can be used when you need more devices than the SPI controller
has chip selects available. An example setup is shown in ASCII art; the actual
setting of the multiplexer to a channel needs to be done by a specific SPI mux
driver.
MOSI /--------------------------------+--------+--------+--------\
MISO |/------------------------------+|-------+|-------+|-------\|
SCL ||/----------------------------+||------+||------+||------\||
||| ||| ||| ||| |||
+------------+ ||| ||| ||| |||
| SoC ||| | +-+++-+ +-+++-+ +-+++-+ +-+++-+
| ||| | | dev | | dev | | dev | | dev |
| +--+++-+ | CS-X +------+\ +--+--+ +--+--+ +--+--+ +--+--+
| | SPI +-|-------+ Mux |\\ CS-0 | | | |
| +------+ | +--+---+\\\-------/ CS-1 | | |
| | | \\\----------------/ CS-2 | |
| +------+ | | \\-------------------------/ CS-3 |
| | ? +-|----------/ \----------------------------------/
| +------+ |
+------------+
allOf:
- $ref: "/schemas/spi/spi-controller.yaml#"
maintainers:
- Chris Packham <chris.packham@alliedtelesis.co.nz>
properties:
compatible:
const: spi-mux
mux-controls:
maxItems: 1
required:
- compatible
- reg
- spi-max-frequency
- mux-controls
examples:
- |
#include <dt-bindings/gpio/gpio.h>
mux: mux-controller {
compatible = "gpio-mux";
#mux-control-cells = <0>;
mux-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
};
spi {
#address-cells = <1>;
#size-cells = <0>;
spi@0 {
compatible = "spi-mux";
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <100000000>;
mux-controls = <&mux>;
spi-flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <40000000>;
};
spi-device@1 {
compatible = "lineartechnology,ltc2488";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <10000000>;
};
};
};
......@@ -2,6 +2,9 @@
Required properties:
- compatible : Should be "nxp,lx2160a-fspi"
"nxp,imx8qxp-fspi"
"nxp,imx8mm-fspi"
- reg : First contains the register location and length,
Second contains the memory mapping address and length
- reg-names : Should contain the resource reg names:
......
* Rockchip SPI Controller
The Rockchip SPI controller is used to interface with various devices such as flash
and display controllers using the SPI communication interface.
Required Properties:
- compatible: should be one of the following.
"rockchip,rv1108-spi" for rv1108 SoCs.
"rockchip,px30-spi", "rockchip,rk3066-spi" for px30 SoCs.
"rockchip,rk3036-spi" for rk3036 SoCS.
"rockchip,rk3066-spi" for rk3066 SoCs.
"rockchip,rk3188-spi" for rk3188 SoCs.
"rockchip,rk3228-spi" for rk3228 SoCS.
"rockchip,rk3288-spi" for rk3288 SoCs.
"rockchip,rk3368-spi" for rk3368 SoCs.
"rockchip,rk3399-spi" for rk3399 SoCs.
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The interrupt number to the cpu. The interrupt specifier format
depends on the interrupt controller.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names: Shall be "spiclk" for the transfer-clock, and "apb_pclk" for
the peripheral clock.
- #address-cells: should be 1.
- #size-cells: should be 0.
Optional Properties:
- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
- dma-names: DMA request names should include "tx" and "rx" if present.
- rx-sample-delay-ns: nanoseconds to delay after the SCLK edge before sampling
Rx data (may need to be fine tuned for high capacitance lines).
No delay (0) by default.
- pinctrl-names: Names for the pin configuration(s); may be "default" or
"sleep", where the "sleep" configuration may describe the state
the pins should be in during system suspend. See also
pinctrl/pinctrl-bindings.txt.
Example:
spi0: spi@ff110000 {
compatible = "rockchip,rk3066-spi";
reg = <0xff110000 0x1000>;
dmas = <&pdma1 11>, <&pdma1 12>;
dma-names = "tx", "rx";
rx-sample-delay-ns = <10>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk";
pinctrl-0 = <&spi1_pins>;
pinctrl-1 = <&spi1_sleep>;
pinctrl-names = "default", "sleep";
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/spi-rockchip.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip SPI Controller
description:
The Rockchip SPI controller is used to interface with various devices such
as flash and display controllers using the SPI communication interface.
allOf:
- $ref: "spi-controller.yaml#"
maintainers:
- Heiko Stuebner <heiko@sntech.de>
# Everything else is described in the common file
properties:
compatible:
oneOf:
- const: rockchip,rk3036-spi
- const: rockchip,rk3066-spi
- const: rockchip,rk3228-spi
- const: rockchip,rv1108-spi
- items:
- enum:
- rockchip,px30-spi
- rockchip,rk3188-spi
- rockchip,rk3288-spi
- rockchip,rk3308-spi
- rockchip,rk3328-spi
- rockchip,rk3368-spi
- rockchip,rk3399-spi
- const: rockchip,rk3066-spi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: transfer-clock
- description: peripheral clock
clock-names:
items:
- const: spiclk
- const: apb_pclk
dmas:
items:
- description: TX DMA Channel
- description: RX DMA Channel
dma-names:
items:
- const: tx
- const: rx
rx-sample-delay-ns:
default: 0
description:
Nano seconds to delay after the SCLK edge before sampling Rx data
(may need to be fine tuned for high capacitance lines).
If not specified 0 will be used.
pinctrl-names:
minItems: 1
items:
- const: default
- const: sleep
description:
Names for the pin configuration(s); may be "default" or "sleep",
where the "sleep" configuration may describe the state
the pins should be in during system suspend.
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/clock/rk3188-cru-common.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi0: spi@ff110000 {
compatible = "rockchip,rk3066-spi";
reg = <0xff110000 0x1000>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk";
dmas = <&pdma1 11>, <&pdma1 12>;
dma-names = "tx", "rx";
pinctrl-0 = <&spi1_pins>;
pinctrl-1 = <&spi1_sleep>;
pinctrl-names = "default", "sleep";
rx-sample-delay-ns = <10>;
#address-cells = <1>;
#size-cells = <0>;
};
......@@ -2276,6 +2276,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git
S: Maintained
F: Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
F: Documentation/devicetree/bindings/spi/spi-rockchip.yaml
F: arch/arm/boot/dts/rk3*
F: arch/arm/boot/dts/rv1108*
F: arch/arm/mach-rockchip/
......@@ -6858,6 +6859,13 @@ S: Maintained
F: drivers/i2c/busses/i2c-fsi.c
F: Documentation/devicetree/bindings/i2c/i2c-fsi.txt
FSI-ATTACHED SPI DRIVER
M: Eddie James <eajames@linux.ibm.com>
L: linux-spi@vger.kernel.org
S: Maintained
F: drivers/spi/spi-fsi.c
F: Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
FSNOTIFY: FILESYSTEM NOTIFICATION INFRASTRUCTURE
M: Jan Kara <jack@suse.cz>
R: Amir Goldstein <amir73il@gmail.com>
......@@ -11256,7 +11264,8 @@ F: drivers/tty/mxser.*
MONOLITHIC POWER SYSTEM PMIC DRIVER
M: Saravanan Sekar <sravanhome@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/regulator/mpq7920.yaml
F: Documentation/devicetree/bindings/regulator/mps,mp*.yaml
F: drivers/regulator/mp5416.c
F: drivers/regulator/mpq7920.c
F: drivers/regulator/mpq7920.h
......
......@@ -52,14 +52,6 @@ config SPI_HISI_SFC
help
This enables support for HiSilicon FMC SPI-NOR flash controller.
config SPI_MTK_QUADSPI
tristate "MediaTek Quad SPI controller"
depends on HAS_IOMEM
help
This enables support for the Quad SPI controller in master mode.
This controller does not support generic SPI. It only supports
SPI NOR.
config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
......
......@@ -3,7 +3,6 @@ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_SPI_MTK_QUADSPI) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o
......
This diff is collapsed.
......@@ -107,6 +107,7 @@ config REGULATOR_AD5398
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
depends on ARCH_MXC || COMPILE_TEST
depends on MFD_SYSCON
help
Say y here to support Freescale i.MX on-chip ANATOP LDOs
......@@ -613,6 +614,16 @@ config REGULATOR_MCP16502
through the regulator interface. In addition it enables
suspend-to-ram/standby transition.
config REGULATOR_MP5416
tristate "Monolithic MP5416 PMIC"
depends on I2C && OF
select REGMAP_I2C
help
Say y here to support the MP5416 PMIC. This will enable supports
the software controllable 4 buck and 4 LDO regulators.
Say M here if you want to include support for the regulator as a
module.
config REGULATOR_MP8859
tristate "MPS MP8859 regulator driver"
depends on I2C
......
......@@ -78,6 +78,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o
obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o
obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
......
......@@ -305,9 +305,13 @@ static int anatop_regulator_probe(struct platform_device *pdev)
/* register regulator */
rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n",
rdesc->name);
return PTR_ERR(rdev);
ret = PTR_ERR(rdev);
if (ret == -EPROBE_DEFER)
dev_dbg(dev, "failed to register %s, deferring...\n",
rdesc->name);
else
dev_err(dev, "failed to register %s\n", rdesc->name);
return ret;
}
platform_set_drvdata(pdev, rdev);
......
......@@ -381,8 +381,7 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
mask = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK |
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK;
enable = (ramp > 0) ?
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN :
!AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN;
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN : 0;
break;
}
......@@ -393,8 +392,7 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
mask = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK |
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK;
enable = (ramp > 0) ?
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN :
!AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN;
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN : 0;
break;
}
......
......@@ -73,7 +73,7 @@ struct da9062_regulators {
int irq_ldo_lim;
unsigned n_regulators;
/* Array size to be defined during init. Keep at end. */
struct da9062_regulator regulator[0];
struct da9062_regulator regulator[];
};
/* Regulator operations */
......
......@@ -66,7 +66,7 @@ struct da9063_regulator_data {
};
struct da9063_regulators_pdata {
unsigned n_regulators;
unsigned int n_regulators;
struct da9063_regulator_data *regulator_data;
};
......@@ -131,7 +131,7 @@ struct da9063_regulator_info {
/* Defines asignment of regulators info table to chip model */
struct da9063_dev_model {
const struct da9063_regulator_info *regulator_info;
unsigned n_regulators;
unsigned int n_regulators;
enum da9063_type type;
};
......@@ -150,9 +150,9 @@ struct da9063_regulator {
/* Encapsulates all information for the regulators driver */
struct da9063_regulators {
unsigned n_regulators;
unsigned int n_regulators;
/* Array size to be defined during init. Keep at end. */
struct da9063_regulator regulator[0];
struct da9063_regulator regulator[];
};
/* BUCK modes for DA9063 */
......@@ -165,38 +165,46 @@ enum {
/* Regulator operations */
/* Current limits array (in uA) for BCORE1, BCORE2, BPRO.
Entry indexes corresponds to register values. */
/*
* Current limits array (in uA) for BCORE1, BCORE2, BPRO.
* Entry indexes corresponds to register values.
*/
static const unsigned int da9063_buck_a_limits[] = {
500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000,
1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000
};
/* Current limits array (in uA) for BMEM, BIO, BPERI.
Entry indexes corresponds to register values. */
/*
* Current limits array (in uA) for BMEM, BIO, BPERI.
* Entry indexes corresponds to register values.
*/
static const unsigned int da9063_buck_b_limits[] = {
1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000,
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
};
/* Current limits array (in uA) for merged BCORE1 and BCORE2.
Entry indexes corresponds to register values. */
/*
* Current limits array (in uA) for merged BCORE1 and BCORE2.
* Entry indexes corresponds to register values.
*/
static const unsigned int da9063_bcores_merged_limits[] = {
1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2200000, 2400000,
2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000
};
/* Current limits array (in uA) for merged BMEM and BIO.
Entry indexes corresponds to register values. */
/*
* Current limits array (in uA) for merged BMEM and BIO.
* Entry indexes corresponds to register values.
*/
static const unsigned int da9063_bmem_bio_merged_limits[] = {
3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000,
4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
};
static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
unsigned val;
unsigned int val;
switch (mode) {
case REGULATOR_MODE_FAST:
......@@ -221,7 +229,7 @@ static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
* There are 3 modes to map to: FAST, NORMAL, and STANDBY.
*/
static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
struct regmap_field *field;
......@@ -271,10 +279,10 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
* There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state.
*/
static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode)
static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
unsigned val;
unsigned int val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
......@@ -290,7 +298,7 @@ static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode)
return regmap_field_write(regl->sleep, val);
}
static unsigned da9063_ldo_get_mode(struct regulator_dev *rdev)
static unsigned int da9063_ldo_get_mode(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
struct regmap_field *field;
......@@ -383,7 +391,8 @@ static int da9063_suspend_disable(struct regulator_dev *rdev)
return regmap_field_write(regl->suspend, 0);
}
static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned mode)
static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
int val;
......@@ -405,10 +414,11 @@ static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned mod
return regmap_field_write(regl->mode, val);
}
static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, unsigned mode)
static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
unsigned val;
unsigned int val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
......@@ -593,7 +603,7 @@ static irqreturn_t da9063_ldo_lim_event(int irq, void *data)
struct da9063_regulators *regulators = data;
struct da9063 *hw = regulators->regulator[0].hw;
struct da9063_regulator *regl;
int bits, i , ret;
int bits, i, ret;
ret = regmap_read(hw->regmap, DA9063_REG_STATUS_D, &bits);
if (ret < 0)
......@@ -605,10 +615,10 @@ static irqreturn_t da9063_ldo_lim_event(int irq, void *data)
continue;
if (BIT(regl->info->oc_event.lsb) & bits) {
regulator_lock(regl->rdev);
regulator_lock(regl->rdev);
regulator_notifier_call_chain(regl->rdev,
REGULATOR_EVENT_OVER_CURRENT, NULL);
regulator_unlock(regl->rdev);
regulator_unlock(regl->rdev);
}
}
......@@ -833,7 +843,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->suspend_sleep);
da9063->regmap, regl->info->suspend_sleep);
if (IS_ERR(regl->suspend_sleep))
return PTR_ERR(regl->suspend_sleep);
}
......@@ -867,12 +877,10 @@ static int da9063_regulator_probe(struct platform_device *pdev)
NULL, da9063_ldo_lim_event,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"LDO_LIM", regulators);
if (ret) {
if (ret)
dev_err(&pdev->dev, "Failed to request LDO_LIM IRQ.\n");
return ret;
}
return 0;
return ret;
}
static struct platform_driver da9063_regulator_driver = {
......
// SPDX-License-Identifier: GPL-2.0+
//
// mp5416.c - regulator driver for mps mp5416
//
// Copyright 2020 Monolithic Power Systems, Inc
//
// Author: Saravanan Sekar <sravanhome@gmail.com>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/i2c.h>
#define MP5416_REG_CTL0 0x00
#define MP5416_REG_CTL1 0x01
#define MP5416_REG_CTL2 0x02
#define MP5416_REG_ILIM 0x03
#define MP5416_REG_BUCK1 0x04
#define MP5416_REG_BUCK2 0x05
#define MP5416_REG_BUCK3 0x06
#define MP5416_REG_BUCK4 0x07
#define MP5416_REG_LDO1 0x08
#define MP5416_REG_LDO2 0x09
#define MP5416_REG_LDO3 0x0a
#define MP5416_REG_LDO4 0x0b
#define MP5416_REGULATOR_EN BIT(7)
#define MP5416_MASK_VSET 0x7f
#define MP5416_MASK_BUCK1_ILIM 0xc0
#define MP5416_MASK_BUCK2_ILIM 0x0c
#define MP5416_MASK_BUCK3_ILIM 0x30
#define MP5416_MASK_BUCK4_ILIM 0x03
#define MP5416_MASK_DVS_SLEWRATE 0xc0
/* values in uV */
#define MP5416_VOLT1_MIN 600000
#define MP5416_VOLT1_MAX 2187500
#define MP5416_VOLT1_STEP 12500
#define MP5416_VOLT2_MIN 800000
#define MP5416_VOLT2_MAX 3975000
#define MP5416_VOLT2_STEP 25000
#define MP5416_VOLT1_RANGE \
((MP5416_VOLT1_MAX - MP5416_VOLT1_MIN)/MP5416_VOLT1_STEP + 1)
#define MP5416_VOLT2_RANGE \
((MP5416_VOLT2_MAX - MP5416_VOLT2_MIN)/MP5416_VOLT2_STEP + 1)
#define MP5416BUCK(_name, _id, _ilim, _dreg, _dval, _vsel) \
[MP5416_BUCK ## _id] = { \
.id = MP5416_BUCK ## _id, \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.ops = &mp5416_buck_ops, \
.min_uV = MP5416_VOLT ##_vsel## _MIN, \
.uV_step = MP5416_VOLT ##_vsel## _STEP, \
.n_voltages = MP5416_VOLT ##_vsel## _RANGE, \
.curr_table = _ilim, \
.n_current_limits = ARRAY_SIZE(_ilim), \
.csel_reg = MP5416_REG_ILIM, \
.csel_mask = MP5416_MASK_BUCK ## _id ##_ILIM, \
.vsel_reg = MP5416_REG_BUCK ## _id, \
.vsel_mask = MP5416_MASK_VSET, \
.enable_reg = MP5416_REG_BUCK ## _id, \
.enable_mask = MP5416_REGULATOR_EN, \
.active_discharge_on = _dval, \
.active_discharge_reg = _dreg, \
.active_discharge_mask = _dval, \
.owner = THIS_MODULE, \
}
#define MP5416LDO(_name, _id, _dval) \
[MP5416_LDO ## _id] = { \
.id = MP5416_LDO ## _id, \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.ops = &mp5416_ldo_ops, \
.min_uV = MP5416_VOLT2_MIN, \
.uV_step = MP5416_VOLT2_STEP, \
.n_voltages = MP5416_VOLT2_RANGE, \
.vsel_reg = MP5416_REG_LDO ##_id, \
.vsel_mask = MP5416_MASK_VSET, \
.enable_reg = MP5416_REG_LDO ##_id, \
.enable_mask = MP5416_REGULATOR_EN, \
.active_discharge_on = _dval, \
.active_discharge_reg = MP5416_REG_CTL2, \
.active_discharge_mask = _dval, \
.owner = THIS_MODULE, \
}
enum mp5416_regulators {
MP5416_BUCK1,
MP5416_BUCK2,
MP5416_BUCK3,
MP5416_BUCK4,
MP5416_LDO1,
MP5416_LDO2,
MP5416_LDO3,
MP5416_LDO4,
MP5416_MAX_REGULATORS,
};
static const struct regmap_config mp5416_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x0d,
};
/* Current limits array (in uA)
* ILIM1 & ILIM3
*/
static const unsigned int mp5416_I_limits1[] = {
3800000, 4600000, 5600000, 6800000
};
/* ILIM2 & ILIM4 */
static const unsigned int mp5416_I_limits2[] = {
2200000, 3200000, 4200000, 5200000
};
static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay);
static const struct regulator_ops mp5416_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap,
};
static const struct regulator_ops mp5416_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap,
.get_current_limit = regulator_get_current_limit_regmap,
.set_current_limit = regulator_set_current_limit_regmap,
.set_ramp_delay = mp5416_set_ramp_delay,
};
static struct regulator_desc mp5416_regulators_desc[MP5416_MAX_REGULATORS] = {
MP5416BUCK("buck1", 1, mp5416_I_limits1, MP5416_REG_CTL1, BIT(0), 1),
MP5416BUCK("buck2", 2, mp5416_I_limits2, MP5416_REG_CTL1, BIT(1), 2),
MP5416BUCK("buck3", 3, mp5416_I_limits1, MP5416_REG_CTL1, BIT(2), 1),
MP5416BUCK("buck4", 4, mp5416_I_limits2, MP5416_REG_CTL2, BIT(5), 2),
MP5416LDO("ldo1", 1, BIT(4)),
MP5416LDO("ldo2", 2, BIT(3)),
MP5416LDO("ldo3", 3, BIT(2)),
MP5416LDO("ldo4", 4, BIT(1)),
};
/*
* DVS ramp rate BUCK1 to BUCK4
* 00: 32mV/us
* 01: 16mV/us
* 10: 8mV/us
* 11: 4mV/us
*/
static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
{
unsigned int ramp_val;
if (ramp_delay > 32000 || ramp_delay < 0)
return -EINVAL;
if (ramp_delay <= 4000)
ramp_val = 3;
else if (ramp_delay <= 8000)
ramp_val = 2;
else if (ramp_delay <= 16000)
ramp_val = 1;
else
ramp_val = 0;
return regmap_update_bits(rdev->regmap, MP5416_REG_CTL2,
MP5416_MASK_DVS_SLEWRATE, ramp_val << 6);
}
static int mp5416_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct regulator_config config = { NULL, };
struct regulator_dev *rdev;
struct regmap *regmap;
int i;
regmap = devm_regmap_init_i2c(client, &mp5416_regmap_config);
if (IS_ERR(regmap)) {
dev_err(dev, "Failed to allocate regmap!\n");
return PTR_ERR(regmap);
}
config.dev = dev;
config.regmap = regmap;
for (i = 0; i < MP5416_MAX_REGULATORS; i++) {
rdev = devm_regulator_register(dev,
&mp5416_regulators_desc[i],
&config);
if (IS_ERR(rdev)) {
dev_err(dev, "Failed to register regulator!\n");
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct of_device_id mp5416_of_match[] = {
{ .compatible = "mps,mp5416" },
{},
};
MODULE_DEVICE_TABLE(of, mp5416_of_match);
static const struct i2c_device_id mp5416_id[] = {
{ "mp5416", },
{ },
};
MODULE_DEVICE_TABLE(i2c, mp5416_id);
static struct i2c_driver mp5416_regulator_driver = {
.driver = {
.name = "mp5416",
.of_match_table = of_match_ptr(mp5416_of_match),
},
.probe_new = mp5416_i2c_probe,
.id_table = mp5416_id,
};
module_i2c_driver(mp5416_regulator_driver);
MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
MODULE_DESCRIPTION("MP5416 PMIC regulator driver");
MODULE_LICENSE("GPL");
......@@ -95,6 +95,7 @@ static const struct regulator_desc mp8859_regulators[] = {
.id = 0,
.type = REGULATOR_VOLTAGE,
.name = "mp8859_dcdc",
.supply_name = "vin",
.of_match = of_match_ptr("mp8859_dcdc"),
.n_voltages = VOL_MAX_IDX + 1,
.linear_ranges = mp8859_dcdc_ranges,
......
......@@ -354,7 +354,11 @@ static int pwm_regulator_probe(struct platform_device *pdev)
drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->pwm)) {
ret = PTR_ERR(drvdata->pwm);
dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret);
if (ret == -EPROBE_DEFER)
dev_dbg(&pdev->dev,
"Failed to get PWM, deferring probe\n");
else
dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret);
return ret;
}
......
......@@ -925,12 +925,21 @@ static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
{ }
};
static const struct rpm_regulator_data rpm_smb208_regulators[] = {
{ "s1a", QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" },
{ "s1b", QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" },
{ "s2a", QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" },
{ "s2b", QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" },
{ }
};
static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8018-regulators",
.data = &rpm_pm8018_regulators },
{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
{ .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators },
{ }
};
MODULE_DEVICE_TABLE(of, rpm_of_match);
......
......@@ -62,6 +62,13 @@ config SPI_ALTERA
help
This is the driver for the Altera SPI Controller.
config SPI_AR934X
tristate "Qualcomm Atheros AR934X/QCA95XX SPI controller driver"
depends on ATH79 || COMPILE_TEST
help
This enables support for the SPI controller present on the
Qualcomm Atheros AR934X/QCA95XX SoCs.
config SPI_ATH79
tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
depends on ATH79 || COMPILE_TEST
......@@ -264,6 +271,13 @@ config SPI_FALCON
has only been tested with m25p80 type chips. The hardware has no
support for other types of SPI peripherals.
config SPI_FSI
tristate "FSI SPI driver"
depends on FSI
help
This enables support for the driver for FSI bus attached SPI
controllers.
config SPI_FSL_LPSPI
tristate "Freescale i.MX LPSPI controller"
depends on ARCH_MXC || COMPILE_TEST
......@@ -285,7 +299,6 @@ config SPI_HISI_SFC_V3XX
tristate "HiSilicon SPI-NOR Flash Controller for Hi16XX chipsets"
depends on (ARM64 && ACPI) || COMPILE_TEST
depends on HAS_IOMEM
select CONFIG_MTD_SPI_NOR
help
This enables support for HiSilicon v3xx SPI-NOR flash controller
found in hi16xx chipsets.
......@@ -415,6 +428,7 @@ config SPI_FSL_ESPI
config SPI_MESON_SPICC
tristate "Amlogic Meson SPICC controller"
depends on COMMON_CLK
depends on ARCH_MESON || COMPILE_TEST
help
This enables master mode support for the SPICC (SPI communication
......@@ -443,6 +457,16 @@ config SPI_MT7621
help
This selects a driver for the MediaTek MT7621 SPI Controller.
config SPI_MTK_NOR
tristate "MediaTek SPI NOR controller"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This enables support for SPI NOR controller found on MediaTek
ARM SoCs. This is a controller specifically for SPI-NOR flash.
It can perform generic SPI transfers up to 6 bytes via generic
SPI interface as well as several SPI-NOR specific instructions
via SPI MEM interface.
config SPI_NPCM_FIU
tristate "Nuvoton NPCM FLASH Interface Unit"
depends on ARCH_NPCM || COMPILE_TEST
......@@ -890,6 +914,17 @@ config SPI_ZYNQMP_GQSPI
# Add new SPI master controllers in alphabetical order above this line
#
comment "SPI Multiplexer support"
config SPI_MUX
tristate "SPI multiplexer support"
select MULTIPLEXER
help
This adds support for SPI multiplexers. Each SPI mux will be
accessible as a SPI controller, the devices behind the mux will appear
to be chip selects on this controller. It is still necessary to
select one or more specific mux-controller drivers.
#
# There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones.
......
......@@ -9,11 +9,13 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
# config declarations into driver model code
obj-$(CONFIG_SPI_MASTER) += spi.o
obj-$(CONFIG_SPI_MEM) += spi-mem.o
obj-$(CONFIG_SPI_MUX) += spi-mux.o
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o
# SPI master controller drivers (bus)
obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
......@@ -40,6 +42,7 @@ spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EFM32) += spi-efm32.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSI) += spi-fsi.o
obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o
obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
......@@ -62,6 +65,7 @@ obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o
obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o
obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o
......
......@@ -173,6 +173,81 @@ static const struct atmel_qspi_mode atmel_qspi_modes[] = {
{ 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD },
};
#ifdef VERBOSE_DEBUG
static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz)
{
switch (offset) {
case QSPI_CR:
return "CR";
case QSPI_MR:
return "MR";
case QSPI_RD:
return "MR";
case QSPI_TD:
return "TD";
case QSPI_SR:
return "SR";
case QSPI_IER:
return "IER";
case QSPI_IDR:
return "IDR";
case QSPI_IMR:
return "IMR";
case QSPI_SCR:
return "SCR";
case QSPI_IAR:
return "IAR";
case QSPI_ICR:
return "ICR/WICR";
case QSPI_IFR:
return "IFR";
case QSPI_RICR:
return "RICR";
case QSPI_SMR:
return "SMR";
case QSPI_SKR:
return "SKR";
case QSPI_WPMR:
return "WPMR";
case QSPI_WPSR:
return "WPSR";
case QSPI_VERSION:
return "VERSION";
default:
snprintf(tmp, sz, "0x%02x", offset);
break;
}
return tmp;
}
#endif /* VERBOSE_DEBUG */
static u32 atmel_qspi_read(struct atmel_qspi *aq, u32 offset)
{
u32 value = readl_relaxed(aq->regs + offset);
#ifdef VERBOSE_DEBUG
char tmp[8];
dev_vdbg(&aq->pdev->dev, "read 0x%08x from %s\n", value,
atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
#endif /* VERBOSE_DEBUG */
return value;
}
static void atmel_qspi_write(u32 value, struct atmel_qspi *aq, u32 offset)
{
#ifdef VERBOSE_DEBUG
char tmp[8];
dev_vdbg(&aq->pdev->dev, "write 0x%08x into %s\n", value,
atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
#endif /* VERBOSE_DEBUG */
writel_relaxed(value, aq->regs + offset);
}
static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op,
const struct atmel_qspi_mode *mode)
{
......@@ -293,32 +368,32 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
* Serial Memory Mode (SMM).
*/
if (aq->mr != QSPI_MR_SMM) {
writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
}
/* Clear pending interrupts */
(void)readl_relaxed(aq->regs + QSPI_SR);
(void)atmel_qspi_read(aq, QSPI_SR);
if (aq->caps->has_ricr) {
if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN)
ifr |= QSPI_IFR_APBTFRTYP_READ;
/* Set QSPI Instruction Frame registers */
writel_relaxed(iar, aq->regs + QSPI_IAR);
atmel_qspi_write(iar, aq, QSPI_IAR);
if (op->data.dir == SPI_MEM_DATA_IN)
writel_relaxed(icr, aq->regs + QSPI_RICR);
atmel_qspi_write(icr, aq, QSPI_RICR);
else
writel_relaxed(icr, aq->regs + QSPI_WICR);
writel_relaxed(ifr, aq->regs + QSPI_IFR);
atmel_qspi_write(icr, aq, QSPI_WICR);
atmel_qspi_write(ifr, aq, QSPI_IFR);
} else {
if (op->data.dir == SPI_MEM_DATA_OUT)
ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR;
/* Set QSPI Instruction Frame registers */
writel_relaxed(iar, aq->regs + QSPI_IAR);
writel_relaxed(icr, aq->regs + QSPI_ICR);
writel_relaxed(ifr, aq->regs + QSPI_IFR);
atmel_qspi_write(iar, aq, QSPI_IAR);
atmel_qspi_write(icr, aq, QSPI_ICR);
atmel_qspi_write(ifr, aq, QSPI_IFR);
}
return 0;
......@@ -345,7 +420,7 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
/* Skip to the final steps if there is no data */
if (op->data.nbytes) {
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
(void)readl_relaxed(aq->regs + QSPI_IFR);
(void)atmel_qspi_read(aq, QSPI_IFR);
/* Send/Receive data */
if (op->data.dir == SPI_MEM_DATA_IN)
......@@ -356,22 +431,22 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
op->data.nbytes);
/* Release the chip-select */
writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR);
atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
}
/* Poll INSTRuction End status */
sr = readl_relaxed(aq->regs + QSPI_SR);
sr = atmel_qspi_read(aq, QSPI_SR);
if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
return err;
/* Wait for INSTRuction End interrupt */
reinit_completion(&aq->cmd_completion);
aq->pending = sr & QSPI_SR_CMD_COMPLETED;
writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER);
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER);
if (!wait_for_completion_timeout(&aq->cmd_completion,
msecs_to_jiffies(1000)))
err = -ETIMEDOUT;
writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR);
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR);
return err;
}
......@@ -410,7 +485,7 @@ static int atmel_qspi_setup(struct spi_device *spi)
scbr--;
aq->scr = QSPI_SCR_SCBR(scbr);
writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
return 0;
}
......@@ -418,14 +493,14 @@ static int atmel_qspi_setup(struct spi_device *spi)
static void atmel_qspi_init(struct atmel_qspi *aq)
{
/* Reset the QSPI controller */
writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR);
atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
/* Set the QSPI controller by default in Serial Memory Mode */
writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
/* Enable the QSPI controller */
writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR);
atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
}
static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
......@@ -433,8 +508,8 @@ static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
struct atmel_qspi *aq = dev_id;
u32 status, mask, pending;
status = readl_relaxed(aq->regs + QSPI_SR);
mask = readl_relaxed(aq->regs + QSPI_IMR);
status = atmel_qspi_read(aq, QSPI_SR);
mask = atmel_qspi_read(aq, QSPI_IMR);
pending = status & mask;
if (!pending)
......@@ -569,7 +644,7 @@ static int atmel_qspi_remove(struct platform_device *pdev)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
spi_unregister_controller(ctrl);
writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR);
atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
clk_disable_unprepare(aq->qspick);
clk_disable_unprepare(aq->pclk);
return 0;
......@@ -596,7 +671,7 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
atmel_qspi_init(aq);
writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
return 0;
}
......
// SPDX-License-Identifier: GPL-2.0
//
// SPI controller driver for Qualcomm Atheros AR934x/QCA95xx SoCs
//
// Copyright (C) 2020 Chuanhong Guo <gch981213@gmail.com>
//
// Based on spi-mt7621.c:
// Copyright (C) 2011 Sergiy <piratfm@gmail.com>
// Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
// Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#define DRIVER_NAME "spi-ar934x"
#define AR934X_SPI_REG_FS 0x00
#define AR934X_SPI_ENABLE BIT(0)
#define AR934X_SPI_REG_IOC 0x08
#define AR934X_SPI_IOC_INITVAL 0x70000
#define AR934X_SPI_REG_CTRL 0x04
#define AR934X_SPI_CLK_MASK GENMASK(5, 0)
#define AR934X_SPI_DATAOUT 0x10
#define AR934X_SPI_REG_SHIFT_CTRL 0x14
#define AR934X_SPI_SHIFT_EN BIT(31)
#define AR934X_SPI_SHIFT_CS(n) BIT(28 + (n))
#define AR934X_SPI_SHIFT_TERM 26
#define AR934X_SPI_SHIFT_VAL(cs, term, count) \
(AR934X_SPI_SHIFT_EN | AR934X_SPI_SHIFT_CS(cs) | \
(term) << AR934X_SPI_SHIFT_TERM | (count))
#define AR934X_SPI_DATAIN 0x18
struct ar934x_spi {
struct spi_controller *ctlr;
void __iomem *base;
struct clk *clk;
unsigned int clk_freq;
};
static inline int ar934x_spi_clk_div(struct ar934x_spi *sp, unsigned int freq)
{
int div = DIV_ROUND_UP(sp->clk_freq, freq * 2) - 1;
if (div < 0)
return 0;
else if (div > AR934X_SPI_CLK_MASK)
return -EINVAL;
else
return div;
}
static int ar934x_spi_setup(struct spi_device *spi)
{
struct ar934x_spi *sp = spi_controller_get_devdata(spi->master);
if ((spi->max_speed_hz == 0) ||
(spi->max_speed_hz > (sp->clk_freq / 2))) {
spi->max_speed_hz = sp->clk_freq / 2;
} else if (spi->max_speed_hz < (sp->clk_freq / 128)) {
dev_err(&spi->dev, "spi clock is too low\n");
return -EINVAL;
}
return 0;
}
static int ar934x_spi_transfer_one_message(struct spi_controller *master,
struct spi_message *m)
{
struct ar934x_spi *sp = spi_controller_get_devdata(master);
struct spi_transfer *t = NULL;
struct spi_device *spi = m->spi;
unsigned long trx_done, trx_cur;
int stat = 0;
u8 term = 0;
int div, i;
u32 reg;
const u8 *tx_buf;
u8 *buf;
m->actual_length = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->speed_hz)
div = ar934x_spi_clk_div(sp, t->speed_hz);
else
div = ar934x_spi_clk_div(sp, spi->max_speed_hz);
if (div < 0) {
stat = -EIO;
goto msg_done;
}
reg = ioread32(sp->base + AR934X_SPI_REG_CTRL);
reg &= ~AR934X_SPI_CLK_MASK;
reg |= div;
iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL);
iowrite32(0, sp->base + AR934X_SPI_DATAOUT);
for (trx_done = 0; trx_done < t->len; trx_done += 4) {
trx_cur = t->len - trx_done;
if (trx_cur > 4)
trx_cur = 4;
else if (list_is_last(&t->transfer_list, &m->transfers))
term = 1;
if (t->tx_buf) {
tx_buf = t->tx_buf + trx_done;
reg = tx_buf[0];
for (i = 1; i < trx_cur; i++)
reg = reg << 8 | tx_buf[i];
iowrite32(reg, sp->base + AR934X_SPI_DATAOUT);
}
reg = AR934X_SPI_SHIFT_VAL(spi->chip_select, term,
trx_cur * 8);
iowrite32(reg, sp->base + AR934X_SPI_REG_SHIFT_CTRL);
stat = readl_poll_timeout(
sp->base + AR934X_SPI_REG_SHIFT_CTRL, reg,
!(reg & AR934X_SPI_SHIFT_EN), 0, 5);
if (stat < 0)
goto msg_done;
if (t->rx_buf) {
reg = ioread32(sp->base + AR934X_SPI_DATAIN);
buf = t->rx_buf + trx_done;
for (i = 0; i < trx_cur; i++) {
buf[trx_cur - i - 1] = reg & 0xff;
reg >>= 8;
}
}
}
m->actual_length += t->len;
}
msg_done:
m->status = stat;
spi_finalize_current_message(master);
return 0;
}
static const struct of_device_id ar934x_spi_match[] = {
{ .compatible = "qca,ar934x-spi" },
{},
};
MODULE_DEVICE_TABLE(of, ar934x_spi_match);
static int ar934x_spi_probe(struct platform_device *pdev)
{
struct spi_controller *ctlr;
struct ar934x_spi *sp;
void __iomem *base;
struct clk *clk;
int ret;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
return PTR_ERR(clk);
}
ret = clk_prepare_enable(clk);
if (ret)
return ret;
ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp));
if (!ctlr) {
dev_info(&pdev->dev, "failed to allocate spi controller\n");
return -ENOMEM;
}
/* disable flash mapping and expose spi controller registers */
iowrite32(AR934X_SPI_ENABLE, base + AR934X_SPI_REG_FS);
/* restore pins to default state: CSn=1 DO=CLK=0 */
iowrite32(AR934X_SPI_IOC_INITVAL, base + AR934X_SPI_REG_IOC);
ctlr->mode_bits = SPI_LSB_FIRST;
ctlr->setup = ar934x_spi_setup;
ctlr->transfer_one_message = ar934x_spi_transfer_one_message;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->dev.of_node = pdev->dev.of_node;
ctlr->num_chipselect = 3;
dev_set_drvdata(&pdev->dev, ctlr);
sp = spi_controller_get_devdata(ctlr);
sp->base = base;
sp->clk = clk;
sp->clk_freq = clk_get_rate(clk);
sp->ctlr = ctlr;
return devm_spi_register_controller(&pdev->dev, ctlr);
}
static int ar934x_spi_remove(struct platform_device *pdev)
{
struct spi_controller *ctlr;
struct ar934x_spi *sp;
ctlr = dev_get_drvdata(&pdev->dev);
sp = spi_controller_get_devdata(ctlr);
clk_disable_unprepare(sp->clk);
return 0;
}
static struct platform_driver ar934x_spi_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = ar934x_spi_match,
},
.probe = ar934x_spi_probe,
.remove = ar934x_spi_remove,
};
module_platform_driver(ar934x_spi_driver);
MODULE_DESCRIPTION("SPI controller driver for Qualcomm Atheros AR934x/QCA95xx");
MODULE_AUTHOR("Chuanhong Guo <gch981213@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
......@@ -6,14 +6,13 @@
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/efm32-spi.h>
#include <linux/of.h>
#define DRIVER_NAME "efm32-spi"
......@@ -82,9 +81,6 @@ struct efm32_spi_ddata {
const u8 *tx_buf;
u8 *rx_buf;
unsigned tx_len, rx_len;
/* chip selects */
unsigned csgpio[];
};
#define ddata_to_dev(ddata) (&(ddata->bitbang.master->dev))
......@@ -102,14 +98,6 @@ static u32 efm32_spi_read32(struct efm32_spi_ddata *ddata, unsigned offset)
return readl_relaxed(ddata->base + offset);
}
static void efm32_spi_chipselect(struct spi_device *spi, int is_on)
{
struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
int value = !(spi->mode & SPI_CS_HIGH) == !(is_on == BITBANG_CS_ACTIVE);
gpio_set_value(ddata->csgpio[spi->chip_select], value);
}
static int efm32_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
......@@ -320,17 +308,11 @@ static int efm32_spi_probe(struct platform_device *pdev)
int ret;
struct spi_master *master;
struct device_node *np = pdev->dev.of_node;
int num_cs, i;
if (!np)
return -EINVAL;
num_cs = of_gpio_named_count(np, "cs-gpios");
if (num_cs < 0)
return num_cs;
master = spi_alloc_master(&pdev->dev,
sizeof(*ddata) + num_cs * sizeof(unsigned));
master = spi_alloc_master(&pdev->dev, sizeof(*ddata));
if (!master) {
dev_dbg(&pdev->dev,
"failed to allocate spi master controller\n");
......@@ -340,14 +322,13 @@ static int efm32_spi_probe(struct platform_device *pdev)
master->dev.of_node = pdev->dev.of_node;
master->num_chipselect = num_cs;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->use_gpio_descriptors = true;
ddata = spi_master_get_devdata(master);
ddata->bitbang.master = master;
ddata->bitbang.chipselect = efm32_spi_chipselect;
ddata->bitbang.setup_transfer = efm32_spi_setup_transfer;
ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
......@@ -361,25 +342,6 @@ static int efm32_spi_probe(struct platform_device *pdev)
goto err;
}
for (i = 0; i < num_cs; ++i) {
ret = of_get_named_gpio(np, "cs-gpios", i);
if (ret < 0) {
dev_err(&pdev->dev, "failed to get csgpio#%u (%d)\n",
i, ret);
goto err;
}
ddata->csgpio[i] = ret;
dev_dbg(&pdev->dev, "csgpio#%u = %u\n", i, ddata->csgpio[i]);
ret = devm_gpio_request_one(&pdev->dev, ddata->csgpio[i],
GPIOF_OUT_INIT_LOW, DRIVER_NAME);
if (ret < 0) {
dev_err(&pdev->dev,
"failed to configure csgpio#%u (%d)\n",
i, ret);
goto err;
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
......
This diff is collapsed.
This diff is collapsed.
......@@ -86,8 +86,6 @@
#define TCR_RXMSK BIT(19)
#define TCR_TXMSK BIT(18)
static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128};
struct lpspi_config {
u8 bpw;
u8 chip_select;
......@@ -125,7 +123,7 @@ struct fsl_lpspi_data {
struct completion dma_rx_completion;
struct completion dma_tx_completion;
int chipselect[0];
int chipselect[];
};
static const struct of_device_id fsl_lpspi_dt_ids[] = {
......@@ -331,15 +329,14 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
}
for (prescale = 0; prescale < 8; prescale++) {
scldiv = perclk_rate /
(clkdivs[prescale] * config.speed_hz) - 2;
scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2;
if (scldiv < 256) {
fsl_lpspi->config.prescale = prescale;
break;
}
}
if (prescale == 8 && scldiv >= 256)
if (scldiv >= 256)
return -EINVAL;
writel(scldiv | (scldiv << 8) | ((scldiv >> 1) << 16),
......
......@@ -6,7 +6,6 @@
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/qcom-geni-se.h>
......@@ -536,6 +535,7 @@ static int spi_geni_probe(struct platform_device *pdev)
struct spi_geni_master *mas;
void __iomem *base;
struct clk *clk;
struct device *dev = &pdev->dev;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
......@@ -545,28 +545,25 @@ static int spi_geni_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, "se");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Err getting SE Core clk %ld\n",
PTR_ERR(clk));
clk = devm_clk_get(dev, "se");
if (IS_ERR(clk))
return PTR_ERR(clk);
}
spi = spi_alloc_master(&pdev->dev, sizeof(*mas));
spi = spi_alloc_master(dev, sizeof(*mas));
if (!spi)
return -ENOMEM;
platform_set_drvdata(pdev, spi);
mas = spi_master_get_devdata(spi);
mas->irq = irq;
mas->dev = &pdev->dev;
mas->se.dev = &pdev->dev;
mas->se.wrapper = dev_get_drvdata(pdev->dev.parent);
mas->dev = dev;
mas->se.dev = dev;
mas->se.wrapper = dev_get_drvdata(dev->parent);
mas->se.base = base;
mas->se.clk = clk;
spi->bus_num = -1;
spi->dev.of_node = pdev->dev.of_node;
spi->dev.of_node = dev->of_node;
spi->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH;
spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
spi->num_chipselect = 4;
......@@ -579,14 +576,13 @@ static int spi_geni_probe(struct platform_device *pdev)
init_completion(&mas->xfer_done);
spin_lock_init(&mas->lock);
pm_runtime_enable(&pdev->dev);
pm_runtime_enable(dev);
ret = spi_geni_init(mas);
if (ret)
goto spi_geni_probe_runtime_disable;
ret = request_irq(mas->irq, geni_spi_isr,
IRQF_TRIGGER_HIGH, "spi_geni", spi);
ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi);
if (ret)
goto spi_geni_probe_runtime_disable;
......@@ -598,7 +594,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi_geni_probe_free_irq:
free_irq(mas->irq, spi);
spi_geni_probe_runtime_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_disable(dev);
spi_master_put(spi);
return ret;
}
......
......@@ -7,6 +7,7 @@
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/dmi.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
......@@ -17,6 +18,12 @@
#define HISI_SFC_V3XX_VERSION (0x1f8)
#define HISI_SFC_V3XX_CMD_CFG (0x300)
#define HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT (1 << 17)
#define HISI_SFC_V3XX_CMD_CFG_DUAL_IO (2 << 17)
#define HISI_SFC_V3XX_CMD_CFG_FULL_DIO (3 << 17)
#define HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT (5 << 17)
#define HISI_SFC_V3XX_CMD_CFG_QUAD_IO (6 << 17)
#define HISI_SFC_V3XX_CMD_CFG_FULL_QIO (7 << 17)
#define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9
#define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8)
#define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7)
......@@ -161,6 +168,43 @@ static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host,
if (op->addr.nbytes)
config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK;
switch (op->data.buswidth) {
case 0 ... 1:
break;
case 2:
if (op->addr.buswidth <= 1) {
config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT;
} else if (op->addr.buswidth == 2) {
if (op->cmd.buswidth <= 1) {
config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IO;
} else if (op->cmd.buswidth == 2) {
config |= HISI_SFC_V3XX_CMD_CFG_FULL_DIO;
} else {
return -EIO;
}
} else {
return -EIO;
}
break;
case 4:
if (op->addr.buswidth <= 1) {
config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT;
} else if (op->addr.buswidth == 4) {
if (op->cmd.buswidth <= 1) {
config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IO;
} else if (op->cmd.buswidth == 4) {
config |= HISI_SFC_V3XX_CMD_CFG_FULL_QIO;
} else {
return -EIO;
}
} else {
return -EIO;
}
break;
default:
return -EOPNOTSUPP;
}
if (op->data.dir != SPI_MEM_NO_DATA) {
config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF;
config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK;
......@@ -207,6 +251,44 @@ static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = {
.exec_op = hisi_sfc_v3xx_exec_op,
};
static int hisi_sfc_v3xx_buswidth_override_bits;
/*
* ACPI FW does not allow us to currently set the device buswidth, so quirk it
* depending on the board.
*/
static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d)
{
hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD;
return 0;
}
static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[] = {
{
.callback = hisi_sfc_v3xx_dmi_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
DMI_MATCH(DMI_PRODUCT_NAME, "D06"),
},
},
{
.callback = hisi_sfc_v3xx_dmi_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"),
},
},
{
.callback = hisi_sfc_v3xx_dmi_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Huawei"),
DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"),
},
},
{}
};
static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
......@@ -222,6 +304,8 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD;
ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits;
host = spi_controller_get_devdata(ctlr);
host->dev = dev;
......@@ -277,7 +361,20 @@ static struct platform_driver hisi_sfc_v3xx_spi_driver = {
.probe = hisi_sfc_v3xx_probe,
};
module_platform_driver(hisi_sfc_v3xx_spi_driver);
static int __init hisi_sfc_v3xx_spi_init(void)
{
dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table);
return platform_driver_register(&hisi_sfc_v3xx_spi_driver);
}
static void __exit hisi_sfc_v3xx_spi_exit(void)
{
platform_driver_unregister(&hisi_sfc_v3xx_spi_driver);
}
module_init(hisi_sfc_v3xx_spi_init);
module_exit(hisi_sfc_v3xx_spi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
......
......@@ -418,12 +418,13 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
struct spi_controller *ctlr = mem->spi->controller;
size_t len;
len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
if (ctlr->mem_ops && ctlr->mem_ops->adjust_op_size)
return ctlr->mem_ops->adjust_op_size(mem, op);
if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) {
len = sizeof(op->cmd.opcode) + op->addr.nbytes +
op->dummy.nbytes;
if (len > spi_max_transfer_size(mem->spi))
return -EINVAL;
......@@ -487,7 +488,7 @@ static ssize_t spi_mem_no_dirmap_write(struct spi_mem_dirmap_desc *desc,
* This function is creating a direct mapping descriptor which can then be used
* to access the memory using spi_mem_dirmap_read() or spi_mem_dirmap_write().
* If the SPI controller driver does not support direct mapping, this function
* fallback to an implementation using spi_mem_exec_op(), so that the caller
* falls back to an implementation using spi_mem_exec_op(), so that the caller
* doesn't have to bother implementing a fallback on his own.
*
* Return: a valid pointer in case of success, and ERR_PTR() otherwise.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -22,7 +22,6 @@
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
......@@ -32,7 +31,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
......
This diff is collapsed.
This diff is collapsed.
......@@ -843,14 +843,17 @@ static const struct dev_pm_ops rockchip_spi_pm = {
};
static const struct of_device_id rockchip_spi_dt_match[] = {
{ .compatible = "rockchip,rv1108-spi", },
{ .compatible = "rockchip,px30-spi", },
{ .compatible = "rockchip,rk3036-spi", },
{ .compatible = "rockchip,rk3066-spi", },
{ .compatible = "rockchip,rk3188-spi", },
{ .compatible = "rockchip,rk3228-spi", },
{ .compatible = "rockchip,rk3288-spi", },
{ .compatible = "rockchip,rk3308-spi", },
{ .compatible = "rockchip,rk3328-spi", },
{ .compatible = "rockchip,rk3368-spi", },
{ .compatible = "rockchip,rk3399-spi", },
{ .compatible = "rockchip,rv1108-spi", },
{ },
};
MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment