Merge tag 'spi-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 01:33:57 +0000 (18:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 01:33:57 +0000 (18:33 -0700)
Pull spi updates from Mark Brown:
 "The overwhelming bulk of this pull request is a change from Uwe
  Kleine-König which changes the return type of the remove() function to
  void as part of some wider work he's doing to do this for all bus
  types, causing updates to most SPI device drivers. The branch with
  that on has been cross merged with a couple of other trees which added
  new SPI drivers this cycle, I'm not expecting any build issues
  resulting from the change.

  Otherwise it's been a relatively quiet release with some new device
  support, a few minor features and the welcome completion of the
  conversion of the subsystem to use GPIO descriptors rather than
  numbers:

   - Change return type of remove() to void.

   - Completion of the conversion of SPI controller drivers to use GPIO
     descriptors rather than numbers.

   - Quite a few DT schema conversions.

   - Support for multiple SPI devices on a bus in ACPI systems.

   - Big overhaul of the PXA2xx SPI driver.

   - Support for AMD AMDI0062, Intel Raptor Lake, Mediatek MT7986 and
     MT8186, nVidia Tegra210 and Tegra234, Renesas RZ/V2L, Tesla FSD and
     Sunplus SP7021"

[ And this is obviously where that spi change that snuck into the
  regulator tree _should_ have been :^]

* tag 'spi-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (124 commits)
  spi: fsi: Implement a timeout for polling status
  spi: Fix erroneous sgs value with min_t()
  spi: tegra20: Use of_device_get_match_data()
  spi: mediatek: add ipm design support for MT7986
  spi: Add compatible for MT7986
  spi: sun4i: fix typos in comments
  spi: mediatek: support tick_delay without enhance_timing
  spi: Update clock-names property for arm pl022
  spi: rockchip-sfc: fix platform_get_irq.cocci warning
  spi: s3c64xx: Add spi port configuration for Tesla FSD SoC
  spi: dt-bindings: samsung: Add fsd spi compatible
  spi: topcliff-pch: Prevent usage of potentially stale DMA device
  spi: tegra210-quad: combined sequence mode
  spi: tegra210-quad: add acpi support
  spi: npcm-fiu: Fix typo ("npxm")
  spi: Fix Tegra QSPI example
  spi: qup: replace spin_lock_irqsave by spin_lock in hard IRQ
  spi: cadence: fix platform_get_irq.cocci warning
  spi: Update NXP Flexspi maintainer details
  dt-bindings: mfd: maxim,max77802: Convert to dtschema
  ...

295 files changed:
Documentation/devicetree/bindings/extcon/maxim,max77843.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
Documentation/devicetree/bindings/mfd/max14577.txt [deleted file]
Documentation/devicetree/bindings/mfd/max77802.txt [deleted file]
Documentation/devicetree/bindings/mfd/maxim,max14577.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/maxim,max77802.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/maxim,max77843.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max77802.txt [deleted file]
Documentation/devicetree/bindings/regulator/maxim,max14577.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/maxim,max77802.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/maxim,max77843.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml
Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/mediatek,spi-mtk-nor.yaml
Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
Documentation/devicetree/bindings/spi/renesas,rspi.yaml
Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/samsung,spi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-controller.yaml
Documentation/devicetree/bindings/spi/spi-mt65xx.txt [deleted file]
Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml
Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
Documentation/devicetree/bindings/spi/spi-pl022.yaml
Documentation/devicetree/bindings/spi/spi-samsung.txt [deleted file]
Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt [deleted file]
Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml [new file with mode: 0644]
Documentation/driver-api/mtd/index.rst
Documentation/driver-api/mtd/intel-spi.rst [deleted file]
Documentation/driver-api/mtd/spi-intel.rst [new file with mode: 0644]
Documentation/spi/pxa2xx.rst
MAINTAINERS
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-s3c/Kconfig
arch/arm/mach-s3c/devs.c
arch/arm/mach-s3c/mach-crag6410-module.c
arch/arm/mach-s3c/mach-crag6410.c
arch/arm/mach-s3c/setup-spi-s3c64xx.c
arch/arm/mach-s3c/spi-core-s3c24xx.h
drivers/bus/moxtet.c
drivers/char/tpm/st33zp24/i2c.c
drivers/char/tpm/st33zp24/spi.c
drivers/char/tpm/st33zp24/st33zp24.c
drivers/char/tpm/st33zp24/st33zp24.h
drivers/char/tpm/tpm_tis_spi_main.c
drivers/clk/clk-lmk04832.c
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-max3191x.c
drivers/gpio/gpio-max7301.c
drivers/gpio/gpio-mc33880.c
drivers/gpio/gpio-pisosr.c
drivers/gpu/drm/panel/panel-abt-y030xx067a.c
drivers/gpu/drm/panel/panel-ilitek-ili9322.c
drivers/gpu/drm/panel/panel-ilitek-ili9341.c
drivers/gpu/drm/panel/panel-innolux-ej030na.c
drivers/gpu/drm/panel/panel-lg-lb035q02.c
drivers/gpu/drm/panel/panel-lg-lg4573.c
drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
drivers/gpu/drm/panel/panel-novatek-nt39016.c
drivers/gpu/drm/panel/panel-samsung-db7430.c
drivers/gpu/drm/panel/panel-samsung-ld9040.c
drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
drivers/gpu/drm/panel/panel-sitronix-st7789v.c
drivers/gpu/drm/panel/panel-sony-acx565akm.c
drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
drivers/gpu/drm/panel/panel-tpo-tpg110.c
drivers/gpu/drm/panel/panel-widechips-ws2401.c
drivers/gpu/drm/tiny/hx8357d.c
drivers/gpu/drm/tiny/ili9163.c
drivers/gpu/drm/tiny/ili9225.c
drivers/gpu/drm/tiny/ili9341.c
drivers/gpu/drm/tiny/ili9486.c
drivers/gpu/drm/tiny/mi0283qt.c
drivers/gpu/drm/tiny/repaper.c
drivers/gpu/drm/tiny/st7586.c
drivers/gpu/drm/tiny/st7735r.c
drivers/hwmon/adcxx.c
drivers/hwmon/max1111.c
drivers/hwmon/max31722.c
drivers/iio/accel/bma400_spi.c
drivers/iio/accel/bmc150-accel-spi.c
drivers/iio/accel/bmi088-accel-spi.c
drivers/iio/accel/kxsd9-spi.c
drivers/iio/accel/mma7455_spi.c
drivers/iio/accel/sca3000.c
drivers/iio/adc/ad7266.c
drivers/iio/adc/ltc2496.c
drivers/iio/adc/mcp320x.c
drivers/iio/adc/mcp3911.c
drivers/iio/adc/ti-adc12138.c
drivers/iio/adc/ti-ads7950.c
drivers/iio/adc/ti-ads8688.c
drivers/iio/adc/ti-tlc4541.c
drivers/iio/amplifiers/ad8366.c
drivers/iio/common/ssp_sensors/ssp_dev.c
drivers/iio/dac/ad5360.c
drivers/iio/dac/ad5380.c
drivers/iio/dac/ad5446.c
drivers/iio/dac/ad5449.c
drivers/iio/dac/ad5504.c
drivers/iio/dac/ad5592r.c
drivers/iio/dac/ad5624r_spi.c
drivers/iio/dac/ad5686-spi.c
drivers/iio/dac/ad5761.c
drivers/iio/dac/ad5764.c
drivers/iio/dac/ad5791.c
drivers/iio/dac/ad8801.c
drivers/iio/dac/ltc1660.c
drivers/iio/dac/ltc2632.c
drivers/iio/dac/mcp4922.c
drivers/iio/dac/ti-dac082s085.c
drivers/iio/dac/ti-dac7311.c
drivers/iio/frequency/adf4350.c
drivers/iio/gyro/bmg160_spi.c
drivers/iio/gyro/fxas21002c_spi.c
drivers/iio/health/afe4403.c
drivers/iio/magnetometer/bmc150_magn_spi.c
drivers/iio/magnetometer/hmc5843_spi.c
drivers/iio/potentiometer/max5487.c
drivers/iio/pressure/ms5611_spi.c
drivers/iio/pressure/zpa2326_spi.c
drivers/input/keyboard/applespi.c
drivers/input/misc/adxl34x-spi.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/cyttsp4_spi.c
drivers/input/touchscreen/tsc2005.c
drivers/leds/leds-cr0014114.c
drivers/leds/leds-dac124s085.c
drivers/leds/leds-el15203000.c
drivers/leds/leds-spi-byte.c
drivers/media/spi/cxd2880-spi.c
drivers/media/spi/gs1662.c
drivers/media/tuners/msi001.c
drivers/mfd/arizona-spi.c
drivers/mfd/da9052-spi.c
drivers/mfd/ezx-pcap.c
drivers/mfd/lpc_ich.c
drivers/mfd/madera-spi.c
drivers/mfd/mc13xxx-spi.c
drivers/mfd/rsmu_spi.c
drivers/mfd/stmpe-spi.c
drivers/mfd/tps65912-spi.c
drivers/misc/ad525x_dpot-spi.c
drivers/misc/eeprom/eeprom_93xx46.c
drivers/misc/lattice-ecp3-config.c
drivers/misc/lis3lv02d/lis3lv02d_spi.c
drivers/mmc/host/mmc_spi.c
drivers/mtd/devices/mchp23k256.c
drivers/mtd/devices/mchp48l640.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/sst25l.c
drivers/mtd/spi-nor/controllers/Kconfig
drivers/mtd/spi-nor/controllers/Makefile
drivers/mtd/spi-nor/controllers/intel-spi-pci.c [deleted file]
drivers/mtd/spi-nor/controllers/intel-spi-platform.c [deleted file]
drivers/mtd/spi-nor/controllers/intel-spi.c [deleted file]
drivers/mtd/spi-nor/controllers/intel-spi.h [deleted file]
drivers/net/can/m_can/tcan4x5x-core.c
drivers/net/can/spi/hi311x.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/dsa/b53/b53_spi.c
drivers/net/dsa/microchip/ksz8795_spi.c
drivers/net/dsa/microchip/ksz9477_spi.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/vitesse-vsc73xx-spi.c
drivers/net/ethernet/asix/ax88796c_main.c
drivers/net/ethernet/micrel/ks8851_spi.c
drivers/net/ethernet/microchip/enc28j60.c
drivers/net/ethernet/microchip/encx24j600.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/vertexcom/mse102x.c
drivers/net/ethernet/wiznet/w5100-spi.c
drivers/net/ieee802154/adf7242.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/ca8210.c
drivers/net/ieee802154/cc2520.c
drivers/net/ieee802154/mcr20a.c
drivers/net/ieee802154/mrf24j40.c
drivers/net/phy/spi_ks8995.c
drivers/net/wan/slic_ds26522.c
drivers/net/wireless/intersil/p54/p54spi.c
drivers/net/wireless/marvell/libertas/if_spi.c
drivers/net/wireless/microchip/wilc1000/spi.c
drivers/net/wireless/st/cw1200/cw1200_spi.c
drivers/net/wireless/ti/wl1251/spi.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/nfc/nfcmrvl/spi.c
drivers/nfc/st-nci/spi.c
drivers/nfc/st95hf/core.c
drivers/nfc/trf7970a.c
drivers/platform/chrome/cros_ec.c
drivers/platform/chrome/cros_ec.h
drivers/platform/chrome/cros_ec_i2c.c
drivers/platform/chrome/cros_ec_lpc.c
drivers/platform/chrome/cros_ec_spi.c
drivers/platform/olpc/olpc-xo175-ec.c
drivers/rtc/rtc-ds1302.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1343.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-amd.c
drivers/spi/spi-ath79.c
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-cadence-xspi.c
drivers/spi/spi-fsi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-intel-pci.c [new file with mode: 0644]
drivers/spi/spi-intel-platform.c [new file with mode: 0644]
drivers/spi/spi-intel.c [new file with mode: 0644]
drivers/spi/spi-intel.h [new file with mode: 0644]
drivers/spi/spi-lantiq-ssc.c
drivers/spi/spi-mem.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-mtk-nor.c
drivers/spi/spi-npcm-fiu.c
drivers/spi/spi-pic32.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-qup.c
drivers/spi/spi-rockchip-sfc.c
drivers/spi/spi-rockchip.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-slave-system-control.c
drivers/spi/spi-slave-time.c
drivers/spi/spi-st-ssc4.c
drivers/spi/spi-stm32.c
drivers/spi/spi-sun4i.c
drivers/spi/spi-sunplus-sp7021.c [new file with mode: 0644]
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi-tegra210-quad.c
drivers/spi/spi-tle62x0.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-zynqmp-gqspi.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/fbtft/fbtft.h
drivers/staging/pi433/pi433_if.c
drivers/staging/wfx/bus_spi.c
drivers/tty/serial/max3100.c
drivers/tty/serial/max310x.c
drivers/tty/serial/sc16is7xx.c
drivers/usb/gadget/udc/max3420_udc.c
drivers/usb/host/max3421-hcd.c
drivers/video/backlight/ams369fg06.c
drivers/video/backlight/corgi_lcd.c
drivers/video/backlight/ili922x.c
drivers/video/backlight/l4f00242t03.c
drivers/video/backlight/lms501kf03.c
drivers/video/backlight/ltv350qv.c
drivers/video/backlight/tdo24m.c
drivers/video/backlight/tosa_lcd.c
drivers/video/backlight/vgg2432a4.c
drivers/video/fbdev/omap/lcd_mipid.c
drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c
drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c
drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c
drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c
drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c
include/linux/mfd/lpc_ich.h
include/linux/platform_data/spi-s3c64xx.h
include/linux/platform_data/x86/intel-spi.h [deleted file]
include/linux/platform_data/x86/spi-intel.h [new file with mode: 0644]
include/linux/spi/pxa2xx_spi.h
include/linux/spi/s3c24xx.h
include/linux/spi/spi.h
sound/pci/hda/cs35l41_hda_spi.c
sound/soc/codecs/adau1761-spi.c
sound/soc/codecs/adau1781-spi.c
sound/soc/codecs/cs35l41-spi.c
sound/soc/codecs/pcm3168a-spi.c
sound/soc/codecs/pcm512x-spi.c
sound/soc/codecs/tlv320aic32x4-spi.c
sound/soc/codecs/tlv320aic3x-spi.c
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm8804-spi.c
sound/spi/at73c213.c

diff --git a/Documentation/devicetree/bindings/extcon/maxim,max77843.yaml b/Documentation/devicetree/bindings/extcon/maxim,max77843.yaml
new file mode 100644 (file)
index 0000000..f9ffe3d
--- /dev/null
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/extcon/maxim,max77843.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77843 MicroUSB and Companion Power Management IC Extcon
+
+maintainers:
+  - Chanwoo Choi <cw00.choi@samsung.com>
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX77843 MicroUSB
+  Integrated Circuit (MUIC).
+
+  See also Documentation/devicetree/bindings/mfd/maxim,max77843.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    const: maxim,max77843-muic
+
+  connector:
+    $ref: /schemas/connector/usb-connector.yaml#
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/port
+    description:
+      Any connector to the data bus of this controller should be modelled using
+      the OF graph bindings specified
+    properties:
+      port:
+        $ref: /schemas/graph.yaml#/properties/port
+
+required:
+  - compatible
+  - connector
+
+additionalProperties: false
index d1f53bd449f7b2764d71acb84c53db2297d0dd24..4caadf73fc4aa3c8dc9551a592c80102a0d6ba1a 100644 (file)
@@ -31,7 +31,7 @@ properties:
 
   controller-data:
     description:
-      SPI controller data, see bindings/spi/spi-samsung.txt
+      SPI controller data, see bindings/spi/samsung,spi-peripheral-props.yaml
     type: object
 
   google,cros-ec-spi-pre-delay:
@@ -148,18 +148,21 @@ patternProperties:
 required:
   - compatible
 
-if:
-  properties:
-    compatible:
-      contains:
-        enum:
-          - google,cros-ec-i2c
-          - google,cros-ec-rpmsg
-then:
-  properties:
-    google,cros-ec-spi-pre-delay: false
-    google,cros-ec-spi-msg-delay: false
-    spi-max-frequency: false
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - google,cros-ec-i2c
+              - google,cros-ec-rpmsg
+    then:
+      properties:
+        google,cros-ec-spi-pre-delay: false
+        google,cros-ec-spi-msg-delay: false
+        spi-max-frequency: false
+    else:
+      $ref: /schemas/spi/spi-peripheral-props.yaml
 
 additionalProperties: false
 
@@ -200,7 +203,7 @@ examples:
             spi-max-frequency = <5000000>;
 
             proximity {
-                    compatible = "google,cros-ec-mkbp-proximity";
+                compatible = "google,cros-ec-mkbp-proximity";
             };
 
             cbas {
diff --git a/Documentation/devicetree/bindings/mfd/max14577.txt b/Documentation/devicetree/bindings/mfd/max14577.txt
deleted file mode 100644 (file)
index be11943..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-Maxim MAX14577/77836 Multi-Function Device
-
-MAX14577 is a Multi-Function Device with Micro-USB Interface Circuit, Li+
-Battery Charger and SFOUT LDO output for powering USB devices. It is
-interfaced to host controller using I2C.
-
-MAX77836 additionally contains PMIC (with two LDO regulators) and Fuel Gauge.
-For the description of Fuel Gauge low SOC alert interrupt see:
-../power/supply/max17040_battery.txt
-
-
-Required properties:
-- compatible : Must be "maxim,max14577" or "maxim,max77836".
-- reg : I2C slave address for the max14577 chip (0x25 for max14577/max77836)
-- interrupts : IRQ line for the chip.
-
-
-Required nodes:
- - charger :
-       Node for configuring the charger driver.
-       Required properties:
-               - compatible : "maxim,max14577-charger"
-                       or "maxim,max77836-charger"
-               - maxim,fast-charge-uamp : Current in uA for Fast Charge;
-                       Valid values:
-                       - for max14577: 90000 - 950000;
-                       - for max77836: 45000 - 475000;
-               - maxim,eoc-uamp : Current in uA for End-Of-Charge mode;
-                       Valid values:
-                       - for max14577: 50000 - 200000;
-                       - for max77836: 5000 - 100000;
-               - maxim,ovp-uvolt : OverVoltage Protection Threshold in uV;
-                       In an overvoltage condition, INT asserts and charging
-                       stops. Valid values:
-                       - 6000000, 6500000, 7000000, 7500000;
-               - maxim,constant-uvolt : Battery Constant Voltage in uV;
-                       Valid values:
-                       - 4000000 - 4280000 (step by 20000);
-                       - 4350000;
-
-
-Optional nodes:
-- max14577-muic/max77836-muic :
-       Node used only by extcon consumers.
-       Required properties:
-               - compatible : "maxim,max14577-muic" or "maxim,max77836-muic"
-
-- regulators :
-       Required properties:
-               - compatible : "maxim,max14577-regulator"
-                       or "maxim,max77836-regulator"
-
-       May contain a sub-node per regulator from the list below. Each
-       sub-node should contain the constraints and initialization information
-       for that regulator. See regulator.txt for a description of standard
-       properties for these sub-nodes.
-
-       List of valid regulator names:
-       - for max14577: CHARGER, SAFEOUT.
-       - for max77836: CHARGER, SAFEOUT, LDO1, LDO2.
-
-       The SAFEOUT is a fixed voltage regulator so there is no need to specify
-       voltages for it.
-
-
-Example:
-
-#include <dt-bindings/interrupt-controller/irq.h>
-
-max14577@25 {
-       compatible = "maxim,max14577";
-       reg = <0x25>;
-       interrupt-parent = <&gpx1>;
-       interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
-
-       muic: max14577-muic {
-               compatible = "maxim,max14577-muic";
-       };
-
-       regulators {
-               compatible = "maxim,max14577-regulator";
-
-               SAFEOUT {
-                       regulator-name = "SAFEOUT";
-               };
-               CHARGER {
-                       regulator-name = "CHARGER";
-                       regulator-min-microamp = <90000>;
-                       regulator-max-microamp = <950000>;
-                       regulator-boot-on;
-               };
-       };
-
-       charger {
-               compatible = "maxim,max14577-charger";
-
-               maxim,constant-uvolt = <4350000>;
-               maxim,fast-charge-uamp = <450000>;
-               maxim,eoc-uamp = <50000>;
-               maxim,ovp-uvolt = <6500000>;
-       };
-};
-
-
-max77836@25 {
-       compatible = "maxim,max77836";
-       reg = <0x25>;
-       interrupt-parent = <&gpx1>;
-       interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
-
-       muic: max77836-muic {
-               compatible = "maxim,max77836-muic";
-       };
-
-       regulators {
-               compatible = "maxim,max77836-regulator";
-
-               SAFEOUT {
-                       regulator-name = "SAFEOUT";
-               };
-               CHARGER {
-                       regulator-name = "CHARGER";
-                       regulator-min-microamp = <90000>;
-                       regulator-max-microamp = <950000>;
-                       regulator-boot-on;
-               };
-               LDO1 {
-                       regulator-name = "LDO1";
-                       regulator-min-microvolt = <2700000>;
-                       regulator-max-microvolt = <2700000>;
-               };
-               LDO2 {
-                       regulator-name = "LDO2";
-                       regulator-min-microvolt = <800000>;
-                       regulator-max-microvolt = <3950000>;
-               };
-       };
-
-       charger {
-               compatible = "maxim,max77836-charger";
-
-               maxim,constant-uvolt = <4350000>;
-               maxim,fast-charge-uamp = <225000>;
-               maxim,eoc-uamp = <7500>;
-               maxim,ovp-uvolt = <6500000>;
-       };
-};
diff --git a/Documentation/devicetree/bindings/mfd/max77802.txt b/Documentation/devicetree/bindings/mfd/max77802.txt
deleted file mode 100644 (file)
index 09decac..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Maxim MAX77802 multi-function device
-
-The Maxim MAX77802 is a Power Management IC (PMIC) that contains 10 high
-efficiency Buck regulators, 32 Low-DropOut (LDO) regulators used to power
-up application processors and peripherals, a 2-channel 32kHz clock outputs,
-a Real-Time-Clock (RTC) and a I2C interface to program the individual
-regulators, clocks outputs and the RTC.
-
-Bindings for the built-in 32k clock generator block and
-regulators are defined in ../clk/maxim,max77802.txt and
-../regulator/max77802.txt respectively.
-
-Required properties:
-- compatible           : Must be "maxim,max77802"
-- reg                  : Specifies the I2C slave address of PMIC block.
-- interrupts           : I2C device IRQ line connected to the main SoC.
-
-Example:
-
-       max77802: pmic@9 {
-               compatible = "maxim,max77802";
-               interrupt-parent = <&intc>;
-               interrupts = <26 IRQ_TYPE_NONE>;
-               reg = <0x09>;
-       };
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml b/Documentation/devicetree/bindings/mfd/maxim,max14577.yaml
new file mode 100644 (file)
index 0000000..27870b8
--- /dev/null
@@ -0,0 +1,195 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max14577.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB
+  Integrated Circuit (MUIC).
+
+  The Maxim MAX14577 is a MicroUSB and Companion Power Management IC which
+  includes voltage safeout regulators, charger and MicroUSB management IC.
+
+  The Maxim MAX77836 is a MicroUSB and Companion Power Management IC which
+  includes voltage safeout and LDO regulators, charger, fuel-gauge and MicroUSB
+  management IC.
+
+properties:
+  compatible:
+    enum:
+      - maxim,max14577
+      - maxim,max77836
+
+  interrupts:
+    maxItems: 1
+
+  reg:
+    maxItems: 1
+
+  wakeup-source: true
+
+  charger:
+    $ref: /schemas/power/supply/maxim,max14577.yaml
+
+  extcon:
+    type: object
+    properties:
+      compatible:
+        enum:
+          - maxim,max14577-muic
+          - maxim,max77836-muic
+
+    required:
+      - compatible
+
+  regulators:
+    $ref: /schemas/regulator/maxim,max14577.yaml
+
+required:
+  - compatible
+  - interrupts
+  - reg
+  - charger
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: maxim,max14577
+    then:
+      properties:
+        charger:
+          properties:
+            compatible:
+              const: maxim,max14577-charger
+        extcon:
+          properties:
+            compatible:
+              const: maxim,max14577-muic
+        regulator:
+          properties:
+            compatible:
+              const: maxim,max14577-regulator
+    else:
+      properties:
+        charger:
+          properties:
+            compatible:
+              const: maxim,max77836-charger
+        extcon:
+          properties:
+            compatible:
+              const: maxim,max77836-muic
+        regulator:
+          properties:
+            compatible:
+              const: maxim,max77836-regulator
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@25 {
+            compatible = "maxim,max14577";
+            reg = <0x25>;
+            interrupt-parent = <&gpx1>;
+            interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+
+            extcon {
+                compatible = "maxim,max14577-muic";
+            };
+
+            regulators {
+                compatible = "maxim,max14577-regulator";
+
+                SAFEOUT {
+                    regulator-name = "SAFEOUT";
+                };
+
+                CHARGER {
+                    regulator-name = "CHARGER";
+                    regulator-min-microamp = <90000>;
+                    regulator-max-microamp = <950000>;
+                    regulator-boot-on;
+                };
+            };
+
+            charger {
+                compatible = "maxim,max14577-charger";
+
+                maxim,constant-uvolt = <4350000>;
+                maxim,fast-charge-uamp = <450000>;
+                maxim,eoc-uamp = <50000>;
+                maxim,ovp-uvolt = <6500000>;
+            };
+        };
+    };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@25 {
+            compatible = "maxim,max77836";
+            interrupt-parent = <&gpx1>;
+            interrupts = <5 IRQ_TYPE_NONE>;
+            reg = <0x25>;
+            wakeup-source;
+
+            extcon {
+                compatible = "maxim,max77836-muic";
+            };
+
+            regulators {
+                compatible = "maxim,max77836-regulator";
+
+                SAFEOUT {
+                    regulator-name = "SAFEOUT";
+                };
+
+                CHARGER {
+                    regulator-name = "CHARGER";
+                    regulator-min-microamp = <45000>;
+                    regulator-max-microamp = <475000>;
+                    regulator-boot-on;
+                };
+
+                LDO1 {
+                    regulator-name = "MOT_2.7V";
+                    regulator-min-microvolt = <1100000>;
+                    regulator-max-microvolt = <2700000>;
+                };
+
+                LDO2 {
+                    regulator-name = "UNUSED_LDO2";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <3950000>;
+                };
+            };
+
+            charger {
+                compatible = "maxim,max77836-charger";
+
+                maxim,constant-uvolt = <4350000>;
+                maxim,fast-charge-uamp = <225000>;
+                maxim,eoc-uamp = <7500>;
+                maxim,ovp-uvolt = <6500000>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77802.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77802.yaml
new file mode 100644 (file)
index 0000000..baa1346
--- /dev/null
@@ -0,0 +1,194 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max77802.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77802 Power Management IC
+
+maintainers:
+  - Javier Martinez Canillas <javier@dowhile0.org>
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX77802 Power Management
+  Integrated Circuit (PMIC).
+
+  The Maxim MAX77802 is a Power Management IC which includes voltage and
+  current regulators (10 high efficiency Buck regulators and 32 Low-DropOut
+  (LDO)), RTC and clock outputs.
+
+  The MAX77802 provides two 32.768khz clock outputs that can be controlled
+  (gated/ungated) over I2C.  The clock IDs are defined as preprocessor macros
+  in dt-bindings/clock/maxim,max77802.h.
+
+properties:
+  compatible:
+    const: maxim,max77802
+
+  '#clock-cells':
+    const: 1
+
+  interrupts:
+    maxItems: 1
+
+  reg:
+    maxItems: 1
+
+  regulators:
+    $ref: /schemas/regulator/maxim,max77802.yaml
+    description:
+      List of child nodes that specify the regulators.
+
+  inb1-supply:
+    description: Power supply for buck1
+  inb2-supply:
+    description: Power supply for buck2
+  inb3-supply:
+    description: Power supply for buck3
+  inb4-supply:
+    description: Power supply for buck4
+  inb5-supply:
+    description: Power supply for buck5
+  inb6-supply:
+    description: Power supply for buck6
+  inb7-supply:
+    description: Power supply for buck7
+  inb8-supply:
+    description: Power supply for buck8
+  inb9-supply:
+    description: Power supply for buck9
+  inb10-supply:
+    description: Power supply for buck10
+
+  inl1-supply:
+    description: Power supply for LDO8, LDO15
+  inl2-supply:
+    description: Power supply for LDO17, LDO27, LDO30, LDO35
+  inl3-supply:
+    description: Power supply for LDO3, LDO5, LDO7, LDO7
+  inl4-supply:
+    description: Power supply for LDO10, LDO11, LDO13, LDO14
+  inl5-supply:
+    description: Power supply for LDO9, LDO19
+  inl6-supply:
+    description: Power supply for LDO4, LDO21, LDO24, LDO33
+  inl7-supply:
+    description: Power supply for LDO18, LDO20, LDO28, LDO29
+  inl9-supply:
+    description: Power supply for LDO12, LDO23, LDO25, LDO26, LDO32, LDO34
+  inl10-supply:
+    description: Power supply for LDO1, LDO2
+
+  wakeup-source: true
+
+required:
+  - compatible
+  - '#clock-cells'
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/regulator/maxim,max77802.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@9 {
+            compatible = "maxim,max77802";
+            interrupt-parent = <&gpx3>;
+            interrupts = <1 IRQ_TYPE_NONE>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&max77802_irq>, <&pmic_selb>,
+                        <&pmic_dvs_1>, <&pmic_dvs_2>, <&pmic_dvs_3>;
+            wakeup-source;
+            reg = <0x9>;
+            #clock-cells = <1>;
+
+            inb1-supply = <&tps65090_dcdc2>;
+            inb2-supply = <&tps65090_dcdc1>;
+            inb3-supply = <&tps65090_dcdc2>;
+            inb4-supply = <&tps65090_dcdc2>;
+            inb5-supply = <&tps65090_dcdc1>;
+            inb6-supply = <&tps65090_dcdc2>;
+            inb7-supply = <&tps65090_dcdc1>;
+            inb8-supply = <&tps65090_dcdc1>;
+            inb9-supply = <&tps65090_dcdc1>;
+            inb10-supply = <&tps65090_dcdc1>;
+
+            inl1-supply = <&buck5_reg>;
+            inl2-supply = <&buck7_reg>;
+            inl3-supply = <&buck9_reg>;
+            inl4-supply = <&buck9_reg>;
+            inl5-supply = <&buck9_reg>;
+            inl6-supply = <&tps65090_dcdc2>;
+            inl7-supply = <&buck9_reg>;
+            inl9-supply = <&tps65090_dcdc2>;
+            inl10-supply = <&buck7_reg>;
+
+            regulators {
+                BUCK1 {
+                    regulator-name = "vdd_mif";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <1300000>;
+                    regulator-always-on;
+                    regulator-boot-on;
+                    regulator-ramp-delay = <12500>;
+                    regulator-state-mem {
+                        regulator-off-in-suspend;
+                    };
+                };
+
+                BUCK2 {
+                    regulator-name = "vdd_arm";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <1500000>;
+                    regulator-always-on;
+                    regulator-boot-on;
+                    regulator-ramp-delay = <12500>;
+                    regulator-coupled-with = <&buck3_reg>;
+                    regulator-coupled-max-spread = <300000>;
+                    regulator-state-mem {
+                        regulator-off-in-suspend;
+                    };
+                };
+
+                // ...
+
+                BUCK10 {
+                    regulator-name = "vdd_1v8";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                    regulator-always-on;
+                    regulator-boot-on;
+                    regulator-state-mem {
+                        regulator-on-in-suspend;
+                    };
+                };
+
+                LDO1 {
+                    regulator-name = "vdd_1v0";
+                    regulator-min-microvolt = <1000000>;
+                    regulator-max-microvolt = <1000000>;
+                    regulator-always-on;
+                    regulator-initial-mode = <MAX77802_OPMODE_NORMAL>;
+                    regulator-state-mem {
+                        regulator-on-in-suspend;
+                        regulator-mode = <MAX77802_OPMODE_LP>;
+                    };
+                };
+
+                // ...
+
+                LDO35 {
+                    regulator-name = "ldo_35";
+                    regulator-min-microvolt = <1200000>;
+                    regulator-max-microvolt = <1200000>;
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77843.yaml
new file mode 100644 (file)
index 0000000..61a0f9d
--- /dev/null
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/maxim,max77843.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77843 MicroUSB and Companion Power Management IC
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX77843 MicroUSB
+  Integrated Circuit (MUIC).
+
+  The Maxim MAX77843 is a MicroUSB and Companion Power Management IC which
+  includes voltage current regulators, charger, fuel-gauge, haptic motor driver
+  and MicroUSB management IC.
+
+properties:
+  compatible:
+    const: maxim,max77843
+
+  interrupts:
+    maxItems: 1
+
+  reg:
+    maxItems: 1
+
+  extcon:
+    $ref: /schemas/extcon/maxim,max77843.yaml
+
+  motor-driver:
+    type: object
+    properties:
+      compatible:
+        const: maxim,max77843-haptic
+
+      haptic-supply:
+        description: Power supply to the haptic motor
+
+      pwms:
+        maxItems: 1
+
+    required:
+      - compatible
+      - haptic-supply
+      - pwms
+
+  regulators:
+    $ref: /schemas/regulator/maxim,max77843.yaml
+
+required:
+  - compatible
+  - interrupts
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@66 {
+            compatible = "maxim,max77843";
+            interrupt-parent = <&gpa1>;
+            interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+            reg = <0x66>;
+
+            extcon {
+                compatible = "maxim,max77843-muic";
+
+                connector {
+                    compatible = "samsung,usb-connector-11pin",
+                                 "usb-b-connector";
+                    label = "micro-USB";
+                    type = "micro";
+
+                    ports {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        port@0 {
+                            /*
+                             * TODO: The DTS this is based on does not have
+                             * port@0 which is a required property. The ports
+                             * look incomplete and need fixing.
+                             * Add a disabled port just to satisfy dtschema.
+                             */
+                            reg = <0>;
+                            status = "disabled";
+                        };
+
+                        port@3 {
+                            reg = <3>;
+                            endpoint {
+                                remote-endpoint = <&mhl_to_musb_con>;
+                            };
+                        };
+                    };
+                };
+
+                ports {
+                    port {
+                        endpoint {
+                            remote-endpoint = <&usb_to_muic>;
+                        };
+                    };
+                };
+            };
+
+            regulators {
+                compatible = "maxim,max77843-regulator";
+
+                SAFEOUT1 {
+                    regulator-name = "SAFEOUT1";
+                    regulator-min-microvolt = <3300000>;
+                    regulator-max-microvolt = <4950000>;
+                };
+
+                SAFEOUT2 {
+                    regulator-name = "SAFEOUT2";
+                    regulator-min-microvolt = <3300000>;
+                    regulator-max-microvolt = <4950000>;
+                };
+
+                CHARGER {
+                    regulator-name = "CHARGER";
+                    regulator-min-microamp = <100000>;
+                    regulator-max-microamp = <3150000>;
+                };
+            };
+
+            motor-driver {
+                compatible = "maxim,max77843-haptic";
+                haptic-supply = <&ldo38_reg>;
+                pwms = <&pwm 0 33670 0>;
+            };
+        };
+    };
index 39421f7233e4c32fc01a5c1fc806497c3e8d4d64..4abfb4cfc1571e1e7fe4665653230384f548170c 100644 (file)
@@ -47,7 +47,8 @@ properties:
       identified by the JEDEC READ ID opcode (0x9F).
 
   reg:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
 
   spi-max-frequency: true
   spi-rx-bus-width: true
diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml
new file mode 100644 (file)
index 0000000..3978b48
--- /dev/null
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/maxim,max14577.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC Charger
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB
+  Integrated Circuit (MUIC).
+
+  See also Documentation/devicetree/bindings/mfd/maxim,max14577.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    enum:
+      - maxim,max14577-charger
+      - maxim,max77836-charger
+
+  maxim,constant-uvolt:
+    description:
+      Battery Constant Voltage in uV
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 4000000
+    maximum: 4350000
+
+  maxim,eoc-uamp:
+    description: |
+      Current in uA for End-Of-Charge mode.
+      MAX14577: 50000-20000
+      MAX77836: 5000-100000
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  maxim,fast-charge-uamp:
+    description: |
+      Current in uA for Fast Charge
+      MAX14577: 90000-950000
+      MAX77836: 45000-475000
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  maxim,ovp-uvolt:
+    description:
+      OverVoltage Protection Threshold in uV; In an overvoltage condition, INT
+      asserts and charging stops.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [6000000, 6500000, 7000000, 7500000]
+
+required:
+  - compatible
+  - maxim,constant-uvolt
+  - maxim,eoc-uamp
+  - maxim,fast-charge-uamp
+  - maxim,ovp-uvolt
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: maxim,max14577-charger
+    then:
+      properties:
+        maxim,eoc-uamp:
+          minimum: 50000
+          maximum: 200000
+        maxim,fast-charge-uamp:
+          minimum: 90000
+          maximum: 950000
+    else:
+      # max77836
+      properties:
+        maxim,eoc-uamp:
+          minimum: 5000
+          maximum: 100000
+        maxim,fast-charge-uamp:
+          minimum: 45000
+          maximum: 475000
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/max77802.txt b/Documentation/devicetree/bindings/regulator/max77802.txt
deleted file mode 100644 (file)
index b82943d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-Binding for Maxim MAX77802 regulators
-
-This is a part of device tree bindings of MAX77802 multi-function device.
-More information can be found in bindings/mfd/max77802.txt file.
-
-The MAX77802 PMIC has 10 high-efficiency Buck and 32 Low-dropout (LDO)
-regulators that can be controlled over I2C.
-
-Following properties should be present in main device node of the MFD chip.
-
-Optional properties:
-- inb1-supply:  The input supply for BUCK1
-- inb2-supply:  The input supply for BUCK2
-- inb3-supply:  The input supply for BUCK3
-- inb4-supply:  The input supply for BUCK4
-- inb5-supply:  The input supply for BUCK5
-- inb6-supply:  The input supply for BUCK6
-- inb7-supply:  The input supply for BUCK7
-- inb8-supply:  The input supply for BUCK8
-- inb9-supply:  The input supply for BUCK9
-- inb10-supply: The input supply for BUCK10
-- inl1-supply:  The input supply for LDO8 and LDO15
-- inl2-supply:  The input supply for LDO17, LDO27, LDO30 and LDO35
-- inl3-supply:  The input supply for LDO3, LDO5, LDO6 and LDO7
-- inl4-supply:  The input supply for LDO10, LDO11, LDO13 and LDO14
-- inl5-supply:  The input supply for LDO9 and LDO19
-- inl6-supply:  The input supply for LDO4, LDO21, LDO24 and LDO33
-- inl7-supply:  The input supply for LDO18, LDO20, LDO28 and LDO29
-- inl9-supply:  The input supply for LDO12, LDO23, LDO25, LDO26, LDO32 and LDO34
-- inl10-supply: The input supply for LDO1 and LDO2
-
-Optional nodes:
-- regulators : The regulators of max77802 have to be instantiated
-  under subnode named "regulators" using the following format.
-
-       regulator-name {
-               standard regulator constraints....
-       };
-       refer Documentation/devicetree/bindings/regulator/regulator.txt
-
-The regulator node name should be initialized with a string to get matched
-with their hardware counterparts as follow. The valid names are:
-
-       -LDOn   :       for LDOs, where n can lie in ranges 1-15, 17-21, 23-30
-                       and 32-35.
-                       example: LDO1, LDO2, LDO35.
-       -BUCKn  :       for BUCKs, where n can lie in range 1 to 10.
-                       example: BUCK1, BUCK5, BUCK10.
-
-The max77802 regulator supports two different operating modes: Normal and Low
-Power Mode. Some regulators support the modes to be changed at startup or by
-the consumers during normal operation while others only support to change the
-mode during system suspend. The standard regulator suspend states binding can
-be used to configure the regulator operating mode.
-
-The regulators that support the standard "regulator-initial-mode" property,
-changing their mode during normal operation are: LDOs 1, 3, 20 and 21.
-
-The possible values for "regulator-initial-mode" and "regulator-mode" are:
-       1: Normal regulator voltage output mode.
-       3: Low Power which reduces the quiescent current down to only 1uA
-
-The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h
-header and can be included by device tree source files.
-
-The standard "regulator-mode" property can only be used for regulators that
-support changing their mode to Low Power Mode during suspend. These regulators
-are: BUCKs 2-4 and LDOs 1-35. Also, it only takes effect if the regulator has
-been enabled for the given suspend state using "regulator-on-in-suspend" and
-has not been disabled for that state using "regulator-off-in-suspend".
-
-Example:
-
-       max77802@9 {
-               compatible = "maxim,max77802";
-               interrupt-parent = <&wakeup_eint>;
-               interrupts = <26 0>;
-               reg = <0x09>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               inb1-supply = <&parent_reg>;
-
-               regulators {
-                       ldo1_reg: LDO1 {
-                               regulator-name = "vdd_1v0";
-                               regulator-min-microvolt = <1000000>;
-                               regulator-max-microvolt = <1000000>;
-                               regulator-always-on;
-                               regulator-initial-mode = <MAX77802_OPMODE_LP>;
-                       };
-
-                       ldo11_reg: LDO11 {
-                               regulator-name = "vdd_ldo11";
-                               regulator-min-microvolt = <1900000>;
-                               regulator-max-microvolt = <1900000>;
-                               regulator-always-on;
-                               regulator-state-mem {
-                                       regulator-on-in-suspend;
-                                       regulator-mode = <MAX77802_OPMODE_LP>;
-                               };
-                       };
-
-                       buck1_reg: BUCK1 {
-                               regulator-name = "vdd_mif";
-                               regulator-min-microvolt = <950000>;
-                               regulator-max-microvolt = <1300000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-       };
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max14577.yaml b/Documentation/devicetree/bindings/regulator/maxim,max14577.yaml
new file mode 100644 (file)
index 0000000..16f0188
--- /dev/null
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/maxim,max14577.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX14577/MAX77836 MicroUSB and Companion Power Management IC regulators
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX14577/MAX77836 MicroUSB
+  Integrated Circuit (MUIC).
+
+  See also Documentation/devicetree/bindings/mfd/maxim,max14577.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    enum:
+      - maxim,max14577-regulator
+      - maxim,max77836-regulator
+
+  CHARGER:
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description: |
+      Current regulator.
+
+    properties:
+      regulator-min-microvolt: false
+      regulator-max-microvolt: false
+
+  SAFEOUT:
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description: |
+      Safeout LDO regulator (fixed voltage).
+
+    properties:
+      regulator-min-microamp: false
+      regulator-max-microamp: false
+      regulator-min-microvolt:
+        const: 4900000
+      regulator-max-microvolt:
+        const: 4900000
+
+patternProperties:
+  "^LDO[12]$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description: |
+      Current regulator.
+
+    properties:
+      regulator-min-microamp: false
+      regulator-max-microamp: false
+      regulator-min-microvolt:
+        minimum: 800000
+      regulator-max-microvolt:
+        maximum: 3950000
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: maxim,max14577-regulator
+    then:
+      properties:
+        LDO1: false
+        LDO2: false
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
new file mode 100644 (file)
index 0000000..f2b4dd1
--- /dev/null
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/maxim,max77802.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77802 Power Management IC regulators
+
+maintainers:
+  - Javier Martinez Canillas <javier@dowhile0.org>
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX77802 Power Management
+  Integrated Circuit (PMIC).
+
+  The Maxim MAX77686 provides 10 high-efficiency Buck and 32 Low-DropOut (LDO)
+  regulators.
+
+  See also Documentation/devicetree/bindings/mfd/maxim,max77802.yaml for
+  additional information and example.
+
+  Certain regulators support "regulator-initial-mode" and "regulator-mode".
+  The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h
+  and their meaning is::
+    1 - Normal regulator voltage output mode.
+    3 - Low Power which reduces the quiescent current down to only 1uA
+
+  The standard "regulator-mode" property can only be used for regulators that
+  support changing their mode to Low Power Mode during suspend. These
+  regulators are:: bucks 2-4 and LDOs 1-35. Also, it only takes effect if the
+  regulator has been enabled for the given suspend state using
+  "regulator-on-in-suspend" and has not been disabled for that state using
+  "regulator-off-in-suspend".
+
+patternProperties:
+  # LDO1, LDO3, LDO20, LDO21
+  "^LDO([13]|2[01])$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      LDOs supporting the regulator-initial-mode property and changing their
+      mode during normal operation.
+
+  # LDO2, LDO4-15, LDO17-19, LDO23-30, LDO32-35
+  "^LDO([24-9]|1[0-5789]|2[3-9]|3[02345])$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      LDOs supporting the regulator-mode property (changing mode to Low Power
+      Mode during suspend).
+
+    properties:
+      regulator-initial-mode: false
+
+  # buck2-4
+  "^BUCK[2-4]$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      bucks supporting the regulator-mode property (changing mode to Low Power
+      Mode during suspend).
+
+    properties:
+      regulator-initial-mode: false
+
+  # buck1, buck5-10
+  "^BUCK([15-9]|10)$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+
+    properties:
+      regulator-initial-mode: false
+
+    patternProperties:
+      regulator-state-(standby|mem|disk):
+        type: object
+        properties:
+          regulator-mode: false
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77843.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77843.yaml
new file mode 100644 (file)
index 0000000..a963025
--- /dev/null
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/maxim,max77843.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim MAX77843 MicroUSB and Companion Power Management IC regulators
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description: |
+  This is a part of device tree bindings for Maxim MAX77843 MicroUSB Integrated
+  Circuit (MUIC).
+
+  See also Documentation/devicetree/bindings/mfd/maxim,max77843.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    const: maxim,max77843-regulator
+
+  CHARGER:
+    type: object
+    $ref: regulator.yaml#
+    additionalProperties: false
+    description: |
+      Current regulator.
+
+    properties:
+      regulator-name: true
+      regulator-always-on: true
+      regulator-boot-on: true
+      regulator-min-microamp:
+        minimum: 100000
+      regulator-max-microamp:
+        maximum: 3150000
+
+    required:
+      - regulator-name
+
+patternProperties:
+  "^SAFEOUT[12]$":
+    type: object
+    $ref: regulator.yaml#
+    additionalProperties: false
+    description: |
+      Safeout LDO regulator.
+
+    properties:
+      regulator-name: true
+      regulator-always-on: true
+      regulator-boot-on: true
+      regulator-min-microvolt:
+        minimum: 3300000
+      regulator-max-microvolt:
+        maximum: 4950000
+
+    required:
+      - regulator-name
+
+required:
+  - compatible
+
+additionalProperties: false
index 273f2d95a04373892e774f56a1bd9d03abae7b63..e72b6a3fae999708bd98fcf42413d8c0b89f1a8e 100644 (file)
@@ -22,7 +22,7 @@ description: |
 
   [1] Documentation/devicetree/bindings/serial/samsung_uart.yaml
   [2] Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
-  [3] Documentation/devicetree/bindings/spi/spi-samsung.txt
+  [3] Documentation/devicetree/bindings/spi/samsung,spi.yaml
 
 properties:
   $nodename:
diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml
new file mode 100644 (file)
index 0000000..818130b
--- /dev/null
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/mediatek,spi-mt65xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SPI Bus controller for MediaTek ARM SoCs
+
+maintainers:
+  - Leilk Liu <leilk.liu@mediatek.com>
+
+allOf:
+  - $ref: "/schemas/spi/spi-controller.yaml#"
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - mediatek,mt7629-spi
+          - const: mediatek,mt7622-spi
+      - items:
+          - enum:
+              - mediatek,mt8516-spi
+          - const: mediatek,mt2712-spi
+      - items:
+          - enum:
+              - mediatek,mt6779-spi
+              - mediatek,mt8186-spi
+              - mediatek,mt8192-spi
+              - mediatek,mt8195-spi
+          - const: mediatek,mt6765-spi
+      - items:
+          - enum:
+              - mediatek,mt7986-spi-ipm
+          - const: mediatek,spi-ipm
+      - items:
+          - enum:
+              - mediatek,mt2701-spi
+              - mediatek,mt2712-spi
+              - mediatek,mt6589-spi
+              - mediatek,mt6765-spi
+              - mediatek,mt6893-spi
+              - mediatek,mt7622-spi
+              - mediatek,mt8135-spi
+              - mediatek,mt8173-spi
+              - mediatek,mt8183-spi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: clock used for the parent clock
+      - description: clock used for the muxes clock
+      - description: clock used for the clock gate
+
+  clock-names:
+    items:
+      - const: parent-clk
+      - const: sel-clk
+      - const: spi-clk
+
+  mediatek,pad-select:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 4
+    items:
+      enum: [0, 1, 2, 3]
+    description:
+      specify which pins group(ck/mi/mo/cs) spi controller used.
+      This is an array.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - '#address-cells'
+  - '#size-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt8173-clk.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    spi@1100a000 {
+      compatible = "mediatek,mt8173-spi";
+      #address-cells = <1>;
+      #size-cells = <0>;
+      reg = <0x1100a000 0x1000>;
+      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
+      clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+               <&topckgen CLK_TOP_SPI_SEL>,
+               <&pericfg CLK_PERI_SPI0>;
+      clock-names = "parent-clk", "sel-clk", "spi-clk";
+      cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>;
+      mediatek,pad-select = <1>, <0>;
+    };
index 4e4694e3d5390780ab187bbf3c98d20f0157acd4..be3cc7faed534d633e220a2b19f32471e1685648 100644 (file)
@@ -30,6 +30,7 @@ properties:
               - mediatek,mt7622-nor
               - mediatek,mt7623-nor
               - mediatek,mt7629-nor
+              - mediatek,mt8186-nor
               - mediatek,mt8192-nor
               - mediatek,mt8195-nor
           - enum:
@@ -49,6 +50,8 @@ properties:
       - description: clock used for controller
       - description: clock used for nor dma bus. this depends on hardware
                      design, so this is optional.
+      - description: clock used for controller axi slave bus.
+                     this depends on hardware design, so it is optional.
 
   clock-names:
     minItems: 2
@@ -56,6 +59,7 @@ properties:
       - const: spi
       - const: sf
       - const: axi
+      - const: axi_s
 
 required:
   - compatible
diff --git a/Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml b/Documentation/devicetree/bindings/spi/mediatek,spi-slave-mt27xx.yaml
new file mode 100644 (file)
index 0000000..7977799
--- /dev/null
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/mediatek,spi-slave-mt27xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SPI Slave controller for MediaTek ARM SoCs
+
+maintainers:
+  - Leilk Liu <leilk.liu@mediatek.com>
+
+allOf:
+  - $ref: "/schemas/spi/spi-controller.yaml#"
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt2712-spi-slave
+      - mediatek,mt8195-spi-slave
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: spi
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt2712-clk.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    spi@10013000 {
+      compatible = "mediatek,mt2712-spi-slave";
+      reg = <0x10013000 0x100>;
+      interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_LOW>;
+      clocks = <&infracfg CLK_INFRA_AO_SPI1>;
+      clock-names = "spi";
+      assigned-clocks = <&topckgen CLK_TOP_SPISLV_SEL>;
+      assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>;
+    };
diff --git a/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml b/Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
new file mode 100644 (file)
index 0000000..ece261b
--- /dev/null
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/microchip,mpfs-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip MPFS {Q,}SPI Controller Device Tree Bindings
+
+maintainers:
+  - Conor Dooley <conor.dooley@microchip.com>
+
+allOf:
+  - $ref: spi-controller.yaml#
+
+properties:
+  compatible:
+    enum:
+      - microchip,mpfs-spi
+      - microchip,mpfs-qspi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clock-names:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include "dt-bindings/clock/microchip,mpfs-clock.h"
+    spi@20108000 {
+        compatible = "microchip,mpfs-spi";
+        reg = <0x20108000 0x1000>;
+        clocks = <&clkcfg CLK_SPI0>;
+        interrupt-parent = <&plic>;
+        interrupts = <54>;
+        spi-max-frequency = <25000000>;
+    };
+...
index 35a8045b2c70db82a1b4ec8961362818dda44ae0..0296edd1de22e7b8f190f52f465d5c777adf6a43 100644 (file)
@@ -19,6 +19,7 @@ properties:
       - nvidia,tegra210-qspi
       - nvidia,tegra186-qspi
       - nvidia,tegra194-qspi
+      - nvidia,tegra234-qspi
 
   reg:
     maxItems: 1
@@ -106,7 +107,7 @@ examples:
             dma-names = "rx", "tx";
 
             flash@0 {
-                    compatible = "spi-nor";
+                    compatible = "jedec,spi-nor";
                     reg = <0>;
                     spi-max-frequency = <104000000>;
                     spi-tx-bus-width = <2>;
index 76e6d9e52fc7222a62db44279875aa7c7014ca94..2c3c6bd6ec45b72e5a23080c2a817636306fa37a 100644 (file)
@@ -22,7 +22,8 @@ properties:
               - renesas,rspi-r7s72100  # RZ/A1H
               - renesas,rspi-r7s9210   # RZ/A2
               - renesas,r9a07g044-rspi # RZ/G2{L,LC}
-          - const: renesas,rspi-rz     # RZ/A and RZ/G2{L,LC}
+              - renesas,r9a07g054-rspi # RZ/V2L
+          - const: renesas,rspi-rz
 
       - items:
           - enum:
@@ -124,6 +125,7 @@ allOf:
             enum:
               - renesas,qspi
               - renesas,r9a07g044-rspi
+              - renesas,r9a07g054-rspi
     then:
       required:
         - resets
diff --git a/Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/samsung,spi-peripheral-props.yaml
new file mode 100644 (file)
index 0000000..f0db3fb
--- /dev/null
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/samsung,spi-peripheral-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Peripheral-specific properties for Samsung S3C/S5P/Exynos SoC SPI controller
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description:
+  See spi-peripheral-props.yaml for more info.
+
+properties:
+  controller-data:
+    type: object
+    additionalProperties: false
+
+    properties:
+      samsung,spi-feedback-delay:
+        description: |
+          The sampling phase shift to be applied on the miso line (to account
+          for any lag in the miso line). Valid values:
+           - 0: No phase shift.
+           - 1: 90 degree phase shift sampling.
+           - 2: 180 degree phase shift sampling.
+           - 3: 270 degree phase shift sampling.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        enum: [0, 1, 2, 3]
+        default: 0
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml
new file mode 100644 (file)
index 0000000..bf9a76d
--- /dev/null
@@ -0,0 +1,188 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/samsung,spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S3C/S5P/Exynos SoC SPI controller
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+description:
+  All the SPI controller nodes should be represented in the aliases node using
+  the following format 'spi{n}' where n is a unique number for the alias.
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450
+          - samsung,s3c6410-spi
+          - samsung,s5pv210-spi # for S5PV210 and S5PC110
+          - samsung,exynos5433-spi
+          - tesla,fsd-spi
+      - const: samsung,exynos7-spi
+        deprecated: true
+
+  clocks:
+    minItems: 2
+    maxItems: 3
+
+  clock-names:
+    minItems: 2
+    maxItems: 3
+
+  cs-gpios: true
+
+  dmas:
+    minItems: 2
+    maxItems: 2
+
+  dma-names:
+    items:
+      - const: tx
+      - const: rx
+
+  interrupts:
+    maxItems: 1
+
+  no-cs-readback:
+    description:
+      The CS line is disconnected, therefore the device should not operate
+      based on CS signalling.
+    type: boolean
+
+  num-cs:
+    minimum: 1
+    maximum: 4
+    default: 1
+
+  samsung,spi-src-clk:
+    description:
+      If the spi controller includes a internal clock mux to select the clock
+      source for the spi bus clock, this property can be used to indicate the
+      clock to be used for driving the spi bus clock. If not specified, the
+      clock number 0 is used as default.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 0
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+  - interrupts
+  - reg
+
+allOf:
+  - $ref: spi-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,exynos5433-spi
+    then:
+      properties:
+        clocks:
+          minItems: 3
+          maxItems: 3
+        clock-names:
+          items:
+            - const: spi
+            - enum:
+                - spi_busclk0
+                - spi_busclk1
+                - spi_busclk2
+                - spi_busclk3
+            - const: spi_ioclk
+    else:
+      properties:
+        clocks:
+          minItems: 2
+          maxItems: 2
+        clock-names:
+          items:
+            - const: spi
+            - enum:
+                - spi_busclk0
+                - spi_busclk1
+                - spi_busclk2
+                - spi_busclk3
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos5433.h>
+    #include <dt-bindings/clock/samsung,s2mps11.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    spi@14d30000 {
+        compatible = "samsung,exynos5433-spi";
+        reg = <0x14d30000 0x100>;
+        interrupts = <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>;
+        dmas = <&pdma0 11>, <&pdma0 10>;
+        dma-names = "tx", "rx";
+        #address-cells = <1>;
+        #size-cells = <0>;
+        clocks = <&cmu_peric CLK_PCLK_SPI1>,
+                 <&cmu_peric CLK_SCLK_SPI1>,
+                 <&cmu_peric CLK_SCLK_IOCLK_SPI1>;
+        clock-names = "spi",
+                      "spi_busclk0",
+                      "spi_ioclk";
+        samsung,spi-src-clk = <0>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&spi1_bus>;
+        num-cs = <1>;
+
+        cs-gpios = <&gpd6 3 GPIO_ACTIVE_HIGH>;
+
+        audio-codec@0 {
+            compatible = "wlf,wm5110";
+            reg = <0x0>;
+            spi-max-frequency = <20000000>;
+            interrupt-parent = <&gpa0>;
+            interrupts = <4 IRQ_TYPE_NONE>;
+            clocks = <&pmu_system_controller 0>,
+                     <&s2mps13_osc S2MPS11_CLK_BT>;
+            clock-names = "mclk1", "mclk2";
+
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+
+            wlf,micd-detect-debounce = <300>;
+            wlf,micd-bias-start-time = <0x1>;
+            wlf,micd-rate = <0x7>;
+            wlf,micd-dbtime = <0x2>;
+            wlf,micd-force-micbias;
+            wlf,micd-configs = <0x0 1 0>;
+            wlf,hpdet-channel = <1>;
+            wlf,gpsw = <0x1>;
+            wlf,inmode = <2 0 2 0>;
+
+            wlf,reset = <&gpc0 7 GPIO_ACTIVE_HIGH>;
+            wlf,ldoena = <&gpf0 0 GPIO_ACTIVE_HIGH>;
+
+            /* core supplies */
+            AVDD-supply = <&ldo18_reg>;
+            DBVDD1-supply = <&ldo18_reg>;
+            CPVDD-supply = <&ldo18_reg>;
+            DBVDD2-supply = <&ldo18_reg>;
+            DBVDD3-supply = <&ldo18_reg>;
+            SPKVDDL-supply = <&ldo18_reg>;
+            SPKVDDR-supply = <&ldo18_reg>;
+
+            controller-data {
+                samsung,spi-feedback-delay = <0>;
+            };
+        };
+    };
index 36b72518f5654cf2af0aee3495c180737f029606..0f4d40218400eb4212a89bce631f7fc9b649afd8 100644 (file)
@@ -139,4 +139,11 @@ examples:
             spi-max-frequency = <100000>;
             reg = <1>;
         };
+
+        flash@2 {
+          compatible = "jedec,spi-nor";
+          spi-max-frequency = <50000000>;
+          reg = <2>, <3>;
+          stacked-memories = /bits/ 64 <0x10000000 0x10000000>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
deleted file mode 100644 (file)
index 2a24969..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-Binding for MTK SPI controller
-
-Required properties:
-- compatible: should be one of the following.
-    - mediatek,mt2701-spi: for mt2701 platforms
-    - mediatek,mt2712-spi: for mt2712 platforms
-    - mediatek,mt6589-spi: for mt6589 platforms
-    - mediatek,mt6765-spi: for mt6765 platforms
-    - mediatek,mt7622-spi: for mt7622 platforms
-    - "mediatek,mt7629-spi", "mediatek,mt7622-spi": for mt7629 platforms
-    - mediatek,mt8135-spi: for mt8135 platforms
-    - mediatek,mt8173-spi: for mt8173 platforms
-    - mediatek,mt8183-spi: for mt8183 platforms
-    - mediatek,mt6893-spi: for mt6893 platforms
-    - "mediatek,mt8192-spi", "mediatek,mt6765-spi": for mt8192 platforms
-    - "mediatek,mt8195-spi", "mediatek,mt6765-spi": for mt8195 platforms
-    - "mediatek,mt8516-spi", "mediatek,mt2712-spi": for mt8516 platforms
-    - "mediatek,mt6779-spi", "mediatek,mt6765-spi": for mt6779 platforms
-
-- #address-cells: should be 1.
-
-- #size-cells: should be 0.
-
-- reg: Address and length of the register set for the device
-
-- interrupts: Should contain spi interrupt
-
-- clocks: phandles to input clocks.
-  The first should be one of the following. It's PLL.
-   -  <&clk26m>: specify parent clock 26MHZ.
-   -  <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ.
-                                     It's the default one.
-   -  <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ.
-   -  <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
-   -  <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
-  The second should be <&topckgen CLK_TOP_SPI_SEL>. It's clock mux.
-  The third is <&pericfg CLK_PERI_SPI0>. It's clock gate.
-
-- clock-names: shall be "parent-clk" for the parent clock, "sel-clk" for the
-  muxes clock, and "spi-clk" for the clock gate.
-
-Optional properties:
--cs-gpios: see spi-bus.txt.
-
-- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
-  controller used. This is an array, the element value should be 0~3,
-  only required for MT8173.
-    0: specify GPIO69,70,71,72 for spi pins.
-    1: specify GPIO102,103,104,105 for spi pins.
-    2: specify GPIO128,129,130,131 for spi pins.
-    3: specify GPIO5,6,7,8 for spi pins.
-
-Example:
-
-- SoC Specific Portion:
-spi: spi@1100a000 {
-       compatible = "mediatek,mt8173-spi";
-       #address-cells = <1>;
-       #size-cells = <0>;
-       reg = <0 0x1100a000 0 0x1000>;
-       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
-       clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
-                <&topckgen CLK_TOP_SPI_SEL>,
-                <&pericfg CLK_PERI_SPI0>;
-       clock-names = "parent-clk", "sel-clk", "spi-clk";
-       cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>;
-       mediatek,pad-select = <1>, <0>;
-};
index 283815d59e85f8b8e7ae69aa500289a2e6dcde82..1b552c298277b1c04b1bb175598f948521640fdc 100644 (file)
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: NXP Flex Serial Peripheral Interface (FSPI)
 
 maintainers:
-  - Kuldeep Singh <kuldeep.singh@nxp.com>
+  - Han Xu <han.xu@nxp.com>
+  - Kuldeep Singh <singh.kuldeep87k@gmail.com>
 
 allOf:
   - $ref: "spi-controller.yaml#"
index 3ec2d7b83775a9c1be30e9629e7bb4933acfd2cf..5e32928c4fc3ca186c865f975350c7f640317216 100644 (file)
@@ -83,8 +83,34 @@ properties:
     description:
       Delay, in microseconds, after a write transfer.
 
+  stacked-memories:
+    description: Several SPI memories can be wired in stacked mode.
+      This basically means that either a device features several chip
+      selects, or that different devices must be seen as a single
+      bigger chip. This basically doubles (or more) the total address
+      space with only a single additional wire, while still needing
+      to repeat the commands when crossing a chip boundary. The size of
+      each chip should be provided as members of the array.
+    $ref: /schemas/types.yaml#/definitions/uint64-array
+    minItems: 2
+    maxItems: 4
+
+  parallel-memories:
+    description: Several SPI memories can be wired in parallel mode.
+      The devices are physically on a different buses but will always
+      act synchronously as each data word is spread across the
+      different memories (eg. even bits are stored in one memory, odd
+      bits in the other). This basically doubles the address space and
+      the throughput while greatly complexifying the wiring because as
+      many busses as devices must be wired. The size of each chip should
+      be provided as members of the array.
+    $ref: /schemas/types.yaml#/definitions/uint64-array
+    minItems: 2
+    maxItems: 4
+
 # The controller specific properties go here.
 allOf:
   - $ref: cdns,qspi-nor-peripheral-props.yaml#
+  - $ref: samsung,spi-peripheral-props.yaml#
 
 additionalProperties: true
index 6d633728fc2be569032f306717d93ae5d6392a1b..bda45ff3d2942f358efd6ae1991720cd76ade11b 100644 (file)
@@ -38,9 +38,7 @@ properties:
 
   clock-names:
     items:
-      - enum:
-          - SSPCLK
-          - sspclk
+      - const: sspclk
       - const: apb_pclk
 
   pl022,autosuspend-delay:
diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt
deleted file mode 100644 (file)
index 49028a4..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-* Samsung SPI Controller
-
-The Samsung SPI controller is used to interface with various devices such as flash
-and display controllers using the SPI communication interface.
-
-Required SoC Specific Properties:
-
-- compatible: should be one of the following.
-    - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
-    - samsung,s3c6410-spi: for s3c6410 platforms
-    - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
-    - samsung,exynos5433-spi: for exynos5433 compatible controllers
-    - samsung,exynos7-spi: for exynos7 platforms <DEPRECATED>
-
-- 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.
-
-- dmas : Two or more DMA channel specifiers following the convention outlined
-  in bindings/dma/dma.txt
-
-- dma-names: Names for the dma channels. There must be at least one channel
-  named "tx" for transmit and named "rx" for receive.
-
-- clocks: specifies the clock IDs provided to the SPI controller; they are
-  required for interacting with the controller itself, for synchronizing the bus
-  and as I/O clock (the latter is required by exynos5433 and exynos7).
-
-- clock-names: string names of the clocks in the 'clocks' property; for all the
-  the devices the names must be "spi", "spi_busclkN" (where N is determined by
-  "samsung,spi-src-clk"), while Exynos5433 should specify a third clock
-  "spi_ioclk" for the I/O clock.
-
-Required Board Specific Properties:
-
-- #address-cells: should be 1.
-- #size-cells: should be 0.
-
-Optional Board Specific Properties:
-
-- samsung,spi-src-clk: If the spi controller includes a internal clock mux to
-  select the clock source for the spi bus clock, this property can be used to
-  indicate the clock to be used for driving the spi bus clock. If not specified,
-  the clock number 0 is used as default.
-
-- num-cs: Specifies the number of chip select lines supported. If
-  not specified, the default number of chip select lines is set to 1.
-
-- cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt)
-
-- no-cs-readback: the CS line is disconnected, therefore the device should not
-  operate based on CS signalling.
-
-SPI Controller specific data in SPI slave nodes:
-
-- The spi slave nodes should provide the following information which is required
-  by the spi controller.
-
-  - samsung,spi-feedback-delay: The sampling phase shift to be applied on the
-    miso line (to account for any lag in the miso line). The following are the
-    valid values.
-
-      - 0: No phase shift.
-      - 1: 90 degree phase shift sampling.
-      - 2: 180 degree phase shift sampling.
-      - 3: 270 degree phase shift sampling.
-
-Aliases:
-
-- All the SPI controller nodes should be represented in the aliases node using
-  the following format 'spi{n}' where n is a unique number for the alias.
-
-
-Example:
-
-- SoC Specific Portion:
-
-       spi_0: spi@12d20000 {
-               compatible = "samsung,exynos4210-spi";
-               reg = <0x12d20000 0x100>;
-               interrupts = <0 66 0>;
-               dmas = <&pdma0 5
-                       &pdma0 4>;
-               dma-names = "tx", "rx";
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
-- Board Specific Portion:
-
-       spi_0: spi@12d20000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&spi0_bus>;
-               cs-gpios = <&gpa2 5 0>;
-
-               w25q80bw@0 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "w25x80";
-                       reg = <0>;
-                       spi-max-frequency = <10000>;
-
-                       controller-data {
-                               samsung,spi-feedback-delay = <0>;
-                       };
-
-                       partition@0 {
-                               label = "U-Boot";
-                               reg = <0x0 0x40000>;
-                               read-only;
-                       };
-
-                       partition@40000 {
-                               label = "Kernel";
-                               reg = <0x40000 0xc0000>;
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt b/Documentation/devicetree/bindings/spi/spi-slave-mt27xx.txt
deleted file mode 100644 (file)
index 9192724..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Binding for MTK SPI Slave controller
-
-Required properties:
-- compatible: should be one of the following.
-    - mediatek,mt2712-spi-slave: for mt2712 platforms
-    - mediatek,mt8195-spi-slave: for mt8195 platforms
-- reg: Address and length of the register set for the device.
-- interrupts: Should contain spi interrupt.
-- clocks: phandles to input clocks.
-  It's clock gate, and should be <&infracfg CLK_INFRA_AO_SPI1>.
-- clock-names: should be "spi" for the clock gate.
-
-Optional properties:
-- assigned-clocks: it's mux clock, should be <&topckgen CLK_TOP_SPISLV_SEL>.
-- assigned-clock-parents: parent of mux clock.
-  It's PLL, and should be one of the following.
-   -  <&topckgen CLK_TOP_UNIVPLL1_D2>: specify parent clock 312MHZ.
-                                      It's the default one.
-   -  <&topckgen CLK_TOP_UNIVPLL1_D4>: specify parent clock 156MHZ.
-   -  <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
-   -  <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
-
-Example:
-- SoC Specific Portion:
-spis1: spi@10013000 {
-       compatible = "mediatek,mt2712-spi-slave";
-       reg = <0 0x10013000 0 0x100>;
-       interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_LOW>;
-       clocks = <&infracfg CLK_INFRA_AO_SPI1>;
-       clock-names = "spi";
-       assigned-clocks = <&topckgen CLK_TOP_SPISLV_SEL>;
-       assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>;
-};
diff --git a/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml b/Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
new file mode 100644 (file)
index 0000000..3a58cf0
--- /dev/null
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (C) Sunplus Co., Ltd. 2021
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/spi-sunplus-sp7021.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sunplus sp7021 SPI controller
+
+allOf:
+  - $ref: "spi-controller.yaml"
+
+maintainers:
+  - Li-hao Kuo <lhjeff911@gmail.com>
+
+properties:
+  compatible:
+    enum:
+      - sunplus,sp7021-spi
+
+  reg:
+    items:
+      - description: the SPI master registers
+      - description: the SPI slave registers
+
+  reg-names:
+    items:
+      - const: master
+      - const: slave
+
+  interrupt-names:
+    items:
+      - const: dma_w
+      - const: master_risc
+      - const: slave_risc
+
+  interrupts:
+    minItems: 3
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - interrupt-names
+  - clocks
+  - resets
+  - pinctrl-names
+  - pinctrl-0
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    spi@9C002D80 {
+        compatible = "sunplus,sp7021-spi";
+        reg = <0x9C002D80 0x80>, <0x9C002E00 0x80>;
+        reg-names = "master", "slave";
+        interrupt-parent = <&intc>;
+        interrupt-names = "dma_w",
+                          "master_risc",
+                          "slave_risc";
+        interrupts = <144 IRQ_TYPE_LEVEL_HIGH>,
+                     <146 IRQ_TYPE_LEVEL_HIGH>,
+                     <145 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clkc 0x32>;
+        resets = <&rstc 0x22>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pins_spi0>;
+    };
+...
index 436ba5a851d7c43a16c55d708ec0902458fcb107..6a4278f409d78176a8b95719aaf54813f155ea90 100644 (file)
@@ -7,6 +7,6 @@ Memory Technology Device (MTD)
 .. toctree::
    :maxdepth: 1
 
-   intel-spi
+   spi-intel
    nand_ecc
    spi-nor
diff --git a/Documentation/driver-api/mtd/intel-spi.rst b/Documentation/driver-api/mtd/intel-spi.rst
deleted file mode 100644 (file)
index 0465f68..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-==============================
-Upgrading BIOS using intel-spi
-==============================
-
-Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
-controller which is used to hold BIOS and other platform specific data.
-Since contents of the SPI serial flash is crucial for machine to function,
-it is typically protected by different hardware protection mechanisms to
-avoid accidental (or on purpose) overwrite of the content.
-
-Not all manufacturers protect the SPI serial flash, mainly because it
-allows upgrading the BIOS image directly from an OS.
-
-The intel-spi driver makes it possible to read and write the SPI serial
-flash, if certain protection bits are not set and locked. If it finds
-any of them set, the whole MTD device is made read-only to prevent
-partial overwrites. By default the driver exposes SPI serial flash
-contents as read-only but it can be changed from kernel command line,
-passing "intel-spi.writeable=1".
-
-Please keep in mind that overwriting the BIOS image on SPI serial flash
-might render the machine unbootable and requires special equipment like
-Dediprog to revive. You have been warned!
-
-Below are the steps how to upgrade MinnowBoard MAX BIOS directly from
-Linux.
-
- 1) Download and extract the latest Minnowboard MAX BIOS SPI image
-    [1]. At the time writing this the latest image is v92.
-
- 2) Install mtd-utils package [2]. We need this in order to erase the SPI
-    serial flash. Distros like Debian and Fedora have this prepackaged with
-    name "mtd-utils".
-
- 3) Add "intel-spi.writeable=1" to the kernel command line and reboot
-    the board (you can also reload the driver passing "writeable=1" as
-    module parameter to modprobe).
-
- 4) Once the board is up and running again, find the right MTD partition
-    (it is named as "BIOS")::
-
-       # cat /proc/mtd
-       dev:    size   erasesize  name
-       mtd0: 00800000 00001000 "BIOS"
-
-    So here it will be /dev/mtd0 but it may vary.
-
- 5) Make backup of the existing image first::
-
-       # dd if=/dev/mtd0ro of=bios.bak
-       16384+0 records in
-       16384+0 records out
-       8388608 bytes (8.4 MB) copied, 10.0269 s, 837 kB/s
-
- 6) Verify the backup::
-
-       # sha1sum /dev/mtd0ro bios.bak
-       fdbb011920572ca6c991377c4b418a0502668b73  /dev/mtd0ro
-       fdbb011920572ca6c991377c4b418a0502668b73  bios.bak
-
-    The SHA1 sums must match. Otherwise do not continue any further!
-
- 7) Erase the SPI serial flash. After this step, do not reboot the
-    board! Otherwise it will not start anymore::
-
-       # flash_erase /dev/mtd0 0 0
-       Erasing 4 Kibyte @ 7ff000 -- 100 % complete
-
- 8) Once completed without errors you can write the new BIOS image::
-
-    # dd if=MNW2MAX1.X64.0092.R01.1605221712.bin of=/dev/mtd0
-
- 9) Verify that the new content of the SPI serial flash matches the new
-    BIOS image::
-
-       # sha1sum /dev/mtd0ro MNW2MAX1.X64.0092.R01.1605221712.bin
-       9b4df9e4be2057fceec3a5529ec3d950836c87a2  /dev/mtd0ro
-       9b4df9e4be2057fceec3a5529ec3d950836c87a2 MNW2MAX1.X64.0092.R01.1605221712.bin
-
-    The SHA1 sums should match.
-
- 10) Now you can reboot your board and observe the new BIOS starting up
-     properly.
-
-References
-----------
-
-[1] https://firmware.intel.com/sites/default/files/MinnowBoard%2EMAX_%2EX64%2E92%2ER01%2Ezip
-
-[2] http://www.linux-mtd.infradead.org/
diff --git a/Documentation/driver-api/mtd/spi-intel.rst b/Documentation/driver-api/mtd/spi-intel.rst
new file mode 100644 (file)
index 0000000..df854f2
--- /dev/null
@@ -0,0 +1,90 @@
+==============================
+Upgrading BIOS using spi-intel
+==============================
+
+Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
+controller which is used to hold BIOS and other platform specific data.
+Since contents of the SPI serial flash is crucial for machine to function,
+it is typically protected by different hardware protection mechanisms to
+avoid accidental (or on purpose) overwrite of the content.
+
+Not all manufacturers protect the SPI serial flash, mainly because it
+allows upgrading the BIOS image directly from an OS.
+
+The spi-intel driver makes it possible to read and write the SPI serial
+flash, if certain protection bits are not set and locked. If it finds
+any of them set, the whole MTD device is made read-only to prevent
+partial overwrites. By default the driver exposes SPI serial flash
+contents as read-only but it can be changed from kernel command line,
+passing "spi_intel.writeable=1".
+
+Please keep in mind that overwriting the BIOS image on SPI serial flash
+might render the machine unbootable and requires special equipment like
+Dediprog to revive. You have been warned!
+
+Below are the steps how to upgrade MinnowBoard MAX BIOS directly from
+Linux.
+
+ 1) Download and extract the latest Minnowboard MAX BIOS SPI image
+    [1]. At the time writing this the latest image is v92.
+
+ 2) Install mtd-utils package [2]. We need this in order to erase the SPI
+    serial flash. Distros like Debian and Fedora have this prepackaged with
+    name "mtd-utils".
+
+ 3) Add "spi_intel.writeable=1" to the kernel command line and reboot
+    the board (you can also reload the driver passing "writeable=1" as
+    module parameter to modprobe).
+
+ 4) Once the board is up and running again, find the right MTD partition
+    (it is named as "BIOS")::
+
+       # cat /proc/mtd
+       dev:    size   erasesize  name
+       mtd0: 00800000 00001000 "BIOS"
+
+    So here it will be /dev/mtd0 but it may vary.
+
+ 5) Make backup of the existing image first::
+
+       # dd if=/dev/mtd0ro of=bios.bak
+       16384+0 records in
+       16384+0 records out
+       8388608 bytes (8.4 MB) copied, 10.0269 s, 837 kB/s
+
+ 6) Verify the backup::
+
+       # sha1sum /dev/mtd0ro bios.bak
+       fdbb011920572ca6c991377c4b418a0502668b73  /dev/mtd0ro
+       fdbb011920572ca6c991377c4b418a0502668b73  bios.bak
+
+    The SHA1 sums must match. Otherwise do not continue any further!
+
+ 7) Erase the SPI serial flash. After this step, do not reboot the
+    board! Otherwise it will not start anymore::
+
+       # flash_erase /dev/mtd0 0 0
+       Erasing 4 Kibyte @ 7ff000 -- 100 % complete
+
+ 8) Once completed without errors you can write the new BIOS image::
+
+    # dd if=MNW2MAX1.X64.0092.R01.1605221712.bin of=/dev/mtd0
+
+ 9) Verify that the new content of the SPI serial flash matches the new
+    BIOS image::
+
+       # sha1sum /dev/mtd0ro MNW2MAX1.X64.0092.R01.1605221712.bin
+       9b4df9e4be2057fceec3a5529ec3d950836c87a2  /dev/mtd0ro
+       9b4df9e4be2057fceec3a5529ec3d950836c87a2 MNW2MAX1.X64.0092.R01.1605221712.bin
+
+    The SHA1 sums should match.
+
+ 10) Now you can reboot your board and observe the new BIOS starting up
+     properly.
+
+References
+----------
+
+[1] https://firmware.intel.com/sites/default/files/MinnowBoard%2EMAX_%2EX64%2E92%2ER01%2Ezip
+
+[2] http://www.linux-mtd.infradead.org/
index 6347580826beff4916f36937cf80ddd0040f3a5e..716f65d87d048d1bc38b5ac32e0634260976e2b2 100644 (file)
@@ -101,7 +101,6 @@ device. All fields are optional.
        u8 rx_threshold;
        u8 dma_burst_size;
        u32 timeout;
-       int gpio_cs;
   };
 
 The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are
@@ -146,7 +145,6 @@ field. Below is a sample configuration using the PXA255 NSSP.
        .rx_threshold = 8, /* SSP hardward FIFO threshold */
        .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
        .timeout = 235, /* See Intel documentation */
-       .gpio_cs = 2, /* Use external chip select */
   };
 
   static struct pxa2xx_spi_chip cs8405a_chip_info = {
@@ -154,7 +152,6 @@ field. Below is a sample configuration using the PXA255 NSSP.
        .rx_threshold = 8, /* SSP hardward FIFO threshold */
        .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
        .timeout = 235, /* See Intel documentation */
-       .gpio_cs = 3, /* Use external chip select */
   };
 
   static struct spi_board_info streetracer_spi_board_info[] __initdata = {
index b4688b0d04f2aca33a5aa521e30ba73cc02d0ae7..b986a7b9bfefe93debb050d693ae7afcd7eeb759 100644 (file)
@@ -11730,7 +11730,7 @@ MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
 M:     Javier Martinez Canillas <javier@dowhile0.org>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
-F:     Documentation/devicetree/bindings/*/*max77802.txt
+F:     Documentation/devicetree/bindings/*/*max77802.yaml
 F:     drivers/regulator/max77802-regulator.c
 F:     include/dt-bindings/*/*max77802.h
 
@@ -11745,6 +11745,7 @@ M:      Krzysztof Kozlowski <krzk@kernel.org>
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     linux-pm@vger.kernel.org
 S:     Supported
+F:     Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml
 F:     drivers/power/supply/max14577_charger.c
 F:     drivers/power/supply/max77693_charger.c
 
@@ -11754,10 +11755,12 @@ M:    Krzysztof Kozlowski <krzk@kernel.org>
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
+F:     Documentation/devicetree/bindings/*/maxim,max14577.yaml
 F:     Documentation/devicetree/bindings/*/maxim,max77686.yaml
+F:     Documentation/devicetree/bindings/*/maxim,max77843.yaml
 F:     Documentation/devicetree/bindings/clock/maxim,max77686.txt
-F:     Documentation/devicetree/bindings/mfd/max14577.txt
 F:     Documentation/devicetree/bindings/mfd/max77693.txt
+F:     drivers/*/*max77843.c
 F:     drivers/*/max14577*.c
 F:     drivers/*/max77686*.c
 F:     drivers/*/max77693*.c
@@ -17140,7 +17143,7 @@ M:      Andi Shyti <andi@etezian.org>
 L:     linux-spi@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/spi/spi-samsung.txt
+F:     Documentation/devicetree/bindings/spi/samsung,spi*.yaml
 F:     drivers/spi/spi-s3c*
 F:     include/linux/platform_data/spi-s3c64xx.h
 F:     include/linux/spi/s3c24xx-fiq.h
@@ -18560,6 +18563,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/rtc/sunplus,sp7021-rtc.yaml
 F:     drivers/rtc/rtc-sunplus.c
 
+SUNPLUS SPI CONTROLLER INTERFACE DRIVER
+M:     Li-hao Kuo <lhjeff911@gmail.com>
+L:     linux-spi@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/spi/spi-sunplus-sp7021.yaml
+F:     drivers/spi/spi-sunplus-sp7021.c
+
 SUPERH
 M:     Yoshinori Sato <ysato@users.sourceforge.jp>
 M:     Rich Felker <dalias@libc.org>
index 593c7f793da53f299b3e6c410eec628bb29c37d1..44659fbc37bab8e8f7f31622fb2b5cf4cda9ef74 100644 (file)
@@ -530,6 +530,16 @@ static struct pxa2xx_spi_controller corgi_spi_info = {
        .num_chipselect = 3,
 };
 
+static struct gpiod_lookup_table corgi_spi_gpio_table = {
+       .dev_id = "pxa2xx-spi.1",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void corgi_wait_for_hsync(void)
 {
        while (gpio_get_value(CORGI_GPIO_HSYNC))
@@ -548,10 +558,6 @@ static struct ads7846_platform_data corgi_ads7846_info = {
        .wait_for_sync          = corgi_wait_for_hsync,
 };
 
-static struct pxa2xx_spi_chip corgi_ads7846_chip = {
-       .gpio_cs        = CORGI_GPIO_ADS7846_CS,
-};
-
 static void corgi_bl_kick_battery(void)
 {
        void (*kick_batt)(void);
@@ -580,14 +586,6 @@ static struct corgi_lcd_platform_data corgi_lcdcon_info = {
        .kick_battery           = corgi_bl_kick_battery,
 };
 
-static struct pxa2xx_spi_chip corgi_lcdcon_chip = {
-       .gpio_cs        = CORGI_GPIO_LCDCON_CS,
-};
-
-static struct pxa2xx_spi_chip corgi_max1111_chip = {
-       .gpio_cs        = CORGI_GPIO_MAX1111_CS,
-};
-
 static struct spi_board_info corgi_spi_devices[] = {
        {
                .modalias       = "ads7846",
@@ -595,7 +593,6 @@ static struct spi_board_info corgi_spi_devices[] = {
                .bus_num        = 1,
                .chip_select    = 0,
                .platform_data  = &corgi_ads7846_info,
-               .controller_data= &corgi_ads7846_chip,
                .irq            = PXA_GPIO_TO_IRQ(CORGI_GPIO_TP_INT),
        }, {
                .modalias       = "corgi-lcd",
@@ -603,18 +600,17 @@ static struct spi_board_info corgi_spi_devices[] = {
                .bus_num        = 1,
                .chip_select    = 1,
                .platform_data  = &corgi_lcdcon_info,
-               .controller_data= &corgi_lcdcon_chip,
        }, {
                .modalias       = "max1111",
                .max_speed_hz   = 450000,
                .bus_num        = 1,
                .chip_select    = 2,
-               .controller_data= &corgi_max1111_chip,
        },
 };
 
 static void __init corgi_init_spi(void)
 {
+       gpiod_add_lookup_table(&corgi_spi_gpio_table);
        pxa2xx_set_spi_info(1, &corgi_spi_info);
        gpiod_add_lookup_table(&corgi_lcdcon_gpio_table);
        spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices));
index 1d4c5db54be29ff9831ff72dde1908b566f30f70..e1870fbb19e7e933641a2c53c4ec46fd2bad5318 100644 (file)
@@ -616,7 +616,6 @@ static struct pxa2xx_spi_chip tsc2046_chip = {
        .tx_threshold = 1,
        .rx_threshold = 2,
        .timeout      = 64,
-       .gpio_cs      = GPIO88_HX4700_TSC2046_CS,
 };
 
 static struct spi_board_info tsc2046_board_info[] __initdata = {
@@ -635,6 +634,14 @@ static struct pxa2xx_spi_controller pxa_ssp2_master_info = {
        .enable_dma     = 1,
 };
 
+static struct gpiod_lookup_table pxa_ssp2_gpio_table = {
+       .dev_id = "pxa2xx-spi.2",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", GPIO88_HX4700_TSC2046_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 /*
  * External power
  */
@@ -896,6 +903,7 @@ static void __init hx4700_init(void)
        pxa_set_i2c_info(NULL);
        i2c_register_board_info(0, ARRAY_AND_SIZE(i2c_board_info));
        i2c_register_board_info(1, ARRAY_AND_SIZE(pi2c_board_info));
+       gpiod_add_lookup_table(&pxa_ssp2_gpio_table);
        pxa2xx_set_spi_info(2, &pxa_ssp2_master_info);
        spi_register_board_info(ARRAY_AND_SIZE(tsc2046_board_info));
 
index 04a12523cdee0418e764027cb0cbc732fd594c20..753fe166ab681aa1fdc917f0804c65a6489ddc7a 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -42,7 +42,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info1 = {
        .rx_threshold   = 128,
        .dma_burst_size = 8,
        .timeout        = 235,
-       .gpio_cs        = ICONTROL_MCP251x_nCS1
 };
 
 static struct pxa2xx_spi_chip mcp251x_chip_info2 = {
@@ -50,7 +49,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info2 = {
        .rx_threshold   = 128,
        .dma_burst_size = 8,
        .timeout        = 235,
-       .gpio_cs        = ICONTROL_MCP251x_nCS2
 };
 
 static struct pxa2xx_spi_chip mcp251x_chip_info3 = {
@@ -58,7 +56,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info3 = {
        .rx_threshold   = 128,
        .dma_burst_size = 8,
        .timeout        = 235,
-       .gpio_cs        = ICONTROL_MCP251x_nCS3
 };
 
 static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
@@ -66,7 +63,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
        .rx_threshold   = 128,
        .dma_burst_size = 8,
        .timeout        = 235,
-       .gpio_cs        = ICONTROL_MCP251x_nCS4
 };
 
 static const struct property_entry mcp251x_properties[] = {
@@ -143,6 +139,24 @@ struct platform_device pxa_spi_ssp4 = {
        }
 };
 
+static struct gpiod_lookup_table pxa_ssp3_gpio_table = {
+       .dev_id = "pxa2xx-spi.3",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS1, "cs", 0, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS2, "cs", 1, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
+static struct gpiod_lookup_table pxa_ssp4_gpio_table = {
+       .dev_id = "pxa2xx-spi.4",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS3, "cs", 0, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", ICONTROL_MCP251x_nCS4, "cs", 1, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static struct platform_device *icontrol_spi_devices[] __initdata = {
        &pxa_spi_ssp3,
        &pxa_spi_ssp4,
@@ -175,6 +189,8 @@ static mfp_cfg_t mfp_can_cfg[] __initdata = {
 static void __init icontrol_can_init(void)
 {
        pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_can_cfg));
+       gpiod_add_lookup_table(&pxa_ssp3_gpio_table);
+       gpiod_add_lookup_table(&pxa_ssp4_gpio_table);
        platform_add_devices(ARRAY_AND_SIZE(icontrol_spi_devices));
        spi_register_board_info(ARRAY_AND_SIZE(mcp251x_board_info));
 }
index 793f61375ee8c6b1b6363bd9e200b21502e01164..73f5953b3bb6b07d59d146853c4b452ea122f957 100644 (file)
@@ -195,7 +195,6 @@ static struct pxa2xx_spi_controller littleton_spi_info = {
 static struct pxa2xx_spi_chip littleton_tdo24m_chip = {
        .rx_threshold   = 1,
        .tx_threshold   = 1,
-       .gpio_cs        = LITTLETON_GPIO_LCD_CS,
 };
 
 static struct spi_board_info littleton_spi_devices[] __initdata = {
@@ -208,8 +207,17 @@ static struct spi_board_info littleton_spi_devices[] __initdata = {
        },
 };
 
+static struct gpiod_lookup_table littleton_spi_gpio_table = {
+       .dev_id = "pxa2xx-spi.2",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", LITTLETON_GPIO_LCD_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void __init littleton_init_spi(void)
 {
+       gpiod_add_lookup_table(&littleton_spi_gpio_table);
        pxa2xx_set_spi_info(2, &littleton_spi_info);
        spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices));
 }
index cd9fa465b9b2a6c62e007c23746fa72f9654b37b..200fd35168e050fdbe7db9e73846a2b3941de454 100644 (file)
@@ -938,8 +938,6 @@ struct pxa2xx_spi_chip tsc2046_chip_info = {
        .tx_threshold   = 1,
        .rx_threshold   = 2,
        .timeout        = 64,
-       /* NOTICE must be GPIO, incompatibility with hw PXA SPI framing */
-       .gpio_cs        = GPIO14_MAGICIAN_TSC2046_CS,
 };
 
 static struct pxa2xx_spi_controller magician_spi_info = {
@@ -947,6 +945,15 @@ static struct pxa2xx_spi_controller magician_spi_info = {
        .enable_dma     = 1,
 };
 
+static struct gpiod_lookup_table magician_spi_gpio_table = {
+       .dev_id = "pxa2xx-spi.2",
+       .table = {
+               /* NOTICE must be GPIO, incompatibility with hw PXA SPI framing */
+               GPIO_LOOKUP_IDX("gpio-pxa", GPIO14_MAGICIAN_TSC2046_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static struct spi_board_info ads7846_spi_board_info[] __initdata = {
        {
                .modalias               = "ads7846",
@@ -1031,6 +1038,7 @@ static void __init magician_init(void)
        } else
                pr_err("LCD detection: CPLD mapping failed\n");
 
+       gpiod_add_lookup_table(&magician_spi_gpio_table);
        pxa2xx_set_spi_info(2, &magician_spi_info);
        spi_register_board_info(ARRAY_AND_SIZE(ads7846_spi_board_info));
 
index 3a4ecc3c8f8b62b38d4fb6de7e991d79b3baad44..58cfa434afdebc0031bb1e2c449bc8d32514e28f 100644 (file)
@@ -197,6 +197,14 @@ static struct pxa2xx_spi_controller poodle_spi_info = {
        .num_chipselect = 1,
 };
 
+static struct gpiod_lookup_table poodle_spi_gpio_table = {
+       .dev_id = "pxa2xx-spi.1",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", POODLE_GPIO_TP_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static struct ads7846_platform_data poodle_ads7846_info = {
        .model                  = 7846,
        .vref_delay_usecs       = 100,
@@ -205,23 +213,19 @@ static struct ads7846_platform_data poodle_ads7846_info = {
        .gpio_pendown           = POODLE_GPIO_TP_INT,
 };
 
-static struct pxa2xx_spi_chip poodle_ads7846_chip = {
-       .gpio_cs                = POODLE_GPIO_TP_CS,
-};
-
 static struct spi_board_info poodle_spi_devices[] = {
        {
                .modalias       = "ads7846",
                .max_speed_hz   = 10000,
                .bus_num        = 1,
                .platform_data  = &poodle_ads7846_info,
-               .controller_data= &poodle_ads7846_chip,
                .irq            = PXA_GPIO_TO_IRQ(POODLE_GPIO_TP_INT),
        },
 };
 
 static void __init poodle_init_spi(void)
 {
+       gpiod_add_lookup_table(&poodle_spi_gpio_table);
        pxa2xx_set_spi_info(1, &poodle_spi_info);
        spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices));
 }
index 371008e9bb02923eda32236ce8f0577689ca764a..a648e7094e84e5ab44a41d7a078f90e584f1206c 100644 (file)
@@ -510,10 +510,6 @@ static struct ads7846_platform_data spitz_ads7846_info = {
        .wait_for_sync          = spitz_ads7846_wait_for_hsync,
 };
 
-static struct pxa2xx_spi_chip spitz_ads7846_chip = {
-       .gpio_cs                = SPITZ_GPIO_ADS7846_CS,
-};
-
 static void spitz_bl_kick_battery(void)
 {
        void (*kick_batt)(void);
@@ -555,14 +551,6 @@ static struct corgi_lcd_platform_data spitz_lcdcon_info = {
        .kick_battery           = spitz_bl_kick_battery,
 };
 
-static struct pxa2xx_spi_chip spitz_lcdcon_chip = {
-       .gpio_cs        = SPITZ_GPIO_LCDCON_CS,
-};
-
-static struct pxa2xx_spi_chip spitz_max1111_chip = {
-       .gpio_cs        = SPITZ_GPIO_MAX1111_CS,
-};
-
 static struct spi_board_info spitz_spi_devices[] = {
        {
                .modalias               = "ads7846",
@@ -570,7 +558,6 @@ static struct spi_board_info spitz_spi_devices[] = {
                .bus_num                = 2,
                .chip_select            = 0,
                .platform_data          = &spitz_ads7846_info,
-               .controller_data        = &spitz_ads7846_chip,
                .irq                    = PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT),
        }, {
                .modalias               = "corgi-lcd",
@@ -578,13 +565,11 @@ static struct spi_board_info spitz_spi_devices[] = {
                .bus_num                = 2,
                .chip_select            = 1,
                .platform_data          = &spitz_lcdcon_info,
-               .controller_data        = &spitz_lcdcon_chip,
        }, {
                .modalias               = "max1111",
                .max_speed_hz           = 450000,
                .bus_num                = 2,
                .chip_select            = 2,
-               .controller_data        = &spitz_max1111_chip,
        },
 };
 
@@ -592,6 +577,16 @@ static struct pxa2xx_spi_controller spitz_spi_info = {
        .num_chipselect = 3,
 };
 
+static struct gpiod_lookup_table spitz_spi_gpio_table = {
+       .dev_id = "pxa2xx-spi.2",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("gpio-pxa", SPITZ_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void __init spitz_spi_init(void)
 {
        if (machine_is_akita())
@@ -599,6 +594,7 @@ static void __init spitz_spi_init(void)
        else
                gpiod_add_lookup_table(&spitz_lcdcon_gpio_table);
 
+       gpiod_add_lookup_table(&spitz_spi_gpio_table);
        pxa2xx_set_spi_info(2, &spitz_spi_info);
        spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
 }
index 8ca02ec1d44ce065eda21a8743f7c4131a4a13e0..b43e2f4536a5aa15390f9876e029bffb543b8075 100644 (file)
@@ -346,6 +346,22 @@ static struct pxa2xx_spi_controller pxa_ssp_master_2_info = {
        .num_chipselect = 1,
 };
 
+static struct gpiod_lookup_table pxa_ssp1_gpio_table = {
+       .dev_id = "pxa2xx-spi.1",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", 24, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
+static struct gpiod_lookup_table pxa_ssp3_gpio_table = {
+       .dev_id = "pxa2xx-spi.3",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", 39, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 /* An upcoming kernel change will scrap SFRM usage so these
  * drivers have been moved to use GPIOs */
 static struct pxa2xx_spi_chip staccel_chip_info = {
@@ -353,7 +369,6 @@ static struct pxa2xx_spi_chip staccel_chip_info = {
        .rx_threshold = 8,
        .dma_burst_size = 8,
        .timeout = 235,
-       .gpio_cs = 24,
 };
 
 static struct pxa2xx_spi_chip cc2420_info = {
@@ -361,7 +376,6 @@ static struct pxa2xx_spi_chip cc2420_info = {
        .rx_threshold = 8,
        .dma_burst_size = 8,
        .timeout = 235,
-       .gpio_cs = 39,
 };
 
 static struct spi_board_info spi_board_info[] __initdata = {
@@ -410,6 +424,8 @@ static void __init imote2_stargate2_init(void)
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
+       gpiod_add_lookup_table(&pxa_ssp1_gpio_table);
+       gpiod_add_lookup_table(&pxa_ssp3_gpio_table);
        pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info);
        pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info);
        pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info);
index 8e74fbb0a96e282294f4332e69a612e92c35a25a..7eaeda2699270184127060189f6da0ddd5b0ea66 100644 (file)
@@ -570,7 +570,6 @@ static struct pxa2xx_spi_chip z2_lbs_chip_info = {
        .rx_threshold   = 8,
        .tx_threshold   = 8,
        .timeout        = 1000,
-       .gpio_cs        = GPIO24_ZIPITZ2_WIFI_CS,
 };
 
 static struct libertas_spi_platform_data z2_lbs_pdata = {
@@ -584,7 +583,6 @@ static struct pxa2xx_spi_chip lms283_chip_info = {
        .rx_threshold   = 1,
        .tx_threshold   = 1,
        .timeout        = 64,
-       .gpio_cs        = GPIO88_ZIPITZ2_LCD_CS,
 };
 
 static struct gpiod_lookup_table lms283_gpio_table = {
@@ -624,8 +622,26 @@ static struct pxa2xx_spi_controller pxa_ssp2_master_info = {
        .num_chipselect = 1,
 };
 
+static struct gpiod_lookup_table pxa_ssp1_gpio_table = {
+       .dev_id = "pxa2xx-spi.1",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", GPIO24_ZIPITZ2_WIFI_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
+static struct gpiod_lookup_table pxa_ssp2_gpio_table = {
+       .dev_id = "pxa2xx-spi.2",
+       .table = {
+               GPIO_LOOKUP_IDX("gpio-pxa", GPIO88_ZIPITZ2_LCD_CS, "cs", 0, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void __init z2_spi_init(void)
 {
+       gpiod_add_lookup_table(&pxa_ssp1_gpio_table);
+       gpiod_add_lookup_table(&pxa_ssp2_gpio_table);
        pxa2xx_set_spi_info(1, &pxa_ssp1_master_info);
        pxa2xx_set_spi_info(2, &pxa_ssp2_master_info);
        gpiod_add_lookup_table(&lms283_gpio_table);
index 25606e668cf9370e305230bd948664e1b9010e51..1899fc3f44fd74762c16431e73972ff4a434ac2a 100644 (file)
@@ -191,18 +191,6 @@ config S3C64XX_DEV_SPI0
          Compile in platform device definitions for S3C64XX's type
          SPI controller 0
 
-config S3C64XX_DEV_SPI1
-       bool
-       help
-         Compile in platform device definitions for S3C64XX's type
-         SPI controller 1
-
-config S3C64XX_DEV_SPI2
-       bool
-       help
-         Compile in platform device definitions for S3C64XX's type
-         SPI controller 2
-
 config SAMSUNG_DEV_TS
        bool
        help
index 06dec64848f9a97dd4512c1bda859cc9d79dd27e..1e266fc24f9b750b995ac0b7a5bc8ca77df8f5a3 100644 (file)
@@ -1107,8 +1107,7 @@ struct platform_device s3c64xx_device_spi0 = {
        },
 };
 
-void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs)
+void __init s3c64xx_spi0_set_platdata(int src_clk_nr, int num_cs)
 {
        struct s3c64xx_spi_info pd;
 
@@ -1120,80 +1119,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
 
        pd.num_cs = num_cs;
        pd.src_clk_nr = src_clk_nr;
-       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
+       pd.cfg_gpio = s3c64xx_spi0_cfg_gpio;
 
        s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI0 */
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-static struct resource s3c64xx_spi1_resource[] = {
-       [0] = DEFINE_RES_MEM(S3C_PA_SPI1, SZ_256),
-       [1] = DEFINE_RES_IRQ(IRQ_SPI1),
-};
-
-struct platform_device s3c64xx_device_spi1 = {
-       .name           = "s3c6410-spi",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s3c64xx_spi1_resource),
-       .resource       = s3c64xx_spi1_resource,
-       .dev = {
-               .dma_mask               = &samsung_device_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
-
-void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs)
-{
-       struct s3c64xx_spi_info pd;
-
-       /* Reject invalid configuration */
-       if (!num_cs || src_clk_nr < 0) {
-               pr_err("%s: Invalid SPI configuration\n", __func__);
-               return;
-       }
-
-       pd.num_cs = num_cs;
-       pd.src_clk_nr = src_clk_nr;
-       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
-
-       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
-}
-#endif /* CONFIG_S3C64XX_DEV_SPI1 */
-
-#ifdef CONFIG_S3C64XX_DEV_SPI2
-static struct resource s3c64xx_spi2_resource[] = {
-       [0] = DEFINE_RES_MEM(S3C_PA_SPI2, SZ_256),
-       [1] = DEFINE_RES_IRQ(IRQ_SPI2),
-};
-
-struct platform_device s3c64xx_device_spi2 = {
-       .name           = "s3c6410-spi",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(s3c64xx_spi2_resource),
-       .resource       = s3c64xx_spi2_resource,
-       .dev = {
-               .dma_mask               = &samsung_device_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
-
-void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs)
-{
-       struct s3c64xx_spi_info pd;
-
-       /* Reject invalid configuration */
-       if (!num_cs || src_clk_nr < 0) {
-               pr_err("%s: Invalid SPI configuration\n", __func__);
-               return;
-       }
-
-       pd.num_cs = num_cs;
-       pd.src_clk_nr = src_clk_nr;
-       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
-
-       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
-}
-#endif /* CONFIG_S3C64XX_DEV_SPI2 */
index 407ad493493e3de8bc6f1ea7342fb8e4e67993ff..5d1d4b67a4b776bbb602cad8f750bab14a95d85f 100644 (file)
 
 #include "crag6410.h"
 
-static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
-       .line = S3C64XX_GPC(3),
-};
-
 static struct wm0010_pdata wm0010_pdata = {
        .gpio_reset = S3C64XX_GPN(6),
        .reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */
@@ -49,7 +45,6 @@ static struct spi_board_info wm1253_devs[] = {
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
                .irq            = S3C_EINT(4),
-               .controller_data = &wm0010_spi_csinfo,
                .platform_data = &wm0010_pdata,
        },
 };
@@ -62,7 +57,6 @@ static struct spi_board_info balblair_devs[] = {
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
                .irq            = S3C_EINT(4),
-               .controller_data = &wm0010_spi_csinfo,
                .platform_data = &wm0010_pdata,
        },
 };
@@ -229,10 +223,6 @@ static struct arizona_pdata wm5102_reva_pdata = {
        },
 };
 
-static struct s3c64xx_spi_csinfo codec_spi_csinfo = {
-       .line = S3C64XX_GPN(5),
-};
-
 static struct spi_board_info wm5102_reva_spi_devs[] = {
        [0] = {
                .modalias       = "wm5102",
@@ -242,7 +232,6 @@ static struct spi_board_info wm5102_reva_spi_devs[] = {
                .mode           = SPI_MODE_0,
                .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
                                  WM831X_IRQ_GPIO_2,
-               .controller_data = &codec_spi_csinfo,
                .platform_data = &wm5102_reva_pdata,
        },
 };
@@ -275,7 +264,6 @@ static struct spi_board_info wm5102_spi_devs[] = {
                .mode           = SPI_MODE_0,
                .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
                                  WM831X_IRQ_GPIO_2,
-               .controller_data = &codec_spi_csinfo,
                .platform_data = &wm5102_pdata,
        },
 };
@@ -298,7 +286,6 @@ static struct spi_board_info wm5110_spi_devs[] = {
                .mode           = SPI_MODE_0,
                .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
                                  WM831X_IRQ_GPIO_2,
-               .controller_data = &codec_spi_csinfo,
                .platform_data = &wm5102_reva_pdata,
        },
 };
index 4a12c75d407fc941f47e74b24d58538a1192b172..e3e0fe897bccb0702a5c22e4cbed061258b7860f 100644 (file)
@@ -825,6 +825,15 @@ static const struct gpio_led_platform_data gpio_leds_pdata = {
 
 static struct dwc2_hsotg_plat crag6410_hsotg_pdata;
 
+static struct gpiod_lookup_table crag_spi0_gpiod_table = {
+       .dev_id = "s3c6410-spi.0",
+       .table = {
+               GPIO_LOOKUP_IDX("GPIOC", 3, "cs", 0, GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP_IDX("GPION", 5, "cs", 1, GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void __init crag6410_machine_init(void)
 {
        /* Open drain IRQs need pullups */
@@ -856,7 +865,9 @@ static void __init crag6410_machine_init(void)
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
        samsung_keypad_set_platdata(&crag6410_keypad_data);
-       s3c64xx_spi0_set_platdata(NULL, 0, 2);
+
+       gpiod_add_lookup_table(&crag_spi0_gpiod_table);
+       s3c64xx_spi0_set_platdata(0, 2);
 
        pwm_add_table(crag6410_pwm_lookup, ARRAY_SIZE(crag6410_pwm_lookup));
        platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
index efcf78d41585389d82ed1d83a1966e21b5b047e5..497aff71c29ccb9dddc1ca9bcbcb3b020e6688a8 100644 (file)
@@ -16,12 +16,3 @@ int s3c64xx_spi0_cfg_gpio(void)
        return 0;
 }
 #endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
-       s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3,
-                               S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-       return 0;
-}
-#endif
index 057667469cc3d1b5a278983a174a4f408b217c88..919c5fd0c9afa7d162e8ceabf16c522a55c1830f 100644 (file)
@@ -16,12 +16,6 @@ static inline void s3c24xx_spi_setname(char *name)
 #ifdef CONFIG_S3C64XX_DEV_SPI0
        s3c64xx_device_spi0.name = name;
 #endif
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-       s3c64xx_device_spi1.name = name;
-#endif
-#ifdef CONFIG_S3C64XX_DEV_SPI2
-       s3c64xx_device_spi2.name = name;
-#endif
 }
 
 #endif /* __PLAT_S3C_SPI_CORE_S3C24XX_H */
index fd87a59837fa2f4cb1f659301d2a71c6a2007e92..5eb0fe73ddc45b2c092877cb002c605dbbf6e043 100644 (file)
@@ -815,7 +815,7 @@ static int moxtet_probe(struct spi_device *spi)
        return 0;
 }
 
-static int moxtet_remove(struct spi_device *spi)
+static void moxtet_remove(struct spi_device *spi)
 {
        struct moxtet *moxtet = spi_get_drvdata(spi);
 
@@ -828,8 +828,6 @@ static int moxtet_remove(struct spi_device *spi)
        device_for_each_child(moxtet->dev, NULL, __unregister);
 
        mutex_destroy(&moxtet->lock);
-
-       return 0;
 }
 
 static const struct of_device_id moxtet_dt_ids[] = {
index 7c617edff4ca2968ef24fc2ae457233fa433e511..3170d59d660c089182874f6e7bf0df8fbaa03260 100644 (file)
@@ -267,11 +267,8 @@ static int st33zp24_i2c_probe(struct i2c_client *client,
 static int st33zp24_i2c_remove(struct i2c_client *client)
 {
        struct tpm_chip *chip = i2c_get_clientdata(client);
-       int ret;
 
-       ret = st33zp24_remove(chip);
-       if (ret)
-               return ret;
+       st33zp24_remove(chip);
 
        return 0;
 }
index a75dafd3944517dda0eacf52175062dbd5bf9ea4..22d184884694a15a0652a4dbea5fc6b7c0570ce9 100644 (file)
@@ -381,16 +381,11 @@ static int st33zp24_spi_probe(struct spi_device *dev)
  * @param: client, the spi_device description (TPM SPI description).
  * @return: 0 in case of success.
  */
-static int st33zp24_spi_remove(struct spi_device *dev)
+static void st33zp24_spi_remove(struct spi_device *dev)
 {
        struct tpm_chip *chip = spi_get_drvdata(dev);
-       int ret;
 
-       ret = st33zp24_remove(chip);
-       if (ret)
-               return ret;
-
-       return 0;
+       st33zp24_remove(chip);
 }
 
 static const struct spi_device_id st33zp24_spi_id[] = {
index ce9efb73c144be2b9cdb4daa77c180d150534811..15b393e92c8eca97960dd3ffab575739ac06731b 100644 (file)
@@ -511,10 +511,9 @@ _tpm_clean_answer:
 }
 EXPORT_SYMBOL(st33zp24_probe);
 
-int st33zp24_remove(struct tpm_chip *chip)
+void st33zp24_remove(struct tpm_chip *chip)
 {
        tpm_chip_unregister(chip);
-       return 0;
 }
 EXPORT_SYMBOL(st33zp24_remove);
 
index 6747be1e250217f48c423e49a96df9f845bd34ac..b387a476c555f3dab199b2372675eede8144cc37 100644 (file)
@@ -34,5 +34,5 @@ int st33zp24_pm_resume(struct device *dev);
 
 int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
                   struct device *dev, int irq, int io_lpcpd);
-int st33zp24_remove(struct tpm_chip *chip);
+void st33zp24_remove(struct tpm_chip *chip);
 #endif /* __LOCAL_ST33ZP24_H__ */
index aaa59a00eeaefb05d1ab99e762664d6fad4bcbfd..184396b3af501c36355ae8707740e7b9be8a0b60 100644 (file)
@@ -254,13 +254,12 @@ static int tpm_tis_spi_driver_probe(struct spi_device *spi)
 
 static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume);
 
-static int tpm_tis_spi_remove(struct spi_device *dev)
+static void tpm_tis_spi_remove(struct spi_device *dev)
 {
        struct tpm_chip *chip = spi_get_drvdata(dev);
 
        tpm_chip_unregister(chip);
        tpm_tis_remove(chip);
-       return 0;
 }
 
 static const struct spi_device_id tpm_tis_spi_id[] = {
index 8f02c0b88000567b8895dd14a2113e3f33e2b224..f416f8bc28987355de7fbcbea454071d1ac0cbdf 100644 (file)
@@ -1544,14 +1544,12 @@ err_disable_oscin:
        return ret;
 }
 
-static int lmk04832_remove(struct spi_device *spi)
+static void lmk04832_remove(struct spi_device *spi)
 {
        struct lmk04832 *lmk = spi_get_drvdata(spi);
 
        clk_disable_unprepare(lmk->oscin);
        of_clk_del_provider(spi->dev.of_node);
-
-       return 0;
 }
 static const struct spi_device_id lmk04832_id[] = {
        { "lmk04832", LMK04832 },
index 4a55cdf089d62a33a793b4eb402ff08a19df720f..e00c333105170f5a2a702593feab340ddc4a7d8e 100644 (file)
@@ -163,15 +163,13 @@ exit_destroy:
        return ret;
 }
 
-static int gen_74x164_remove(struct spi_device *spi)
+static void gen_74x164_remove(struct spi_device *spi)
 {
        struct gen_74x164_chip *chip = spi_get_drvdata(spi);
 
        gpiod_set_value_cansleep(chip->gpiod_oe, 0);
        gpiochip_remove(&chip->gpio_chip);
        mutex_destroy(&chip->lock);
-
-       return 0;
 }
 
 static const struct spi_device_id gen_74x164_spi_ids[] = {
index 51cd6f98d1c746dabb191e89dec142cb6a2377e0..161c4751c5f7a01ec2997764e7c95f51d1fd6ef9 100644 (file)
@@ -443,14 +443,12 @@ static int max3191x_probe(struct spi_device *spi)
        return 0;
 }
 
-static int max3191x_remove(struct spi_device *spi)
+static void max3191x_remove(struct spi_device *spi)
 {
        struct max3191x_chip *max3191x = spi_get_drvdata(spi);
 
        gpiochip_remove(&max3191x->gpio);
        mutex_destroy(&max3191x->lock);
-
-       return 0;
 }
 
 static int __init max3191x_register_driver(struct spi_driver *sdrv)
index 5862d73bf32541c0f551232fdfff06c3eaf63d02..11813f41d4609cabbf95d7df3b7aa3f6bbcaf657 100644 (file)
@@ -64,11 +64,9 @@ static int max7301_probe(struct spi_device *spi)
        return ret;
 }
 
-static int max7301_remove(struct spi_device *spi)
+static void max7301_remove(struct spi_device *spi)
 {
        __max730x_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id max7301_id[] = {
index 31d2be1bebc84e40efdda24ad8cc3d52e868f861..cd9b16dbe1a97072e3e4a7a094965be587127b15 100644 (file)
@@ -134,7 +134,7 @@ exit_destroy:
        return ret;
 }
 
-static int mc33880_remove(struct spi_device *spi)
+static void mc33880_remove(struct spi_device *spi)
 {
        struct mc33880 *mc;
 
@@ -142,8 +142,6 @@ static int mc33880_remove(struct spi_device *spi)
 
        gpiochip_remove(&mc->chip);
        mutex_destroy(&mc->lock);
-
-       return 0;
 }
 
 static struct spi_driver mc33880_driver = {
index 8e04054cf07e3d63f6751d9c8030397408442427..81a47ae09ff8c98fc07123e494661da793ca6bad 100644 (file)
@@ -163,15 +163,13 @@ static int pisosr_gpio_probe(struct spi_device *spi)
        return 0;
 }
 
-static int pisosr_gpio_remove(struct spi_device *spi)
+static void pisosr_gpio_remove(struct spi_device *spi)
 {
        struct pisosr_gpio *gpio = spi_get_drvdata(spi);
 
        gpiochip_remove(&gpio->chip);
 
        mutex_destroy(&gpio->lock);
-
-       return 0;
 }
 
 static const struct spi_device_id pisosr_gpio_id_table[] = {
index f043b484055b2da39632c7b02d172289c845f1a0..ed626fdc08e883b3ff78817a7cf010669050f24c 100644 (file)
@@ -293,15 +293,13 @@ static int y030xx067a_probe(struct spi_device *spi)
        return 0;
 }
 
-static int y030xx067a_remove(struct spi_device *spi)
+static void y030xx067a_remove(struct spi_device *spi)
 {
        struct y030xx067a *priv = spi_get_drvdata(spi);
 
        drm_panel_remove(&priv->panel);
        drm_panel_disable(&priv->panel);
        drm_panel_unprepare(&priv->panel);
-
-       return 0;
 }
 
 static const struct drm_display_mode y030xx067a_modes[] = {
index 8e84df9a0033d3a517131e79f01cee82a07f1166..3dfafa585127ff909a9b389b8da114e9474379db 100644 (file)
@@ -896,14 +896,12 @@ static int ili9322_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili9322_remove(struct spi_device *spi)
+static void ili9322_remove(struct spi_device *spi)
 {
        struct ili9322 *ili = spi_get_drvdata(spi);
 
        ili9322_power_off(ili);
        drm_panel_remove(&ili->panel);
-
-       return 0;
 }
 
 /*
index 2c3378a259b1e12baf6f246fc4e1841416ee40b6..a07ef26234e57ccf71b5bc000b15772cc1601d15 100644 (file)
@@ -728,7 +728,7 @@ static int ili9341_probe(struct spi_device *spi)
        return -1;
 }
 
-static int ili9341_remove(struct spi_device *spi)
+static void ili9341_remove(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
        struct ili9341 *ili = spi_get_drvdata(spi);
@@ -741,7 +741,6 @@ static int ili9341_remove(struct spi_device *spi)
                drm_dev_unplug(drm);
                drm_atomic_helper_shutdown(drm);
        }
-       return 0;
 }
 
 static void ili9341_shutdown(struct spi_device *spi)
index c558de3f99be72d035d0232181a6aff72cfc287f..e3b1daa0cb7201c7ce2f45b3c89b493c574853a2 100644 (file)
@@ -219,15 +219,13 @@ static int ej030na_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ej030na_remove(struct spi_device *spi)
+static void ej030na_remove(struct spi_device *spi)
 {
        struct ej030na *priv = spi_get_drvdata(spi);
 
        drm_panel_remove(&priv->panel);
        drm_panel_disable(&priv->panel);
        drm_panel_unprepare(&priv->panel);
-
-       return 0;
 }
 
 static const struct drm_display_mode ej030na_modes[] = {
index f3183b68704f6e0911499c257e00c71c7e06adb2..9d0d4faa3f58aa4950e48d082352e0013880ee30 100644 (file)
@@ -203,14 +203,12 @@ static int lb035q02_probe(struct spi_device *spi)
        return 0;
 }
 
-static int lb035q02_remove(struct spi_device *spi)
+static void lb035q02_remove(struct spi_device *spi)
 {
        struct lb035q02_device *lcd = spi_get_drvdata(spi);
 
        drm_panel_remove(&lcd->panel);
        drm_panel_disable(&lcd->panel);
-
-       return 0;
 }
 
 static const struct of_device_id lb035q02_of_match[] = {
index 8e5160af1de5dd177b19c1083969ec8e969257f9..cf246d15b7b628a0b3821bfb2697842b6e484319 100644 (file)
@@ -266,14 +266,12 @@ static int lg4573_probe(struct spi_device *spi)
        return 0;
 }
 
-static int lg4573_remove(struct spi_device *spi)
+static void lg4573_remove(struct spi_device *spi)
 {
        struct lg4573 *ctx = spi_get_drvdata(spi);
 
        lg4573_display_off(ctx);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id lg4573_of_match[] = {
index 6e5ab1debc8b43534d77be6251d70cea8d576a53..81c5c541a351cca1535e40ed722d5cb4c33d6708 100644 (file)
@@ -212,15 +212,13 @@ static int nl8048_probe(struct spi_device *spi)
        return 0;
 }
 
-static int nl8048_remove(struct spi_device *spi)
+static void nl8048_remove(struct spi_device *spi)
 {
        struct nl8048_panel *lcd = spi_get_drvdata(spi);
 
        drm_panel_remove(&lcd->panel);
        drm_panel_disable(&lcd->panel);
        drm_panel_unprepare(&lcd->panel);
-
-       return 0;
 }
 
 static const struct of_device_id nl8048_of_match[] = {
index d036853db865ff58ee7b118dc151298c8f2b0aa1..f58cfb10b58a2ad48d670ed53828d0a17a965051 100644 (file)
@@ -292,7 +292,7 @@ static int nt39016_probe(struct spi_device *spi)
        return 0;
 }
 
-static int nt39016_remove(struct spi_device *spi)
+static void nt39016_remove(struct spi_device *spi)
 {
        struct nt39016 *panel = spi_get_drvdata(spi);
 
@@ -300,8 +300,6 @@ static int nt39016_remove(struct spi_device *spi)
 
        nt39016_disable(&panel->drm_panel);
        nt39016_unprepare(&panel->drm_panel);
-
-       return 0;
 }
 
 static const struct drm_display_mode kd035g6_display_modes[] = {
index ead479719f008faa61c41daf830572c28fcf14ce..04640c5256a84af4bbbd44314dcee2c12410b651 100644 (file)
@@ -314,12 +314,11 @@ static int db7430_probe(struct spi_device *spi)
        return 0;
 }
 
-static int db7430_remove(struct spi_device *spi)
+static void db7430_remove(struct spi_device *spi)
 {
        struct db7430 *db = spi_get_drvdata(spi);
 
        drm_panel_remove(&db->panel);
-       return 0;
 }
 
 /*
index c4b388850a13e01f0cadc02a8a541c6dc91fabf1..01eb211f32f7578389835cfb9a7e012e4c359710 100644 (file)
@@ -358,14 +358,12 @@ static int ld9040_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ld9040_remove(struct spi_device *spi)
+static void ld9040_remove(struct spi_device *spi)
 {
        struct ld9040 *ctx = spi_get_drvdata(spi);
 
        ld9040_power_off(ctx);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id ld9040_of_match[] = {
index 1696ceb36aa0227220a4e912fa5420da205fd389..2adb223a895c9c89703abcf1148fbe9bd6c0da41 100644 (file)
@@ -291,12 +291,11 @@ static int s6d27a1_probe(struct spi_device *spi)
        return 0;
 }
 
-static int s6d27a1_remove(struct spi_device *spi)
+static void s6d27a1_remove(struct spi_device *spi)
 {
        struct s6d27a1 *ctx = spi_get_drvdata(spi);
 
        drm_panel_remove(&ctx->panel);
-       return 0;
 }
 
 static const struct of_device_id s6d27a1_match[] = {
index c178d962b0d51dff00cdadd5307c54fb2f5f78d4..d99afcc672ca1590105de5edbdc28aec84ffa32a 100644 (file)
@@ -62,10 +62,9 @@ static int s6e63m0_spi_probe(struct spi_device *spi)
                             s6e63m0_spi_dcs_write, false);
 }
 
-static int s6e63m0_spi_remove(struct spi_device *spi)
+static void s6e63m0_spi_remove(struct spi_device *spi)
 {
        s6e63m0_remove(&spi->dev);
-       return 0;
 }
 
 static const struct of_device_id s6e63m0_spi_of_match[] = {
index 61e565524542c7e284726a5c34f770180e9084f4..bbc4569cbcdc227af2fa55e0e7955aa4ec21e9f7 100644 (file)
@@ -387,13 +387,11 @@ static int st7789v_probe(struct spi_device *spi)
        return 0;
 }
 
-static int st7789v_remove(struct spi_device *spi)
+static void st7789v_remove(struct spi_device *spi)
 {
        struct st7789v *ctx = spi_get_drvdata(spi);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id st7789v_of_match[] = {
index ba0b3ead150f9023cea090475b9d9d367c324e7b..0d7541a33f87f4595ab2e5e11a1d3f2ce1f91d77 100644 (file)
@@ -655,7 +655,7 @@ static int acx565akm_probe(struct spi_device *spi)
        return 0;
 }
 
-static int acx565akm_remove(struct spi_device *spi)
+static void acx565akm_remove(struct spi_device *spi)
 {
        struct acx565akm_panel *lcd = spi_get_drvdata(spi);
 
@@ -666,8 +666,6 @@ static int acx565akm_remove(struct spi_device *spi)
 
        drm_panel_disable(&lcd->panel);
        drm_panel_unprepare(&lcd->panel);
-
-       return 0;
 }
 
 static const struct of_device_id acx565akm_of_match[] = {
index ba0c00d1a001c7aa36148a940dde3cc9863fba1c..4dbf8b88f264f7afcacf2ae8f67704f5a7505341 100644 (file)
@@ -350,15 +350,13 @@ static int td028ttec1_probe(struct spi_device *spi)
        return 0;
 }
 
-static int td028ttec1_remove(struct spi_device *spi)
+static void td028ttec1_remove(struct spi_device *spi)
 {
        struct td028ttec1_panel *lcd = spi_get_drvdata(spi);
 
        drm_panel_remove(&lcd->panel);
        drm_panel_disable(&lcd->panel);
        drm_panel_unprepare(&lcd->panel);
-
-       return 0;
 }
 
 static const struct of_device_id td028ttec1_of_match[] = {
index 1866cdb8f9c1d3141e8e49b449db866ff1109c7e..cf4609bb9b1da969973ac0ecc67436185691941a 100644 (file)
@@ -463,7 +463,7 @@ static int td043mtea1_probe(struct spi_device *spi)
        return 0;
 }
 
-static int td043mtea1_remove(struct spi_device *spi)
+static void td043mtea1_remove(struct spi_device *spi)
 {
        struct td043mtea1_panel *lcd = spi_get_drvdata(spi);
 
@@ -472,8 +472,6 @@ static int td043mtea1_remove(struct spi_device *spi)
        drm_panel_unprepare(&lcd->panel);
 
        sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group);
-
-       return 0;
 }
 
 static const struct of_device_id td043mtea1_of_match[] = {
index e3791dad6830c31e8c5d4eeecc59e88afdd73843..0b1f5a11a055417df8e9c7c1fca4ea2070921944 100644 (file)
@@ -450,12 +450,11 @@ static int tpg110_probe(struct spi_device *spi)
        return 0;
 }
 
-static int tpg110_remove(struct spi_device *spi)
+static void tpg110_remove(struct spi_device *spi)
 {
        struct tpg110 *tpg = spi_get_drvdata(spi);
 
        drm_panel_remove(&tpg->panel);
-       return 0;
 }
 
 static const struct of_device_id tpg110_match[] = {
index 8bc976f54b8015589e7ced7ce2bc5491e026f34e..236f3cb2b594e011f7e2e40f5eff3d7c1f538c23 100644 (file)
@@ -407,12 +407,11 @@ static int ws2401_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ws2401_remove(struct spi_device *spi)
+static void ws2401_remove(struct spi_device *spi)
 {
        struct ws2401 *ws = spi_get_drvdata(spi);
 
        drm_panel_remove(&ws->panel);
-       return 0;
 }
 
 /*
index 9b33c05732aa85b43269fdfcb62b49b5a0cadbfd..ebb025543f8de65c40e1f9b118de2116dc4af6d8 100644 (file)
@@ -263,14 +263,12 @@ static int hx8357d_probe(struct spi_device *spi)
        return 0;
 }
 
-static int hx8357d_remove(struct spi_device *spi)
+static void hx8357d_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void hx8357d_shutdown(struct spi_device *spi)
index bcc181351236931eb0ad02b3a17222cc5608a827..fc8ed245b0bc989dc1a0b21e7d5a87862ada2b1f 100644 (file)
@@ -193,14 +193,12 @@ static int ili9163_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili9163_remove(struct spi_device *spi)
+static void ili9163_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void ili9163_shutdown(struct spi_device *spi)
index 976d3209f1647f0b5b678217619a2b15e1cba72f..cc92eb9f2a07bc8d65f6894d41e126d00f579993 100644 (file)
@@ -411,14 +411,12 @@ static int ili9225_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili9225_remove(struct spi_device *spi)
+static void ili9225_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void ili9225_shutdown(struct spi_device *spi)
index 37e0c33399c8fad164399e3e31e695d44e3494df..5b8cc770ee7b92519718041ba2441928b2f7417e 100644 (file)
@@ -225,14 +225,12 @@ static int ili9341_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili9341_remove(struct spi_device *spi)
+static void ili9341_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void ili9341_shutdown(struct spi_device *spi)
index e9a63f4b2993c7a6d0dc45352bf27db110435c05..6d655e18e0aa2062c59d7d7be0469eccf27a6b87 100644 (file)
@@ -243,14 +243,12 @@ static int ili9486_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili9486_remove(struct spi_device *spi)
+static void ili9486_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void ili9486_shutdown(struct spi_device *spi)
index 023de49e7a8e6ea8dc86c17edc8d0acf6e35eccc..5e060f6910bb45f557aa61f1540bb1139bb77b1d 100644 (file)
@@ -233,14 +233,12 @@ static int mi0283qt_probe(struct spi_device *spi)
        return 0;
 }
 
-static int mi0283qt_remove(struct spi_device *spi)
+static void mi0283qt_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void mi0283qt_shutdown(struct spi_device *spi)
index 97a775c48cea7750a5ae4ab31e00ba70d5b0d0ed..beeeb170d0b19d63b89b0087b36f07b973bde3e5 100644 (file)
@@ -1140,14 +1140,12 @@ static int repaper_probe(struct spi_device *spi)
        return 0;
 }
 
-static int repaper_remove(struct spi_device *spi)
+static void repaper_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void repaper_shutdown(struct spi_device *spi)
index 51b9b9fb3ead19895e8086e54337adf9fd020389..3f38faa1cd8c827f8c9df3d04f04e7365bffda5c 100644 (file)
@@ -360,14 +360,12 @@ static int st7586_probe(struct spi_device *spi)
        return 0;
 }
 
-static int st7586_remove(struct spi_device *spi)
+static void st7586_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void st7586_shutdown(struct spi_device *spi)
index fc40dd10efa8f140d225f97a571b615acbfa3886..29d618093e94618266a352e210173f4bd6733a82 100644 (file)
@@ -247,14 +247,12 @@ static int st7735r_probe(struct spi_device *spi)
        return 0;
 }
 
-static int st7735r_remove(struct spi_device *spi)
+static void st7735r_remove(struct spi_device *spi)
 {
        struct drm_device *drm = spi_get_drvdata(spi);
 
        drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
-
-       return 0;
 }
 
 static void st7735r_shutdown(struct spi_device *spi)
index e5bc5ce09f4e78e9ed0669e4456a23b586f0c30d..de37bce24fa6882f06e893a13bcb0310154c7249 100644 (file)
@@ -194,7 +194,7 @@ out_err:
        return status;
 }
 
-static int adcxx_remove(struct spi_device *spi)
+static void adcxx_remove(struct spi_device *spi)
 {
        struct adcxx *adc = spi_get_drvdata(spi);
        int i;
@@ -205,8 +205,6 @@ static int adcxx_remove(struct spi_device *spi)
                device_remove_file(&spi->dev, &ad_input[i].dev_attr);
 
        mutex_unlock(&adc->lock);
-
-       return 0;
 }
 
 static const struct spi_device_id adcxx_ids[] = {
index 5fcfd57df61e12b15144a6100302fc7dfda56116..4c5487aeb3cfca487c0518554e4e61bc7a16e753 100644 (file)
@@ -254,7 +254,7 @@ err_remove:
        return err;
 }
 
-static int max1111_remove(struct spi_device *spi)
+static void max1111_remove(struct spi_device *spi)
 {
        struct max1111_data *data = spi_get_drvdata(spi);
 
@@ -265,7 +265,6 @@ static int max1111_remove(struct spi_device *spi)
        sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);
        sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
        mutex_destroy(&data->drvdata_lock);
-       return 0;
 }
 
 static const struct spi_device_id max1111_ids[] = {
index 4cf4fe6809a32959da58ed7191d36d7c8378fe9e..93e048ee49557c08acc1dd88ef381ade83750685 100644 (file)
@@ -100,7 +100,7 @@ static int max31722_probe(struct spi_device *spi)
        return 0;
 }
 
-static int max31722_remove(struct spi_device *spi)
+static void max31722_remove(struct spi_device *spi)
 {
        struct max31722_data *data = spi_get_drvdata(spi);
        int ret;
@@ -111,8 +111,6 @@ static int max31722_remove(struct spi_device *spi)
        if (ret)
                /* There is nothing we can do about this ... */
                dev_warn(&spi->dev, "Failed to put device in stand-by mode\n");
-
-       return 0;
 }
 
 static int __maybe_unused max31722_suspend(struct device *dev)
index 9f622e37477b4a22da9321f3539086082675066b..9040a717b2470a1aa02c417ddeb0b83836b06ca3 100644 (file)
@@ -87,11 +87,9 @@ static int bma400_spi_probe(struct spi_device *spi)
        return bma400_probe(&spi->dev, regmap, id->name);
 }
 
-static int bma400_spi_remove(struct spi_device *spi)
+static void bma400_spi_remove(struct spi_device *spi)
 {
        bma400_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id bma400_spi_ids[] = {
index 11559567cb398dcfaee86e05ff6a1f0eba2c4218..80007cc2d04466443a237de69eacda8c85574477 100644 (file)
@@ -35,11 +35,9 @@ static int bmc150_accel_probe(struct spi_device *spi)
                                       true);
 }
 
-static int bmc150_accel_remove(struct spi_device *spi)
+static void bmc150_accel_remove(struct spi_device *spi)
 {
        bmc150_accel_core_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct acpi_device_id bmc150_accel_acpi_match[] = {
index 758ad2f128962b37de2027669b0ae2c1ecacdd96..06d99d9949f3f47b1a84717fbf18eb258b276564 100644 (file)
@@ -56,11 +56,9 @@ static int bmi088_accel_probe(struct spi_device *spi)
                                       true);
 }
 
-static int bmi088_accel_remove(struct spi_device *spi)
+static void bmi088_accel_remove(struct spi_device *spi)
 {
        bmi088_accel_core_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id bmi088_accel_id[] = {
index 441e6b764281c3e2c5c54188309a20e992bd9b9c..57c451cfb9e5df7749422226f048027384cd1ea7 100644 (file)
@@ -32,11 +32,9 @@ static int kxsd9_spi_probe(struct spi_device *spi)
                                  spi_get_device_id(spi)->name);
 }
 
-static int kxsd9_spi_remove(struct spi_device *spi)
+static void kxsd9_spi_remove(struct spi_device *spi)
 {
        kxsd9_common_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id kxsd9_spi_id[] = {
index ecf690692dcc85c83d8023f3d0282e06032d8b70..b746031551a39f1708e4061108addb437b6e0994 100644 (file)
@@ -22,11 +22,9 @@ static int mma7455_spi_probe(struct spi_device *spi)
        return mma7455_core_probe(&spi->dev, regmap, id->name);
 }
 
-static int mma7455_spi_remove(struct spi_device *spi)
+static void mma7455_spi_remove(struct spi_device *spi)
 {
        mma7455_core_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id mma7455_spi_ids[] = {
index 43ecacbdc95ae2577e1fc28588d463bcefb400ec..83c81072511ee2c30e7d1893c4b354a86913bec0 100644 (file)
@@ -1524,7 +1524,7 @@ error_ret:
        return ret;
 }
 
-static int sca3000_remove(struct spi_device *spi)
+static void sca3000_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct sca3000_state *st = iio_priv(indio_dev);
@@ -1535,8 +1535,6 @@ static int sca3000_remove(struct spi_device *spi)
        sca3000_stop_all_interrupts(st);
        if (spi->irq)
                free_irq(spi->irq, indio_dev);
-
-       return 0;
 }
 
 static const struct spi_device_id sca3000_id[] = {
index 1d345d66742d8edd1ec1a8f3a9d2d1ec6208cf5f..c17d9b5fbaf64ebb7f2009988bd3ac80ee628f31 100644 (file)
@@ -479,7 +479,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad7266_remove(struct spi_device *spi)
+static void ad7266_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7266_state *st = iio_priv(indio_dev);
@@ -488,8 +488,6 @@ static int ad7266_remove(struct spi_device *spi)
        iio_triggered_buffer_cleanup(indio_dev);
        if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad7266_id[] = {
index dd956a7c216e133a76d9aa9ce1215bca1b5c4301..5a55f79f2574905ae63fb8f2bbd51928757a04ee 100644 (file)
@@ -78,13 +78,11 @@ static int ltc2496_probe(struct spi_device *spi)
        return ltc2497core_probe(dev, indio_dev);
 }
 
-static int ltc2496_remove(struct spi_device *spi)
+static void ltc2496_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
        ltc2497core_remove(indio_dev);
-
-       return 0;
 }
 
 static const struct of_device_id ltc2496_of_match[] = {
index 8d1cff28cae0ad0af17bab32753021b35e51c4e8..b4c69acb33e34b468902feed69ffa9f2aae83910 100644 (file)
@@ -459,15 +459,13 @@ reg_disable:
        return ret;
 }
 
-static int mcp320x_remove(struct spi_device *spi)
+static void mcp320x_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct mcp320x *adc = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
        regulator_disable(adc->reg);
-
-       return 0;
 }
 
 static const struct of_device_id mcp320x_dt_ids[] = {
index 13535f148c4c6c2eb4513844d889987b1a43d490..1cb4590fe4125a9987d5442a5f31964c50eb358d 100644 (file)
@@ -321,7 +321,7 @@ reg_disable:
        return ret;
 }
 
-static int mcp3911_remove(struct spi_device *spi)
+static void mcp3911_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct mcp3911 *adc = iio_priv(indio_dev);
@@ -331,8 +331,6 @@ static int mcp3911_remove(struct spi_device *spi)
        clk_disable_unprepare(adc->clki);
        if (adc->vref)
                regulator_disable(adc->vref);
-
-       return 0;
 }
 
 static const struct of_device_id mcp3911_dt_ids[] = {
index 6eb62b564dae2665440c6a74fbb67c58a7f3ac65..59d75d09604f34acb077fc74dbba4d2ffd8196b1 100644 (file)
@@ -503,7 +503,7 @@ err_clk_disable:
        return ret;
 }
 
-static int adc12138_remove(struct spi_device *spi)
+static void adc12138_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct adc12138 *adc = iio_priv(indio_dev);
@@ -514,8 +514,6 @@ static int adc12138_remove(struct spi_device *spi)
                regulator_disable(adc->vref_n);
        regulator_disable(adc->vref_p);
        clk_disable_unprepare(adc->cclk);
-
-       return 0;
 }
 
 static const struct of_device_id adc12138_dt_ids[] = {
index a7efa3eada2c471c291077ed07003af209bd1528..e3658b969c5bf112a4ab33f9cd2d534f2db5286c 100644 (file)
@@ -662,7 +662,7 @@ error_destroy_mutex:
        return ret;
 }
 
-static int ti_ads7950_remove(struct spi_device *spi)
+static void ti_ads7950_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ti_ads7950_state *st = iio_priv(indio_dev);
@@ -672,8 +672,6 @@ static int ti_ads7950_remove(struct spi_device *spi)
        iio_triggered_buffer_cleanup(indio_dev);
        regulator_disable(st->reg);
        mutex_destroy(&st->slock);
-
-       return 0;
 }
 
 static const struct spi_device_id ti_ads7950_id[] = {
index 2e24717d7f5537508ac8d83a6eee862be85d8ea7..22c2583eedd0f36df39cc1a6de5664b86c4daea2 100644 (file)
@@ -479,7 +479,7 @@ err_regulator_disable:
        return ret;
 }
 
-static int ads8688_remove(struct spi_device *spi)
+static void ads8688_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ads8688_state *st = iio_priv(indio_dev);
@@ -489,8 +489,6 @@ static int ads8688_remove(struct spi_device *spi)
 
        if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ads8688_id[] = {
index 403b787f9f7ec69b970cd9a317ce80b5f1dbea6b..2406eda9dfc6ab7357b7a33f4e89e8892ff97747 100644 (file)
@@ -224,7 +224,7 @@ error_disable_reg:
        return ret;
 }
 
-static int tlc4541_remove(struct spi_device *spi)
+static void tlc4541_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct tlc4541_state *st = iio_priv(indio_dev);
@@ -232,8 +232,6 @@ static int tlc4541_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
        iio_triggered_buffer_cleanup(indio_dev);
        regulator_disable(st->reg);
-
-       return 0;
 }
 
 static const struct of_device_id tlc4541_dt_ids[] = {
index cfcf18a0bce8517a20c14b95cc11a84ace53fff7..1134ae12e5319a9465453fd87bd782cd0b28e81c 100644 (file)
@@ -298,7 +298,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad8366_remove(struct spi_device *spi)
+static void ad8366_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad8366_state *st = iio_priv(indio_dev);
@@ -308,8 +308,6 @@ static int ad8366_remove(struct spi_device *spi)
 
        if (!IS_ERR(reg))
                regulator_disable(reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad8366_id[] = {
index 1aee87100038172b1cb973f874065c86c77b4417..eafaf4529df54253c341488ff1cee145f0544a1b 100644 (file)
@@ -586,7 +586,7 @@ err_setup_irq:
        return ret;
 }
 
-static int ssp_remove(struct spi_device *spi)
+static void ssp_remove(struct spi_device *spi)
 {
        struct ssp_data *data = spi_get_drvdata(spi);
 
@@ -608,8 +608,6 @@ static int ssp_remove(struct spi_device *spi)
        mutex_destroy(&data->pending_lock);
 
        mfd_remove_devices(&spi->dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 2d3b14c407d838f70aa87809acb414ecace27493..ecbc6a51d60fabf858ec48a333e25586a16be584 100644 (file)
@@ -521,7 +521,7 @@ error_free_channels:
        return ret;
 }
 
-static int ad5360_remove(struct spi_device *spi)
+static void ad5360_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5360_state *st = iio_priv(indio_dev);
@@ -531,8 +531,6 @@ static int ad5360_remove(struct spi_device *spi)
        kfree(indio_dev->channels);
 
        regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5360_ids[] = {
index e38860a6a9f3f5e1ac9ce82d9920bc335f31b91c..82e1d9bd773e556bfd343be0fbd0a2db2f276ef7 100644 (file)
@@ -488,11 +488,9 @@ static int ad5380_spi_probe(struct spi_device *spi)
        return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
 }
 
-static int ad5380_spi_remove(struct spi_device *spi)
+static void ad5380_spi_remove(struct spi_device *spi)
 {
        ad5380_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5380_spi_ids[] = {
index 1c9b54c012a7e55fe491573f806c863569f82dfa..14cfabacbea5309c5e0d03d01313af649ce8c911 100644 (file)
@@ -491,11 +491,9 @@ static int ad5446_spi_probe(struct spi_device *spi)
                &ad5446_spi_chip_info[id->driver_data]);
 }
 
-static int ad5446_spi_remove(struct spi_device *spi)
+static void ad5446_spi_remove(struct spi_device *spi)
 {
        ad5446_remove(&spi->dev);
-
-       return 0;
 }
 
 static struct spi_driver ad5446_spi_driver = {
index f5e93c6acc9d016b91181e63984661a47398fb65..bad9bdaafa94d62fdd98dc4136afca6e29173914 100644 (file)
@@ -330,7 +330,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad5449_spi_remove(struct spi_device *spi)
+static void ad5449_spi_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5449 *st = iio_priv(indio_dev);
@@ -338,8 +338,6 @@ static int ad5449_spi_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
 
        regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5449_spi_ids[] = {
index b631261efa97aba3c3a18c26b36a9661a011e928..8507573aa13e98c088288b473aef5afa3b317a14 100644 (file)
@@ -336,7 +336,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad5504_remove(struct spi_device *spi)
+static void ad5504_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5504_state *st = iio_priv(indio_dev);
@@ -345,8 +345,6 @@ static int ad5504_remove(struct spi_device *spi)
 
        if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5504_id[] = {
index 6bfd7951e18caa45e9e6c2490a984a7c028dd582..0f7abfa75bec7371fbdc4154b8b208e49efc4075 100644 (file)
@@ -130,11 +130,9 @@ static int ad5592r_spi_probe(struct spi_device *spi)
        return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops);
 }
 
-static int ad5592r_spi_remove(struct spi_device *spi)
+static void ad5592r_spi_remove(struct spi_device *spi)
 {
        ad5592r_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5592r_spi_ids[] = {
index 3c98941b9f99ab071a5f7380453767e146294567..371e812850ebad63b74fc82c59b8268197af92df 100644 (file)
@@ -293,7 +293,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad5624r_remove(struct spi_device *spi)
+static void ad5624r_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5624r_state *st = iio_priv(indio_dev);
@@ -301,8 +301,6 @@ static int ad5624r_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
        if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5624r_id[] = {
index 2628810fdbb1ffc9f8ff7e825b0a51d8b4da87b3..d26fb29b6b04dd31d35a4e7c7b6f44dfa0ca2a02 100644 (file)
@@ -95,11 +95,9 @@ static int ad5686_spi_probe(struct spi_device *spi)
                            ad5686_spi_write, ad5686_spi_read);
 }
 
-static int ad5686_spi_remove(struct spi_device *spi)
+static void ad5686_spi_remove(struct spi_device *spi)
 {
        ad5686_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5686_spi_id[] = {
index e37e095e94fc2d9d07bfc7ceb63d62402903877f..4cb8471db81e07a183b8d78bd28099ea8eebafae 100644 (file)
@@ -394,7 +394,7 @@ disable_regulator_err:
        return ret;
 }
 
-static int ad5761_remove(struct spi_device *spi)
+static void ad5761_remove(struct spi_device *spi)
 {
        struct iio_dev *iio_dev = spi_get_drvdata(spi);
        struct ad5761_state *st = iio_priv(iio_dev);
@@ -403,8 +403,6 @@ static int ad5761_remove(struct spi_device *spi)
 
        if (!IS_ERR_OR_NULL(st->vref_reg))
                regulator_disable(st->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5761_id[] = {
index ae089b9145cb7b5108e0dbfbc8d5bbe1f1f31a50..d235a8047ba0c62a3ac72e5faea3a1d55c9b5b9e 100644 (file)
@@ -332,7 +332,7 @@ error_disable_reg:
        return ret;
 }
 
-static int ad5764_remove(struct spi_device *spi)
+static void ad5764_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5764_state *st = iio_priv(indio_dev);
@@ -341,8 +341,6 @@ static int ad5764_remove(struct spi_device *spi)
 
        if (st->chip_info->int_vref == 0)
                regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5764_ids[] = {
index 7b4579d73d18b9c5bdac055c6f9528aa89d2a4ff..2b14914b40500629e48c973031b7cafab579203e 100644 (file)
@@ -428,7 +428,7 @@ error_disable_reg_pos:
        return ret;
 }
 
-static int ad5791_remove(struct spi_device *spi)
+static void ad5791_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad5791_state *st = iio_priv(indio_dev);
@@ -439,8 +439,6 @@ static int ad5791_remove(struct spi_device *spi)
 
        if (!IS_ERR(st->reg_vss))
                regulator_disable(st->reg_vss);
-
-       return 0;
 }
 
 static const struct spi_device_id ad5791_id[] = {
index 5ecfdad54dec3cb12686203f90ed2db8e67e093f..6be35c92d435a184dd3fce0ecfd8b0d57cd84216 100644 (file)
@@ -193,7 +193,7 @@ error_disable_vrefh_reg:
        return ret;
 }
 
-static int ad8801_remove(struct spi_device *spi)
+static void ad8801_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad8801_state *state = iio_priv(indio_dev);
@@ -202,8 +202,6 @@ static int ad8801_remove(struct spi_device *spi)
        if (state->vrefl_reg)
                regulator_disable(state->vrefl_reg);
        regulator_disable(state->vrefh_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ad8801_ids[] = {
index f6ec9bf5815ea7af30dee677afb0fe9818eaf9db..c76233c9bb72b7524a1f15986b9731565013c36f 100644 (file)
@@ -206,15 +206,13 @@ error_disable_reg:
        return ret;
 }
 
-static int ltc1660_remove(struct spi_device *spi)
+static void ltc1660_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ltc1660_priv *priv = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
        regulator_disable(priv->vref_reg);
-
-       return 0;
 }
 
 static const struct of_device_id ltc1660_dt_ids[] = {
index 53e4b887d372d693c155e17ab387c8645968ef40..aed46c80757e3d1d2777aadc2655ee1edc5a8aee 100644 (file)
@@ -372,7 +372,7 @@ static int ltc2632_probe(struct spi_device *spi)
        return iio_device_register(indio_dev);
 }
 
-static int ltc2632_remove(struct spi_device *spi)
+static void ltc2632_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ltc2632_state *st = iio_priv(indio_dev);
@@ -381,8 +381,6 @@ static int ltc2632_remove(struct spi_device *spi)
 
        if (st->vref_reg)
                regulator_disable(st->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id ltc2632_id[] = {
index 0ae414ee171660b747f29eb5b830f775154a167f..cb9e60e71b9155b2c6375a60694b7f033ca84d38 100644 (file)
@@ -172,7 +172,7 @@ error_disable_reg:
        return ret;
 }
 
-static int mcp4922_remove(struct spi_device *spi)
+static void mcp4922_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct mcp4922_state *state;
@@ -180,8 +180,6 @@ static int mcp4922_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
        state = iio_priv(indio_dev);
        regulator_disable(state->vref_reg);
-
-       return 0;
 }
 
 static const struct spi_device_id mcp4922_id[] = {
index 6beda2193683a4dd076793db60252221b4d48c83..4e1156e6deb2d7c0e11b225a886f928c64d07480 100644 (file)
@@ -313,7 +313,7 @@ err:
        return ret;
 }
 
-static int ti_dac_remove(struct spi_device *spi)
+static void ti_dac_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
@@ -321,8 +321,6 @@ static int ti_dac_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
        mutex_destroy(&ti_dac->lock);
        regulator_disable(ti_dac->vref);
-
-       return 0;
 }
 
 static const struct of_device_id ti_dac_of_id[] = {
index 99f275829ec211178c7f18b8a955f121b86d2109..e10d17e60ed39f02e57f77e78affd3f45fd53758 100644 (file)
@@ -292,7 +292,7 @@ err:
        return ret;
 }
 
-static int ti_dac_remove(struct spi_device *spi)
+static void ti_dac_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
@@ -300,7 +300,6 @@ static int ti_dac_remove(struct spi_device *spi)
        iio_device_unregister(indio_dev);
        mutex_destroy(&ti_dac->lock);
        regulator_disable(ti_dac->vref);
-       return 0;
 }
 
 static const struct of_device_id ti_dac_of_id[] = {
index 3d9eba716b69155f525070ff44d3c1b8a0c4f09d..f3521330f6fb22dc07a068071c1a13525c83435f 100644 (file)
@@ -589,7 +589,7 @@ error_disable_clk:
        return ret;
 }
 
-static int adf4350_remove(struct spi_device *spi)
+static void adf4350_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct adf4350_state *st = iio_priv(indio_dev);
@@ -604,8 +604,6 @@ static int adf4350_remove(struct spi_device *spi)
 
        if (!IS_ERR(reg))
                regulator_disable(reg);
-
-       return 0;
 }
 
 static const struct of_device_id adf4350_of_match[] = {
index 745962e1e42357bcadc0d929041718620b9e3f79..fc2e453527b97d4bc0e9ea539dd20b9e4082f3ba 100644 (file)
@@ -27,11 +27,9 @@ static int bmg160_spi_probe(struct spi_device *spi)
        return bmg160_core_probe(&spi->dev, regmap, spi->irq, id->name);
 }
 
-static int bmg160_spi_remove(struct spi_device *spi)
+static void bmg160_spi_remove(struct spi_device *spi)
 {
        bmg160_core_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id bmg160_spi_id[] = {
index 77ceebef4e34c1c05d3bc0bff881c5d8b8fc5f0d..c3ac169facf9beaf0ce52546c6c8fe0da9a95892 100644 (file)
@@ -34,11 +34,9 @@ static int fxas21002c_spi_probe(struct spi_device *spi)
        return fxas21002c_core_probe(&spi->dev, regmap, spi->irq, id->name);
 }
 
-static int fxas21002c_spi_remove(struct spi_device *spi)
+static void fxas21002c_spi_remove(struct spi_device *spi)
 {
        fxas21002c_core_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id fxas21002c_spi_id[] = {
index 273f16dcaff84e1c6e39d7bf7f280f8a3bc64969..856ec901b091317049cf55bbc704e6a87f6d1e76 100644 (file)
@@ -570,7 +570,7 @@ err_disable_reg:
        return ret;
 }
 
-static int afe4403_remove(struct spi_device *spi)
+static void afe4403_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct afe4403_data *afe = iio_priv(indio_dev);
@@ -586,8 +586,6 @@ static int afe4403_remove(struct spi_device *spi)
        ret = regulator_disable(afe->regulator);
        if (ret)
                dev_warn(afe->dev, "Unable to disable regulator\n");
-
-       return 0;
 }
 
 static const struct spi_device_id afe4403_ids[] = {
index c6ed3ea8460ae42156b094f71fbe69fe7a9e7426..4c570412d65cc646430db1d288ea1ecce4290bb9 100644 (file)
@@ -29,11 +29,9 @@ static int bmc150_magn_spi_probe(struct spi_device *spi)
        return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name);
 }
 
-static int bmc150_magn_spi_remove(struct spi_device *spi)
+static void bmc150_magn_spi_remove(struct spi_device *spi)
 {
        bmc150_magn_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id bmc150_magn_spi_id[] = {
index 89cf59a62c289d2294c0cf5ec387bad7de3e0a8e..a99dd9b33e95f4631224d07bfb7c4d80fa97016c 100644 (file)
@@ -74,11 +74,9 @@ static int hmc5843_spi_probe(struct spi_device *spi)
                        id->driver_data, id->name);
 }
 
-static int hmc5843_spi_remove(struct spi_device *spi)
+static void hmc5843_spi_remove(struct spi_device *spi)
 {
        hmc5843_common_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id hmc5843_id[] = {
index 007c2bd324cb1fdccca007de8cbdaf306a2efe6e..42723c996c9f4f7ef48fdc8800c72bbae829fc2e 100644 (file)
@@ -112,7 +112,7 @@ static int max5487_spi_probe(struct spi_device *spi)
        return iio_device_register(indio_dev);
 }
 
-static int max5487_spi_remove(struct spi_device *spi)
+static void max5487_spi_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        int ret;
@@ -123,8 +123,6 @@ static int max5487_spi_remove(struct spi_device *spi)
        ret = max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV);
        if (ret)
                dev_warn(&spi->dev, "Failed to save wiper regs to NV regs\n");
-
-       return 0;
 }
 
 static const struct spi_device_id max5487_id[] = {
index 9fa2dcd71760bff2b8084589ef6baaa86c8e2e5d..7ccd960ced5dbed9a7e1ebcde471ee79056a7764 100644 (file)
@@ -107,11 +107,9 @@ static int ms5611_spi_probe(struct spi_device *spi)
                            spi_get_device_id(spi)->driver_data);
 }
 
-static int ms5611_spi_remove(struct spi_device *spi)
+static void ms5611_spi_remove(struct spi_device *spi)
 {
        ms5611_remove(spi_get_drvdata(spi));
-
-       return 0;
 }
 
 static const struct of_device_id ms5611_spi_matches[] = {
index 85201a4bae44c2e5899f00756a09905b9cd9c224..ee8ed77536cac93c9354e3f1acd8771bca0fc1b9 100644 (file)
@@ -57,11 +57,9 @@ static int zpa2326_probe_spi(struct spi_device *spi)
                             spi->irq, ZPA2326_DEVICE_ID, regmap);
 }
 
-static int zpa2326_remove_spi(struct spi_device *spi)
+static void zpa2326_remove_spi(struct spi_device *spi)
 {
        zpa2326_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id zpa2326_spi_ids[] = {
index eda1b23002b58de882c84c430f0c692b57c07fc1..d1f5354d5ea283ab36737fb60441c59d931395b8 100644 (file)
@@ -1858,7 +1858,7 @@ static void applespi_drain_reads(struct applespi_data *applespi)
        spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
 }
 
-static int applespi_remove(struct spi_device *spi)
+static void applespi_remove(struct spi_device *spi)
 {
        struct applespi_data *applespi = spi_get_drvdata(spi);
 
@@ -1871,8 +1871,6 @@ static int applespi_remove(struct spi_device *spi)
        applespi_drain_reads(applespi);
 
        debugfs_remove_recursive(applespi->debugfs_root);
-
-       return 0;
 }
 
 static void applespi_shutdown(struct spi_device *spi)
index 6e51c9bc619f2b2a875c0214d3e1eb887b431c22..91e44d4c66f7a5bd9106e39b119e0926873bd324 100644 (file)
@@ -87,13 +87,11 @@ static int adxl34x_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int adxl34x_spi_remove(struct spi_device *spi)
+static void adxl34x_spi_remove(struct spi_device *spi)
 {
        struct adxl34x *ac = spi_get_drvdata(spi);
 
        adxl34x_remove(ac);
-
-       return 0;
 }
 
 static int __maybe_unused adxl34x_spi_suspend(struct device *dev)
index a25a77dd9a32dc1f2959c523f9bf66a4c1b779d9..bed68a68f3303c900f0741cce3571c1afa25ef6f 100644 (file)
@@ -1411,13 +1411,11 @@ static int ads7846_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ads7846_remove(struct spi_device *spi)
+static void ads7846_remove(struct spi_device *spi)
 {
        struct ads7846 *ts = spi_get_drvdata(spi);
 
        ads7846_stop(ts);
-
-       return 0;
 }
 
 static struct spi_driver ads7846_driver = {
index 2aec41eb76b72fde33029fbe6ce56ab91202647e..5d7db84f2749c06d3723245dc2556b5ccf39dc2c 100644 (file)
@@ -164,12 +164,10 @@ static int cyttsp4_spi_probe(struct spi_device *spi)
        return PTR_ERR_OR_ZERO(ts);
 }
 
-static int cyttsp4_spi_remove(struct spi_device *spi)
+static void cyttsp4_spi_remove(struct spi_device *spi)
 {
        struct cyttsp4 *ts = spi_get_drvdata(spi);
        cyttsp4_remove(ts);
-
-       return 0;
 }
 
 static struct spi_driver cyttsp4_spi_driver = {
index a2f55920b9b2e184ef740888629ea2b08942617e..555dfe98b3c4c648235a986f15cf1331c5ce8356 100644 (file)
@@ -64,11 +64,9 @@ static int tsc2005_probe(struct spi_device *spi)
                             tsc2005_cmd);
 }
 
-static int tsc2005_remove(struct spi_device *spi)
+static void tsc2005_remove(struct spi_device *spi)
 {
        tsc200x_remove(&spi->dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_OF
index d03cfd3c0bfbecd83ee65e1729cf7143ac61f800..c87686bd7c189fccc0629bcefdea8306d9c67d70 100644 (file)
@@ -266,14 +266,12 @@ static int cr0014114_probe(struct spi_device *spi)
        return 0;
 }
 
-static int cr0014114_remove(struct spi_device *spi)
+static void cr0014114_remove(struct spi_device *spi)
 {
        struct cr0014114 *priv = spi_get_drvdata(spi);
 
        cancel_delayed_work_sync(&priv->work);
        mutex_destroy(&priv->lock);
-
-       return 0;
 }
 
 static const struct of_device_id cr0014114_dt_ids[] = {
index 20dc9b9d7deacee81ad4c392869a381b97caec80..cf5fb1195f87f89e351704914a89eacd6f38077e 100644 (file)
@@ -85,15 +85,13 @@ eledcr:
        return ret;
 }
 
-static int dac124s085_remove(struct spi_device *spi)
+static void dac124s085_remove(struct spi_device *spi)
 {
        struct dac124s085       *dac = spi_get_drvdata(spi);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(dac->leds); i++)
                led_classdev_unregister(&dac->leds[i].ldev);
-
-       return 0;
 }
 
 static struct spi_driver dac124s085_driver = {
index f9eb59a2557054934bcc36786584b0383252ec48..7e7b617bcd56e4812c16bbe9f97af2e820253d16 100644 (file)
@@ -315,13 +315,11 @@ static int el15203000_probe(struct spi_device *spi)
        return el15203000_probe_dt(priv);
 }
 
-static int el15203000_remove(struct spi_device *spi)
+static void el15203000_remove(struct spi_device *spi)
 {
        struct el15203000 *priv = spi_get_drvdata(spi);
 
        mutex_destroy(&priv->lock);
-
-       return 0;
 }
 
 static const struct of_device_id el15203000_dt_ids[] = {
index f1964c96fb15915435bc3a4d0d9379d0bcc1b2ff..2bc5c99daf51a8c999d9694336a29cafba41a408 100644 (file)
@@ -130,13 +130,11 @@ static int spi_byte_probe(struct spi_device *spi)
        return 0;
 }
 
-static int spi_byte_remove(struct spi_device *spi)
+static void spi_byte_remove(struct spi_device *spi)
 {
        struct spi_byte_led     *led = spi_get_drvdata(spi);
 
        mutex_destroy(&led->mutex);
-
-       return 0;
 }
 
 static struct spi_driver spi_byte_driver = {
index 6f2a66bc87fb8a031f77a595a6b0bb4b29f6eb58..6be4e5528879fb2fa82d2f052f9e6c647041d7ff 100644 (file)
@@ -625,7 +625,7 @@ fail_regulator:
        return ret;
 }
 
-static int
+static void
 cxd2880_spi_remove(struct spi_device *spi)
 {
        struct cxd2880_dvb_spi *dvb_spi = spi_get_drvdata(spi);
@@ -643,8 +643,6 @@ cxd2880_spi_remove(struct spi_device *spi)
 
        kfree(dvb_spi);
        pr_info("cxd2880_spi remove ok.\n");
-
-       return 0;
 }
 
 static const struct spi_device_id cxd2880_spi_id[] = {
index f86ef1ca12885743791b15e756d4e8d9d7346941..75c21a93e6d00f4115f2c3cd91e254434c4c9381 100644 (file)
@@ -458,13 +458,11 @@ static int gs_probe(struct spi_device *spi)
        return ret;
 }
 
-static int gs_remove(struct spi_device *spi)
+static void gs_remove(struct spi_device *spi)
 {
        struct v4l2_subdev *sd = spi_get_drvdata(spi);
 
        v4l2_device_unregister_subdev(sd);
-
-       return 0;
 }
 
 static struct spi_driver gs_driver = {
index 44247049a31903f5cbb9159d9be8ae934d5fb9ae..ad6c72c1ed04267a3e12c7b004f6fc0888f6245d 100644 (file)
@@ -472,7 +472,7 @@ err:
        return ret;
 }
 
-static int msi001_remove(struct spi_device *spi)
+static void msi001_remove(struct spi_device *spi)
 {
        struct v4l2_subdev *sd = spi_get_drvdata(spi);
        struct msi001_dev *dev = sd_to_msi001_dev(sd);
@@ -486,7 +486,6 @@ static int msi001_remove(struct spi_device *spi)
        v4l2_device_unregister_subdev(&dev->sd);
        v4l2_ctrl_handler_free(&dev->hdl);
        kfree(dev);
-       return 0;
 }
 
 static const struct spi_device_id msi001_id_table[] = {
index 9fe06dda37829cade10555b12efa90b146de7751..03620c8efe34af05c22dfa87e3bb38d97378e251 100644 (file)
@@ -206,13 +206,11 @@ static int arizona_spi_probe(struct spi_device *spi)
        return arizona_dev_init(arizona);
 }
 
-static int arizona_spi_remove(struct spi_device *spi)
+static void arizona_spi_remove(struct spi_device *spi)
 {
        struct arizona *arizona = spi_get_drvdata(spi);
 
        arizona_dev_exit(arizona);
-
-       return 0;
 }
 
 static const struct spi_device_id arizona_spi_ids[] = {
index 5faf3766a5e2082528a62fbcc13d50214e68fae9..b79a57b45c1e87922183ff23b04c40e233988982 100644 (file)
@@ -55,12 +55,11 @@ static int da9052_spi_probe(struct spi_device *spi)
        return da9052_device_init(da9052, id->driver_data);
 }
 
-static int da9052_spi_remove(struct spi_device *spi)
+static void da9052_spi_remove(struct spi_device *spi)
 {
        struct da9052 *da9052 = spi_get_drvdata(spi);
 
        da9052_device_exit(da9052);
-       return 0;
 }
 
 static const struct spi_device_id da9052_spi_id[] = {
index b14d3f98e1ebda814301a997d98a2864f384adde..3d5ce18aa9ae7ae5cb9ef1e8fabd6047782b78a3 100644 (file)
@@ -390,7 +390,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap,
        return ret;
 }
 
-static int ezx_pcap_remove(struct spi_device *spi)
+static void ezx_pcap_remove(struct spi_device *spi)
 {
        struct pcap_chip *pcap = spi_get_drvdata(spi);
        unsigned long flags;
@@ -410,8 +410,6 @@ static int ezx_pcap_remove(struct spi_device *spi)
                irq_set_chip_and_handler(i, NULL, NULL);
 
        destroy_workqueue(pcap->workqueue);
-
-       return 0;
 }
 
 static int ezx_pcap_probe(struct spi_device *spi)
index f10e53187f67afcff26525352399265fefe6f831..9ffab9aafd81b165ed2ecdc1d3d5fb62840370e0 100644 (file)
@@ -63,6 +63,8 @@
 #define SPIBASE_BYT            0x54
 #define SPIBASE_BYT_SZ         512
 #define SPIBASE_BYT_EN         BIT(1)
+#define BYT_BCR                        0xfc
+#define BYT_BCR_WPD            BIT(0)
 
 #define SPIBASE_LPT            0x3800
 #define SPIBASE_LPT_SZ         512
@@ -1084,12 +1086,57 @@ wdt_done:
        return ret;
 }
 
+static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
+{
+       u32 val;
+
+       val = readl(base + BYT_BCR);
+       if (!(val & BYT_BCR_WPD)) {
+               val |= BYT_BCR_WPD;
+               writel(val, base + BYT_BCR);
+               val = readl(base + BYT_BCR);
+       }
+
+       return val & BYT_BCR_WPD;
+}
+
+static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
+{
+       struct pci_dev *pdev = data;
+       u32 bcr;
+
+       pci_read_config_dword(pdev, BCR, &bcr);
+       if (!(bcr & BCR_WPD)) {
+               bcr |= BCR_WPD;
+               pci_write_config_dword(pdev, BCR, bcr);
+               pci_read_config_dword(pdev, BCR, &bcr);
+       }
+
+       return bcr & BCR_WPD;
+}
+
+static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
+{
+       unsigned int spi = PCI_DEVFN(13, 2);
+       struct pci_bus *bus = data;
+       u32 bcr;
+
+       pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+       if (!(bcr & BCR_WPD)) {
+               bcr |= BCR_WPD;
+               pci_bus_write_config_dword(bus, spi, BCR, bcr);
+               pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+       }
+
+       return bcr & BCR_WPD;
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
        struct resource *res = &intel_spi_res[0];
        struct intel_spi_boardinfo *info;
-       u32 spi_base, rcba, bcr;
+       u32 spi_base, rcba;
 
        info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
        if (!info)
@@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
                if (spi_base & SPIBASE_BYT_EN) {
                        res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
                        res->end = res->start + SPIBASE_BYT_SZ - 1;
+
+                       info->set_writeable = lpc_ich_byt_set_writeable;
                }
                break;
 
@@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
                        res->start = spi_base + SPIBASE_LPT;
                        res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-                       pci_read_config_dword(dev, BCR, &bcr);
-                       info->writeable = !!(bcr & BCR_WPD);
+                       info->set_writeable = lpc_ich_lpt_set_writeable;
+                       info->data = dev;
                }
                break;
 
@@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
                        res->start = spi_base & 0xfffffff0;
                        res->end = res->start + SPIBASE_APL_SZ - 1;
 
-                       pci_bus_read_config_dword(bus, spi, BCR, &bcr);
-                       info->writeable = !!(bcr & BCR_WPD);
+                       info->set_writeable = lpc_ich_bxt_set_writeable;
+                       info->data = bus;
                }
 
                pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
index e860f5ff0933691844f30af8a87689c424359a7d..da84eb50e53a366669cf878389f4d795af2977a0 100644 (file)
@@ -112,13 +112,11 @@ static int madera_spi_probe(struct spi_device *spi)
        return madera_dev_init(madera);
 }
 
-static int madera_spi_remove(struct spi_device *spi)
+static void madera_spi_remove(struct spi_device *spi)
 {
        struct madera *madera = spi_get_drvdata(spi);
 
        madera_dev_exit(madera);
-
-       return 0;
 }
 
 static const struct spi_device_id madera_spi_ids[] = {
index 4d8913d647e6345688ec23dd3b4009e96466cdcc..f803527e5819407f8e2d47c9caf72abc05ceb9c0 100644 (file)
@@ -166,10 +166,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
        return mc13xxx_common_init(&spi->dev);
 }
 
-static int mc13xxx_spi_remove(struct spi_device *spi)
+static void mc13xxx_spi_remove(struct spi_device *spi)
 {
        mc13xxx_common_exit(&spi->dev);
-       return 0;
 }
 
 static struct spi_driver mc13xxx_spi_driver = {
index fec2b4ec477c5c676e6244cbcb1ec335d1f597ef..d2f3d8f1e05af054892190e5cbf081836497ea13 100644 (file)
@@ -220,13 +220,11 @@ static int rsmu_spi_probe(struct spi_device *client)
        return rsmu_core_init(rsmu);
 }
 
-static int rsmu_spi_remove(struct spi_device *client)
+static void rsmu_spi_remove(struct spi_device *client)
 {
        struct rsmu_ddata *rsmu = spi_get_drvdata(client);
 
        rsmu_core_exit(rsmu);
-
-       return 0;
 }
 
 static const struct spi_device_id rsmu_spi_id[] = {
index 6c5915016be500002bfc95fc2d8efd0168d2bb97..ad8055a0e28692b6de70c96211e55e46924a4c2c 100644 (file)
@@ -102,13 +102,11 @@ stmpe_spi_probe(struct spi_device *spi)
        return stmpe_probe(&spi_ci, id->driver_data);
 }
 
-static int stmpe_spi_remove(struct spi_device *spi)
+static void stmpe_spi_remove(struct spi_device *spi)
 {
        struct stmpe *stmpe = spi_get_drvdata(spi);
 
        stmpe_remove(stmpe);
-
-       return 0;
 }
 
 static const struct of_device_id stmpe_spi_of_match[] = {
index d701926aa46e67826b8086f88fbb86143d97e378..bba38fbc781dfa15f1d78494b777a7614c9dd24b 100644 (file)
@@ -50,13 +50,11 @@ static int tps65912_spi_probe(struct spi_device *spi)
        return tps65912_device_init(tps);
 }
 
-static int tps65912_spi_remove(struct spi_device *spi)
+static void tps65912_spi_remove(struct spi_device *spi)
 {
        struct tps65912 *tps = spi_get_drvdata(spi);
 
        tps65912_device_exit(tps);
-
-       return 0;
 }
 
 static const struct spi_device_id tps65912_spi_id_table[] = {
index a9e75d80ad362594587f8f83872ba757bf9a654a..263055bda48b7d99c980a96881d1c422871a3802 100644 (file)
@@ -90,10 +90,9 @@ static int ad_dpot_spi_probe(struct spi_device *spi)
                             spi_get_device_id(spi)->name);
 }
 
-static int ad_dpot_spi_remove(struct spi_device *spi)
+static void ad_dpot_spi_remove(struct spi_device *spi)
 {
        ad_dpot_remove(&spi->dev);
-       return 0;
 }
 
 static const struct spi_device_id ad_dpot_spi_id[] = {
index 1f15399e5cb49199f5f4b467f8ff8ef8fb6771f8..b630625b3024ba6a95fbc0255f5f171b23265737 100644 (file)
@@ -555,14 +555,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
        return 0;
 }
 
-static int eeprom_93xx46_remove(struct spi_device *spi)
+static void eeprom_93xx46_remove(struct spi_device *spi)
 {
        struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi);
 
        if (!(edev->pdata->flags & EE_READONLY))
                device_remove_file(&spi->dev, &dev_attr_erase);
-
-       return 0;
 }
 
 static struct spi_driver eeprom_93xx46_driver = {
index 98828030b5a4d8eb32c0193ee6d0b7cc6791c58b..bac4df2e5231475df76317997366a9b12813c2e1 100644 (file)
@@ -211,13 +211,11 @@ static int lattice_ecp3_probe(struct spi_device *spi)
        return 0;
 }
 
-static int lattice_ecp3_remove(struct spi_device *spi)
+static void lattice_ecp3_remove(struct spi_device *spi)
 {
        struct fpga_data *data = spi_get_drvdata(spi);
 
        wait_for_completion(&data->fw_loaded);
-
-       return 0;
 }
 
 static const struct spi_device_id lattice_ecp3_id[] = {
index 9e40dfb607425b6c6c4242a3336d13929845a67f..203a108b8883c416f35dfc375fc92713bff7b1d9 100644 (file)
@@ -96,15 +96,13 @@ static int lis302dl_spi_probe(struct spi_device *spi)
        return lis3lv02d_init_device(&lis3_dev);
 }
 
-static int lis302dl_spi_remove(struct spi_device *spi)
+static void lis302dl_spi_remove(struct spi_device *spi)
 {
        struct lis3lv02d *lis3 = spi_get_drvdata(spi);
        lis3lv02d_joystick_disable(lis3);
        lis3lv02d_poweroff(lis3);
 
        lis3lv02d_remove_fs(&lis3_dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index a576181e9db03734efc349cfbae84e9d29af1354..106dd204b1a7f267a8538df6272c8993943e4cf5 100644 (file)
@@ -1489,7 +1489,7 @@ nomem:
 }
 
 
-static int mmc_spi_remove(struct spi_device *spi)
+static void mmc_spi_remove(struct spi_device *spi)
 {
        struct mmc_host         *mmc = dev_get_drvdata(&spi->dev);
        struct mmc_spi_host     *host = mmc_priv(mmc);
@@ -1507,7 +1507,6 @@ static int mmc_spi_remove(struct spi_device *spi)
        spi->max_speed_hz = mmc->f_max;
        mmc_spi_put_pdata(spi);
        mmc_free_host(mmc);
-       return 0;
 }
 
 static const struct spi_device_id mmc_spi_dev_ids[] = {
index a8b31bddf14b8ddb44f52c8be183d871436c4bc8..008df9d8898db00519c40452293d1438137f9d21 100644 (file)
@@ -209,13 +209,11 @@ static int mchp23k256_probe(struct spi_device *spi)
        return 0;
 }
 
-static int mchp23k256_remove(struct spi_device *spi)
+static void mchp23k256_remove(struct spi_device *spi)
 {
        struct mchp23k256_flash *flash = spi_get_drvdata(spi);
 
        WARN_ON(mtd_device_unregister(&flash->mtd));
-
-       return 0;
 }
 
 static const struct of_device_id mchp23k256_of_table[] = {
index 231a1079019607aedabd80487a80e10f9d0b3854..a3fd426df74bedde629e0e2dfeb525c4f4f293dd 100644 (file)
@@ -341,13 +341,11 @@ static int mchp48l640_probe(struct spi_device *spi)
        return 0;
 }
 
-static int mchp48l640_remove(struct spi_device *spi)
+static void mchp48l640_remove(struct spi_device *spi)
 {
        struct mchp48l640_flash *flash = spi_get_drvdata(spi);
 
        WARN_ON(mtd_device_unregister(&flash->mtd));
-
-       return 0;
 }
 
 static const struct of_device_id mchp48l640_of_table[] = {
index 734878abaa236cd98c5cb7502fb6f4a7da650ed4..134e2732859747582a173e672682761fd546a3f5 100644 (file)
@@ -916,7 +916,7 @@ static int dataflash_probe(struct spi_device *spi)
        return status;
 }
 
-static int dataflash_remove(struct spi_device *spi)
+static void dataflash_remove(struct spi_device *spi)
 {
        struct dataflash        *flash = spi_get_drvdata(spi);
 
@@ -925,8 +925,6 @@ static int dataflash_remove(struct spi_device *spi)
        WARN_ON(mtd_device_unregister(&flash->mtd));
 
        kfree(flash);
-
-       return 0;
 }
 
 static struct spi_driver dataflash_driver = {
index 7f124c1bfa4066e127ace1e78d71b914f325cf8e..8813994ce9f453d3dfae9d7a5a1b40437fd797ce 100644 (file)
@@ -398,13 +398,11 @@ static int sst25l_probe(struct spi_device *spi)
        return 0;
 }
 
-static int sst25l_remove(struct spi_device *spi)
+static void sst25l_remove(struct spi_device *spi)
 {
        struct sst25l_flash *flash = spi_get_drvdata(spi);
 
        WARN_ON(mtd_device_unregister(&flash->mtd));
-
-       return 0;
 }
 
 static struct spi_driver sst25l_driver = {
index 5c0e0ec2e6d1f1002cf3f2f421d222e73a790cf8..50f4f3484d42618bf8ad82d5c5339043f6dd28fd 100644 (file)
@@ -26,39 +26,3 @@ config SPI_NXP_SPIFI
          SPIFI is a specialized controller for connecting serial SPI
          Flash. Enable this option if you have a device with a SPIFI
          controller and want to access the Flash as a mtd device.
-
-config SPI_INTEL_SPI
-       tristate
-
-config SPI_INTEL_SPI_PCI
-       tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
-       depends on X86 && PCI
-       select SPI_INTEL_SPI
-       help
-         This enables PCI support for the Intel PCH/PCU SPI controller in
-         master mode. This controller is present in modern Intel hardware
-         and is used to hold BIOS and other persistent settings. Using
-         this driver it is possible to upgrade BIOS directly from Linux.
-
-         Say N here unless you know what you are doing. Overwriting the
-         SPI flash may render the system unbootable.
-
-         To compile this driver as a module, choose M here: the module
-         will be called intel-spi-pci.
-
-config SPI_INTEL_SPI_PLATFORM
-       tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
-       depends on X86
-       select SPI_INTEL_SPI
-       help
-         This enables platform support for the Intel PCH/PCU SPI
-         controller in master mode. This controller is present in modern
-         Intel hardware and is used to hold BIOS and other persistent
-         settings. Using this driver it is possible to upgrade BIOS
-         directly from Linux.
-
-         Say N here unless you know what you are doing. Overwriting the
-         SPI flash may render the system unbootable.
-
-         To compile this driver as a module, choose M here: the module
-         will be called intel-spi-platform.
index e7abba491d98329fbeb565e70f6ea75299102143..6e2a1dc684662aeac48c5f9cc1da722ded2a2f48 100644 (file)
@@ -2,6 +2,3 @@
 obj-$(CONFIG_SPI_ASPEED_SMC)   += aspeed-smc.o
 obj-$(CONFIG_SPI_HISI_SFC)     += hisi-sfc.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
-obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)   += intel-spi-platform.o
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
deleted file mode 100644 (file)
index 1bc53b8..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel PCH/PCU SPI flash PCI driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "intel-spi.h"
-
-#define BCR            0xdc
-#define BCR_WPD                BIT(0)
-
-static const struct intel_spi_boardinfo bxt_info = {
-       .type = INTEL_SPI_BXT,
-};
-
-static const struct intel_spi_boardinfo cnl_info = {
-       .type = INTEL_SPI_CNL,
-};
-
-static int intel_spi_pci_probe(struct pci_dev *pdev,
-                              const struct pci_device_id *id)
-{
-       struct intel_spi_boardinfo *info;
-       struct intel_spi *ispi;
-       u32 bcr;
-       int ret;
-
-       ret = pcim_enable_device(pdev);
-       if (ret)
-               return ret;
-
-       info = devm_kmemdup(&pdev->dev, (void *)id->driver_data, sizeof(*info),
-                           GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       /* Try to make the chip read/write */
-       pci_read_config_dword(pdev, BCR, &bcr);
-       if (!(bcr & BCR_WPD)) {
-               bcr |= BCR_WPD;
-               pci_write_config_dword(pdev, BCR, bcr);
-               pci_read_config_dword(pdev, BCR, &bcr);
-       }
-       info->writeable = !!(bcr & BCR_WPD);
-
-       ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
-       if (IS_ERR(ispi))
-               return PTR_ERR(ispi);
-
-       pci_set_drvdata(pdev, ispi);
-       return 0;
-}
-
-static void intel_spi_pci_remove(struct pci_dev *pdev)
-{
-       intel_spi_remove(pci_get_drvdata(pdev));
-}
-
-static const struct pci_device_id intel_spi_pci_ids[] = {
-       { PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
-       { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },
-       { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },
-       { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },
-       { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
-       { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
-       { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&bxt_info },
-       { },
-};
-MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
-
-static struct pci_driver intel_spi_pci_driver = {
-       .name = "intel-spi",
-       .id_table = intel_spi_pci_ids,
-       .probe = intel_spi_pci_probe,
-       .remove = intel_spi_pci_remove,
-};
-
-module_pci_driver(intel_spi_pci_driver);
-
-MODULE_DESCRIPTION("Intel PCH/PCU SPI flash PCI driver");
-MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c b/drivers/mtd/spi-nor/controllers/intel-spi-platform.c
deleted file mode 100644 (file)
index f80f108..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel PCH/PCU SPI flash platform driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "intel-spi.h"
-
-static int intel_spi_platform_probe(struct platform_device *pdev)
-{
-       struct intel_spi_boardinfo *info;
-       struct intel_spi *ispi;
-       struct resource *mem;
-
-       info = dev_get_platdata(&pdev->dev);
-       if (!info)
-               return -EINVAL;
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       ispi = intel_spi_probe(&pdev->dev, mem, info);
-       if (IS_ERR(ispi))
-               return PTR_ERR(ispi);
-
-       platform_set_drvdata(pdev, ispi);
-       return 0;
-}
-
-static int intel_spi_platform_remove(struct platform_device *pdev)
-{
-       struct intel_spi *ispi = platform_get_drvdata(pdev);
-
-       return intel_spi_remove(ispi);
-}
-
-static struct platform_driver intel_spi_platform_driver = {
-       .probe = intel_spi_platform_probe,
-       .remove = intel_spi_platform_remove,
-       .driver = {
-               .name = "intel-spi",
-       },
-};
-
-module_platform_driver(intel_spi_platform_driver);
-
-MODULE_DESCRIPTION("Intel PCH/PCU SPI flash platform driver");
-MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:intel-spi");
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
deleted file mode 100644 (file)
index a413892..0000000
+++ /dev/null
@@ -1,968 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel PCH/PCU SPI flash driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/spi-nor.h>
-
-#include "intel-spi.h"
-
-/* Offsets are from @ispi->base */
-#define BFPREG                         0x00
-
-#define HSFSTS_CTL                     0x04
-#define HSFSTS_CTL_FSMIE               BIT(31)
-#define HSFSTS_CTL_FDBC_SHIFT          24
-#define HSFSTS_CTL_FDBC_MASK           (0x3f << HSFSTS_CTL_FDBC_SHIFT)
-
-#define HSFSTS_CTL_FCYCLE_SHIFT                17
-#define HSFSTS_CTL_FCYCLE_MASK         (0x0f << HSFSTS_CTL_FCYCLE_SHIFT)
-/* HW sequencer opcodes */
-#define HSFSTS_CTL_FCYCLE_READ         (0x00 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_WRITE                (0x02 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_ERASE                (0x03 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_ERASE_64K    (0x04 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_RDID         (0x06 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_WRSR         (0x07 << HSFSTS_CTL_FCYCLE_SHIFT)
-#define HSFSTS_CTL_FCYCLE_RDSR         (0x08 << HSFSTS_CTL_FCYCLE_SHIFT)
-
-#define HSFSTS_CTL_FGO                 BIT(16)
-#define HSFSTS_CTL_FLOCKDN             BIT(15)
-#define HSFSTS_CTL_FDV                 BIT(14)
-#define HSFSTS_CTL_SCIP                        BIT(5)
-#define HSFSTS_CTL_AEL                 BIT(2)
-#define HSFSTS_CTL_FCERR               BIT(1)
-#define HSFSTS_CTL_FDONE               BIT(0)
-
-#define FADDR                          0x08
-#define DLOCK                          0x0c
-#define FDATA(n)                       (0x10 + ((n) * 4))
-
-#define FRACC                          0x50
-
-#define FREG(n)                                (0x54 + ((n) * 4))
-#define FREG_BASE_MASK                 0x3fff
-#define FREG_LIMIT_SHIFT               16
-#define FREG_LIMIT_MASK                        (0x03fff << FREG_LIMIT_SHIFT)
-
-/* Offset is from @ispi->pregs */
-#define PR(n)                          ((n) * 4)
-#define PR_WPE                         BIT(31)
-#define PR_LIMIT_SHIFT                 16
-#define PR_LIMIT_MASK                  (0x3fff << PR_LIMIT_SHIFT)
-#define PR_RPE                         BIT(15)
-#define PR_BASE_MASK                   0x3fff
-
-/* Offsets are from @ispi->sregs */
-#define SSFSTS_CTL                     0x00
-#define SSFSTS_CTL_FSMIE               BIT(23)
-#define SSFSTS_CTL_DS                  BIT(22)
-#define SSFSTS_CTL_DBC_SHIFT           16
-#define SSFSTS_CTL_SPOP                        BIT(11)
-#define SSFSTS_CTL_ACS                 BIT(10)
-#define SSFSTS_CTL_SCGO                        BIT(9)
-#define SSFSTS_CTL_COP_SHIFT           12
-#define SSFSTS_CTL_FRS                 BIT(7)
-#define SSFSTS_CTL_DOFRS               BIT(6)
-#define SSFSTS_CTL_AEL                 BIT(4)
-#define SSFSTS_CTL_FCERR               BIT(3)
-#define SSFSTS_CTL_FDONE               BIT(2)
-#define SSFSTS_CTL_SCIP                        BIT(0)
-
-#define PREOP_OPTYPE                   0x04
-#define OPMENU0                                0x08
-#define OPMENU1                                0x0c
-
-#define OPTYPE_READ_NO_ADDR            0
-#define OPTYPE_WRITE_NO_ADDR           1
-#define OPTYPE_READ_WITH_ADDR          2
-#define OPTYPE_WRITE_WITH_ADDR         3
-
-/* CPU specifics */
-#define BYT_PR                         0x74
-#define BYT_SSFSTS_CTL                 0x90
-#define BYT_BCR                                0xfc
-#define BYT_BCR_WPD                    BIT(0)
-#define BYT_FREG_NUM                   5
-#define BYT_PR_NUM                     5
-
-#define LPT_PR                         0x74
-#define LPT_SSFSTS_CTL                 0x90
-#define LPT_FREG_NUM                   5
-#define LPT_PR_NUM                     5
-
-#define BXT_PR                         0x84
-#define BXT_SSFSTS_CTL                 0xa0
-#define BXT_FREG_NUM                   12
-#define BXT_PR_NUM                     6
-
-#define CNL_PR                         0x84
-#define CNL_FREG_NUM                   6
-#define CNL_PR_NUM                     5
-
-#define LVSCC                          0xc4
-#define UVSCC                          0xc8
-#define ERASE_OPCODE_SHIFT             8
-#define ERASE_OPCODE_MASK              (0xff << ERASE_OPCODE_SHIFT)
-#define ERASE_64K_OPCODE_SHIFT         16
-#define ERASE_64K_OPCODE_MASK          (0xff << ERASE_OPCODE_SHIFT)
-
-#define INTEL_SPI_TIMEOUT              5000 /* ms */
-#define INTEL_SPI_FIFO_SZ              64
-
-/**
- * struct intel_spi - Driver private data
- * @dev: Device pointer
- * @info: Pointer to board specific info
- * @nor: SPI NOR layer structure
- * @base: Beginning of MMIO space
- * @pregs: Start of protection registers
- * @sregs: Start of software sequencer registers
- * @nregions: Maximum number of regions
- * @pr_num: Maximum number of protected range registers
- * @writeable: Is the chip writeable
- * @locked: Is SPI setting locked
- * @swseq_reg: Use SW sequencer in register reads/writes
- * @swseq_erase: Use SW sequencer in erase operation
- * @erase_64k: 64k erase supported
- * @atomic_preopcode: Holds preopcode when atomic sequence is requested
- * @opcodes: Opcodes which are supported. This are programmed by BIOS
- *           before it locks down the controller.
- */
-struct intel_spi {
-       struct device *dev;
-       const struct intel_spi_boardinfo *info;
-       struct spi_nor nor;
-       void __iomem *base;
-       void __iomem *pregs;
-       void __iomem *sregs;
-       size_t nregions;
-       size_t pr_num;
-       bool writeable;
-       bool locked;
-       bool swseq_reg;
-       bool swseq_erase;
-       bool erase_64k;
-       u8 atomic_preopcode;
-       u8 opcodes[8];
-};
-
-static bool writeable;
-module_param(writeable, bool, 0);
-MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
-
-static void intel_spi_dump_regs(struct intel_spi *ispi)
-{
-       u32 value;
-       int i;
-
-       dev_dbg(ispi->dev, "BFPREG=0x%08x\n", readl(ispi->base + BFPREG));
-
-       value = readl(ispi->base + HSFSTS_CTL);
-       dev_dbg(ispi->dev, "HSFSTS_CTL=0x%08x\n", value);
-       if (value & HSFSTS_CTL_FLOCKDN)
-               dev_dbg(ispi->dev, "-> Locked\n");
-
-       dev_dbg(ispi->dev, "FADDR=0x%08x\n", readl(ispi->base + FADDR));
-       dev_dbg(ispi->dev, "DLOCK=0x%08x\n", readl(ispi->base + DLOCK));
-
-       for (i = 0; i < 16; i++)
-               dev_dbg(ispi->dev, "FDATA(%d)=0x%08x\n",
-                       i, readl(ispi->base + FDATA(i)));
-
-       dev_dbg(ispi->dev, "FRACC=0x%08x\n", readl(ispi->base + FRACC));
-
-       for (i = 0; i < ispi->nregions; i++)
-               dev_dbg(ispi->dev, "FREG(%d)=0x%08x\n", i,
-                       readl(ispi->base + FREG(i)));
-       for (i = 0; i < ispi->pr_num; i++)
-               dev_dbg(ispi->dev, "PR(%d)=0x%08x\n", i,
-                       readl(ispi->pregs + PR(i)));
-
-       if (ispi->sregs) {
-               value = readl(ispi->sregs + SSFSTS_CTL);
-               dev_dbg(ispi->dev, "SSFSTS_CTL=0x%08x\n", value);
-               dev_dbg(ispi->dev, "PREOP_OPTYPE=0x%08x\n",
-                       readl(ispi->sregs + PREOP_OPTYPE));
-               dev_dbg(ispi->dev, "OPMENU0=0x%08x\n",
-                       readl(ispi->sregs + OPMENU0));
-               dev_dbg(ispi->dev, "OPMENU1=0x%08x\n",
-                       readl(ispi->sregs + OPMENU1));
-       }
-
-       if (ispi->info->type == INTEL_SPI_BYT)
-               dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
-
-       dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
-       dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
-
-       dev_dbg(ispi->dev, "Protected regions:\n");
-       for (i = 0; i < ispi->pr_num; i++) {
-               u32 base, limit;
-
-               value = readl(ispi->pregs + PR(i));
-               if (!(value & (PR_WPE | PR_RPE)))
-                       continue;
-
-               limit = (value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
-               base = value & PR_BASE_MASK;
-
-               dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n",
-                        i, base << 12, (limit << 12) | 0xfff,
-                        value & PR_WPE ? 'W' : '.',
-                        value & PR_RPE ? 'R' : '.');
-       }
-
-       dev_dbg(ispi->dev, "Flash regions:\n");
-       for (i = 0; i < ispi->nregions; i++) {
-               u32 region, base, limit;
-
-               region = readl(ispi->base + FREG(i));
-               base = region & FREG_BASE_MASK;
-               limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
-
-               if (base >= limit || (i > 0 && limit == 0))
-                       dev_dbg(ispi->dev, " %02d disabled\n", i);
-               else
-                       dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n",
-                                i, base << 12, (limit << 12) | 0xfff);
-       }
-
-       dev_dbg(ispi->dev, "Using %cW sequencer for register access\n",
-               ispi->swseq_reg ? 'S' : 'H');
-       dev_dbg(ispi->dev, "Using %cW sequencer for erase operation\n",
-               ispi->swseq_erase ? 'S' : 'H');
-}
-
-/* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */
-static int intel_spi_read_block(struct intel_spi *ispi, void *buf, size_t size)
-{
-       size_t bytes;
-       int i = 0;
-
-       if (size > INTEL_SPI_FIFO_SZ)
-               return -EINVAL;
-
-       while (size > 0) {
-               bytes = min_t(size_t, size, 4);
-               memcpy_fromio(buf, ispi->base + FDATA(i), bytes);
-               size -= bytes;
-               buf += bytes;
-               i++;
-       }
-
-       return 0;
-}
-
-/* Writes max INTEL_SPI_FIFO_SZ bytes to the device fifo */
-static int intel_spi_write_block(struct intel_spi *ispi, const void *buf,
-                                size_t size)
-{
-       size_t bytes;
-       int i = 0;
-
-       if (size > INTEL_SPI_FIFO_SZ)
-               return -EINVAL;
-
-       while (size > 0) {
-               bytes = min_t(size_t, size, 4);
-               memcpy_toio(ispi->base + FDATA(i), buf, bytes);
-               size -= bytes;
-               buf += bytes;
-               i++;
-       }
-
-       return 0;
-}
-
-static int intel_spi_wait_hw_busy(struct intel_spi *ispi)
-{
-       u32 val;
-
-       return readl_poll_timeout(ispi->base + HSFSTS_CTL, val,
-                                 !(val & HSFSTS_CTL_SCIP), 0,
-                                 INTEL_SPI_TIMEOUT * 1000);
-}
-
-static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
-{
-       u32 val;
-
-       return readl_poll_timeout(ispi->sregs + SSFSTS_CTL, val,
-                                 !(val & SSFSTS_CTL_SCIP), 0,
-                                 INTEL_SPI_TIMEOUT * 1000);
-}
-
-static int intel_spi_init(struct intel_spi *ispi)
-{
-       u32 opmenu0, opmenu1, lvscc, uvscc, val;
-       int i;
-
-       switch (ispi->info->type) {
-       case INTEL_SPI_BYT:
-               ispi->sregs = ispi->base + BYT_SSFSTS_CTL;
-               ispi->pregs = ispi->base + BYT_PR;
-               ispi->nregions = BYT_FREG_NUM;
-               ispi->pr_num = BYT_PR_NUM;
-               ispi->swseq_reg = true;
-
-               if (writeable) {
-                       /* Disable write protection */
-                       val = readl(ispi->base + BYT_BCR);
-                       if (!(val & BYT_BCR_WPD)) {
-                               val |= BYT_BCR_WPD;
-                               writel(val, ispi->base + BYT_BCR);
-                               val = readl(ispi->base + BYT_BCR);
-                       }
-
-                       ispi->writeable = !!(val & BYT_BCR_WPD);
-               }
-
-               break;
-
-       case INTEL_SPI_LPT:
-               ispi->sregs = ispi->base + LPT_SSFSTS_CTL;
-               ispi->pregs = ispi->base + LPT_PR;
-               ispi->nregions = LPT_FREG_NUM;
-               ispi->pr_num = LPT_PR_NUM;
-               ispi->swseq_reg = true;
-               break;
-
-       case INTEL_SPI_BXT:
-               ispi->sregs = ispi->base + BXT_SSFSTS_CTL;
-               ispi->pregs = ispi->base + BXT_PR;
-               ispi->nregions = BXT_FREG_NUM;
-               ispi->pr_num = BXT_PR_NUM;
-               ispi->erase_64k = true;
-               break;
-
-       case INTEL_SPI_CNL:
-               ispi->sregs = NULL;
-               ispi->pregs = ispi->base + CNL_PR;
-               ispi->nregions = CNL_FREG_NUM;
-               ispi->pr_num = CNL_PR_NUM;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* Disable #SMI generation from HW sequencer */
-       val = readl(ispi->base + HSFSTS_CTL);
-       val &= ~HSFSTS_CTL_FSMIE;
-       writel(val, ispi->base + HSFSTS_CTL);
-
-       /*
-        * Determine whether erase operation should use HW or SW sequencer.
-        *
-        * The HW sequencer has a predefined list of opcodes, with only the
-        * erase opcode being programmable in LVSCC and UVSCC registers.
-        * If these registers don't contain a valid erase opcode, erase
-        * cannot be done using HW sequencer.
-        */
-       lvscc = readl(ispi->base + LVSCC);
-       uvscc = readl(ispi->base + UVSCC);
-       if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK))
-               ispi->swseq_erase = true;
-       /* SPI controller on Intel BXT supports 64K erase opcode */
-       if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase)
-               if (!(lvscc & ERASE_64K_OPCODE_MASK) ||
-                   !(uvscc & ERASE_64K_OPCODE_MASK))
-                       ispi->erase_64k = false;
-
-       if (ispi->sregs == NULL && (ispi->swseq_reg || ispi->swseq_erase)) {
-               dev_err(ispi->dev, "software sequencer not supported, but required\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Some controllers can only do basic operations using hardware
-        * sequencer. All other operations are supposed to be carried out
-        * using software sequencer.
-        */
-       if (ispi->swseq_reg) {
-               /* Disable #SMI generation from SW sequencer */
-               val = readl(ispi->sregs + SSFSTS_CTL);
-               val &= ~SSFSTS_CTL_FSMIE;
-               writel(val, ispi->sregs + SSFSTS_CTL);
-       }
-
-       /* Check controller's lock status */
-       val = readl(ispi->base + HSFSTS_CTL);
-       ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN);
-
-       if (ispi->locked && ispi->sregs) {
-               /*
-                * BIOS programs allowed opcodes and then locks down the
-                * register. So read back what opcodes it decided to support.
-                * That's the set we are going to support as well.
-                */
-               opmenu0 = readl(ispi->sregs + OPMENU0);
-               opmenu1 = readl(ispi->sregs + OPMENU1);
-
-               if (opmenu0 && opmenu1) {
-                       for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) {
-                               ispi->opcodes[i] = opmenu0 >> i * 8;
-                               ispi->opcodes[i + 4] = opmenu1 >> i * 8;
-                       }
-               }
-       }
-
-       intel_spi_dump_regs(ispi);
-
-       return 0;
-}
-
-static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype)
-{
-       int i;
-       int preop;
-
-       if (ispi->locked) {
-               for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++)
-                       if (ispi->opcodes[i] == opcode)
-                               return i;
-
-               return -EINVAL;
-       }
-
-       /* The lock is off, so just use index 0 */
-       writel(opcode, ispi->sregs + OPMENU0);
-       preop = readw(ispi->sregs + PREOP_OPTYPE);
-       writel(optype << 16 | preop, ispi->sregs + PREOP_OPTYPE);
-
-       return 0;
-}
-
-static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, size_t len)
-{
-       u32 val, status;
-       int ret;
-
-       val = readl(ispi->base + HSFSTS_CTL);
-       val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK);
-
-       switch (opcode) {
-       case SPINOR_OP_RDID:
-               val |= HSFSTS_CTL_FCYCLE_RDID;
-               break;
-       case SPINOR_OP_WRSR:
-               val |= HSFSTS_CTL_FCYCLE_WRSR;
-               break;
-       case SPINOR_OP_RDSR:
-               val |= HSFSTS_CTL_FCYCLE_RDSR;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (len > INTEL_SPI_FIFO_SZ)
-               return -EINVAL;
-
-       val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT;
-       val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-       val |= HSFSTS_CTL_FGO;
-       writel(val, ispi->base + HSFSTS_CTL);
-
-       ret = intel_spi_wait_hw_busy(ispi);
-       if (ret)
-               return ret;
-
-       status = readl(ispi->base + HSFSTS_CTL);
-       if (status & HSFSTS_CTL_FCERR)
-               return -EIO;
-       else if (status & HSFSTS_CTL_AEL)
-               return -EACCES;
-
-       return 0;
-}
-
-static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
-                             int optype)
-{
-       u32 val = 0, status;
-       u8 atomic_preopcode;
-       int ret;
-
-       ret = intel_spi_opcode_index(ispi, opcode, optype);
-       if (ret < 0)
-               return ret;
-
-       if (len > INTEL_SPI_FIFO_SZ)
-               return -EINVAL;
-
-       /*
-        * Always clear it after each SW sequencer operation regardless
-        * of whether it is successful or not.
-        */
-       atomic_preopcode = ispi->atomic_preopcode;
-       ispi->atomic_preopcode = 0;
-
-       /* Only mark 'Data Cycle' bit when there is data to be transferred */
-       if (len > 0)
-               val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS;
-       val |= ret << SSFSTS_CTL_COP_SHIFT;
-       val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE;
-       val |= SSFSTS_CTL_SCGO;
-       if (atomic_preopcode) {
-               u16 preop;
-
-               switch (optype) {
-               case OPTYPE_WRITE_NO_ADDR:
-               case OPTYPE_WRITE_WITH_ADDR:
-                       /* Pick matching preopcode for the atomic sequence */
-                       preop = readw(ispi->sregs + PREOP_OPTYPE);
-                       if ((preop & 0xff) == atomic_preopcode)
-                               ; /* Do nothing */
-                       else if ((preop >> 8) == atomic_preopcode)
-                               val |= SSFSTS_CTL_SPOP;
-                       else
-                               return -EINVAL;
-
-                       /* Enable atomic sequence */
-                       val |= SSFSTS_CTL_ACS;
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-
-       }
-       writel(val, ispi->sregs + SSFSTS_CTL);
-
-       ret = intel_spi_wait_sw_busy(ispi);
-       if (ret)
-               return ret;
-
-       status = readl(ispi->sregs + SSFSTS_CTL);
-       if (status & SSFSTS_CTL_FCERR)
-               return -EIO;
-       else if (status & SSFSTS_CTL_AEL)
-               return -EACCES;
-
-       return 0;
-}
-
-static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
-                             size_t len)
-{
-       struct intel_spi *ispi = nor->priv;
-       int ret;
-
-       /* Address of the first chip */
-       writel(0, ispi->base + FADDR);
-
-       if (ispi->swseq_reg)
-               ret = intel_spi_sw_cycle(ispi, opcode, len,
-                                        OPTYPE_READ_NO_ADDR);
-       else
-               ret = intel_spi_hw_cycle(ispi, opcode, len);
-
-       if (ret)
-               return ret;
-
-       return intel_spi_read_block(ispi, buf, len);
-}
-
-static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
-                              size_t len)
-{
-       struct intel_spi *ispi = nor->priv;
-       int ret;
-
-       /*
-        * This is handled with atomic operation and preop code in Intel
-        * controller so we only verify that it is available. If the
-        * controller is not locked, program the opcode to the PREOP
-        * register for later use.
-        *
-        * When hardware sequencer is used there is no need to program
-        * any opcodes (it handles them automatically as part of a command).
-        */
-       if (opcode == SPINOR_OP_WREN) {
-               u16 preop;
-
-               if (!ispi->swseq_reg)
-                       return 0;
-
-               preop = readw(ispi->sregs + PREOP_OPTYPE);
-               if ((preop & 0xff) != opcode && (preop >> 8) != opcode) {
-                       if (ispi->locked)
-                               return -EINVAL;
-                       writel(opcode, ispi->sregs + PREOP_OPTYPE);
-               }
-
-               /*
-                * This enables atomic sequence on next SW sycle. Will
-                * be cleared after next operation.
-                */
-               ispi->atomic_preopcode = opcode;
-               return 0;
-       }
-
-       /*
-        * We hope that HW sequencer will do the right thing automatically and
-        * with the SW sequencer we cannot use preopcode anyway, so just ignore
-        * the Write Disable operation and pretend it was completed
-        * successfully.
-        */
-       if (opcode == SPINOR_OP_WRDI)
-               return 0;
-
-       writel(0, ispi->base + FADDR);
-
-       /* Write the value beforehand */
-       ret = intel_spi_write_block(ispi, buf, len);
-       if (ret)
-               return ret;
-
-       if (ispi->swseq_reg)
-               return intel_spi_sw_cycle(ispi, opcode, len,
-                                         OPTYPE_WRITE_NO_ADDR);
-       return intel_spi_hw_cycle(ispi, opcode, len);
-}
-
-static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
-                             u_char *read_buf)
-{
-       struct intel_spi *ispi = nor->priv;
-       size_t block_size, retlen = 0;
-       u32 val, status;
-       ssize_t ret;
-
-       /*
-        * Atomic sequence is not expected with HW sequencer reads. Make
-        * sure it is cleared regardless.
-        */
-       if (WARN_ON_ONCE(ispi->atomic_preopcode))
-               ispi->atomic_preopcode = 0;
-
-       switch (nor->read_opcode) {
-       case SPINOR_OP_READ:
-       case SPINOR_OP_READ_FAST:
-       case SPINOR_OP_READ_4B:
-       case SPINOR_OP_READ_FAST_4B:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       while (len > 0) {
-               block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
-
-               /* Read cannot cross 4K boundary */
-               block_size = min_t(loff_t, from + block_size,
-                                  round_up(from + 1, SZ_4K)) - from;
-
-               writel(from, ispi->base + FADDR);
-
-               val = readl(ispi->base + HSFSTS_CTL);
-               val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
-               val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-               val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
-               val |= HSFSTS_CTL_FCYCLE_READ;
-               val |= HSFSTS_CTL_FGO;
-               writel(val, ispi->base + HSFSTS_CTL);
-
-               ret = intel_spi_wait_hw_busy(ispi);
-               if (ret)
-                       return ret;
-
-               status = readl(ispi->base + HSFSTS_CTL);
-               if (status & HSFSTS_CTL_FCERR)
-                       ret = -EIO;
-               else if (status & HSFSTS_CTL_AEL)
-                       ret = -EACCES;
-
-               if (ret < 0) {
-                       dev_err(ispi->dev, "read error: %llx: %#x\n", from,
-                               status);
-                       return ret;
-               }
-
-               ret = intel_spi_read_block(ispi, read_buf, block_size);
-               if (ret)
-                       return ret;
-
-               len -= block_size;
-               from += block_size;
-               retlen += block_size;
-               read_buf += block_size;
-       }
-
-       return retlen;
-}
-
-static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
-                              const u_char *write_buf)
-{
-       struct intel_spi *ispi = nor->priv;
-       size_t block_size, retlen = 0;
-       u32 val, status;
-       ssize_t ret;
-
-       /* Not needed with HW sequencer write, make sure it is cleared */
-       ispi->atomic_preopcode = 0;
-
-       while (len > 0) {
-               block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
-
-               /* Write cannot cross 4K boundary */
-               block_size = min_t(loff_t, to + block_size,
-                                  round_up(to + 1, SZ_4K)) - to;
-
-               writel(to, ispi->base + FADDR);
-
-               val = readl(ispi->base + HSFSTS_CTL);
-               val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
-               val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-               val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
-               val |= HSFSTS_CTL_FCYCLE_WRITE;
-
-               ret = intel_spi_write_block(ispi, write_buf, block_size);
-               if (ret) {
-                       dev_err(ispi->dev, "failed to write block\n");
-                       return ret;
-               }
-
-               /* Start the write now */
-               val |= HSFSTS_CTL_FGO;
-               writel(val, ispi->base + HSFSTS_CTL);
-
-               ret = intel_spi_wait_hw_busy(ispi);
-               if (ret) {
-                       dev_err(ispi->dev, "timeout\n");
-                       return ret;
-               }
-
-               status = readl(ispi->base + HSFSTS_CTL);
-               if (status & HSFSTS_CTL_FCERR)
-                       ret = -EIO;
-               else if (status & HSFSTS_CTL_AEL)
-                       ret = -EACCES;
-
-               if (ret < 0) {
-                       dev_err(ispi->dev, "write error: %llx: %#x\n", to,
-                               status);
-                       return ret;
-               }
-
-               len -= block_size;
-               to += block_size;
-               retlen += block_size;
-               write_buf += block_size;
-       }
-
-       return retlen;
-}
-
-static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
-{
-       size_t erase_size, len = nor->mtd.erasesize;
-       struct intel_spi *ispi = nor->priv;
-       u32 val, status, cmd;
-       int ret;
-
-       /* If the hardware can do 64k erase use that when possible */
-       if (len >= SZ_64K && ispi->erase_64k) {
-               cmd = HSFSTS_CTL_FCYCLE_ERASE_64K;
-               erase_size = SZ_64K;
-       } else {
-               cmd = HSFSTS_CTL_FCYCLE_ERASE;
-               erase_size = SZ_4K;
-       }
-
-       if (ispi->swseq_erase) {
-               while (len > 0) {
-                       writel(offs, ispi->base + FADDR);
-
-                       ret = intel_spi_sw_cycle(ispi, nor->erase_opcode,
-                                                0, OPTYPE_WRITE_WITH_ADDR);
-                       if (ret)
-                               return ret;
-
-                       offs += erase_size;
-                       len -= erase_size;
-               }
-
-               return 0;
-       }
-
-       /* Not needed with HW sequencer erase, make sure it is cleared */
-       ispi->atomic_preopcode = 0;
-
-       while (len > 0) {
-               writel(offs, ispi->base + FADDR);
-
-               val = readl(ispi->base + HSFSTS_CTL);
-               val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
-               val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-               val |= cmd;
-               val |= HSFSTS_CTL_FGO;
-               writel(val, ispi->base + HSFSTS_CTL);
-
-               ret = intel_spi_wait_hw_busy(ispi);
-               if (ret)
-                       return ret;
-
-               status = readl(ispi->base + HSFSTS_CTL);
-               if (status & HSFSTS_CTL_FCERR)
-                       return -EIO;
-               else if (status & HSFSTS_CTL_AEL)
-                       return -EACCES;
-
-               offs += erase_size;
-               len -= erase_size;
-       }
-
-       return 0;
-}
-
-static bool intel_spi_is_protected(const struct intel_spi *ispi,
-                                  unsigned int base, unsigned int limit)
-{
-       int i;
-
-       for (i = 0; i < ispi->pr_num; i++) {
-               u32 pr_base, pr_limit, pr_value;
-
-               pr_value = readl(ispi->pregs + PR(i));
-               if (!(pr_value & (PR_WPE | PR_RPE)))
-                       continue;
-
-               pr_limit = (pr_value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
-               pr_base = pr_value & PR_BASE_MASK;
-
-               if (pr_base >= base && pr_limit <= limit)
-                       return true;
-       }
-
-       return false;
-}
-
-/*
- * There will be a single partition holding all enabled flash regions. We
- * call this "BIOS".
- */
-static void intel_spi_fill_partition(struct intel_spi *ispi,
-                                    struct mtd_partition *part)
-{
-       u64 end;
-       int i;
-
-       memset(part, 0, sizeof(*part));
-
-       /* Start from the mandatory descriptor region */
-       part->size = 4096;
-       part->name = "BIOS";
-
-       /*
-        * Now try to find where this partition ends based on the flash
-        * region registers.
-        */
-       for (i = 1; i < ispi->nregions; i++) {
-               u32 region, base, limit;
-
-               region = readl(ispi->base + FREG(i));
-               base = region & FREG_BASE_MASK;
-               limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
-
-               if (base >= limit || limit == 0)
-                       continue;
-
-               /*
-                * If any of the regions have protection bits set, make the
-                * whole partition read-only to be on the safe side.
-                */
-               if (intel_spi_is_protected(ispi, base, limit))
-                       ispi->writeable = false;
-
-               end = (limit << 12) + 4096;
-               if (end > part->size)
-                       part->size = end;
-       }
-}
-
-static const struct spi_nor_controller_ops intel_spi_controller_ops = {
-       .read_reg = intel_spi_read_reg,
-       .write_reg = intel_spi_write_reg,
-       .read = intel_spi_read,
-       .write = intel_spi_write,
-       .erase = intel_spi_erase,
-};
-
-struct intel_spi *intel_spi_probe(struct device *dev,
-       struct resource *mem, const struct intel_spi_boardinfo *info)
-{
-       const struct spi_nor_hwcaps hwcaps = {
-               .mask = SNOR_HWCAPS_READ |
-                       SNOR_HWCAPS_READ_FAST |
-                       SNOR_HWCAPS_PP,
-       };
-       struct mtd_partition part;
-       struct intel_spi *ispi;
-       int ret;
-
-       if (!info || !mem)
-               return ERR_PTR(-EINVAL);
-
-       ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL);
-       if (!ispi)
-               return ERR_PTR(-ENOMEM);
-
-       ispi->base = devm_ioremap_resource(dev, mem);
-       if (IS_ERR(ispi->base))
-               return ERR_CAST(ispi->base);
-
-       ispi->dev = dev;
-       ispi->info = info;
-       ispi->writeable = info->writeable;
-
-       ret = intel_spi_init(ispi);
-       if (ret)
-               return ERR_PTR(ret);
-
-       ispi->nor.dev = ispi->dev;
-       ispi->nor.priv = ispi;
-       ispi->nor.controller_ops = &intel_spi_controller_ops;
-
-       ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps);
-       if (ret) {
-               dev_info(dev, "failed to locate the chip\n");
-               return ERR_PTR(ret);
-       }
-
-       intel_spi_fill_partition(ispi, &part);
-
-       /* Prevent writes if not explicitly enabled */
-       if (!ispi->writeable || !writeable)
-               ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
-
-       ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return ispi;
-}
-EXPORT_SYMBOL_GPL(intel_spi_probe);
-
-int intel_spi_remove(struct intel_spi *ispi)
-{
-       return mtd_device_unregister(&ispi->nor.mtd);
-}
-EXPORT_SYMBOL_GPL(intel_spi_remove);
-
-MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");
-MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h
deleted file mode 100644 (file)
index f287117..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel PCH/PCU SPI flash driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#ifndef INTEL_SPI_H
-#define INTEL_SPI_H
-
-#include <linux/platform_data/x86/intel-spi.h>
-
-struct intel_spi;
-struct resource;
-
-struct intel_spi *intel_spi_probe(struct device *dev,
-       struct resource *mem, const struct intel_spi_boardinfo *info);
-int intel_spi_remove(struct intel_spi *ispi);
-
-#endif /* INTEL_SPI_H */
index 04687b15b250ec9978df2464fb502f617ac6c11d..41645a24384ce5226aea5f14119a93bfa798cd4a 100644 (file)
@@ -388,7 +388,7 @@ out_power:
        return ret;
 }
 
-static int tcan4x5x_can_remove(struct spi_device *spi)
+static void tcan4x5x_can_remove(struct spi_device *spi)
 {
        struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
 
@@ -397,8 +397,6 @@ static int tcan4x5x_can_remove(struct spi_device *spi)
        tcan4x5x_power_enable(priv->power, 0);
 
        m_can_class_free_dev(priv->cdev.net);
-
-       return 0;
 }
 
 static const struct of_device_id tcan4x5x_of_match[] = {
index cfcc14fe3e42d0cdedc84f979d642a3c8871f25d..664b8f14d7b05cf356b429a0cb3356cca2aec04a 100644 (file)
@@ -948,7 +948,7 @@ static int hi3110_can_probe(struct spi_device *spi)
        return dev_err_probe(dev, ret, "Probe failed\n");
 }
 
-static int hi3110_can_remove(struct spi_device *spi)
+static void hi3110_can_remove(struct spi_device *spi)
 {
        struct hi3110_priv *priv = spi_get_drvdata(spi);
        struct net_device *net = priv->net;
@@ -960,8 +960,6 @@ static int hi3110_can_remove(struct spi_device *spi)
        clk_disable_unprepare(priv->clk);
 
        free_candev(net);
-
-       return 0;
 }
 
 static int __maybe_unused hi3110_can_suspend(struct device *dev)
index 025e07cb74397ce1e2b98ed378b2831675ab2214..d23edaf2242046d1575747c978f79a7d14d5c895 100644 (file)
@@ -1427,7 +1427,7 @@ out_free:
        return ret;
 }
 
-static int mcp251x_can_remove(struct spi_device *spi)
+static void mcp251x_can_remove(struct spi_device *spi)
 {
        struct mcp251x_priv *priv = spi_get_drvdata(spi);
        struct net_device *net = priv->net;
@@ -1442,8 +1442,6 @@ static int mcp251x_can_remove(struct spi_device *spi)
        clk_disable_unprepare(priv->clk);
 
        free_candev(net);
-
-       return 0;
 }
 
 static int __maybe_unused mcp251x_can_suspend(struct device *dev)
index b5986df6eca0b3d280cec2ed305dc3d76db23b53..65c9b31666a6a5ae16a93cad9e397f9016b6a07c 100644 (file)
@@ -1966,7 +1966,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
        return err;
 }
 
-static int mcp251xfd_remove(struct spi_device *spi)
+static void mcp251xfd_remove(struct spi_device *spi)
 {
        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
        struct net_device *ndev = priv->ndev;
@@ -1975,8 +1975,6 @@ static int mcp251xfd_remove(struct spi_device *spi)
        mcp251xfd_unregister(priv);
        spi->max_speed_hz = priv->spi_max_speed_hz_orig;
        free_candev(ndev);
-
-       return 0;
 }
 
 static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device)
index 2b88f03e5252182251a47e056221f60802311543..0e54b2a0c21189794d313f741ada5a0f3ca6dec1 100644 (file)
@@ -314,7 +314,7 @@ static int b53_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int b53_spi_remove(struct spi_device *spi)
+static void b53_spi_remove(struct spi_device *spi)
 {
        struct b53_device *dev = spi_get_drvdata(spi);
 
@@ -322,8 +322,6 @@ static int b53_spi_remove(struct spi_device *spi)
                b53_switch_remove(dev);
 
        spi_set_drvdata(spi, NULL);
-
-       return 0;
 }
 
 static void b53_spi_shutdown(struct spi_device *spi)
index b0a7dee27ffc983f7df7f2aea6fcc9e67c8ceccf..5f8d94aee774c82571efc9387fed2e9798de1c0f 100644 (file)
@@ -87,7 +87,7 @@ static int ksz8795_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ksz8795_spi_remove(struct spi_device *spi)
+static void ksz8795_spi_remove(struct spi_device *spi)
 {
        struct ksz_device *dev = spi_get_drvdata(spi);
 
@@ -95,8 +95,6 @@ static int ksz8795_spi_remove(struct spi_device *spi)
                ksz_switch_remove(dev);
 
        spi_set_drvdata(spi, NULL);
-
-       return 0;
 }
 
 static void ksz8795_spi_shutdown(struct spi_device *spi)
index 43addeabfc25911c93c05ae6c667430dc55ab37a..87ca464dad323334eba49e7943860d9e295bb028 100644 (file)
@@ -65,7 +65,7 @@ static int ksz9477_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ksz9477_spi_remove(struct spi_device *spi)
+static void ksz9477_spi_remove(struct spi_device *spi)
 {
        struct ksz_device *dev = spi_get_drvdata(spi);
 
@@ -73,8 +73,6 @@ static int ksz9477_spi_remove(struct spi_device *spi)
                ksz_switch_remove(dev);
 
        spi_set_drvdata(spi, NULL);
-
-       return 0;
 }
 
 static void ksz9477_spi_shutdown(struct spi_device *spi)
index b513713be61015f208bd5ffa65fb393ed10e8444..c2a47c6693b80c5666e903277373dc757d7459b5 100644 (file)
@@ -3346,18 +3346,16 @@ static int sja1105_probe(struct spi_device *spi)
        return dsa_register_switch(priv->ds);
 }
 
-static int sja1105_remove(struct spi_device *spi)
+static void sja1105_remove(struct spi_device *spi)
 {
        struct sja1105_private *priv = spi_get_drvdata(spi);
 
        if (!priv)
-               return 0;
+               return;
 
        dsa_unregister_switch(priv->ds);
 
        spi_set_drvdata(spi, NULL);
-
-       return 0;
 }
 
 static void sja1105_shutdown(struct spi_device *spi)
index 645398901e05e928361e9a31bb80a8db9c050887..3110895358d8dcc31715228acbe42e183c37c4fd 100644 (file)
@@ -159,18 +159,16 @@ static int vsc73xx_spi_probe(struct spi_device *spi)
        return vsc73xx_probe(&vsc_spi->vsc);
 }
 
-static int vsc73xx_spi_remove(struct spi_device *spi)
+static void vsc73xx_spi_remove(struct spi_device *spi)
 {
        struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi);
 
        if (!vsc_spi)
-               return 0;
+               return;
 
        vsc73xx_remove(&vsc_spi->vsc);
 
        spi_set_drvdata(spi, NULL);
-
-       return 0;
 }
 
 static void vsc73xx_spi_shutdown(struct spi_device *spi)
index e7a9f9863258749d6df5d081805758792b07befe..bf70481bb1cadc722362dd506bec93ed754dd101 100644 (file)
@@ -1102,7 +1102,7 @@ err:
        return ret;
 }
 
-static int ax88796c_remove(struct spi_device *spi)
+static void ax88796c_remove(struct spi_device *spi)
 {
        struct ax88796c_device *ax_local = dev_get_drvdata(&spi->dev);
        struct net_device *ndev = ax_local->ndev;
@@ -1112,8 +1112,6 @@ static int ax88796c_remove(struct spi_device *spi)
        netif_info(ax_local, probe, ndev, "removing network device %s %s\n",
                   dev_driver_string(&spi->dev),
                   dev_name(&spi->dev));
-
-       return 0;
 }
 
 #ifdef CONFIG_OF
index 0303e727e99f9650f6d1f4afbce4d73e3ad6cf9e..d167d93e4c12fa28e3f9377f309c7a0384913548 100644 (file)
@@ -452,11 +452,9 @@ static int ks8851_probe_spi(struct spi_device *spi)
        return ks8851_probe_common(netdev, dev, msg_enable);
 }
 
-static int ks8851_remove_spi(struct spi_device *spi)
+static void ks8851_remove_spi(struct spi_device *spi)
 {
        ks8851_remove_common(&spi->dev);
-
-       return 0;
 }
 
 static const struct of_device_id ks8851_match_table[] = {
index 634ac7649c43e11b3a44a0a70fd2f03287571321..db5a3edb4c3c0cdf21d3c1acd51366a73695cc82 100644 (file)
@@ -1612,15 +1612,13 @@ error_alloc:
        return ret;
 }
 
-static int enc28j60_remove(struct spi_device *spi)
+static void enc28j60_remove(struct spi_device *spi)
 {
        struct enc28j60_net *priv = spi_get_drvdata(spi);
 
        unregister_netdev(priv->netdev);
        free_irq(spi->irq, priv);
        free_netdev(priv->netdev);
-
-       return 0;
 }
 
 static const struct of_device_id enc28j60_dt_ids[] = {
index b90efc80fb59fa6f6b1e3b1a193d666976fd6e98..dc1840cb5b10fe12b05980b6dcbc94eecafc9b3d 100644 (file)
@@ -1093,7 +1093,7 @@ error_out:
        return ret;
 }
 
-static int encx24j600_spi_remove(struct spi_device *spi)
+static void encx24j600_spi_remove(struct spi_device *spi)
 {
        struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev);
 
@@ -1101,8 +1101,6 @@ static int encx24j600_spi_remove(struct spi_device *spi)
        kthread_stop(priv->kworker_task);
 
        free_netdev(priv->ndev);
-
-       return 0;
 }
 
 static const struct spi_device_id encx24j600_spi_id_table[] = {
index 955cce644392a93fec13ee95557b4fc10297eb64..3c5494afd3c043759cc00f078084fb2b9118996d 100644 (file)
@@ -1001,7 +1001,7 @@ qca_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int
+static void
 qca_spi_remove(struct spi_device *spi)
 {
        struct net_device *qcaspi_devs = spi_get_drvdata(spi);
@@ -1011,8 +1011,6 @@ qca_spi_remove(struct spi_device *spi)
 
        unregister_netdev(qcaspi_devs);
        free_netdev(qcaspi_devs);
-
-       return 0;
 }
 
 static const struct spi_device_id qca_spi_id[] = {
index 89a31783fbb4815f697eaf462c6dddfed51d051f..25739b182ac7bc3a944c54cf40c21c7f8f97cec6 100644 (file)
@@ -731,7 +731,7 @@ static int mse102x_probe_spi(struct spi_device *spi)
        return 0;
 }
 
-static int mse102x_remove_spi(struct spi_device *spi)
+static void mse102x_remove_spi(struct spi_device *spi)
 {
        struct mse102x_net *mse = dev_get_drvdata(&spi->dev);
        struct mse102x_net_spi *mses = to_mse102x_spi(mse);
@@ -741,8 +741,6 @@ static int mse102x_remove_spi(struct spi_device *spi)
 
        mse102x_remove_device_debugfs(mses);
        unregister_netdev(mse->ndev);
-
-       return 0;
 }
 
 static const struct of_device_id mse102x_match_table[] = {
index 7779a36da3c85dd6d6abaadefdfa6f18f78bc809..7c52796273a4958975d98e7622abbc728966625d 100644 (file)
@@ -461,11 +461,9 @@ static int w5100_spi_probe(struct spi_device *spi)
        return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL);
 }
 
-static int w5100_spi_remove(struct spi_device *spi)
+static void w5100_spi_remove(struct spi_device *spi)
 {
        w5100_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id w5100_spi_ids[] = {
index 7db9cbd0f5ded13c96060d6b3ef5946db8b3fcd0..6afdf1622944e4efc9d888dbb93b86c901dddf6f 100644 (file)
@@ -1304,7 +1304,7 @@ err_alloc_wq:
        return ret;
 }
 
-static int adf7242_remove(struct spi_device *spi)
+static void adf7242_remove(struct spi_device *spi)
 {
        struct adf7242_local *lp = spi_get_drvdata(spi);
 
@@ -1316,8 +1316,6 @@ static int adf7242_remove(struct spi_device *spi)
        ieee802154_unregister_hw(lp->hw);
        mutex_destroy(&lp->bmux);
        ieee802154_free_hw(lp->hw);
-
-       return 0;
 }
 
 static const struct of_device_id adf7242_of_match[] = {
index 4f5ef8a9a9a8796db21f270bbb707eb5204e10f1..549d04b5f3d4f67a1d3147775d05e1aa2762b237 100644 (file)
@@ -1768,7 +1768,7 @@ free_dev:
        return rc;
 }
 
-static int at86rf230_remove(struct spi_device *spi)
+static void at86rf230_remove(struct spi_device *spi)
 {
        struct at86rf230_local *lp = spi_get_drvdata(spi);
 
@@ -1778,8 +1778,6 @@ static int at86rf230_remove(struct spi_device *spi)
        ieee802154_free_hw(lp->hw);
        at86rf230_debugfs_remove();
        dev_dbg(&spi->dev, "unregistered at86rf230\n");
-
-       return 0;
 }
 
 static const struct of_device_id at86rf230_of_match[] = {
index 2bc730fd260ebb0f386ef9d4f7cc4630a6dbbe43..187cbc634ce8e13cf50a3362abf0c472a3ca6a05 100644 (file)
@@ -831,7 +831,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl)
 finish:;
 }
 
-static int ca8210_remove(struct spi_device *spi_device);
+static void ca8210_remove(struct spi_device *spi_device);
 
 /**
  * ca8210_spi_transfer_complete() - Called when a single spi transfer has
@@ -3049,7 +3049,7 @@ static void ca8210_test_interface_clear(struct ca8210_priv *priv)
  *
  * Return: 0 or linux error code
  */
-static int ca8210_remove(struct spi_device *spi_device)
+static void ca8210_remove(struct spi_device *spi_device)
 {
        struct ca8210_priv *priv;
        struct ca8210_platform_data *pdata;
@@ -3089,8 +3089,6 @@ static int ca8210_remove(struct spi_device *spi_device)
                if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS))
                        ca8210_test_interface_clear(priv);
        }
-
-       return 0;
 }
 
 /**
index 89c046b204e0c0181bbaf4f15a9c11cb7fa39fdb..1e1f40f628a028a234c017f9f75c81afaf37aa52 100644 (file)
@@ -1213,7 +1213,7 @@ err_hw_init:
        return ret;
 }
 
-static int cc2520_remove(struct spi_device *spi)
+static void cc2520_remove(struct spi_device *spi)
 {
        struct cc2520_private *priv = spi_get_drvdata(spi);
 
@@ -1222,8 +1222,6 @@ static int cc2520_remove(struct spi_device *spi)
 
        ieee802154_unregister_hw(priv->hw);
        ieee802154_free_hw(priv->hw);
-
-       return 0;
 }
 
 static const struct spi_device_id cc2520_ids[] = {
index 383231b85464252a9dfc6a20f938247e5b546959..c927a5ae0d05e91e05db04c9b8c0205075d28d7d 100644 (file)
@@ -1335,7 +1335,7 @@ free_dev:
        return ret;
 }
 
-static int mcr20a_remove(struct spi_device *spi)
+static void mcr20a_remove(struct spi_device *spi)
 {
        struct mcr20a_local *lp = spi_get_drvdata(spi);
 
@@ -1343,8 +1343,6 @@ static int mcr20a_remove(struct spi_device *spi)
 
        ieee802154_unregister_hw(lp->hw);
        ieee802154_free_hw(lp->hw);
-
-       return 0;
 }
 
 static const struct of_device_id mcr20a_of_match[] = {
index ff83e00b77af7e7c3b091ed52f15b838bbcbf745..ee4cfbf2c5cc03e8269d5511ad22721a40b55466 100644 (file)
@@ -1356,7 +1356,7 @@ err_ret:
        return ret;
 }
 
-static int mrf24j40_remove(struct spi_device *spi)
+static void mrf24j40_remove(struct spi_device *spi)
 {
        struct mrf24j40 *devrec = spi_get_drvdata(spi);
 
@@ -1366,8 +1366,6 @@ static int mrf24j40_remove(struct spi_device *spi)
        ieee802154_free_hw(devrec->hw);
        /* TODO: Will ieee802154_free_device() wait until ->xmit() is
         * complete? */
-
-       return 0;
 }
 
 static const struct of_device_id mrf24j40_of_match[] = {
index 8b5445a724ce55bc5b31eff163eb6c72493d6def..ff37f8ba6758bfc6ac798c3a7dea31f921a0c7ee 100644 (file)
@@ -517,7 +517,7 @@ static int ks8995_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ks8995_remove(struct spi_device *spi)
+static void ks8995_remove(struct spi_device *spi)
 {
        struct ks8995_switch *ks = spi_get_drvdata(spi);
 
@@ -526,8 +526,6 @@ static int ks8995_remove(struct spi_device *spi)
        /* assert reset */
        if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio))
                gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1);
-
-       return 0;
 }
 
 /* ------------------------------------------------------------------------ */
index 8e3b1c717c107e09e73a5c2c92688f9f3d872c74..6063552cea9b239ef853eaf5887c91aba0b836ac 100644 (file)
@@ -194,10 +194,9 @@ static int slic_ds26522_init_configure(struct spi_device *spi)
        return 0;
 }
 
-static int slic_ds26522_remove(struct spi_device *spi)
+static void slic_ds26522_remove(struct spi_device *spi)
 {
        pr_info("DS26522 module uninstalled\n");
-       return 0;
 }
 
 static int slic_ds26522_probe(struct spi_device *spi)
index ab0fe85658518120dfaf066c9b1293b0e8064583..f99b7ba69fc3d8a77a1ba1295a01843a837dd18b 100644 (file)
@@ -669,7 +669,7 @@ err_free:
        return ret;
 }
 
-static int p54spi_remove(struct spi_device *spi)
+static void p54spi_remove(struct spi_device *spi)
 {
        struct p54s_priv *priv = spi_get_drvdata(spi);
 
@@ -684,8 +684,6 @@ static int p54spi_remove(struct spi_device *spi)
        mutex_destroy(&priv->mutex);
 
        p54_free_common(priv->hw);
-
-       return 0;
 }
 
 
index cd9f8ecf171f3eb91249a73b2afb181f396b5533..ff1c7ec8c450ba449d85085777b35667e64cff23 100644 (file)
@@ -1195,7 +1195,7 @@ out:
        return err;
 }
 
-static int libertas_spi_remove(struct spi_device *spi)
+static void libertas_spi_remove(struct spi_device *spi)
 {
        struct if_spi_card *card = spi_get_drvdata(spi);
        struct lbs_private *priv = card->priv;
@@ -1212,8 +1212,6 @@ static int libertas_spi_remove(struct spi_device *spi)
        if (card->pdata->teardown)
                card->pdata->teardown(spi);
        free_if_spi_card(card);
-
-       return 0;
 }
 
 static int if_spi_suspend(struct device *dev)
index 2c2ed4b09efd52dc6c83a2ce147ef601d3c08206..d2db522893997a3e19776181651432dad6011886 100644 (file)
@@ -240,7 +240,7 @@ free:
        return ret;
 }
 
-static int wilc_bus_remove(struct spi_device *spi)
+static void wilc_bus_remove(struct spi_device *spi)
 {
        struct wilc *wilc = spi_get_drvdata(spi);
        struct wilc_spi *spi_priv = wilc->bus_data;
@@ -248,8 +248,6 @@ static int wilc_bus_remove(struct spi_device *spi)
        clk_disable_unprepare(wilc->rtc_clk);
        wilc_netdev_cleanup(wilc);
        kfree(spi_priv);
-
-       return 0;
 }
 
 static const struct of_device_id wilc_of_match[] = {
index 271ed2ce2d7f9bef40fa7797a9f304e39ad8f0e7..fe0d220da44d0e019967a3c219cdd8d6d8d9dc74 100644 (file)
@@ -423,7 +423,7 @@ static int cw1200_spi_probe(struct spi_device *func)
 }
 
 /* Disconnect Function to be called by SPI stack when device is disconnected */
-static int cw1200_spi_disconnect(struct spi_device *func)
+static void cw1200_spi_disconnect(struct spi_device *func)
 {
        struct hwbus_priv *self = spi_get_drvdata(func);
 
@@ -435,8 +435,6 @@ static int cw1200_spi_disconnect(struct spi_device *func)
                }
        }
        cw1200_spi_off(dev_get_platdata(&func->dev));
-
-       return 0;
 }
 
 static int __maybe_unused cw1200_spi_suspend(struct device *dev)
index 5b894bd6237ee5c3533fe18fc65b4dbfe83c4913..9df38726e8b0b52aa6212e4b1b45bd9dcbec39e5 100644 (file)
@@ -327,14 +327,12 @@ out_free:
        return ret;
 }
 
-static int wl1251_spi_remove(struct spi_device *spi)
+static void wl1251_spi_remove(struct spi_device *spi)
 {
        struct wl1251 *wl = spi_get_drvdata(spi);
 
        wl1251_free_hw(wl);
        regulator_disable(wl->vio);
-
-       return 0;
 }
 
 static struct spi_driver wl1251_spi_driver = {
index 354a7e1c3315c6e2da1164a94a77f48863432e3b..7eae1ec2eb2b31a9286e68fad677a2bd60df3e5f 100644 (file)
@@ -546,13 +546,11 @@ out_dev_put:
        return ret;
 }
 
-static int wl1271_remove(struct spi_device *spi)
+static void wl1271_remove(struct spi_device *spi)
 {
        struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
 
        platform_device_unregister(glue->core);
-
-       return 0;
 }
 
 static struct spi_driver wl1271_spi_driver = {
index 5b833a9a83f80fe42232b4df55b62b6cc5168392..a38e2fcdfd39fc7270310636e4495462e1ba998d 100644 (file)
@@ -174,12 +174,11 @@ static int nfcmrvl_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int nfcmrvl_spi_remove(struct spi_device *spi)
+static void nfcmrvl_spi_remove(struct spi_device *spi)
 {
        struct nfcmrvl_spi_drv_data *drv_data = spi_get_drvdata(spi);
 
        nfcmrvl_nci_unregister_dev(drv_data->priv);
-       return 0;
 }
 
 static const struct of_device_id of_nfcmrvl_spi_match[] __maybe_unused = {
index 4e723992e74c24d371713e971ce6bcd0d5810b1b..169eacc0a32aeb18ddf6d2c2148be59777c95ee1 100644 (file)
@@ -263,13 +263,11 @@ static int st_nci_spi_probe(struct spi_device *dev)
        return r;
 }
 
-static int st_nci_spi_remove(struct spi_device *dev)
+static void st_nci_spi_remove(struct spi_device *dev)
 {
        struct st_nci_spi_phy *phy = spi_get_drvdata(dev);
 
        ndlc_remove(phy->ndlc);
-
-       return 0;
 }
 
 static struct spi_device_id st_nci_spi_id_table[] = {
index b23f47936473d9eb93f8cd6d0f023eb9f6a54eff..ed704bb772264755dba8487bd4b52efb40fd7a43 100644 (file)
@@ -1198,7 +1198,7 @@ err_disable_regulator:
        return ret;
 }
 
-static int st95hf_remove(struct spi_device *nfc_spi_dev)
+static void st95hf_remove(struct spi_device *nfc_spi_dev)
 {
        int result = 0;
        unsigned char reset_cmd = ST95HF_COMMAND_RESET;
@@ -1236,8 +1236,6 @@ static int st95hf_remove(struct spi_device *nfc_spi_dev)
        /* disable regulator */
        if (stcontext->st95hf_supply)
                regulator_disable(stcontext->st95hf_supply);
-
-       return 0;
 }
 
 /* Register as SPI protocol driver */
index 29ca9c328df2b48732c1148076a6f44758ed0c33..21d68664fe0824bb8499c8fcb91b27ab9b224188 100644 (file)
@@ -2144,7 +2144,7 @@ err_destroy_lock:
        return ret;
 }
 
-static int trf7970a_remove(struct spi_device *spi)
+static void trf7970a_remove(struct spi_device *spi)
 {
        struct trf7970a *trf = spi_get_drvdata(spi);
 
@@ -2160,8 +2160,6 @@ static int trf7970a_remove(struct spi_device *spi)
        regulator_disable(trf->regulator);
 
        mutex_destroy(&trf->lock);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index fc5aa1525d13cab233c45a61ca8490199e38e012..d49a4efe46c8a6100476d9f09a15d57792bd30c3 100644 (file)
@@ -302,13 +302,11 @@ EXPORT_SYMBOL(cros_ec_register);
  *
  * Return: 0 on success or negative error code.
  */
-int cros_ec_unregister(struct cros_ec_device *ec_dev)
+void cros_ec_unregister(struct cros_ec_device *ec_dev)
 {
        if (ec_dev->pd)
                platform_device_unregister(ec_dev->pd);
        platform_device_unregister(ec_dev->ec);
-
-       return 0;
 }
 EXPORT_SYMBOL(cros_ec_unregister);
 
index 78363dcfdf23a681b7e347227ab681d27fe5b078..bbca0096868ac99904cee132d8bf239ff3cbaf19 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/interrupt.h>
 
 int cros_ec_register(struct cros_ec_device *ec_dev);
-int cros_ec_unregister(struct cros_ec_device *ec_dev);
+void cros_ec_unregister(struct cros_ec_device *ec_dev);
 
 int cros_ec_suspend(struct cros_ec_device *ec_dev);
 int cros_ec_resume(struct cros_ec_device *ec_dev);
index 30c8938c27d54ea70b85324c2b5cc137cbe8b22a..22feb0fd4ce71a890db01a695f5d527db471d7fb 100644 (file)
@@ -313,7 +313,9 @@ static int cros_ec_i2c_remove(struct i2c_client *client)
 {
        struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
 
-       return cros_ec_unregister(ec_dev);
+       cros_ec_unregister(ec_dev);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index d6306d2a096f135c9669a6af7944dd702cefe2a0..7651417b4a25b0bbedc620e1583c3d0567ade0ec 100644 (file)
@@ -439,7 +439,9 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
                acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
                                           cros_ec_lpc_acpi_notify);
 
-       return cros_ec_unregister(ec_dev);
+       cros_ec_unregister(ec_dev);
+
+       return 0;
 }
 
 static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
index 14c4046fa04d52ca399e422f7ce31660af90195e..8493af0f680e20adeba56f7ee5cd2db4cb7dca4b 100644 (file)
@@ -786,11 +786,11 @@ static int cros_ec_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int cros_ec_spi_remove(struct spi_device *spi)
+static void cros_ec_spi_remove(struct spi_device *spi)
 {
        struct cros_ec_device *ec_dev = spi_get_drvdata(spi);
 
-       return cros_ec_unregister(ec_dev);
+       cros_ec_unregister(ec_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 0d46706afd2da352e6825b6d8bb04467388c4bf7..4823bd2819f64fdec8e3b7c8764513816a0d231e 100644 (file)
@@ -648,7 +648,7 @@ static struct olpc_ec_driver olpc_xo175_ec_driver = {
        .ec_cmd = olpc_xo175_ec_cmd,
 };
 
-static int olpc_xo175_ec_remove(struct spi_device *spi)
+static void olpc_xo175_ec_remove(struct spi_device *spi)
 {
        if (pm_power_off == olpc_xo175_ec_power_off)
                pm_power_off = NULL;
@@ -657,8 +657,6 @@ static int olpc_xo175_ec_remove(struct spi_device *spi)
 
        platform_device_unregister(olpc_ec);
        olpc_ec = NULL;
-
-       return 0;
 }
 
 static int olpc_xo175_ec_probe(struct spi_device *spi)
index 2f83adef966eb526415665112b00f856e274d641..6d66ab5a8b1768ade12da5f9be137cce47bf219a 100644 (file)
@@ -185,10 +185,9 @@ static int ds1302_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ds1302_remove(struct spi_device *spi)
+static void ds1302_remove(struct spi_device *spi)
 {
        spi_set_drvdata(spi, NULL);
-       return 0;
 }
 
 #ifdef CONFIG_OF
index 9ef107b99b658042172a46668c9820ef7b94df79..ed9360486953e77ad668ec44756dc4ea49677b48 100644 (file)
@@ -720,7 +720,7 @@ static int ds1305_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ds1305_remove(struct spi_device *spi)
+static void ds1305_remove(struct spi_device *spi)
 {
        struct ds1305 *ds1305 = spi_get_drvdata(spi);
 
@@ -730,8 +730,6 @@ static int ds1305_remove(struct spi_device *spi)
                devm_free_irq(&spi->dev, spi->irq, ds1305);
                cancel_work_sync(&ds1305->work);
        }
-
-       return 0;
 }
 
 static struct spi_driver ds1305_driver = {
index f14ed6c96437b44d6ccf42651d37edca41fab699..ed5a6ba89a3eeb2a0b9d6dea3c8b3d40aa2cf317 100644 (file)
@@ -434,11 +434,9 @@ static int ds1343_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ds1343_remove(struct spi_device *spi)
+static void ds1343_remove(struct spi_device *spi)
 {
        dev_pm_clear_wake_irq(&spi->dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index b2a8821971e1d184953a40ab2a44040d977e2201..31a2cef3790cc30eb77d10f196e6158a685a6e4e 100644 (file)
@@ -427,6 +427,45 @@ config SPI_INGENIC
          To compile this driver as a module, choose M here: the module
          will be called spi-ingenic.
 
+config SPI_INTEL
+       tristate
+
+config SPI_INTEL_PCI
+       tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
+       depends on PCI
+       depends on X86 || COMPILE_TEST
+       depends on SPI_MEM
+       select SPI_INTEL
+       help
+         This enables PCI support for the Intel PCH/PCU SPI controller in
+         master mode. This controller is present in modern Intel hardware
+         and is used to hold BIOS and other persistent settings. Using
+         this driver it is possible to upgrade BIOS directly from Linux.
+
+         Say N here unless you know what you are doing. Overwriting the
+         SPI flash may render the system unbootable.
+
+         To compile this driver as a module, choose M here: the module
+         will be called spi-intel-pci.
+
+config SPI_INTEL_PLATFORM
+       tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
+       depends on X86 || COMPILE_TEST
+       depends on SPI_MEM
+       select SPI_INTEL
+       help
+         This enables platform support for the Intel PCH/PCU SPI
+         controller in master mode. This controller is present in modern
+         Intel hardware and is used to hold BIOS and other persistent
+         settings. Using this driver it is possible to upgrade BIOS
+         directly from Linux.
+
+         Say N here unless you know what you are doing. Overwriting the
+         SPI flash may render the system unbootable.
+
+         To compile this driver as a module, choose M here: the module
+         will be called spi-intel-platform.
+
 config SPI_JCORE
        tristate "J-Core SPI Master"
        depends on OF && (SUPERH || COMPILE_TEST)
@@ -866,6 +905,17 @@ config SPI_SUN6I
        help
          This enables using the SPI controller on the Allwinner A31 SoCs.
 
+config SPI_SUNPLUS_SP7021
+       tristate "Sunplus SP7021 SPI controller"
+       depends on SOC_SP7021 || COMPILE_TEST
+       help
+         This enables Sunplus SP7021 SPI controller driver on the SP7021 SoCs.
+         This driver can also be built as a module. If so, the module will be
+         called as spi-sunplus-sp7021.
+
+         If you have a  Sunplus SP7021 platform say Y here.
+         If unsure, say N.
+
 config SPI_SYNQUACER
        tristate "Socionext's SynQuacer HighSpeed SPI controller"
        depends on ARCH_SYNQUACER || COMPILE_TEST
index dd7393a6046fa434831ffd02d97c94bedf4ee873..3aa28ed3f7617c50d4e260c3f47f94f2f8ec026a 100644 (file)
@@ -61,6 +61,9 @@ obj-$(CONFIG_SPI_HISI_SFC_V3XX)               += spi-hisi-sfc-v3xx.o
 obj-$(CONFIG_SPI_IMG_SPFI)             += spi-img-spfi.o
 obj-$(CONFIG_SPI_IMX)                  += spi-imx.o
 obj-$(CONFIG_SPI_INGENIC)              += spi-ingenic.o
+obj-$(CONFIG_SPI_INTEL)                        += spi-intel.o
+obj-$(CONFIG_SPI_INTEL_PCI)            += spi-intel-pci.o
+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
@@ -119,6 +122,7 @@ obj-$(CONFIG_SPI_STM32_QSPI)                += spi-stm32-qspi.o
 obj-$(CONFIG_SPI_ST_SSC4)              += spi-st-ssc4.o
 obj-$(CONFIG_SPI_SUN4I)                        += spi-sun4i.o
 obj-$(CONFIG_SPI_SUN6I)                        += spi-sun6i.o
+obj-$(CONFIG_SPI_SUNPLUS_SP7021)       += spi-sunplus-sp7021.o
 obj-$(CONFIG_SPI_SYNQUACER)            += spi-synquacer.o
 obj-$(CONFIG_SPI_TEGRA210_QUAD)                += spi-tegra210-quad.o
 obj-$(CONFIG_SPI_TEGRA114)             += spi-tegra114.o
index 4b3ac7aceaf62ed39e0b8f1eb5ef516610570b57..cba6a4486c24c408d9bed3d44cf7a098c5728609 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
+#include <linux/iopoll.h>
 
 #define AMD_SPI_CTRL0_REG      0x00
 #define AMD_SPI_EXEC_CMD       BIT(16)
 #define AMD_SPI_FIFO_CLEAR     BIT(20)
 #define AMD_SPI_BUSY           BIT(31)
 
+#define AMD_SPI_OPCODE_REG     0x45
+#define AMD_SPI_CMD_TRIGGER_REG        0x47
+#define AMD_SPI_TRIGGER_CMD    BIT(7)
+
 #define AMD_SPI_OPCODE_MASK    0xFF
 
 #define AMD_SPI_ALT_CS_REG     0x1D
 #define AMD_SPI_XFER_TX                1
 #define AMD_SPI_XFER_RX                2
 
+enum amd_spi_versions {
+       AMD_SPI_V1 = 1, /* AMDI0061 */
+       AMD_SPI_V2,     /* AMDI0062 */
+};
+
 struct amd_spi {
        void __iomem *io_remap_addr;
        unsigned long io_base_addr;
-       u32 rom_addr;
+       enum amd_spi_versions version;
 };
 
 static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
@@ -81,14 +91,29 @@ static void amd_spi_select_chip(struct amd_spi *amd_spi, u8 cs)
        amd_spi_setclear_reg8(amd_spi, AMD_SPI_ALT_CS_REG, cs, AMD_SPI_ALT_CS_MASK);
 }
 
+static inline void amd_spi_clear_chip(struct amd_spi *amd_spi, u8 chip_select)
+{
+       amd_spi_writereg8(amd_spi, AMD_SPI_ALT_CS_REG, chip_select & ~AMD_SPI_ALT_CS_MASK);
+}
+
 static void amd_spi_clear_fifo_ptr(struct amd_spi *amd_spi)
 {
        amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR, AMD_SPI_FIFO_CLEAR);
 }
 
-static void amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)
+static int amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)
 {
-       amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, AMD_SPI_OPCODE_MASK);
+       switch (amd_spi->version) {
+       case AMD_SPI_V1:
+               amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode,
+                                      AMD_SPI_OPCODE_MASK);
+               return 0;
+       case AMD_SPI_V2:
+               amd_spi_writereg8(amd_spi, AMD_SPI_OPCODE_REG, cmd_opcode);
+               return 0;
+       default:
+               return -ENODEV;
+       }
 }
 
 static inline void amd_spi_set_rx_count(struct amd_spi *amd_spi, u8 rx_count)
@@ -103,16 +128,22 @@ static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count)
 
 static int amd_spi_busy_wait(struct amd_spi *amd_spi)
 {
-       int timeout = 100000;
-
-       /* poll for SPI bus to become idle */
-       while (amd_spi_readreg32(amd_spi, AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) {
-               usleep_range(10, 20);
-               if (timeout-- < 0)
-                       return -ETIMEDOUT;
+       u32 val;
+       int reg;
+
+       switch (amd_spi->version) {
+       case AMD_SPI_V1:
+               reg = AMD_SPI_CTRL0_REG;
+               break;
+       case AMD_SPI_V2:
+               reg = AMD_SPI_STATUS_REG;
+               break;
+       default:
+               return -ENODEV;
        }
 
-       return 0;
+       return readl_poll_timeout(amd_spi->io_remap_addr + reg, val,
+                                 !(val & AMD_SPI_BUSY), 20, 2000000);
 }
 
 static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
@@ -123,10 +154,20 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
        if (ret)
                return ret;
 
-       /* Set ExecuteOpCode bit in the CTRL0 register */
-       amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, AMD_SPI_EXEC_CMD);
-
-       return 0;
+       switch (amd_spi->version) {
+       case AMD_SPI_V1:
+               /* Set ExecuteOpCode bit in the CTRL0 register */
+               amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD,
+                                      AMD_SPI_EXEC_CMD);
+               return 0;
+       case AMD_SPI_V2:
+               /* Trigger the command execution */
+               amd_spi_setclear_reg8(amd_spi, AMD_SPI_CMD_TRIGGER_REG,
+                                     AMD_SPI_TRIGGER_CMD, AMD_SPI_TRIGGER_CMD);
+               return 0;
+       default:
+               return -ENODEV;
+       }
 }
 
 static int amd_spi_master_setup(struct spi_device *spi)
@@ -196,6 +237,17 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
        message->actual_length = tx_len + rx_len + 1;
        /* complete the transaction */
        message->status = 0;
+
+       switch (amd_spi->version) {
+       case AMD_SPI_V1:
+               break;
+       case AMD_SPI_V2:
+               amd_spi_clear_chip(amd_spi, message->spi->chip_select);
+               break;
+       default:
+               return -ENODEV;
+       }
+
        spi_finalize_current_message(master);
 
        return 0;
@@ -241,6 +293,8 @@ 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);
+
        /* Initialize the spi_master fields */
        master->bus_num = 0;
        master->num_chipselect = 4;
@@ -266,7 +320,8 @@ err_free_master:
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id spi_acpi_match[] = {
-       { "AMDI0061", 0 },
+       { "AMDI0061", AMD_SPI_V1 },
+       { "AMDI0062", AMD_SPI_V2 },
        {},
 };
 MODULE_DEVICE_TABLE(acpi, spi_acpi_match);
index d1e287d2d9cdc438aff9d84e24be5410a2f5cfc1..607e7a49fb89fde2e8672e0c9e2471c62c796cda 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/bitops.h>
 #include <linux/clk.h>
@@ -133,6 +134,38 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
        return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
 }
 
+static int ath79_exec_mem_op(struct spi_mem *mem,
+                            const struct spi_mem_op *op)
+{
+       struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi);
+
+       /* Ensures that reading is performed on device connected to hardware cs0 */
+       if (mem->spi->chip_select || mem->spi->cs_gpiod)
+               return -ENOTSUPP;
+
+       /* Only use for fast-read op. */
+       if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN ||
+           op->addr.nbytes != 3 || op->dummy.nbytes != 1)
+               return -ENOTSUPP;
+
+       /* disable GPIO mode */
+       ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+
+       memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes);
+
+       /* enable GPIO mode */
+       ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+       /* restore IOC register */
+       ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+
+       return 0;
+}
+
+static const struct spi_controller_mem_ops ath79_mem_ops = {
+       .exec_op = ath79_exec_mem_op,
+};
+
 static int ath79_spi_probe(struct platform_device *pdev)
 {
        struct spi_master *master;
@@ -154,6 +187,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
        master->flags = SPI_MASTER_GPIO_SS;
        master->num_chipselect = 3;
+       master->mem_ops = &ath79_mem_ops;
 
        sp->bitbang.master = master;
        sp->bitbang.chipselect = ath79_spi_chipselect;
index 7d709a8c833bb6b8e33562fe079dd50b35fcc152..e28521922330854a91a47a5fe12f9a68877eb4d1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
@@ -445,25 +444,12 @@ static void bcm2835aux_spi_handle_err(struct spi_master *master,
 
 static int bcm2835aux_spi_setup(struct spi_device *spi)
 {
-       int ret;
-
        /* sanity check for native cs */
        if (spi->mode & SPI_NO_CS)
                return 0;
-       if (gpio_is_valid(spi->cs_gpio)) {
-               /* with gpio-cs set the GPIO to the correct level
-                * and as output (in case the dt has the gpio not configured
-                * as output but native cs)
-                */
-               ret = gpio_direction_output(spi->cs_gpio,
-                                           (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-               if (ret)
-                       dev_err(&spi->dev,
-                               "could not set gpio %i as output: %i\n",
-                               spi->cs_gpio, ret);
-
-               return ret;
-       }
+
+       if (spi->cs_gpiod)
+               return 0;
 
        /* for dt-backwards compatibility: only support native on CS0
         * known things not supported with broken native CS:
@@ -519,6 +505,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
        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;
 
        bs = spi_master_get_devdata(master);
 
index ae61d72c7d281091270b59d6c897cb95158839d3..267342dfa73880d3db4f1573f8a79ba32436e728 100644 (file)
@@ -41,6 +41,8 @@
  * chips need ... there may be several reasons you'd need to tweak timings
  * in these routines, not just to make it faster or slower to match a
  * particular CPU clock rate.
+ *
+ * ToDo: Maybe the bitrev macros can be used to improve the code?
  */
 
 static inline u32
@@ -106,3 +108,67 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
        }
        return word;
 }
+
+static inline u32
+bitbang_txrx_le_cpha0(struct spi_device *spi,
+               unsigned int nsecs, unsigned int cpol, unsigned int flags,
+               u32 word, u8 bits)
+{
+       /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
+
+       u32 oldbit = !(word & 1);
+       /* clock starts at inactive polarity */
+       for (; likely(bits); bits--) {
+
+               /* setup LSB (to slave) on trailing edge */
+               if ((flags & SPI_MASTER_NO_TX) == 0) {
+                       if ((word & 1) != oldbit) {
+                               setmosi(spi, word & 1);
+                               oldbit = word & 1;
+                       }
+               }
+               spidelay(nsecs);        /* T(setup) */
+
+               setsck(spi, !cpol);
+               spidelay(nsecs);
+
+               /* sample LSB (from slave) on leading edge */
+               word >>= 1;
+               if ((flags & SPI_MASTER_NO_RX) == 0)
+                       word |= getmiso(spi) << (bits - 1);
+               setsck(spi, cpol);
+       }
+       return word;
+}
+
+static inline u32
+bitbang_txrx_le_cpha1(struct spi_device *spi,
+               unsigned int nsecs, unsigned int cpol, unsigned int flags,
+               u32 word, u8 bits)
+{
+       /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
+
+       u32 oldbit = !(word & 1);
+       /* clock starts at inactive polarity */
+       for (; likely(bits); bits--) {
+
+               /* setup LSB (to slave) on leading edge */
+               setsck(spi, !cpol);
+               if ((flags & SPI_MASTER_NO_TX) == 0) {
+                       if ((word & 1) != oldbit) {
+                               setmosi(spi, word & 1);
+                               oldbit = word & 1;
+                       }
+               }
+               spidelay(nsecs); /* T(setup) */
+
+               setsck(spi, cpol);
+               spidelay(nsecs);
+
+               /* sample LSB (from slave) on trailing edge */
+               word >>= 1;
+               if ((flags & SPI_MASTER_NO_RX) == 0)
+                       word |= getmiso(spi) << (bits - 1);
+       }
+       return word;
+}
index 4bc1b93fc276b728cd9ba55d8a97ee93dcf6ddfb..3ab19be8309514db4b96bcc94321b620fd9d4db4 100644 (file)
@@ -578,10 +578,8 @@ static int cdns_xspi_probe(struct platform_device *pdev)
        }
 
        cdns_xspi->irq = platform_get_irq(pdev, 0);
-       if (cdns_xspi->irq < 0) {
-               dev_err(dev, "Failed to get IRQ\n");
+       if (cdns_xspi->irq < 0)
                return -ENXIO;
-       }
 
        ret = devm_request_irq(dev, cdns_xspi->irq, cdns_xspi_irq_handler,
                               IRQF_SHARED, pdev->name, cdns_xspi);
index b6c7467f0b590db18a7497850ff81082a8d27490..d403a7a3021d0067028d3aaba58a0ee4d3d7902b 100644 (file)
@@ -25,6 +25,7 @@
 
 #define SPI_FSI_BASE                   0x70000
 #define SPI_FSI_INIT_TIMEOUT_MS                1000
+#define SPI_FSI_STATUS_TIMEOUT_MS      100
 #define SPI_FSI_MAX_RX_SIZE            8
 #define SPI_FSI_MAX_TX_SIZE            40
 
@@ -299,6 +300,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
                                 struct spi_transfer *transfer)
 {
        int rc = 0;
+       unsigned long end;
        u64 status = 0ULL;
 
        if (transfer->tx_buf) {
@@ -315,10 +317,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
                        if (rc)
                                return rc;
 
+                       end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS);
                        do {
                                rc = fsi_spi_status(ctx, &status, "TX");
                                if (rc)
                                        return rc;
+
+                               if (time_after(jiffies, end))
+                                       return -ETIMEDOUT;
                        } while (status & SPI_FSI_STATUS_TDR_FULL);
 
                        sent += nb;
@@ -329,10 +335,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
                u8 *rx = transfer->rx_buf;
 
                while (transfer->len > recv) {
+                       end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS);
                        do {
                                rc = fsi_spi_status(ctx, &status, "RX");
                                if (rc)
                                        return rc;
+
+                               if (time_after(jiffies, end))
+                                       return -ETIMEDOUT;
                        } while (!(status & SPI_FSI_STATUS_RDR_FULL));
 
                        rc = fsi_spi_read_reg(ctx, SPI_FSI_DATA_RX, &in);
index 0584f4d2fde29b8afd7145784c2d7c26ced08c8e..4b12c4964a6643bfef95fa02b815162b0811bcd0 100644 (file)
@@ -135,25 +135,37 @@ static inline int getmiso(const struct spi_device *spi)
 static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-       return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-       return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-       return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
 }
 
 static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-       return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
 }
 
 /*
@@ -170,28 +182,40 @@ static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
        flags = spi->master->flags;
-       return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
        flags = spi->master->flags;
-       return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
        flags = spi->master->flags;
-       return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
                unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
        flags = spi->master->flags;
-       return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
+       if (unlikely(spi->mode & SPI_LSB_FIRST))
+               return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits);
+       else
+               return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
 }
 
 /*----------------------------------------------------------------------*/
@@ -378,7 +402,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
 
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
        master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
-                           SPI_CS_HIGH;
+                           SPI_CS_HIGH | SPI_LSB_FIRST;
        if (!spi_gpio->mosi) {
                /* HW configuration without MOSI pin
                 *
diff --git a/drivers/spi/spi-intel-pci.c b/drivers/spi/spi-intel-pci.c
new file mode 100644 (file)
index 0000000..a5ef7a5
--- /dev/null
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel PCH/PCU SPI flash PCI driver.
+ *
+ * Copyright (C) 2016 - 2022, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "spi-intel.h"
+
+#define BCR            0xdc
+#define BCR_WPD                BIT(0)
+
+static bool intel_spi_pci_set_writeable(void __iomem *base, void *data)
+{
+       struct pci_dev *pdev = data;
+       u32 bcr;
+
+       /* Try to make the chip read/write */
+       pci_read_config_dword(pdev, BCR, &bcr);
+       if (!(bcr & BCR_WPD)) {
+               bcr |= BCR_WPD;
+               pci_write_config_dword(pdev, BCR, bcr);
+               pci_read_config_dword(pdev, BCR, &bcr);
+       }
+
+       return bcr & BCR_WPD;
+}
+
+static const struct intel_spi_boardinfo bxt_info = {
+       .type = INTEL_SPI_BXT,
+       .set_writeable = intel_spi_pci_set_writeable,
+};
+
+static const struct intel_spi_boardinfo cnl_info = {
+       .type = INTEL_SPI_CNL,
+       .set_writeable = intel_spi_pci_set_writeable,
+};
+
+static int intel_spi_pci_probe(struct pci_dev *pdev,
+                              const struct pci_device_id *id)
+{
+       struct intel_spi_boardinfo *info;
+       int ret;
+
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       info = devm_kmemdup(&pdev->dev, (void *)id->driver_data, sizeof(*info),
+                           GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->data = pdev;
+       return intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
+}
+
+static const struct pci_device_id intel_spi_pci_ids[] = {
+       { PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&bxt_info },
+       { },
+};
+MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
+
+static struct pci_driver intel_spi_pci_driver = {
+       .name = "intel-spi",
+       .id_table = intel_spi_pci_ids,
+       .probe = intel_spi_pci_probe,
+};
+
+module_pci_driver(intel_spi_pci_driver);
+
+MODULE_DESCRIPTION("Intel PCH/PCU SPI flash PCI driver");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-intel-platform.c b/drivers/spi/spi-intel-platform.c
new file mode 100644 (file)
index 0000000..2ef09fa
--- /dev/null
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel PCH/PCU SPI flash platform driver.
+ *
+ * Copyright (C) 2016 - 2022, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "spi-intel.h"
+
+static int intel_spi_platform_probe(struct platform_device *pdev)
+{
+       struct intel_spi_boardinfo *info;
+       struct resource *mem;
+
+       info = dev_get_platdata(&pdev->dev);
+       if (!info)
+               return -EINVAL;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       return intel_spi_probe(&pdev->dev, mem, info);
+}
+
+static struct platform_driver intel_spi_platform_driver = {
+       .probe = intel_spi_platform_probe,
+       .driver = {
+               .name = "intel-spi",
+       },
+};
+
+module_platform_driver(intel_spi_platform_driver);
+
+MODULE_DESCRIPTION("Intel PCH/PCU SPI flash platform driver");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:intel-spi");
diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c
new file mode 100644 (file)
index 0000000..e937cfe
--- /dev/null
@@ -0,0 +1,1250 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel PCH/PCU SPI flash driver.
+ *
+ * Copyright (C) 2016 - 2022, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#include <linux/iopoll.h>
+#include <linux/module.h>
+
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+#include "spi-intel.h"
+
+/* Offsets are from @ispi->base */
+#define BFPREG                         0x00
+
+#define HSFSTS_CTL                     0x04
+#define HSFSTS_CTL_FSMIE               BIT(31)
+#define HSFSTS_CTL_FDBC_SHIFT          24
+#define HSFSTS_CTL_FDBC_MASK           (0x3f << HSFSTS_CTL_FDBC_SHIFT)
+
+#define HSFSTS_CTL_FCYCLE_SHIFT                17
+#define HSFSTS_CTL_FCYCLE_MASK         (0x0f << HSFSTS_CTL_FCYCLE_SHIFT)
+/* HW sequencer opcodes */
+#define HSFSTS_CTL_FCYCLE_READ         (0x00 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_WRITE                (0x02 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_ERASE                (0x03 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_ERASE_64K    (0x04 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_RDID         (0x06 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_WRSR         (0x07 << HSFSTS_CTL_FCYCLE_SHIFT)
+#define HSFSTS_CTL_FCYCLE_RDSR         (0x08 << HSFSTS_CTL_FCYCLE_SHIFT)
+
+#define HSFSTS_CTL_FGO                 BIT(16)
+#define HSFSTS_CTL_FLOCKDN             BIT(15)
+#define HSFSTS_CTL_FDV                 BIT(14)
+#define HSFSTS_CTL_SCIP                        BIT(5)
+#define HSFSTS_CTL_AEL                 BIT(2)
+#define HSFSTS_CTL_FCERR               BIT(1)
+#define HSFSTS_CTL_FDONE               BIT(0)
+
+#define FADDR                          0x08
+#define DLOCK                          0x0c
+#define FDATA(n)                       (0x10 + ((n) * 4))
+
+#define FRACC                          0x50
+
+#define FREG(n)                                (0x54 + ((n) * 4))
+#define FREG_BASE_MASK                 0x3fff
+#define FREG_LIMIT_SHIFT               16
+#define FREG_LIMIT_MASK                        (0x03fff << FREG_LIMIT_SHIFT)
+
+/* Offset is from @ispi->pregs */
+#define PR(n)                          ((n) * 4)
+#define PR_WPE                         BIT(31)
+#define PR_LIMIT_SHIFT                 16
+#define PR_LIMIT_MASK                  (0x3fff << PR_LIMIT_SHIFT)
+#define PR_RPE                         BIT(15)
+#define PR_BASE_MASK                   0x3fff
+
+/* Offsets are from @ispi->sregs */
+#define SSFSTS_CTL                     0x00
+#define SSFSTS_CTL_FSMIE               BIT(23)
+#define SSFSTS_CTL_DS                  BIT(22)
+#define SSFSTS_CTL_DBC_SHIFT           16
+#define SSFSTS_CTL_SPOP                        BIT(11)
+#define SSFSTS_CTL_ACS                 BIT(10)
+#define SSFSTS_CTL_SCGO                        BIT(9)
+#define SSFSTS_CTL_COP_SHIFT           12
+#define SSFSTS_CTL_FRS                 BIT(7)
+#define SSFSTS_CTL_DOFRS               BIT(6)
+#define SSFSTS_CTL_AEL                 BIT(4)
+#define SSFSTS_CTL_FCERR               BIT(3)
+#define SSFSTS_CTL_FDONE               BIT(2)
+#define SSFSTS_CTL_SCIP                        BIT(0)
+
+#define PREOP_OPTYPE                   0x04
+#define OPMENU0                                0x08
+#define OPMENU1                                0x0c
+
+#define OPTYPE_READ_NO_ADDR            0
+#define OPTYPE_WRITE_NO_ADDR           1
+#define OPTYPE_READ_WITH_ADDR          2
+#define OPTYPE_WRITE_WITH_ADDR         3
+
+/* CPU specifics */
+#define BYT_PR                         0x74
+#define BYT_SSFSTS_CTL                 0x90
+#define BYT_FREG_NUM                   5
+#define BYT_PR_NUM                     5
+
+#define LPT_PR                         0x74
+#define LPT_SSFSTS_CTL                 0x90
+#define LPT_FREG_NUM                   5
+#define LPT_PR_NUM                     5
+
+#define BXT_PR                         0x84
+#define BXT_SSFSTS_CTL                 0xa0
+#define BXT_FREG_NUM                   12
+#define BXT_PR_NUM                     6
+
+#define CNL_PR                         0x84
+#define CNL_FREG_NUM                   6
+#define CNL_PR_NUM                     5
+
+#define LVSCC                          0xc4
+#define UVSCC                          0xc8
+#define ERASE_OPCODE_SHIFT             8
+#define ERASE_OPCODE_MASK              (0xff << ERASE_OPCODE_SHIFT)
+#define ERASE_64K_OPCODE_SHIFT         16
+#define ERASE_64K_OPCODE_MASK          (0xff << ERASE_OPCODE_SHIFT)
+
+#define INTEL_SPI_TIMEOUT              5000 /* ms */
+#define INTEL_SPI_FIFO_SZ              64
+
+/**
+ * struct intel_spi - Driver private data
+ * @dev: Device pointer
+ * @info: Pointer to board specific info
+ * @base: Beginning of MMIO space
+ * @pregs: Start of protection registers
+ * @sregs: Start of software sequencer registers
+ * @master: Pointer to the SPI controller structure
+ * @nregions: Maximum number of regions
+ * @pr_num: Maximum number of protected range registers
+ * @locked: Is SPI setting locked
+ * @swseq_reg: Use SW sequencer in register reads/writes
+ * @swseq_erase: Use SW sequencer in erase operation
+ * @atomic_preopcode: Holds preopcode when atomic sequence is requested
+ * @opcodes: Opcodes which are supported. This are programmed by BIOS
+ *           before it locks down the controller.
+ * @mem_ops: Pointer to SPI MEM ops supported by the controller
+ */
+struct intel_spi {
+       struct device *dev;
+       const struct intel_spi_boardinfo *info;
+       void __iomem *base;
+       void __iomem *pregs;
+       void __iomem *sregs;
+       struct spi_controller *master;
+       size_t nregions;
+       size_t pr_num;
+       bool locked;
+       bool swseq_reg;
+       bool swseq_erase;
+       u8 atomic_preopcode;
+       u8 opcodes[8];
+       const struct intel_spi_mem_op *mem_ops;
+};
+
+struct intel_spi_mem_op {
+       struct spi_mem_op mem_op;
+       u32 replacement_op;
+       int (*exec_op)(struct intel_spi *ispi,
+                      const struct intel_spi_mem_op *iop,
+                      const struct spi_mem_op *op);
+};
+
+static bool writeable;
+module_param(writeable, bool, 0);
+MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
+
+static void intel_spi_dump_regs(struct intel_spi *ispi)
+{
+       u32 value;
+       int i;
+
+       dev_dbg(ispi->dev, "BFPREG=0x%08x\n", readl(ispi->base + BFPREG));
+
+       value = readl(ispi->base + HSFSTS_CTL);
+       dev_dbg(ispi->dev, "HSFSTS_CTL=0x%08x\n", value);
+       if (value & HSFSTS_CTL_FLOCKDN)
+               dev_dbg(ispi->dev, "-> Locked\n");
+
+       dev_dbg(ispi->dev, "FADDR=0x%08x\n", readl(ispi->base + FADDR));
+       dev_dbg(ispi->dev, "DLOCK=0x%08x\n", readl(ispi->base + DLOCK));
+
+       for (i = 0; i < 16; i++)
+               dev_dbg(ispi->dev, "FDATA(%d)=0x%08x\n",
+                       i, readl(ispi->base + FDATA(i)));
+
+       dev_dbg(ispi->dev, "FRACC=0x%08x\n", readl(ispi->base + FRACC));
+
+       for (i = 0; i < ispi->nregions; i++)
+               dev_dbg(ispi->dev, "FREG(%d)=0x%08x\n", i,
+                       readl(ispi->base + FREG(i)));
+       for (i = 0; i < ispi->pr_num; i++)
+               dev_dbg(ispi->dev, "PR(%d)=0x%08x\n", i,
+                       readl(ispi->pregs + PR(i)));
+
+       if (ispi->sregs) {
+               value = readl(ispi->sregs + SSFSTS_CTL);
+               dev_dbg(ispi->dev, "SSFSTS_CTL=0x%08x\n", value);
+               dev_dbg(ispi->dev, "PREOP_OPTYPE=0x%08x\n",
+                       readl(ispi->sregs + PREOP_OPTYPE));
+               dev_dbg(ispi->dev, "OPMENU0=0x%08x\n",
+                       readl(ispi->sregs + OPMENU0));
+               dev_dbg(ispi->dev, "OPMENU1=0x%08x\n",
+                       readl(ispi->sregs + OPMENU1));
+       }
+
+       dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
+       dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
+
+       dev_dbg(ispi->dev, "Protected regions:\n");
+       for (i = 0; i < ispi->pr_num; i++) {
+               u32 base, limit;
+
+               value = readl(ispi->pregs + PR(i));
+               if (!(value & (PR_WPE | PR_RPE)))
+                       continue;
+
+               limit = (value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
+               base = value & PR_BASE_MASK;
+
+               dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n",
+                       i, base << 12, (limit << 12) | 0xfff,
+                       value & PR_WPE ? 'W' : '.', value & PR_RPE ? 'R' : '.');
+       }
+
+       dev_dbg(ispi->dev, "Flash regions:\n");
+       for (i = 0; i < ispi->nregions; i++) {
+               u32 region, base, limit;
+
+               region = readl(ispi->base + FREG(i));
+               base = region & FREG_BASE_MASK;
+               limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
+
+               if (base >= limit || (i > 0 && limit == 0))
+                       dev_dbg(ispi->dev, " %02d disabled\n", i);
+               else
+                       dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n",
+                               i, base << 12, (limit << 12) | 0xfff);
+       }
+
+       dev_dbg(ispi->dev, "Using %cW sequencer for register access\n",
+               ispi->swseq_reg ? 'S' : 'H');
+       dev_dbg(ispi->dev, "Using %cW sequencer for erase operation\n",
+               ispi->swseq_erase ? 'S' : 'H');
+}
+
+/* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */
+static int intel_spi_read_block(struct intel_spi *ispi, void *buf, size_t size)
+{
+       size_t bytes;
+       int i = 0;
+
+       if (size > INTEL_SPI_FIFO_SZ)
+               return -EINVAL;
+
+       while (size > 0) {
+               bytes = min_t(size_t, size, 4);
+               memcpy_fromio(buf, ispi->base + FDATA(i), bytes);
+               size -= bytes;
+               buf += bytes;
+               i++;
+       }
+
+       return 0;
+}
+
+/* Writes max INTEL_SPI_FIFO_SZ bytes to the device fifo */
+static int intel_spi_write_block(struct intel_spi *ispi, const void *buf,
+                                size_t size)
+{
+       size_t bytes;
+       int i = 0;
+
+       if (size > INTEL_SPI_FIFO_SZ)
+               return -EINVAL;
+
+       while (size > 0) {
+               bytes = min_t(size_t, size, 4);
+               memcpy_toio(ispi->base + FDATA(i), buf, bytes);
+               size -= bytes;
+               buf += bytes;
+               i++;
+       }
+
+       return 0;
+}
+
+static int intel_spi_wait_hw_busy(struct intel_spi *ispi)
+{
+       u32 val;
+
+       return readl_poll_timeout(ispi->base + HSFSTS_CTL, val,
+                                 !(val & HSFSTS_CTL_SCIP), 0,
+                                 INTEL_SPI_TIMEOUT * 1000);
+}
+
+static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
+{
+       u32 val;
+
+       return readl_poll_timeout(ispi->sregs + SSFSTS_CTL, val,
+                                 !(val & SSFSTS_CTL_SCIP), 0,
+                                 INTEL_SPI_TIMEOUT * 1000);
+}
+
+static bool intel_spi_set_writeable(struct intel_spi *ispi)
+{
+       if (!ispi->info->set_writeable)
+               return false;
+
+       return ispi->info->set_writeable(ispi->base, ispi->info->data);
+}
+
+static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype)
+{
+       int i;
+       int preop;
+
+       if (ispi->locked) {
+               for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++)
+                       if (ispi->opcodes[i] == opcode)
+                               return i;
+
+               return -EINVAL;
+       }
+
+       /* The lock is off, so just use index 0 */
+       writel(opcode, ispi->sregs + OPMENU0);
+       preop = readw(ispi->sregs + PREOP_OPTYPE);
+       writel(optype << 16 | preop, ispi->sregs + PREOP_OPTYPE);
+
+       return 0;
+}
+
+static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, size_t len)
+{
+       u32 val, status;
+       int ret;
+
+       val = readl(ispi->base + HSFSTS_CTL);
+       val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK);
+
+       switch (opcode) {
+       case SPINOR_OP_RDID:
+               val |= HSFSTS_CTL_FCYCLE_RDID;
+               break;
+       case SPINOR_OP_WRSR:
+               val |= HSFSTS_CTL_FCYCLE_WRSR;
+               break;
+       case SPINOR_OP_RDSR:
+               val |= HSFSTS_CTL_FCYCLE_RDSR;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (len > INTEL_SPI_FIFO_SZ)
+               return -EINVAL;
+
+       val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT;
+       val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+       val |= HSFSTS_CTL_FGO;
+       writel(val, ispi->base + HSFSTS_CTL);
+
+       ret = intel_spi_wait_hw_busy(ispi);
+       if (ret)
+               return ret;
+
+       status = readl(ispi->base + HSFSTS_CTL);
+       if (status & HSFSTS_CTL_FCERR)
+               return -EIO;
+       else if (status & HSFSTS_CTL_AEL)
+               return -EACCES;
+
+       return 0;
+}
+
+static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
+                             int optype)
+{
+       u32 val = 0, status;
+       u8 atomic_preopcode;
+       int ret;
+
+       ret = intel_spi_opcode_index(ispi, opcode, optype);
+       if (ret < 0)
+               return ret;
+
+       if (len > INTEL_SPI_FIFO_SZ)
+               return -EINVAL;
+
+       /*
+        * Always clear it after each SW sequencer operation regardless
+        * of whether it is successful or not.
+        */
+       atomic_preopcode = ispi->atomic_preopcode;
+       ispi->atomic_preopcode = 0;
+
+       /* Only mark 'Data Cycle' bit when there is data to be transferred */
+       if (len > 0)
+               val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS;
+       val |= ret << SSFSTS_CTL_COP_SHIFT;
+       val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE;
+       val |= SSFSTS_CTL_SCGO;
+       if (atomic_preopcode) {
+               u16 preop;
+
+               switch (optype) {
+               case OPTYPE_WRITE_NO_ADDR:
+               case OPTYPE_WRITE_WITH_ADDR:
+                       /* Pick matching preopcode for the atomic sequence */
+                       preop = readw(ispi->sregs + PREOP_OPTYPE);
+                       if ((preop & 0xff) == atomic_preopcode)
+                               ; /* Do nothing */
+                       else if ((preop >> 8) == atomic_preopcode)
+                               val |= SSFSTS_CTL_SPOP;
+                       else
+                               return -EINVAL;
+
+                       /* Enable atomic sequence */
+                       val |= SSFSTS_CTL_ACS;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+       }
+       writel(val, ispi->sregs + SSFSTS_CTL);
+
+       ret = intel_spi_wait_sw_busy(ispi);
+       if (ret)
+               return ret;
+
+       status = readl(ispi->sregs + SSFSTS_CTL);
+       if (status & SSFSTS_CTL_FCERR)
+               return -EIO;
+       else if (status & SSFSTS_CTL_AEL)
+               return -EACCES;
+
+       return 0;
+}
+
+static int intel_spi_read_reg(struct intel_spi *ispi,
+                             const struct intel_spi_mem_op *iop,
+                             const struct spi_mem_op *op)
+{
+       size_t nbytes = op->data.nbytes;
+       u8 opcode = op->cmd.opcode;
+       int ret;
+
+       /* Address of the first chip */
+       writel(0, ispi->base + FADDR);
+
+       if (ispi->swseq_reg)
+               ret = intel_spi_sw_cycle(ispi, opcode, nbytes,
+                                        OPTYPE_READ_NO_ADDR);
+       else
+               ret = intel_spi_hw_cycle(ispi, opcode, nbytes);
+
+       if (ret)
+               return ret;
+
+       return intel_spi_read_block(ispi, op->data.buf.in, nbytes);
+}
+
+static int intel_spi_write_reg(struct intel_spi *ispi,
+                              const struct intel_spi_mem_op *iop,
+                              const struct spi_mem_op *op)
+{
+       size_t nbytes = op->data.nbytes;
+       u8 opcode = op->cmd.opcode;
+       int ret;
+
+       /*
+        * This is handled with atomic operation and preop code in Intel
+        * controller so we only verify that it is available. If the
+        * controller is not locked, program the opcode to the PREOP
+        * register for later use.
+        *
+        * When hardware sequencer is used there is no need to program
+        * any opcodes (it handles them automatically as part of a command).
+        */
+       if (opcode == SPINOR_OP_WREN) {
+               u16 preop;
+
+               if (!ispi->swseq_reg)
+                       return 0;
+
+               preop = readw(ispi->sregs + PREOP_OPTYPE);
+               if ((preop & 0xff) != opcode && (preop >> 8) != opcode) {
+                       if (ispi->locked)
+                               return -EINVAL;
+                       writel(opcode, ispi->sregs + PREOP_OPTYPE);
+               }
+
+               /*
+                * This enables atomic sequence on next SW sycle. Will
+                * be cleared after next operation.
+                */
+               ispi->atomic_preopcode = opcode;
+               return 0;
+       }
+
+       /*
+        * We hope that HW sequencer will do the right thing automatically and
+        * with the SW sequencer we cannot use preopcode anyway, so just ignore
+        * the Write Disable operation and pretend it was completed
+        * successfully.
+        */
+       if (opcode == SPINOR_OP_WRDI)
+               return 0;
+
+       writel(0, ispi->base + FADDR);
+
+       /* Write the value beforehand */
+       ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes);
+       if (ret)
+               return ret;
+
+       if (ispi->swseq_reg)
+               return intel_spi_sw_cycle(ispi, opcode, nbytes,
+                                         OPTYPE_WRITE_NO_ADDR);
+       return intel_spi_hw_cycle(ispi, opcode, nbytes);
+}
+
+static int intel_spi_read(struct intel_spi *ispi,
+                         const struct intel_spi_mem_op *iop,
+                         const struct spi_mem_op *op)
+{
+       void *read_buf = op->data.buf.in;
+       size_t block_size, nbytes = op->data.nbytes;
+       u32 addr = op->addr.val;
+       u32 val, status;
+       int ret;
+
+       /*
+        * Atomic sequence is not expected with HW sequencer reads. Make
+        * sure it is cleared regardless.
+        */
+       if (WARN_ON_ONCE(ispi->atomic_preopcode))
+               ispi->atomic_preopcode = 0;
+
+       while (nbytes > 0) {
+               block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ);
+
+               /* Read cannot cross 4K boundary */
+               block_size = min_t(loff_t, addr + block_size,
+                                  round_up(addr + 1, SZ_4K)) - addr;
+
+               writel(addr, ispi->base + FADDR);
+
+               val = readl(ispi->base + HSFSTS_CTL);
+               val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
+               val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+               val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
+               val |= HSFSTS_CTL_FCYCLE_READ;
+               val |= HSFSTS_CTL_FGO;
+               writel(val, ispi->base + HSFSTS_CTL);
+
+               ret = intel_spi_wait_hw_busy(ispi);
+               if (ret)
+                       return ret;
+
+               status = readl(ispi->base + HSFSTS_CTL);
+               if (status & HSFSTS_CTL_FCERR)
+                       ret = -EIO;
+               else if (status & HSFSTS_CTL_AEL)
+                       ret = -EACCES;
+
+               if (ret < 0) {
+                       dev_err(ispi->dev, "read error: %x: %#x\n", addr, status);
+                       return ret;
+               }
+
+               ret = intel_spi_read_block(ispi, read_buf, block_size);
+               if (ret)
+                       return ret;
+
+               nbytes -= block_size;
+               addr += block_size;
+               read_buf += block_size;
+       }
+
+       return 0;
+}
+
+static int intel_spi_write(struct intel_spi *ispi,
+                          const struct intel_spi_mem_op *iop,
+                          const struct spi_mem_op *op)
+{
+       size_t block_size, nbytes = op->data.nbytes;
+       const void *write_buf = op->data.buf.out;
+       u32 addr = op->addr.val;
+       u32 val, status;
+       int ret;
+
+       /* Not needed with HW sequencer write, make sure it is cleared */
+       ispi->atomic_preopcode = 0;
+
+       while (nbytes > 0) {
+               block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ);
+
+               /* Write cannot cross 4K boundary */
+               block_size = min_t(loff_t, addr + block_size,
+                                  round_up(addr + 1, SZ_4K)) - addr;
+
+               writel(addr, ispi->base + FADDR);
+
+               val = readl(ispi->base + HSFSTS_CTL);
+               val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
+               val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+               val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
+               val |= HSFSTS_CTL_FCYCLE_WRITE;
+
+               ret = intel_spi_write_block(ispi, write_buf, block_size);
+               if (ret) {
+                       dev_err(ispi->dev, "failed to write block\n");
+                       return ret;
+               }
+
+               /* Start the write now */
+               val |= HSFSTS_CTL_FGO;
+               writel(val, ispi->base + HSFSTS_CTL);
+
+               ret = intel_spi_wait_hw_busy(ispi);
+               if (ret) {
+                       dev_err(ispi->dev, "timeout\n");
+                       return ret;
+               }
+
+               status = readl(ispi->base + HSFSTS_CTL);
+               if (status & HSFSTS_CTL_FCERR)
+                       ret = -EIO;
+               else if (status & HSFSTS_CTL_AEL)
+                       ret = -EACCES;
+
+               if (ret < 0) {
+                       dev_err(ispi->dev, "write error: %x: %#x\n", addr, status);
+                       return ret;
+               }
+
+               nbytes -= block_size;
+               addr += block_size;
+               write_buf += block_size;
+       }
+
+       return 0;
+}
+
+static int intel_spi_erase(struct intel_spi *ispi,
+                          const struct intel_spi_mem_op *iop,
+                          const struct spi_mem_op *op)
+{
+       u8 opcode = op->cmd.opcode;
+       u32 addr = op->addr.val;
+       u32 val, status;
+       int ret;
+
+       writel(addr, ispi->base + FADDR);
+
+       if (ispi->swseq_erase)
+               return intel_spi_sw_cycle(ispi, opcode, 0,
+                                         OPTYPE_WRITE_WITH_ADDR);
+
+       /* Not needed with HW sequencer erase, make sure it is cleared */
+       ispi->atomic_preopcode = 0;
+
+       val = readl(ispi->base + HSFSTS_CTL);
+       val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
+       val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+       val |= HSFSTS_CTL_FGO;
+       val |= iop->replacement_op;
+       writel(val, ispi->base + HSFSTS_CTL);
+
+       ret = intel_spi_wait_hw_busy(ispi);
+       if (ret)
+               return ret;
+
+       status = readl(ispi->base + HSFSTS_CTL);
+       if (status & HSFSTS_CTL_FCERR)
+               return -EIO;
+       if (status & HSFSTS_CTL_AEL)
+               return -EACCES;
+
+       return 0;
+}
+
+static bool intel_spi_cmp_mem_op(const struct intel_spi_mem_op *iop,
+                                const struct spi_mem_op *op)
+{
+       if (iop->mem_op.cmd.nbytes != op->cmd.nbytes ||
+           iop->mem_op.cmd.buswidth != op->cmd.buswidth ||
+           iop->mem_op.cmd.dtr != op->cmd.dtr ||
+           iop->mem_op.cmd.opcode != op->cmd.opcode)
+               return false;
+
+       if (iop->mem_op.addr.nbytes != op->addr.nbytes ||
+           iop->mem_op.addr.dtr != op->addr.dtr)
+               return false;
+
+       if (iop->mem_op.data.dir != op->data.dir ||
+           iop->mem_op.data.dtr != op->data.dtr)
+               return false;
+
+       if (iop->mem_op.data.dir != SPI_MEM_NO_DATA) {
+               if (iop->mem_op.data.buswidth != op->data.buswidth)
+                       return false;
+       }
+
+       return true;
+}
+
+static const struct intel_spi_mem_op *
+intel_spi_match_mem_op(struct intel_spi *ispi, const struct spi_mem_op *op)
+{
+       const struct intel_spi_mem_op *iop;
+
+       for (iop = ispi->mem_ops; iop->mem_op.cmd.opcode; iop++) {
+               if (intel_spi_cmp_mem_op(iop, op))
+                       break;
+       }
+
+       return iop->mem_op.cmd.opcode ? iop : NULL;
+}
+
+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);
+       const struct intel_spi_mem_op *iop;
+
+       iop = intel_spi_match_mem_op(ispi, op);
+       if (!iop) {
+               dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode);
+               return false;
+       }
+
+       /*
+        * For software sequencer check that the opcode is actually
+        * present in the opmenu if it is locked.
+        */
+       if (ispi->swseq_reg && ispi->locked) {
+               int i;
+
+               /* Check if it is in the locked opcodes list */
+               for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
+                       if (ispi->opcodes[i] == op->cmd.opcode)
+                               return true;
+               }
+
+               dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode);
+               return false;
+       }
+
+       return true;
+}
+
+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);
+       const struct intel_spi_mem_op *iop;
+
+       iop = intel_spi_match_mem_op(ispi, op);
+       if (!iop)
+               return -EOPNOTSUPP;
+
+       return iop->exec_op(ispi, iop, op);
+}
+
+static const char *intel_spi_get_name(struct spi_mem *mem)
+{
+       const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+
+       /*
+        * Return name of the flash controller device to be compatible
+        * with the MTD version.
+        */
+       return dev_name(ispi->dev);
+}
+
+static const struct spi_controller_mem_ops intel_spi_mem_ops = {
+       .supports_op = intel_spi_supports_mem_op,
+       .exec_op = intel_spi_exec_mem_op,
+       .get_name = intel_spi_get_name,
+};
+
+#define INTEL_SPI_OP_ADDR(__nbytes)                                    \
+       {                                                               \
+               .nbytes = __nbytes,                                     \
+       }
+
+#define INTEL_SPI_OP_NO_DATA                                           \
+       {                                                               \
+               .dir = SPI_MEM_NO_DATA,                                 \
+       }
+
+#define INTEL_SPI_OP_DATA_IN(__buswidth)                               \
+       {                                                               \
+               .dir = SPI_MEM_DATA_IN,                                 \
+               .buswidth = __buswidth,                                 \
+       }
+
+#define INTEL_SPI_OP_DATA_OUT(__buswidth)                              \
+       {                                                               \
+               .dir = SPI_MEM_DATA_OUT,                                \
+               .buswidth = __buswidth,                                 \
+       }
+
+#define INTEL_SPI_MEM_OP(__cmd, __addr, __data, __exec_op)             \
+       {                                                               \
+               .mem_op = {                                             \
+                       .cmd = __cmd,                                   \
+                       .addr = __addr,                                 \
+                       .data = __data,                                 \
+               },                                                      \
+               .exec_op = __exec_op,                                   \
+       }
+
+#define INTEL_SPI_MEM_OP_REPL(__cmd, __addr, __data, __exec_op, __repl)        \
+       {                                                               \
+               .mem_op = {                                             \
+                       .cmd = __cmd,                                   \
+                       .addr = __addr,                                 \
+                       .data = __data,                                 \
+               },                                                      \
+               .exec_op = __exec_op,                                   \
+               .replacement_op = __repl,                               \
+       }
+
+/*
+ * The controller handles pretty much everything internally based on the
+ * SFDP data but we want to make sure we only support the operations
+ * actually possible. Only check buswidth and transfer direction, the
+ * core validates data.
+ */
+#define INTEL_SPI_GENERIC_OPS                                          \
+       /* Status register operations */                                \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),             \
+                        SPI_MEM_OP_NO_ADDR,                            \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read_reg),                           \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1),             \
+                        SPI_MEM_OP_NO_ADDR,                            \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read_reg),                           \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1),             \
+                        SPI_MEM_OP_NO_ADDR,                            \
+                        INTEL_SPI_OP_DATA_OUT(1),                      \
+                        intel_spi_write_reg),                          \
+       /* Normal read */                                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),             \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       /* Fast read */                                                 \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),        \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       /* Read with 4-byte address opcode */                           \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),          \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),          \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),          \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       /* Fast read with 4-byte address opcode */                      \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),     \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(1),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),     \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(2),                       \
+                        intel_spi_read),                               \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),     \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_IN(4),                       \
+                        intel_spi_read),                               \
+       /* Write operations */                                          \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1),               \
+                        INTEL_SPI_OP_ADDR(3),                          \
+                        INTEL_SPI_OP_DATA_OUT(1),                      \
+                        intel_spi_write),                              \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1),               \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_OUT(1),                      \
+                        intel_spi_write),                              \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP_4B, 1),            \
+                        INTEL_SPI_OP_ADDR(4),                          \
+                        INTEL_SPI_OP_DATA_OUT(1),                      \
+                        intel_spi_write),                              \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 1),             \
+                        SPI_MEM_OP_NO_ADDR,                            \
+                        SPI_MEM_OP_NO_DATA,                            \
+                        intel_spi_write_reg),                          \
+       INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 1),             \
+                        SPI_MEM_OP_NO_ADDR,                            \
+                        SPI_MEM_OP_NO_DATA,                            \
+                        intel_spi_write_reg),                          \
+       /* Erase operations */                                          \
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1),       \
+                             INTEL_SPI_OP_ADDR(3),                     \
+                             SPI_MEM_OP_NO_DATA,                       \
+                             intel_spi_erase,                          \
+                             HSFSTS_CTL_FCYCLE_ERASE),                 \
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1),       \
+                             INTEL_SPI_OP_ADDR(4),                     \
+                             SPI_MEM_OP_NO_DATA,                       \
+                             intel_spi_erase,                          \
+                             HSFSTS_CTL_FCYCLE_ERASE),                 \
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K_4B, 1),    \
+                             INTEL_SPI_OP_ADDR(4),                     \
+                             SPI_MEM_OP_NO_DATA,                       \
+                             intel_spi_erase,                          \
+                             HSFSTS_CTL_FCYCLE_ERASE)                  \
+
+static const struct intel_spi_mem_op generic_mem_ops[] = {
+       INTEL_SPI_GENERIC_OPS,
+       { },
+};
+
+static const struct intel_spi_mem_op erase_64k_mem_ops[] = {
+       INTEL_SPI_GENERIC_OPS,
+       /* 64k sector erase operations */
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1),
+                             INTEL_SPI_OP_ADDR(3),
+                             SPI_MEM_OP_NO_DATA,
+                             intel_spi_erase,
+                             HSFSTS_CTL_FCYCLE_ERASE_64K),
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1),
+                             INTEL_SPI_OP_ADDR(4),
+                             SPI_MEM_OP_NO_DATA,
+                             intel_spi_erase,
+                             HSFSTS_CTL_FCYCLE_ERASE_64K),
+       INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE_4B, 1),
+                             INTEL_SPI_OP_ADDR(4),
+                             SPI_MEM_OP_NO_DATA,
+                             intel_spi_erase,
+                             HSFSTS_CTL_FCYCLE_ERASE_64K),
+       { },
+};
+
+static int intel_spi_init(struct intel_spi *ispi)
+{
+       u32 opmenu0, opmenu1, lvscc, uvscc, val;
+       bool erase_64k = false;
+       int i;
+
+       switch (ispi->info->type) {
+       case INTEL_SPI_BYT:
+               ispi->sregs = ispi->base + BYT_SSFSTS_CTL;
+               ispi->pregs = ispi->base + BYT_PR;
+               ispi->nregions = BYT_FREG_NUM;
+               ispi->pr_num = BYT_PR_NUM;
+               ispi->swseq_reg = true;
+               break;
+
+       case INTEL_SPI_LPT:
+               ispi->sregs = ispi->base + LPT_SSFSTS_CTL;
+               ispi->pregs = ispi->base + LPT_PR;
+               ispi->nregions = LPT_FREG_NUM;
+               ispi->pr_num = LPT_PR_NUM;
+               ispi->swseq_reg = true;
+               break;
+
+       case INTEL_SPI_BXT:
+               ispi->sregs = ispi->base + BXT_SSFSTS_CTL;
+               ispi->pregs = ispi->base + BXT_PR;
+               ispi->nregions = BXT_FREG_NUM;
+               ispi->pr_num = BXT_PR_NUM;
+               erase_64k = true;
+               break;
+
+       case INTEL_SPI_CNL:
+               ispi->sregs = NULL;
+               ispi->pregs = ispi->base + CNL_PR;
+               ispi->nregions = CNL_FREG_NUM;
+               ispi->pr_num = CNL_PR_NUM;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* Try to disable write protection if user asked to do so */
+       if (writeable && !intel_spi_set_writeable(ispi)) {
+               dev_warn(ispi->dev, "can't disable chip write protection\n");
+               writeable = false;
+       }
+
+       /* Disable #SMI generation from HW sequencer */
+       val = readl(ispi->base + HSFSTS_CTL);
+       val &= ~HSFSTS_CTL_FSMIE;
+       writel(val, ispi->base + HSFSTS_CTL);
+
+       /*
+        * Determine whether erase operation should use HW or SW sequencer.
+        *
+        * The HW sequencer has a predefined list of opcodes, with only the
+        * erase opcode being programmable in LVSCC and UVSCC registers.
+        * If these registers don't contain a valid erase opcode, erase
+        * cannot be done using HW sequencer.
+        */
+       lvscc = readl(ispi->base + LVSCC);
+       uvscc = readl(ispi->base + UVSCC);
+       if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK))
+               ispi->swseq_erase = true;
+       /* SPI controller on Intel BXT supports 64K erase opcode */
+       if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase)
+               if (!(lvscc & ERASE_64K_OPCODE_MASK) ||
+                   !(uvscc & ERASE_64K_OPCODE_MASK))
+                       erase_64k = false;
+
+       if (!ispi->sregs && (ispi->swseq_reg || ispi->swseq_erase)) {
+               dev_err(ispi->dev, "software sequencer not supported, but required\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Some controllers can only do basic operations using hardware
+        * sequencer. All other operations are supposed to be carried out
+        * using software sequencer.
+        */
+       if (ispi->swseq_reg) {
+               /* Disable #SMI generation from SW sequencer */
+               val = readl(ispi->sregs + SSFSTS_CTL);
+               val &= ~SSFSTS_CTL_FSMIE;
+               writel(val, ispi->sregs + SSFSTS_CTL);
+       }
+
+       /* Check controller's lock status */
+       val = readl(ispi->base + HSFSTS_CTL);
+       ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN);
+
+       if (ispi->locked && ispi->sregs) {
+               /*
+                * BIOS programs allowed opcodes and then locks down the
+                * register. So read back what opcodes it decided to support.
+                * That's the set we are going to support as well.
+                */
+               opmenu0 = readl(ispi->sregs + OPMENU0);
+               opmenu1 = readl(ispi->sregs + OPMENU1);
+
+               if (opmenu0 && opmenu1) {
+                       for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) {
+                               ispi->opcodes[i] = opmenu0 >> i * 8;
+                               ispi->opcodes[i + 4] = opmenu1 >> i * 8;
+                       }
+               }
+       }
+
+       if (erase_64k) {
+               dev_dbg(ispi->dev, "Using erase_64k memory operations");
+               ispi->mem_ops = erase_64k_mem_ops;
+       } else {
+               dev_dbg(ispi->dev, "Using generic memory operations");
+               ispi->mem_ops = generic_mem_ops;
+       }
+
+       intel_spi_dump_regs(ispi);
+       return 0;
+}
+
+static bool intel_spi_is_protected(const struct intel_spi *ispi,
+                                  unsigned int base, unsigned int limit)
+{
+       int i;
+
+       for (i = 0; i < ispi->pr_num; i++) {
+               u32 pr_base, pr_limit, pr_value;
+
+               pr_value = readl(ispi->pregs + PR(i));
+               if (!(pr_value & (PR_WPE | PR_RPE)))
+                       continue;
+
+               pr_limit = (pr_value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
+               pr_base = pr_value & PR_BASE_MASK;
+
+               if (pr_base >= base && pr_limit <= limit)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * There will be a single partition holding all enabled flash regions. We
+ * call this "BIOS".
+ */
+static void intel_spi_fill_partition(struct intel_spi *ispi,
+                                    struct mtd_partition *part)
+{
+       u64 end;
+       int i;
+
+       memset(part, 0, sizeof(*part));
+
+       /* Start from the mandatory descriptor region */
+       part->size = 4096;
+       part->name = "BIOS";
+
+       /*
+        * Now try to find where this partition ends based on the flash
+        * region registers.
+        */
+       for (i = 1; i < ispi->nregions; i++) {
+               u32 region, base, limit;
+
+               region = readl(ispi->base + FREG(i));
+               base = region & FREG_BASE_MASK;
+               limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
+
+               if (base >= limit || limit == 0)
+                       continue;
+
+               /*
+                * If any of the regions have protection bits set, make the
+                * whole partition read-only to be on the safe side.
+                *
+                * Also if the user did not ask the chip to be writeable
+                * mask the bit too.
+                */
+               if (!writeable || intel_spi_is_protected(ispi, base, limit))
+                       part->mask_flags |= MTD_WRITEABLE;
+
+               end = (limit << 12) + 4096;
+               if (end > part->size)
+                       part->size = end;
+       }
+}
+
+static int intel_spi_populate_chip(struct intel_spi *ispi)
+{
+       struct flash_platform_data *pdata;
+       struct spi_board_info chip;
+
+       pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       pdata->nr_parts = 1;
+       pdata->parts = devm_kcalloc(ispi->dev, sizeof(*pdata->parts),
+                                   pdata->nr_parts, GFP_KERNEL);
+       if (!pdata->parts)
+               return -ENOMEM;
+
+       intel_spi_fill_partition(ispi, pdata->parts);
+
+       memset(&chip, 0, sizeof(chip));
+       snprintf(chip.modalias, 8, "spi-nor");
+       chip.platform_data = pdata;
+
+       return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV;
+}
+
+/**
+ * intel_spi_probe() - Probe the Intel SPI flash controller
+ * @dev: Pointer to the parent device
+ * @mem: MMIO resource
+ * @info: Platform spefific information
+ *
+ * Probes Intel SPI flash controller and creates the flash chip device.
+ * Returns %0 on success and negative errno in case of failure.
+ */
+int intel_spi_probe(struct device *dev, struct resource *mem,
+                   const struct intel_spi_boardinfo *info)
+{
+       struct spi_controller *master;
+       struct intel_spi *ispi;
+       int ret;
+
+       master = devm_spi_alloc_master(dev, sizeof(*ispi));
+       if (!master)
+               return -ENOMEM;
+
+       master->mem_ops = &intel_spi_mem_ops;
+
+       ispi = spi_master_get_devdata(master);
+
+       ispi->base = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(ispi->base))
+               return PTR_ERR(ispi->base);
+
+       ispi->dev = dev;
+       ispi->master = master;
+       ispi->info = info;
+
+       ret = intel_spi_init(ispi);
+       if (ret)
+               return ret;
+
+       ret = devm_spi_register_master(dev, master);
+       if (ret)
+               return ret;
+
+       return intel_spi_populate_chip(ispi);
+}
+EXPORT_SYMBOL_GPL(intel_spi_probe);
+
+MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-intel.h b/drivers/spi/spi-intel.h
new file mode 100644 (file)
index 0000000..a4f0327
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Intel PCH/PCU SPI flash driver.
+ *
+ * Copyright (C) 2016 - 2022, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#ifndef SPI_INTEL_H
+#define SPI_INTEL_H
+
+#include <linux/platform_data/x86/spi-intel.h>
+
+struct resource;
+
+int intel_spi_probe(struct device *dev, struct resource *mem,
+                   const struct intel_spi_boardinfo *info);
+
+#endif /* SPI_INTEL_H */
index bcb52601804a9919b09a31a522fb133949bf524d..aae26f62ea87ac31ce98f7d058af173a7318cf4f 100644 (file)
@@ -906,17 +906,11 @@ static int lantiq_ssc_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct lantiq_ssc_spi *spi;
        const struct lantiq_ssc_hwcfg *hwcfg;
-       const struct of_device_id *match;
        u32 id, supports_dma, revision;
        unsigned int num_cs;
        int err;
 
-       match = of_match_device(lantiq_ssc_match, dev);
-       if (!match) {
-               dev_err(dev, "no device match\n");
-               return -EINVAL;
-       }
-       hwcfg = match->data;
+       hwcfg = of_device_get_match_data(dev);
 
        master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));
        if (!master)
index 37f4443ce9a0971d8e5fce49cff72c15faa8e65f..e9d83d65873bdb696726f22e4874e607476ec464 100644 (file)
@@ -854,15 +854,13 @@ static int spi_mem_probe(struct spi_device *spi)
        return memdrv->probe(mem);
 }
 
-static int spi_mem_remove(struct spi_device *spi)
+static void spi_mem_remove(struct spi_device *spi)
 {
        struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);
        struct spi_mem *mem = spi_get_drvdata(spi);
 
        if (memdrv->remove)
-               return memdrv->remove(mem);
-
-       return 0;
+               memdrv->remove(mem);
 }
 
 static void spi_mem_shutdown(struct spi_device *spi)
index 78a9bca8cc689aa383f13d973ecfb2b1ea8493be..03630359ce70db0d5d773be566c046ebf2d2c1b3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/spi/spi.h>
 #include <linux/fsl_devices.h>
-#include <linux/gpio.h>
 #include <asm/mpc52xx_psc.h>
 
 enum {
@@ -128,17 +127,28 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
        out_be32(psc_addr(mps, ccr), ccr);
        mps->bits_per_word = cs->bits_per_word;
 
-       if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
-               mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+       if (spi->cs_gpiod) {
+               if (mps->cs_control)
+                       /* boardfile override */
+                       mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+               else
+                       /* gpiolib will deal with the inversion */
+                       gpiod_set_value(spi->cs_gpiod, 1);
+       }
 }
 
 static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
 {
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
 
-       if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
-               mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-
+       if (spi->cs_gpiod) {
+               if (mps->cs_control)
+                       /* boardfile override */
+                       mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+               else
+                       /* gpiolib will deal with the inversion */
+                       gpiod_set_value(spi->cs_gpiod, 0);
+       }
 }
 
 /* extract and scale size field in txsz or rxsz */
@@ -363,7 +373,6 @@ static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
 static int mpc512x_psc_spi_setup(struct spi_device *spi)
 {
        struct mpc512x_psc_spi_cs *cs = spi->controller_state;
-       int ret;
 
        if (spi->bits_per_word % 8)
                return -EINVAL;
@@ -373,18 +382,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)
                if (!cs)
                        return -ENOMEM;
 
-               if (gpio_is_valid(spi->cs_gpio)) {
-                       ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));
-                       if (ret) {
-                               dev_err(&spi->dev, "can't get CS gpio: %d\n",
-                                       ret);
-                               kfree(cs);
-                               return ret;
-                       }
-                       gpio_direction_output(spi->cs_gpio,
-                                       spi->mode & SPI_CS_HIGH ? 0 : 1);
-               }
-
                spi->controller_state = cs;
        }
 
@@ -396,8 +393,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)
 
 static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
 {
-       if (gpio_is_valid(spi->cs_gpio))
-               gpio_free(spi->cs_gpio);
        kfree(spi->controller_state);
 }
 
@@ -476,11 +471,6 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
-static void mpc512x_spi_cs_control(struct spi_device *spi, bool onoff)
-{
-       gpio_set_value(spi->cs_gpio, onoff);
-}
-
 static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                              u32 size, unsigned int irq)
 {
@@ -500,9 +490,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        mps->type = (int)of_device_get_match_data(dev);
        mps->irq = irq;
 
-       if (pdata == NULL) {
-               mps->cs_control = mpc512x_spi_cs_control;
-       } else {
+       if (pdata) {
                mps->cs_control = pdata->cs_control;
                master->bus_num = pdata->bus_num;
                master->num_chipselect = pdata->max_chipselect;
@@ -513,6 +501,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw;
        master->transfer_one_message = mpc512x_psc_spi_msg_xfer;
        master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw;
+       master->use_gpio_descriptors = true;
        master->cleanup = mpc512x_psc_spi_cleanup;
        master->dev.of_node = dev->of_node;
 
index 753bd313e6fdaaabe4063fc068e84d8d05b42983..1a0b3208dfcaf719a07d0f16e6faea24ae82f2e1 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/spi-mt65xx.h>
 #include <linux/pm_runtime.h>
@@ -31,6 +31,7 @@
 #define SPI_CFG2_REG                      0x0028
 #define SPI_TX_SRC_REG_64                 0x002c
 #define SPI_RX_DST_REG_64                 0x0030
+#define SPI_CFG3_IPM_REG                  0x0040
 
 #define SPI_CFG0_SCK_HIGH_OFFSET          0
 #define SPI_CFG0_SCK_LOW_OFFSET           8
 #define SPI_CFG1_PACKET_LOOP_OFFSET       8
 #define SPI_CFG1_PACKET_LENGTH_OFFSET     16
 #define SPI_CFG1_GET_TICK_DLY_OFFSET      29
+#define SPI_CFG1_GET_TICK_DLY_OFFSET_V1   30
 
 #define SPI_CFG1_GET_TICK_DLY_MASK        0xe0000000
+#define SPI_CFG1_GET_TICK_DLY_MASK_V1     0xc0000000
+
 #define SPI_CFG1_CS_IDLE_MASK             0xff
 #define SPI_CFG1_PACKET_LOOP_MASK         0xff00
 #define SPI_CFG1_PACKET_LENGTH_MASK       0x3ff0000
+#define SPI_CFG1_IPM_PACKET_LENGTH_MASK   GENMASK(31, 16)
 #define SPI_CFG2_SCK_HIGH_OFFSET          0
 #define SPI_CFG2_SCK_LOW_OFFSET           16
 
 #define SPI_CMD_TX_ENDIAN            BIT(15)
 #define SPI_CMD_FINISH_IE            BIT(16)
 #define SPI_CMD_PAUSE_IE             BIT(17)
+#define SPI_CMD_IPM_NONIDLE_MODE     BIT(19)
+#define SPI_CMD_IPM_SPIM_LOOP        BIT(21)
+#define SPI_CMD_IPM_GET_TICKDLY_OFFSET    22
 
+#define SPI_CMD_IPM_GET_TICKDLY_MASK   GENMASK(24, 22)
+#define SPI_CFG3_IPM_HALF_DUPLEX_DIR           BIT(2)
+#define SPI_CFG3_IPM_HALF_DUPLEX_EN            BIT(3)
 #define MT8173_SPI_MAX_PAD_SEL 3
 
 #define MTK_SPI_PAUSE_INT_STATUS 0x2
@@ -78,6 +89,7 @@
 
 #define MTK_SPI_MAX_FIFO_SIZE 32U
 #define MTK_SPI_PACKET_SIZE 1024
+#define MTK_SPI_IPM_PACKET_SIZE SZ_64K
 #define MTK_SPI_32BITS_MASK  (0xffffffff)
 
 #define DMA_ADDR_EXT_BITS (36)
@@ -93,6 +105,9 @@ struct mtk_spi_compatible {
        bool dma_ext;
        /* some IC no need unprepare SPI clk */
        bool no_need_unprepare;
+       /* IPM design adjust and extend register to support more features */
+       bool ipm_design;
+
 };
 
 struct mtk_spi {
@@ -116,6 +131,12 @@ static const struct mtk_spi_compatible mt2712_compat = {
        .must_tx = true,
 };
 
+static const struct mtk_spi_compatible mtk_ipm_compat = {
+       .enhance_timing = true,
+       .dma_ext = true,
+       .ipm_design = true,
+};
+
 static const struct mtk_spi_compatible mt6765_compat = {
        .need_pad_sel = true,
        .must_tx = true,
@@ -157,6 +178,9 @@ static const struct mtk_chip_config mtk_default_chip_info = {
 };
 
 static const struct of_device_id mtk_spi_of_match[] = {
+       { .compatible = "mediatek,spi-ipm",
+               .data = (void *)&mtk_ipm_compat,
+       },
        { .compatible = "mediatek,mt2701-spi",
                .data = (void *)&mtk_common_compat,
        },
@@ -275,12 +299,11 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi)
        return 0;
 }
 
-static int mtk_spi_prepare_message(struct spi_master *master,
-                                  struct spi_message *msg)
+static int mtk_spi_hw_init(struct spi_master *master,
+                          struct spi_device *spi)
 {
        u16 cpha, cpol;
        u32 reg_val;
-       struct spi_device *spi = msg->spi;
        struct mtk_chip_config *chip_config = spi->controller_data;
        struct mtk_spi *mdata = spi_master_get_devdata(master);
 
@@ -288,6 +311,15 @@ static int mtk_spi_prepare_message(struct spi_master *master,
        cpol = spi->mode & SPI_CPOL ? 1 : 0;
 
        reg_val = readl(mdata->base + SPI_CMD_REG);
+       if (mdata->dev_comp->ipm_design) {
+               /* SPI transfer without idle time until packet length done */
+               reg_val |= SPI_CMD_IPM_NONIDLE_MODE;
+               if (spi->mode & SPI_LOOP)
+                       reg_val |= SPI_CMD_IPM_SPIM_LOOP;
+               else
+                       reg_val &= ~SPI_CMD_IPM_SPIM_LOOP;
+       }
+
        if (cpha)
                reg_val |= SPI_CMD_CPHA;
        else
@@ -345,17 +377,39 @@ static int mtk_spi_prepare_message(struct spi_master *master,
                       mdata->base + SPI_PAD_SEL_REG);
 
        /* tick delay */
-       reg_val = readl(mdata->base + SPI_CFG1_REG);
-       reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
-       reg_val |= ((chip_config->tick_delay & 0x7)
-               << SPI_CFG1_GET_TICK_DLY_OFFSET);
-       writel(reg_val, mdata->base + SPI_CFG1_REG);
+       if (mdata->dev_comp->enhance_timing) {
+               if (mdata->dev_comp->ipm_design) {
+                       reg_val = readl(mdata->base + SPI_CMD_REG);
+                       reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK;
+                       reg_val |= ((chip_config->tick_delay & 0x7)
+                                   << SPI_CMD_IPM_GET_TICKDLY_OFFSET);
+                       writel(reg_val, mdata->base + SPI_CMD_REG);
+               } else {
+                       reg_val = readl(mdata->base + SPI_CFG1_REG);
+                       reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
+                       reg_val |= ((chip_config->tick_delay & 0x7)
+                                   << SPI_CFG1_GET_TICK_DLY_OFFSET);
+                       writel(reg_val, mdata->base + SPI_CFG1_REG);
+               }
+       } else {
+               reg_val = readl(mdata->base + SPI_CFG1_REG);
+               reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1;
+               reg_val |= ((chip_config->tick_delay & 0x3)
+                           << SPI_CFG1_GET_TICK_DLY_OFFSET_V1);
+               writel(reg_val, mdata->base + SPI_CFG1_REG);
+       }
 
        /* set hw cs timing */
        mtk_spi_set_hw_cs_timing(spi);
        return 0;
 }
 
+static int mtk_spi_prepare_message(struct spi_master *master,
+                                  struct spi_message *msg)
+{
+       return mtk_spi_hw_init(master, msg->spi);
+}
+
 static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
 {
        u32 reg_val;
@@ -377,13 +431,13 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
 }
 
 static void mtk_spi_prepare_transfer(struct spi_master *master,
-                                    struct spi_transfer *xfer)
+                                    u32 speed_hz)
 {
        u32 div, sck_time, reg_val;
        struct mtk_spi *mdata = spi_master_get_devdata(master);
 
-       if (xfer->speed_hz < mdata->spi_clk_hz / 2)
-               div = DIV_ROUND_UP(mdata->spi_clk_hz, xfer->speed_hz);
+       if (speed_hz < mdata->spi_clk_hz / 2)
+               div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz);
        else
                div = 1;
 
@@ -414,12 +468,24 @@ static void mtk_spi_setup_packet(struct spi_master *master)
        u32 packet_size, packet_loop, reg_val;
        struct mtk_spi *mdata = spi_master_get_devdata(master);
 
-       packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE);
+       if (mdata->dev_comp->ipm_design)
+               packet_size = min_t(u32,
+                                   mdata->xfer_len,
+                                   MTK_SPI_IPM_PACKET_SIZE);
+       else
+               packet_size = min_t(u32,
+                                   mdata->xfer_len,
+                                   MTK_SPI_PACKET_SIZE);
+
        packet_loop = mdata->xfer_len / packet_size;
 
        reg_val = readl(mdata->base + SPI_CFG1_REG);
-       reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK);
+       if (mdata->dev_comp->ipm_design)
+               reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK;
+       else
+               reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK;
        reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
+       reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK;
        reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
        writel(reg_val, mdata->base + SPI_CFG1_REG);
 }
@@ -514,7 +580,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
        mdata->cur_transfer = xfer;
        mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
        mdata->num_xfered = 0;
-       mtk_spi_prepare_transfer(master, xfer);
+       mtk_spi_prepare_transfer(master, xfer->speed_hz);
        mtk_spi_setup_packet(master);
 
        if (xfer->tx_buf) {
@@ -547,7 +613,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,
        mdata->cur_transfer = xfer;
        mdata->num_xfered = 0;
 
-       mtk_spi_prepare_transfer(master, xfer);
+       mtk_spi_prepare_transfer(master, xfer->speed_hz);
 
        cmd = readl(mdata->base + SPI_CMD_REG);
        if (xfer->tx_buf)
@@ -582,6 +648,19 @@ static int mtk_spi_transfer_one(struct spi_master *master,
                                struct spi_device *spi,
                                struct spi_transfer *xfer)
 {
+       struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
+       u32 reg_val = 0;
+
+       /* prepare xfer direction and duplex mode */
+       if (mdata->dev_comp->ipm_design) {
+               if (!xfer->tx_buf || !xfer->rx_buf) {
+                       reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN;
+                       if (xfer->rx_buf)
+                               reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR;
+               }
+               writel(reg_val, mdata->base + SPI_CFG3_IPM_REG);
+       }
+
        if (master->can_dma(master, spi, xfer))
                return mtk_spi_dma_transfer(master, spi, xfer);
        else
@@ -605,8 +684,9 @@ static int mtk_spi_setup(struct spi_device *spi)
        if (!spi->controller_data)
                spi->controller_data = (void *)&mtk_default_chip_info;
 
-       if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio))
-               gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+       if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod)
+               /* CS de-asserted, gpiolib will handle inversion */
+               gpiod_direction_output(spi->cs_gpiod, 0);
 
        return 0;
 }
@@ -730,6 +810,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
        master->can_dma = mtk_spi_can_dma;
        master->setup = mtk_spi_setup;
        master->set_cs_timing = mtk_spi_set_hw_cs_timing;
+       master->use_gpio_descriptors = true;
 
        of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
        if (!of_id) {
@@ -746,6 +827,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
 
        if (mdata->dev_comp->must_tx)
                master->flags = SPI_MASTER_MUST_TX;
+       if (mdata->dev_comp->ipm_design)
+               master->mode_bits |= SPI_LOOP;
 
        if (mdata->dev_comp->need_pad_sel) {
                mdata->pad_num = of_property_count_u32_elems(
@@ -853,25 +936,12 @@ static int mtk_spi_probe(struct platform_device *pdev)
                        goto err_disable_runtime_pm;
                }
 
-               if (!master->cs_gpios && master->num_chipselect > 1) {
+               if (!master->cs_gpiods && master->num_chipselect > 1) {
                        dev_err(&pdev->dev,
                                "cs_gpios not specified and num_chipselect > 1\n");
                        ret = -EINVAL;
                        goto err_disable_runtime_pm;
                }
-
-               if (master->cs_gpios) {
-                       for (i = 0; i < master->num_chipselect; i++) {
-                               ret = devm_gpio_request(&pdev->dev,
-                                                       master->cs_gpios[i],
-                                                       dev_name(&pdev->dev));
-                               if (ret) {
-                                       dev_err(&pdev->dev,
-                                               "can't get CS GPIO %i\n", i);
-                                       goto err_disable_runtime_pm;
-                               }
-                       }
-               }
        }
 
        if (mdata->dev_comp->dma_ext)
index 5c93730615f8d7eac53af6f4f91338a774e23518..94fb09696677f14a53f1b24375c4d9429a518252 100644 (file)
 
 #define CLK_TO_US(sp, clkcnt)          DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)
 
+struct mtk_nor_caps {
+       u8 dma_bits;
+
+       /* extra_dummy_bit is adding for the IP of new SoCs.
+        * Some new SoCs modify the timing of fetching registers' values
+        * and IDs of nor flash, they need a extra_dummy_bit which can add
+        * more clock cycles for fetching data.
+        */
+       u8 extra_dummy_bit;
+};
+
 struct mtk_nor {
        struct spi_controller *ctlr;
        struct device *dev;
@@ -104,11 +115,13 @@ struct mtk_nor {
        struct clk *spi_clk;
        struct clk *ctlr_clk;
        struct clk *axi_clk;
+       struct clk *axi_s_clk;
        unsigned int spi_freq;
        bool wbuf_en;
        bool has_irq;
        bool high_dma;
        struct completion op_done;
+       const struct mtk_nor_caps *caps;
 };
 
 static inline void mtk_nor_rmw(struct mtk_nor *sp, u32 reg, u32 set, u32 clr)
@@ -554,7 +567,12 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op)
        }
 
        // trigger op
-       writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT);
+       if (rx_len)
+               writel(prg_len * BITS_PER_BYTE + sp->caps->extra_dummy_bit,
+                      sp->base + MTK_NOR_REG_PRG_CNT);
+       else
+               writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT);
+
        ret = mtk_nor_cmd_exec(sp, MTK_NOR_CMD_PROGRAM,
                               prg_len * BITS_PER_BYTE);
        if (ret)
@@ -674,6 +692,7 @@ static void mtk_nor_disable_clk(struct mtk_nor *sp)
        clk_disable_unprepare(sp->spi_clk);
        clk_disable_unprepare(sp->ctlr_clk);
        clk_disable_unprepare(sp->axi_clk);
+       clk_disable_unprepare(sp->axi_s_clk);
 }
 
 static int mtk_nor_enable_clk(struct mtk_nor *sp)
@@ -697,6 +716,14 @@ static int mtk_nor_enable_clk(struct mtk_nor *sp)
                return ret;
        }
 
+       ret = clk_prepare_enable(sp->axi_s_clk);
+       if (ret) {
+               clk_disable_unprepare(sp->spi_clk);
+               clk_disable_unprepare(sp->ctlr_clk);
+               clk_disable_unprepare(sp->axi_clk);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -743,9 +770,25 @@ static const struct spi_controller_mem_ops mtk_nor_mem_ops = {
        .exec_op = mtk_nor_exec_op
 };
 
+static const struct mtk_nor_caps mtk_nor_caps_mt8173 = {
+       .dma_bits = 32,
+       .extra_dummy_bit = 0,
+};
+
+static const struct mtk_nor_caps mtk_nor_caps_mt8186 = {
+       .dma_bits = 32,
+       .extra_dummy_bit = 1,
+};
+
+static const struct mtk_nor_caps mtk_nor_caps_mt8192 = {
+       .dma_bits = 36,
+       .extra_dummy_bit = 0,
+};
+
 static const struct of_device_id mtk_nor_match[] = {
-       { .compatible = "mediatek,mt8192-nor", .data = (void *)36 },
-       { .compatible = "mediatek,mt8173-nor", .data = (void *)32 },
+       { .compatible = "mediatek,mt8173-nor", .data = &mtk_nor_caps_mt8173 },
+       { .compatible = "mediatek,mt8186-nor", .data = &mtk_nor_caps_mt8186 },
+       { .compatible = "mediatek,mt8192-nor", .data = &mtk_nor_caps_mt8192 },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mtk_nor_match);
@@ -754,10 +797,10 @@ static int mtk_nor_probe(struct platform_device *pdev)
 {
        struct spi_controller *ctlr;
        struct mtk_nor *sp;
+       struct mtk_nor_caps *caps;
        void __iomem *base;
-       struct clk *spi_clk, *ctlr_clk, *axi_clk;
+       struct clk *spi_clk, *ctlr_clk, *axi_clk, *axi_s_clk;
        int ret, irq;
-       unsigned long dma_bits;
 
        base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
@@ -775,10 +818,16 @@ static int mtk_nor_probe(struct platform_device *pdev)
        if (IS_ERR(axi_clk))
                return PTR_ERR(axi_clk);
 
-       dma_bits = (unsigned long)of_device_get_match_data(&pdev->dev);
-       if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits))) {
-               dev_err(&pdev->dev, "failed to set dma mask(%lu)\n", dma_bits);
-               return -EINVAL;
+       axi_s_clk = devm_clk_get_optional(&pdev->dev, "axi_s");
+       if (IS_ERR(axi_s_clk))
+               return PTR_ERR(axi_s_clk);
+
+       caps = (struct mtk_nor_caps *)of_device_get_match_data(&pdev->dev);
+
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(caps->dma_bits));
+       if (ret) {
+               dev_err(&pdev->dev, "failed to set dma mask(%u)\n", caps->dma_bits);
+               return ret;
        }
 
        ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp));
@@ -808,7 +857,9 @@ static int mtk_nor_probe(struct platform_device *pdev)
        sp->spi_clk = spi_clk;
        sp->ctlr_clk = ctlr_clk;
        sp->axi_clk = axi_clk;
-       sp->high_dma = (dma_bits > 32);
+       sp->axi_s_clk = axi_s_clk;
+       sp->caps = caps;
+       sp->high_dma = caps->dma_bits > 32;
        sp->buffer = dmam_alloc_coherent(&pdev->dev,
                                MTK_NOR_BOUNCE_BUF_SIZE + MTK_NOR_DMA_ALIGN,
                                &sp->buffer_dma, GFP_KERNEL);
index b62471ab6d7f25200aed6869d90c940ef2574904..ba67dbed9fb8f902dcee29c08a648d4f9d7e6195 100644 (file)
@@ -201,7 +201,7 @@ struct fiu_data {
        int fiu_max;
 };
 
-static const struct npcm_fiu_info npxm7xx_fiu_info[] = {
+static const struct npcm_fiu_info npcm7xx_fiu_info[] = {
        {.name = "FIU0", .fiu_id = FIU0,
                .max_map_size = MAP_SIZE_128MB, .max_cs = 2},
        {.name = "FIU3", .fiu_id = FIU3,
@@ -209,8 +209,8 @@ static const struct npcm_fiu_info npxm7xx_fiu_info[] = {
        {.name = "FIUX", .fiu_id = FIUX,
                .max_map_size = MAP_SIZE_16MB, .max_cs = 2} };
 
-static const struct fiu_data npxm7xx_fiu_data = {
-       .npcm_fiu_data_info = npxm7xx_fiu_info,
+static const struct fiu_data npcm7xx_fiu_data = {
+       .npcm_fiu_data_info = npcm7xx_fiu_info,
        .fiu_max = 3,
 };
 
@@ -664,14 +664,13 @@ static const struct spi_controller_mem_ops npcm_fiu_mem_ops = {
 };
 
 static const struct of_device_id npcm_fiu_dt_ids[] = {
-       { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data  },
+       { .compatible = "nuvoton,npcm750-fiu", .data = &npcm7xx_fiu_data  },
        { /* sentinel */ }
 };
 
 static int npcm_fiu_probe(struct platform_device *pdev)
 {
        const struct fiu_data *fiu_data_match;
-       const struct of_device_id *match;
        struct device *dev = &pdev->dev;
        struct spi_controller *ctrl;
        struct npcm_fiu_spi *fiu;
@@ -685,13 +684,12 @@ static int npcm_fiu_probe(struct platform_device *pdev)
 
        fiu = spi_controller_get_devdata(ctrl);
 
-       match = of_match_device(npcm_fiu_dt_ids, dev);
-       if (!match || !match->data) {
+       fiu_data_match = of_device_get_match_data(dev);
+       if (!fiu_data_match) {
                dev_err(dev, "No compatible OF match\n");
                return -ENODEV;
        }
 
-       fiu_data_match = match->data;
        id = of_alias_get_id(dev->of_node, "fiu");
        if (id < 0 || id >= fiu_data_match->fiu_max) {
                dev_err(dev, "Invalid platform device id: %d\n", id);
index f86433b29260e0e95dadc34ceac74aa34f6bfb66..7e5c09a7d48904bafb69cfc74c25897542e5ff80 100644 (file)
@@ -591,18 +591,16 @@ static int pic32_spi_setup(struct spi_device *spi)
         * unreliable/erroneous SPI transactions.
         * To avoid that we will always handle /CS by toggling GPIO.
         */
-       if (!gpio_is_valid(spi->cs_gpio))
+       if (!spi->cs_gpiod)
                return -EINVAL;
 
-       gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
-
        return 0;
 }
 
 static void pic32_spi_cleanup(struct spi_device *spi)
 {
-       /* de-activate cs-gpio */
-       gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+       /* de-activate cs-gpio, gpiolib will handle inversion */
+       gpiod_direction_output(spi->cs_gpiod, 0);
 }
 
 static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev)
@@ -784,6 +782,7 @@ static int pic32_spi_probe(struct platform_device *pdev)
        master->unprepare_message       = pic32_spi_unprepare_message;
        master->prepare_transfer_hardware       = pic32_spi_prepare_hardware;
        master->unprepare_transfer_hardware     = pic32_spi_unprepare_hardware;
+       master->use_gpio_descriptors = true;
 
        /* optional DMA support */
        ret = pic32_spi_dma_prep(pic32s, &pdev->dev);
index 2e134eb4bd2c9b0f705bd28f0fe87da876df7d5e..861b21c6350432029719714f82780727db386dd2 100644 (file)
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
 
-enum {
-       PORT_QUARK_X1000,
-       PORT_BYT,
-       PORT_MRFLD,
-       PORT_BSW0,
-       PORT_BSW1,
-       PORT_BSW2,
-       PORT_CE4100,
-       PORT_LPT0,
-       PORT_LPT1,
-};
+#define PCI_DEVICE_ID_INTEL_QUARK_X1000                0x0935
+#define PCI_DEVICE_ID_INTEL_BYT                        0x0f0e
+#define PCI_DEVICE_ID_INTEL_MRFLD              0x1194
+#define PCI_DEVICE_ID_INTEL_BSW0               0x228e
+#define PCI_DEVICE_ID_INTEL_BSW1               0x2290
+#define PCI_DEVICE_ID_INTEL_BSW2               0x22ac
+#define PCI_DEVICE_ID_INTEL_CE4100             0x2e6a
+#define PCI_DEVICE_ID_INTEL_LPT0_0             0x9c65
+#define PCI_DEVICE_ID_INTEL_LPT0_1             0x9c66
+#define PCI_DEVICE_ID_INTEL_LPT1_0             0x9ce5
+#define PCI_DEVICE_ID_INTEL_LPT1_1             0x9ce6
 
 struct pxa_spi_info {
-       enum pxa_ssp_type type;
-       int port_id;
-       int num_chipselect;
-       unsigned long max_clk_rate;
-
-       /* DMA channel request parameters */
-       bool (*dma_filter)(struct dma_chan *chan, void *param);
-       void *tx_param;
-       void *rx_param;
-
-       int dma_burst_size;
-
-       int (*setup)(struct pci_dev *pdev, struct pxa_spi_info *c);
+       int (*setup)(struct pci_dev *pdev, struct pxa2xx_spi_controller *c);
 };
 
 static struct dw_dma_slave byt_tx_param = { .dst_id = 0 };
@@ -65,6 +53,24 @@ static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 };
 static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 };
 static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 };
 
+static void pxa2xx_spi_pci_clk_unregister(void *clk)
+{
+       clk_unregister(clk);
+}
+
+static int pxa2xx_spi_pci_clk_register(struct pci_dev *dev, struct ssp_device *ssp,
+                                      unsigned long rate)
+{
+       char buf[40];
+
+       snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id);
+       ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, rate);
+       if (IS_ERR(ssp->clk))
+               return PTR_ERR(ssp->clk);
+
+       return devm_add_action_or_reset(&dev->dev, pxa2xx_spi_pci_clk_unregister, ssp->clk);
+}
+
 static bool lpss_dma_filter(struct dma_chan *chan, void *param)
 {
        struct dw_dma_slave *dws = param;
@@ -76,55 +82,131 @@ static bool lpss_dma_filter(struct dma_chan *chan, void *param)
        return true;
 }
 
-static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+static void lpss_dma_put_device(void *dma_dev)
 {
+       pci_dev_put(dma_dev);
+}
+
+static int lpss_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c)
+{
+       struct ssp_device *ssp = &c->ssp;
+       struct dw_dma_slave *tx, *rx;
        struct pci_dev *dma_dev;
+       int ret;
 
-       c->num_chipselect = 1;
-       c->max_clk_rate = 50000000;
+       switch (dev->device) {
+       case PCI_DEVICE_ID_INTEL_BYT:
+               ssp->type = LPSS_BYT_SSP;
+               ssp->port_id = 0;
+               c->tx_param = &byt_tx_param;
+               c->rx_param = &byt_rx_param;
+               break;
+       case PCI_DEVICE_ID_INTEL_BSW0:
+               ssp->type = LPSS_BSW_SSP;
+               ssp->port_id = 0;
+               c->tx_param = &bsw0_tx_param;
+               c->rx_param = &bsw0_rx_param;
+               break;
+       case PCI_DEVICE_ID_INTEL_BSW1:
+               ssp->type = LPSS_BSW_SSP;
+               ssp->port_id = 1;
+               c->tx_param = &bsw1_tx_param;
+               c->rx_param = &bsw1_rx_param;
+               break;
+       case PCI_DEVICE_ID_INTEL_BSW2:
+               ssp->type = LPSS_BSW_SSP;
+               ssp->port_id = 2;
+               c->tx_param = &bsw2_tx_param;
+               c->rx_param = &bsw2_rx_param;
+               break;
+       case PCI_DEVICE_ID_INTEL_LPT0_0:
+       case PCI_DEVICE_ID_INTEL_LPT1_0:
+               ssp->type = LPSS_LPT_SSP;
+               ssp->port_id = 0;
+               c->tx_param = &lpt0_tx_param;
+               c->rx_param = &lpt0_rx_param;
+               break;
+       case PCI_DEVICE_ID_INTEL_LPT0_1:
+       case PCI_DEVICE_ID_INTEL_LPT1_1:
+               ssp->type = LPSS_LPT_SSP;
+               ssp->port_id = 1;
+               c->tx_param = &lpt1_tx_param;
+               c->rx_param = &lpt1_rx_param;
+               break;
+       default:
+               return -ENODEV;
+       }
 
-       dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       c->num_chipselect = 1;
 
-       if (c->tx_param) {
-               struct dw_dma_slave *slave = c->tx_param;
+       ret = pxa2xx_spi_pci_clk_register(dev, ssp, 50000000);
+       if (ret)
+               return ret;
 
-               slave->dma_dev = &dma_dev->dev;
-               slave->m_master = 0;
-               slave->p_master = 1;
-       }
+       dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev);
+       if (ret)
+               return ret;
 
-       if (c->rx_param) {
-               struct dw_dma_slave *slave = c->rx_param;
+       tx = c->tx_param;
+       tx->dma_dev = &dma_dev->dev;
+       tx->m_master = 0;
+       tx->p_master = 1;
 
-               slave->dma_dev = &dma_dev->dev;
-               slave->m_master = 0;
-               slave->p_master = 1;
-       }
+       rx = c->rx_param;
+       rx->dma_dev = &dma_dev->dev;
+       rx->m_master = 0;
+       rx->p_master = 1;
 
        c->dma_filter = lpss_dma_filter;
+       c->dma_burst_size = 1;
+       c->enable_dma = 1;
        return 0;
 }
 
-static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
+static const struct pxa_spi_info lpss_info_config = {
+       .setup = lpss_spi_setup,
+};
+
+static int ce4100_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c)
 {
-       struct pci_dev *dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0));
+       struct ssp_device *ssp = &c->ssp;
+
+       ssp->type = PXA25x_SSP;
+       ssp->port_id = dev->devfn;
+       c->num_chipselect = dev->devfn;
+
+       return pxa2xx_spi_pci_clk_register(dev, ssp, 3686400);
+}
+
+static const struct pxa_spi_info ce4100_info_config = {
+       .setup = ce4100_spi_setup,
+};
+
+static int mrfld_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c)
+{
+       struct ssp_device *ssp = &c->ssp;
        struct dw_dma_slave *tx, *rx;
+       struct pci_dev *dma_dev;
+       int ret;
+
+       ssp->type = MRFLD_SSP;
 
        switch (PCI_FUNC(dev->devfn)) {
        case 0:
-               c->port_id = 3;
+               ssp->port_id = 3;
                c->num_chipselect = 1;
                c->tx_param = &mrfld3_tx_param;
                c->rx_param = &mrfld3_rx_param;
                break;
        case 1:
-               c->port_id = 5;
+               ssp->port_id = 5;
                c->num_chipselect = 4;
                c->tx_param = &mrfld5_tx_param;
                c->rx_param = &mrfld5_rx_param;
                break;
        case 2:
-               c->port_id = 6;
+               ssp->port_id = 6;
                c->num_chipselect = 1;
                c->tx_param = &mrfld6_tx_param;
                c->rx_param = &mrfld6_rx_param;
@@ -133,6 +215,15 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
                return -ENODEV;
        }
 
+       ret = pxa2xx_spi_pci_clk_register(dev, ssp, 25000000);
+       if (ret)
+               return ret;
+
+       dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0));
+       ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev);
+       if (ret)
+               return ret;
+
        tx = c->tx_param;
        tx->dma_dev = &dma_dev->dev;
 
@@ -141,81 +232,38 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)
 
        c->dma_filter = lpss_dma_filter;
        c->dma_burst_size = 8;
+       c->enable_dma = 1;
        return 0;
 }
 
-static struct pxa_spi_info spi_info_configs[] = {
-       [PORT_CE4100] = {
-               .type = PXA25x_SSP,
-               .port_id =  -1,
-               .num_chipselect = -1,
-               .max_clk_rate = 3686400,
-       },
-       [PORT_BYT] = {
-               .type = LPSS_BYT_SSP,
-               .port_id = 0,
-               .setup = lpss_spi_setup,
-               .tx_param = &byt_tx_param,
-               .rx_param = &byt_rx_param,
-       },
-       [PORT_BSW0] = {
-               .type = LPSS_BSW_SSP,
-               .port_id = 0,
-               .setup = lpss_spi_setup,
-               .tx_param = &bsw0_tx_param,
-               .rx_param = &bsw0_rx_param,
-       },
-       [PORT_BSW1] = {
-               .type = LPSS_BSW_SSP,
-               .port_id = 1,
-               .setup = lpss_spi_setup,
-               .tx_param = &bsw1_tx_param,
-               .rx_param = &bsw1_rx_param,
-       },
-       [PORT_BSW2] = {
-               .type = LPSS_BSW_SSP,
-               .port_id = 2,
-               .setup = lpss_spi_setup,
-               .tx_param = &bsw2_tx_param,
-               .rx_param = &bsw2_rx_param,
-       },
-       [PORT_MRFLD] = {
-               .type = MRFLD_SSP,
-               .max_clk_rate = 25000000,
-               .setup = mrfld_spi_setup,
-       },
-       [PORT_QUARK_X1000] = {
-               .type = QUARK_X1000_SSP,
-               .port_id = -1,
-               .num_chipselect = 1,
-               .max_clk_rate = 50000000,
-       },
-       [PORT_LPT0] = {
-               .type = LPSS_LPT_SSP,
-               .port_id = 0,
-               .setup = lpss_spi_setup,
-               .tx_param = &lpt0_tx_param,
-               .rx_param = &lpt0_rx_param,
-       },
-       [PORT_LPT1] = {
-               .type = LPSS_LPT_SSP,
-               .port_id = 1,
-               .setup = lpss_spi_setup,
-               .tx_param = &lpt1_tx_param,
-               .rx_param = &lpt1_rx_param,
-       },
+static const struct pxa_spi_info mrfld_info_config = {
+       .setup = mrfld_spi_setup,
+};
+
+static int qrk_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c)
+{
+       struct ssp_device *ssp = &c->ssp;
+
+       ssp->type = QUARK_X1000_SSP;
+       ssp->port_id = dev->devfn;
+       c->num_chipselect = 1;
+
+       return pxa2xx_spi_pci_clk_register(dev, ssp, 50000000);
+}
+
+static const struct pxa_spi_info qrk_info_config = {
+       .setup = qrk_spi_setup,
 };
 
 static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
                const struct pci_device_id *ent)
 {
+       const struct pxa_spi_info *info;
        struct platform_device_info pi;
        int ret;
        struct platform_device *pdev;
        struct pxa2xx_spi_controller spi_pdata;
        struct ssp_device *ssp;
-       struct pxa_spi_info *c;
-       char buf[40];
 
        ret = pcim_enable_device(dev);
        if (ret)
@@ -225,27 +273,17 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
        if (ret)
                return ret;
 
-       c = &spi_info_configs[ent->driver_data];
-       if (c->setup) {
-               ret = c->setup(dev, c);
-               if (ret)
-                       return ret;
-       }
-
        memset(&spi_pdata, 0, sizeof(spi_pdata));
-       spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn;
-       spi_pdata.dma_filter = c->dma_filter;
-       spi_pdata.tx_param = c->tx_param;
-       spi_pdata.rx_param = c->rx_param;
-       spi_pdata.enable_dma = c->rx_param && c->tx_param;
-       spi_pdata.dma_burst_size = c->dma_burst_size ? c->dma_burst_size : 1;
 
        ssp = &spi_pdata.ssp;
        ssp->dev = &dev->dev;
        ssp->phys_base = pci_resource_start(dev, 0);
        ssp->mmio_base = pcim_iomap_table(dev)[0];
-       ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
-       ssp->type = c->type;
+
+       info = (struct pxa_spi_info *)ent->driver_data;
+       ret = info->setup(dev, &spi_pdata);
+       if (ret)
+               return ret;
 
        pci_set_master(dev);
 
@@ -254,14 +292,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
                return ret;
        ssp->irq = pci_irq_vector(dev, 0);
 
-       snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id);
-       ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0,
-                                          c->max_clk_rate);
-       if (IS_ERR(ssp->clk))
-               return PTR_ERR(ssp->clk);
-
        memset(&pi, 0, sizeof(pi));
-       pi.fwnode = dev->dev.fwnode;
+       pi.fwnode = dev_fwnode(&dev->dev);
        pi.parent = &dev->dev;
        pi.name = "pxa2xx-spi";
        pi.id = ssp->port_id;
@@ -269,10 +301,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
        pi.size_data = sizeof(spi_pdata);
 
        pdev = platform_device_register_full(&pi);
-       if (IS_ERR(pdev)) {
-               clk_unregister(ssp->clk);
+       if (IS_ERR(pdev))
                return PTR_ERR(pdev);
-       }
 
        pci_set_drvdata(dev, pdev);
 
@@ -282,26 +312,22 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
 static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
 {
        struct platform_device *pdev = pci_get_drvdata(dev);
-       struct pxa2xx_spi_controller *spi_pdata;
-
-       spi_pdata = dev_get_platdata(&pdev->dev);
 
        platform_device_unregister(pdev);
-       clk_unregister(spi_pdata->ssp.clk);
 }
 
 static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
-       { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 },
-       { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
-       { PCI_VDEVICE(INTEL, 0x1194), PORT_MRFLD },
-       { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
-       { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
-       { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 },
-       { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
-       { PCI_VDEVICE(INTEL, 0x9c65), PORT_LPT0 },
-       { PCI_VDEVICE(INTEL, 0x9c66), PORT_LPT1 },
-       { PCI_VDEVICE(INTEL, 0x9ce5), PORT_LPT0 },
-       { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT1 },
+       { PCI_DEVICE_DATA(INTEL, QUARK_X1000, &qrk_info_config) },
+       { PCI_DEVICE_DATA(INTEL, BYT, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, MRFLD, &mrfld_info_config) },
+       { PCI_DEVICE_DATA(INTEL, BSW0, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, BSW1, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, BSW2, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, CE4100, &ce4100_info_config) },
+       { PCI_DEVICE_DATA(INTEL, LPT0_0, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, LPT0_1, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, LPT1_0, &lpss_info_config) },
+       { PCI_DEVICE_DATA(INTEL, LPT1_1, &lpss_info_config) },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
index e88f86274eeb0943f448f1c7302d3b357a80d3d4..edb42d08857d0f0115276204676ea4bf3fd5a9d9 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/gpio/consumer.h>
-#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -1163,57 +1162,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller)
        return 0;
 }
 
-static void cleanup_cs(struct spi_device *spi)
-{
-       if (!gpio_is_valid(spi->cs_gpio))
-               return;
-
-       gpio_free(spi->cs_gpio);
-       spi->cs_gpio = -ENOENT;
-}
-
-static int setup_cs(struct spi_device *spi, struct chip_data *chip,
-                   struct pxa2xx_spi_chip *chip_info)
-{
-       struct driver_data *drv_data = spi_controller_get_devdata(spi->controller);
-
-       if (chip == NULL)
-               return 0;
-
-       if (chip_info == NULL)
-               return 0;
-
-       if (drv_data->ssp_type == CE4100_SSP)
-               return 0;
-
-       /*
-        * NOTE: setup() can be called multiple times, possibly with
-        * different chip_info, release previously requested GPIO.
-        */
-       cleanup_cs(spi);
-
-       if (gpio_is_valid(chip_info->gpio_cs)) {
-               int gpio = chip_info->gpio_cs;
-               int err;
-
-               err = gpio_request(gpio, "SPI_CS");
-               if (err) {
-                       dev_err(&spi->dev, "failed to request chip select GPIO%d\n", gpio);
-                       return err;
-               }
-
-               err = gpio_direction_output(gpio, !(spi->mode & SPI_CS_HIGH));
-               if (err) {
-                       gpio_free(gpio);
-                       return err;
-               }
-
-               spi->cs_gpio = gpio;
-       }
-
-       return 0;
-}
-
 static int setup(struct spi_device *spi)
 {
        struct pxa2xx_spi_chip *chip_info;
@@ -1222,7 +1170,6 @@ static int setup(struct spi_device *spi)
        struct driver_data *drv_data =
                spi_controller_get_devdata(spi->controller);
        uint tx_thres, tx_hi_thres, rx_thres;
-       int err;
 
        switch (drv_data->ssp_type) {
        case QUARK_X1000_SSP:
@@ -1365,21 +1312,13 @@ static int setup(struct spi_device *spi)
 
        spi_set_ctldata(spi, chip);
 
-       if (drv_data->ssp_type == CE4100_SSP)
-               return 0;
-
-       err = setup_cs(spi, chip, chip_info);
-       if (err)
-               kfree(chip);
-
-       return err;
+       return 0;
 }
 
 static void cleanup(struct spi_device *spi)
 {
        struct chip_data *chip = spi_get_ctldata(spi);
 
-       cleanup_cs(spi);
        kfree(chip);
 }
 
@@ -1455,6 +1394,11 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP },
+       /* RPL-S */
+       { PCI_VDEVICE(INTEL, 0x7a2a), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x7a2b), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x7a79), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x7a7b), LPSS_CNL_SSP },
        /* ADL-S */
        { PCI_VDEVICE(INTEL, 0x7aaa), LPSS_CNL_SSP },
        { PCI_VDEVICE(INTEL, 0x7aab), LPSS_CNL_SSP },
index d39dec6d1c91e8e68fc46e48c464ad8a0ac1edc6..00d6084306b4a366d89ff7643daa586504371419 100644 (file)
@@ -593,7 +593,6 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
 {
        struct spi_qup *controller = dev_id;
        u32 opflags, qup_err, spi_err;
-       unsigned long flags;
        int error = 0;
 
        qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
@@ -625,10 +624,10 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
                error = -EIO;
        }
 
-       spin_lock_irqsave(&controller->lock, flags);
+       spin_lock(&controller->lock);
        if (!controller->error)
                controller->error = error;
-       spin_unlock_irqrestore(&controller->lock, flags);
+       spin_unlock(&controller->lock);
 
        if (spi_qup_is_dma_xfer(controller->mode)) {
                writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
index a46b38544027321e5f9a8b70a3dd778ee3c5d245..bd87d3c92dd335f03c49a7f40b234c61f9cff579 100644 (file)
@@ -624,10 +624,8 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
 
        /* Find the irq */
        ret = platform_get_irq(pdev, 0);
-       if (ret < 0) {
-               dev_err(dev, "Failed to get the irq\n");
+       if (ret < 0)
                goto err_irq;
-       }
 
        ret = devm_request_irq(dev, ret, rockchip_sfc_irq_handler,
                               0, pdev->name, sfc);
index c6a1bb09be056683a47cce906bf5f02730172c80..cdc16eecaf6b581ec11735d33bd5de6a6f11b3b8 100644 (file)
 #define INT_TF_OVERFLOW                                (1 << 1)
 #define INT_RF_UNDERFLOW                       (1 << 2)
 #define INT_RF_OVERFLOW                                (1 << 3)
-#define INT_RF_FULL                                    (1 << 4)
+#define INT_RF_FULL                            (1 << 4)
+#define INT_CS_INACTIVE                                (1 << 6)
 
 /* Bit fields in ICR, 4bit */
 #define ICR_MASK                                       0x0f
@@ -194,6 +195,8 @@ struct rockchip_spi {
        bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
        bool slave_abort;
+       bool cs_inactive; /* spi slave tansmition stop when cs inactive */
+       struct spi_transfer *xfer; /* Store xfer temporarily */
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
@@ -275,8 +278,9 @@ static void rockchip_spi_handle_err(struct spi_controller *ctlr,
         */
        spi_enable_chip(rs, false);
 
-       /* make sure all interrupts are masked */
+       /* make sure all interrupts are masked and status cleared */
        writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+       writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
 
        if (atomic_read(&rs->state) & TXDMA)
                dmaengine_terminate_async(ctlr->dma_tx);
@@ -343,6 +347,15 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)
        struct spi_controller *ctlr = dev_id;
        struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 
+       /* When int_cs_inactive comes, spi slave abort */
+       if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_IMR) & INT_CS_INACTIVE) {
+               ctlr->slave_abort(ctlr);
+               writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+               writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
+
+               return IRQ_HANDLED;
+       }
+
        if (rs->tx_left)
                rockchip_spi_pio_writer(rs);
 
@@ -350,6 +363,7 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)
        if (!rs->rx_left) {
                spi_enable_chip(rs, false);
                writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+               writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
                spi_finalize_current_transfer(ctlr);
        }
 
@@ -357,14 +371,18 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)
 }
 
 static int rockchip_spi_prepare_irq(struct rockchip_spi *rs,
-               struct spi_transfer *xfer)
+                                   struct spi_controller *ctlr,
+                                   struct spi_transfer *xfer)
 {
        rs->tx = xfer->tx_buf;
        rs->rx = xfer->rx_buf;
        rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;
        rs->rx_left = xfer->len / rs->n_bytes;
 
-       writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);
+       if (rs->cs_inactive)
+               writel_relaxed(INT_RF_FULL | INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR);
+       else
+               writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);
        spi_enable_chip(rs, true);
 
        if (rs->tx_left)
@@ -383,6 +401,9 @@ static void rockchip_spi_dma_rxcb(void *data)
        if (state & TXDMA && !rs->slave_abort)
                return;
 
+       if (rs->cs_inactive)
+               writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+
        spi_enable_chip(rs, false);
        spi_finalize_current_transfer(ctlr);
 }
@@ -423,14 +444,16 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
 
        atomic_set(&rs->state, 0);
 
+       rs->tx = xfer->tx_buf;
+       rs->rx = xfer->rx_buf;
+
        rxdesc = NULL;
        if (xfer->rx_buf) {
                struct dma_slave_config rxconf = {
                        .direction = DMA_DEV_TO_MEM,
                        .src_addr = rs->dma_addr_rx,
                        .src_addr_width = rs->n_bytes,
-                       .src_maxburst = rockchip_spi_calc_burst_size(xfer->len /
-                                                                    rs->n_bytes),
+                       .src_maxburst = rockchip_spi_calc_burst_size(xfer->len / rs->n_bytes),
                };
 
                dmaengine_slave_config(ctlr->dma_rx, &rxconf);
@@ -474,10 +497,13 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
        /* rx must be started before tx due to spi instinct */
        if (rxdesc) {
                atomic_or(RXDMA, &rs->state);
-               dmaengine_submit(rxdesc);
+               ctlr->dma_rx->cookie = dmaengine_submit(rxdesc);
                dma_async_issue_pending(ctlr->dma_rx);
        }
 
+       if (rs->cs_inactive)
+               writel_relaxed(INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR);
+
        spi_enable_chip(rs, true);
 
        if (txdesc) {
@@ -584,7 +610,42 @@ static size_t rockchip_spi_max_transfer_size(struct spi_device *spi)
 static int rockchip_spi_slave_abort(struct spi_controller *ctlr)
 {
        struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+       u32 rx_fifo_left;
+       struct dma_tx_state state;
+       enum dma_status status;
+
+       /* Get current dma rx point */
+       if (atomic_read(&rs->state) & RXDMA) {
+               dmaengine_pause(ctlr->dma_rx);
+               status = dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state);
+               if (status == DMA_ERROR) {
+                       rs->rx = rs->xfer->rx_buf;
+                       rs->xfer->len = 0;
+                       rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
+                       for (; rx_fifo_left; rx_fifo_left--)
+                               readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+                       goto out;
+               } else {
+                       rs->rx += rs->xfer->len - rs->n_bytes * state.residue;
+               }
+       }
+
+       /* Get the valid data left in rx fifo and set rs->xfer->len real rx size */
+       if (rs->rx) {
+               rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
+               for (; rx_fifo_left; rx_fifo_left--) {
+                       u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+
+                       if (rs->n_bytes == 1)
+                               *(u8 *)rs->rx = (u8)rxw;
+                       else
+                               *(u16 *)rs->rx = (u16)rxw;
+                       rs->rx += rs->n_bytes;
+               }
+               rs->xfer->len = (unsigned int)(rs->rx - rs->xfer->rx_buf);
+       }
 
+out:
        if (atomic_read(&rs->state) & RXDMA)
                dmaengine_terminate_sync(ctlr->dma_rx);
        if (atomic_read(&rs->state) & TXDMA)
@@ -626,7 +687,7 @@ static int rockchip_spi_transfer_one(
        }
 
        rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2;
-
+       rs->xfer = xfer;
        use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false;
 
        ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave);
@@ -636,7 +697,7 @@ static int rockchip_spi_transfer_one(
        if (use_dma)
                return rockchip_spi_prepare_dma(rs, ctlr, xfer);
 
-       return rockchip_spi_prepare_irq(rs, xfer);
+       return rockchip_spi_prepare_irq(rs, ctlr, xfer);
 }
 
 static bool rockchip_spi_can_dma(struct spi_controller *ctlr,
@@ -653,6 +714,29 @@ static bool rockchip_spi_can_dma(struct spi_controller *ctlr,
        return xfer->len / bytes_per_word >= rs->fifo_len;
 }
 
+static int rockchip_spi_setup(struct spi_device *spi)
+{
+       struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller);
+       u32 cr0;
+
+       pm_runtime_get_sync(rs->dev);
+
+       cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+       cr0 &= ~(0x3 << CR0_SCPH_OFFSET);
+       cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET);
+       if (spi->mode & SPI_CS_HIGH && spi->chip_select <= 1)
+               cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;
+       else if (spi->chip_select <= 1)
+               cr0 &= ~(BIT(spi->chip_select) << CR0_SOI_OFFSET);
+
+       writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+       pm_runtime_put(rs->dev);
+
+       return 0;
+}
+
 static int rockchip_spi_probe(struct platform_device *pdev)
 {
        int ret;
@@ -780,6 +864,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        ctlr->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;
        ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT);
 
+       ctlr->setup = rockchip_spi_setup;
        ctlr->set_cs = rockchip_spi_set_cs;
        ctlr->transfer_one = rockchip_spi_transfer_one;
        ctlr->max_transfer_size = rockchip_spi_max_transfer_size;
@@ -815,8 +900,13 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) {
        case ROCKCHIP_SPI_VER2_TYPE2:
                ctlr->mode_bits |= SPI_CS_HIGH;
+               if (ctlr->can_dma && slave_mode)
+                       rs->cs_inactive = true;
+               else
+                       rs->cs_inactive = false;
                break;
        default:
+               rs->cs_inactive = false;
                break;
        }
 
@@ -875,14 +965,14 @@ static int rockchip_spi_suspend(struct device *dev)
 {
        int ret;
        struct spi_controller *ctlr = dev_get_drvdata(dev);
+       struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 
        ret = spi_controller_suspend(ctlr);
        if (ret < 0)
                return ret;
 
-       ret = pm_runtime_force_suspend(dev);
-       if (ret < 0)
-               return ret;
+       clk_disable_unprepare(rs->spiclk);
+       clk_disable_unprepare(rs->apb_pclk);
 
        pinctrl_pm_select_sleep_state(dev);
 
@@ -897,10 +987,14 @@ static int rockchip_spi_resume(struct device *dev)
 
        pinctrl_pm_select_default_state(dev);
 
-       ret = pm_runtime_force_resume(dev);
+       ret = clk_prepare_enable(rs->apb_pclk);
        if (ret < 0)
                return ret;
 
+       ret = clk_prepare_enable(rs->spiclk);
+       if (ret < 0)
+               clk_disable_unprepare(rs->apb_pclk);
+
        ret = spi_controller_resume(ctlr);
        if (ret < 0) {
                clk_disable_unprepare(rs->spiclk);
@@ -942,7 +1036,7 @@ static int rockchip_spi_runtime_resume(struct device *dev)
 #endif /* CONFIG_PM */
 
 static const struct dev_pm_ops rockchip_spi_pm = {
-       SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
        SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,
                           rockchip_spi_runtime_resume, NULL)
 };
index d6f51695ca5b20ec6363501c5922639d187e6189..660aa866af06fe099199e99651e91d0b80e516b0 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 
@@ -62,9 +61,6 @@ struct s3c24xx_spi {
        unsigned char            fiq_inuse;
        unsigned char            fiq_claimed;
 
-       void                    (*set_cs)(struct s3c2410_spi_info *spi,
-                                         int cs, int pol);
-
        /* data buffers */
        const unsigned char     *tx;
        unsigned char           *rx;
@@ -84,29 +80,21 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
        return spi_master_get_devdata(sdev->master);
 }
 
-static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
-{
-       gpio_set_value(spi->pin_cs, pol);
-}
-
 static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
 {
        struct s3c24xx_spi_devstate *cs = spi->controller_state;
        struct s3c24xx_spi *hw = to_hw(spi);
-       unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
 
        /* change the chipselect state and the state of the spi engine clock */
 
        switch (value) {
        case BITBANG_CS_INACTIVE:
-               hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
                writeb(cs->spcon, hw->regs + S3C2410_SPCON);
                break;
 
        case BITBANG_CS_ACTIVE:
                writeb(cs->spcon | S3C2410_SPCON_ENSCK,
                       hw->regs + S3C2410_SPCON);
-               hw->set_cs(hw->pdata, spi->chip_select, cspol);
                break;
        }
 }
@@ -452,14 +440,6 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
        writeb(0xff, hw->regs + S3C2410_SPPRE);
        writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
        writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
-
-       if (hw->pdata) {
-               if (hw->set_cs == s3c24xx_spi_gpiocs)
-                       gpio_direction_output(hw->pdata->pin_cs, 1);
-
-               if (hw->pdata->gpio_setup)
-                       hw->pdata->gpio_setup(hw->pdata, 1);
-       }
 }
 
 static int s3c24xx_spi_probe(struct platform_device *pdev)
@@ -502,6 +482,9 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        master->num_chipselect = hw->pdata->num_cs;
        master->bus_num = pdata->bus_num;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
+       /* we need to call the local chipselect callback */
+       master->flags = SPI_MASTER_GPIO_SS;
+       master->use_gpio_descriptors = true;
 
        /* setup the state for the bitbang driver */
 
@@ -541,27 +524,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
                goto err_no_pdata;
        }
 
-       /* setup any gpio we can */
-
-       if (!pdata->set_cs) {
-               if (pdata->pin_cs < 0) {
-                       dev_err(&pdev->dev, "No chipselect pin\n");
-                       err = -EINVAL;
-                       goto err_register;
-               }
-
-               err = devm_gpio_request(&pdev->dev, pdata->pin_cs,
-                                       dev_name(&pdev->dev));
-               if (err) {
-                       dev_err(&pdev->dev, "Failed to get gpio for cs\n");
-                       goto err_register;
-               }
-
-               hw->set_cs = s3c24xx_spi_gpiocs;
-               gpio_direction_output(pdata->pin_cs, 1);
-       } else
-               hw->set_cs = pdata->set_cs;
-
        s3c24xx_spi_initialsetup(hw);
 
        /* register our spi controller */
@@ -604,9 +566,6 @@ static int s3c24xx_spi_suspend(struct device *dev)
        if (ret)
                return ret;
 
-       if (hw->pdata && hw->pdata->gpio_setup)
-               hw->pdata->gpio_setup(hw->pdata, 0);
-
        clk_disable(hw->clk);
        return 0;
 }
index 8755cd85e83ceb05c48716f131ed222d81d366d8..c26440e9058d774c26b3d73531f17d9cb4f207b9 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
-#include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 
 #include <linux/platform_data/spi-s3c64xx.h>
 
@@ -656,7 +654,11 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
 
        /* Configure feedback delay */
-       writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
+       if (!cs)
+               /* No delay if not defined */
+               writel(0, sdd->regs + S3C64XX_SPI_FB_CLK);
+       else
+               writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
 
        return 0;
 }
@@ -796,16 +798,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
                return ERR_PTR(-EINVAL);
        }
 
-       data_np = of_get_child_by_name(slave_np, "controller-data");
-       if (!data_np) {
-               dev_err(&spi->dev, "child node 'controller-data' not found\n");
-               return ERR_PTR(-EINVAL);
-       }
-
        cs = kzalloc(sizeof(*cs), GFP_KERNEL);
-       if (!cs) {
-               of_node_put(data_np);
+       if (!cs)
                return ERR_PTR(-ENOMEM);
+
+       data_np = of_get_child_by_name(slave_np, "controller-data");
+       if (!data_np) {
+               dev_info(&spi->dev, "feedback delay set to default (0)\n");
+               return cs;
        }
 
        of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
@@ -830,34 +830,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        if (spi->dev.of_node) {
                cs = s3c64xx_get_slave_ctrldata(spi);
                spi->controller_data = cs;
-       } else if (cs) {
-               /* On non-DT platforms the SPI core will set spi->cs_gpio
-                * to -ENOENT. The GPIO pin used to drive the chip select
-                * is defined by using platform data so spi->cs_gpio value
-                * has to be override to have the proper GPIO pin number.
-                */
-               spi->cs_gpio = cs->line;
        }
 
-       if (IS_ERR_OR_NULL(cs)) {
+       /* NULL is fine, we just avoid using the FB delay (=0) */
+       if (IS_ERR(cs)) {
                dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
                return -ENODEV;
        }
 
-       if (!spi_get_ctldata(spi)) {
-               if (gpio_is_valid(spi->cs_gpio)) {
-                       err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH,
-                                              dev_name(&spi->dev));
-                       if (err) {
-                               dev_err(&spi->dev,
-                                       "Failed to get /CS gpio [%d]: %d\n",
-                                       spi->cs_gpio, err);
-                               goto err_gpio_req;
-                       }
-               }
-
+       if (!spi_get_ctldata(spi))
                spi_set_ctldata(spi, cs);
-       }
 
        pm_runtime_get_sync(&sdd->pdev->dev);
 
@@ -909,11 +891,9 @@ setup_exit:
        /* setup() returns with device de-selected */
        s3c64xx_spi_set_cs(spi, false);
 
-       if (gpio_is_valid(spi->cs_gpio))
-               gpio_free(spi->cs_gpio);
        spi_set_ctldata(spi, NULL);
 
-err_gpio_req:
+       /* This was dynamically allocated on the DT path */
        if (spi->dev.of_node)
                kfree(cs);
 
@@ -924,19 +904,9 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi)
 {
        struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
 
-       if (gpio_is_valid(spi->cs_gpio)) {
-               gpio_free(spi->cs_gpio);
-               if (spi->dev.of_node)
-                       kfree(cs);
-               else {
-                       /* On non-DT platforms, the SPI core sets
-                        * spi->cs_gpio to -ENOENT and .setup()
-                        * overrides it with the GPIO pin value
-                        * passed using platform data.
-                        */
-                       spi->cs_gpio = -ENOENT;
-               }
-       }
+       /* This was dynamically allocated on the DT path */
+       if (spi->dev.of_node)
+               kfree(cs);
 
        spi_set_ctldata(spi, NULL);
 }
@@ -1131,6 +1101,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        master->prepare_message = s3c64xx_spi_prepare_message;
        master->transfer_one = s3c64xx_spi_transfer_one;
        master->num_chipselect = sci->num_cs;
+       master->use_gpio_descriptors = true;
        master->dma_alignment = 8;
        master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
                                        SPI_BPW_MASK(8);
@@ -1442,6 +1413,16 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = {
        .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
 };
 
+static struct s3c64xx_spi_port_config fsd_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f},
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+       .clk_from_cmu   = true,
+       .clk_ioclk      = false,
+       .quirks         = S3C64XX_SPI_QUIRK_CS_AUTO,
+};
+
 static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
        {
                .name           = "s3c2443-spi",
@@ -1472,6 +1453,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {
        { .compatible = "samsung,exynos5433-spi",
                        .data = (void *)&exynos5433_spi_port_config,
        },
+       { .compatible = "tesla,fsd-spi",
+                       .data = (void *)&fsd_spi_port_config,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
index 169f3d595f60cb4071bd044e6cd7c73a9d7f8c61..d37cfe995a6324923cb19abbf430bb12eb0954ca 100644 (file)
@@ -132,13 +132,12 @@ static int spi_slave_system_control_probe(struct spi_device *spi)
        return 0;
 }
 
-static int spi_slave_system_control_remove(struct spi_device *spi)
+static void spi_slave_system_control_remove(struct spi_device *spi)
 {
        struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi);
 
        spi_slave_abort(spi);
        wait_for_completion(&priv->finished);
-       return 0;
 }
 
 static struct spi_driver spi_slave_system_control_driver = {
index f2e07a392d6863ea22a098ee8cdef5c841cdd6b8..f56c1afb853400e57f756746871ee1316d5ab5ec 100644 (file)
@@ -106,13 +106,12 @@ static int spi_slave_time_probe(struct spi_device *spi)
        return 0;
 }
 
-static int spi_slave_time_remove(struct spi_device *spi)
+static void spi_slave_time_remove(struct spi_device *spi)
 {
        struct spi_slave_time_priv *priv = spi_get_drvdata(spi);
 
        spi_slave_abort(spi);
        wait_for_completion(&priv->finished);
-       return 0;
 }
 
 static struct spi_driver spi_slave_time_driver = {
index 6c44dda9ee8c590eaa5243a5618d79b2a0e78258..843be803696bca251a6db55b367a7aac02a87249 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
@@ -171,11 +170,6 @@ static int spi_st_transfer_one(struct spi_master *master,
        return t->len;
 }
 
-static void spi_st_cleanup(struct spi_device *spi)
-{
-       gpio_free(spi->cs_gpio);
-}
-
 /* the spi->mode bits understood by this driver: */
 #define MODEBITS  (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH)
 static int spi_st_setup(struct spi_device *spi)
@@ -183,29 +177,17 @@ static int spi_st_setup(struct spi_device *spi)
        struct spi_st *spi_st = spi_master_get_devdata(spi->master);
        u32 spi_st_clk, sscbrg, var;
        u32 hz = spi->max_speed_hz;
-       int cs = spi->cs_gpio;
-       int ret;
 
        if (!hz)  {
                dev_err(&spi->dev, "max_speed_hz unspecified\n");
                return -EINVAL;
        }
 
-       if (!gpio_is_valid(cs)) {
-               dev_err(&spi->dev, "%d is not a valid gpio\n", cs);
+       if (!spi->cs_gpiod) {
+               dev_err(&spi->dev, "no valid gpio assigned\n");
                return -EINVAL;
        }
 
-       ret = gpio_request(cs, dev_name(&spi->dev));
-       if (ret) {
-               dev_err(&spi->dev, "could not request gpio:%d\n", cs);
-               return ret;
-       }
-
-       ret = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
-       if (ret)
-               goto out_free_gpio;
-
        spi_st_clk = clk_get_rate(spi_st->clk);
 
        /* Set SSC_BRF */
@@ -213,8 +195,7 @@ static int spi_st_setup(struct spi_device *spi)
        if (sscbrg < 0x07 || sscbrg > BIT(16)) {
                dev_err(&spi->dev,
                        "baudrate %d outside valid range %d\n", sscbrg, hz);
-               ret = -EINVAL;
-               goto out_free_gpio;
+               return -EINVAL;
        }
 
        spi_st->baud = spi_st_clk / (2 * sscbrg);
@@ -263,10 +244,6 @@ static int spi_st_setup(struct spi_device *spi)
        readl_relaxed(spi_st->base + SSC_RBUF);
 
        return 0;
-
-out_free_gpio:
-       gpio_free(cs);
-       return ret;
 }
 
 /* Interrupt fired when TX shift register becomes empty */
@@ -309,11 +286,11 @@ static int spi_st_probe(struct platform_device *pdev)
        master->dev.of_node             = np;
        master->mode_bits               = MODEBITS;
        master->setup                   = spi_st_setup;
-       master->cleanup                 = spi_st_cleanup;
        master->transfer_one            = spi_st_transfer_one;
        master->bits_per_word_mask      = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
        master->auto_runtime_pm         = true;
        master->bus_num                 = pdev->id;
+       master->use_gpio_descriptors    = true;
        spi_st                          = spi_master_get_devdata(master);
 
        spi_st->clk = devm_clk_get(&pdev->dev, "ssc");
index 7fc24505a72cdd0db46dcb293fdcbe0d2bcd95f2..a6adc20f686263a2091199195f1605805e3de762 100644 (file)
@@ -763,7 +763,7 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
        if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX ||
                                 spi->cur_comm == SPI_3WIRE_TX)) {
                /* OVR flag shouldn't be handled for TX only mode */
-               sr &= ~STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE;
+               sr &= ~(STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE);
                mask |= STM32F4_SPI_SR_TXE;
        }
 
index 1fdfc6e6691d2e47df5b743d422f671e54dd169e..6000d0761206c66be2376037848522d15cf433bf 100644 (file)
@@ -280,7 +280,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
         * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
         * Or we can use CDR2, which is calculated with the formula:
         * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
-        * Wether we use the former or the latter is set through the
+        * Whether we use the former or the latter is set through the
         * DRS bit.
         *
         * First try CDR2, and if we can't reach the expected
diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c
new file mode 100644 (file)
index 0000000..f989f7b
--- /dev/null
@@ -0,0 +1,584 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 Sunplus Inc.
+// Author: Li-hao Kuo <lhjeff911@gmail.com>
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+
+#define SP7021_DATA_RDY_REG            0x0044
+#define SP7021_SLAVE_DMA_CTRL_REG      0x0048
+#define SP7021_SLAVE_DMA_LENGTH_REG    0x004c
+#define SP7021_SLAVE_DMA_ADDR_REG      0x004c
+
+#define SP7021_SLAVE_DATA_RDY          BIT(0)
+#define SP7021_SLAVE_SW_RST            BIT(1)
+#define SP7021_SLA_DMA_W_INT           BIT(8)
+#define SP7021_SLAVE_CLR_INT           BIT(8)
+#define SP7021_SLAVE_DMA_EN            BIT(0)
+#define SP7021_SLAVE_DMA_RW            BIT(6)
+#define SP7021_SLAVE_DMA_CMD           GENMASK(3, 2)
+
+#define SP7021_FIFO_REG                        0x0034
+#define SP7021_SPI_STATUS_REG          0x0038
+#define SP7021_SPI_CONFIG_REG          0x003c
+#define SP7021_INT_BUSY_REG            0x004c
+#define SP7021_DMA_CTRL_REG            0x0050
+
+#define SP7021_SPI_START_FD            BIT(0)
+#define SP7021_FD_SW_RST               BIT(1)
+#define SP7021_TX_EMP_FLAG             BIT(2)
+#define SP7021_RX_EMP_FLAG             BIT(4)
+#define SP7021_RX_FULL_FLAG            BIT(5)
+#define SP7021_FINISH_FLAG             BIT(6)
+
+#define SP7021_TX_CNT_MASK             GENMASK(11, 8)
+#define SP7021_RX_CNT_MASK             GENMASK(15, 12)
+#define SP7021_TX_LEN_MASK             GENMASK(23, 16)
+#define SP7021_GET_LEN_MASK            GENMASK(31, 24)
+#define SP7021_SET_TX_LEN              GENMASK(23, 16)
+#define SP7021_SET_XFER_LEN            GENMASK(31, 24)
+
+#define SP7021_CPOL_FD                 BIT(0)
+#define SP7021_CPHA_R                  BIT(1)
+#define SP7021_CPHA_W                  BIT(2)
+#define SP7021_LSB_SEL                 BIT(4)
+#define SP7021_CS_POR                  BIT(5)
+#define SP7021_FD_SEL                  BIT(6)
+
+#define SP7021_RX_UNIT                 GENMASK(8, 7)
+#define SP7021_TX_UNIT                 GENMASK(10, 9)
+#define SP7021_TX_EMP_FLAG_MASK                BIT(11)
+#define SP7021_RX_FULL_FLAG_MASK       BIT(14)
+#define SP7021_FINISH_FLAG_MASK                BIT(15)
+#define SP7021_CLEAN_RW_BYTE           GENMASK(10, 7)
+#define SP7021_CLEAN_FLUG_MASK         GENMASK(15, 11)
+#define SP7021_CLK_MASK                        GENMASK(31, 16)
+
+#define SP7021_INT_BYPASS              BIT(3)
+#define SP7021_CLR_MASTER_INT          BIT(6)
+
+#define SP7021_SPI_DATA_SIZE           (255)
+#define SP7021_FIFO_DATA_LEN           (16)
+
+enum {
+       SP7021_MASTER_MODE = 0,
+       SP7021_SLAVE_MODE = 1,
+};
+
+struct sp7021_spi_ctlr {
+       struct device *dev;
+       struct spi_controller *ctlr;
+       void __iomem *m_base;
+       void __iomem *s_base;
+       u32 xfer_conf;
+       int mode;
+       int m_irq;
+       int s_irq;
+       struct clk *spi_clk;
+       struct reset_control *rstc;
+       // irq spin lock
+       spinlock_t lock;
+       // data xfer lock
+       struct mutex buf_lock;
+       struct completion isr_done;
+       struct completion slave_isr;
+       unsigned int  rx_cur_len;
+       unsigned int  tx_cur_len;
+       unsigned int  data_unit;
+       const u8 *tx_buf;
+       u8 *rx_buf;
+};
+
+static irqreturn_t sp7021_spi_slave_irq(int irq, void *dev)
+{
+       struct sp7021_spi_ctlr *pspim = dev;
+       unsigned int data_status;
+
+       data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG);
+       data_status |= SP7021_SLAVE_CLR_INT;
+       writel(data_status , pspim->s_base + SP7021_DATA_RDY_REG);
+       complete(&pspim->slave_isr);
+       return IRQ_HANDLED;
+}
+
+static int sp7021_spi_slave_abort(struct spi_controller *ctlr)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       complete(&pspim->slave_isr);
+       complete(&pspim->isr_done);
+       return 0;
+}
+
+static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer)
+{
+       struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
+       u32 value;
+
+       reinit_completion(&pspim->slave_isr);
+       value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
+       writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
+       writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
+       writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
+       value = readl(pspim->s_base + SP7021_DATA_RDY_REG);
+       value |= SP7021_SLAVE_DATA_RDY;
+       writel(value, pspim->s_base + SP7021_DATA_RDY_REG);
+       if (wait_for_completion_interruptible(&pspim->isr_done)) {
+               dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__);
+               return -EINTR;
+       }
+       return 0;
+}
+
+static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer)
+{
+       struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
+       u32 value;
+
+       reinit_completion(&pspim->isr_done);
+       value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
+       writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
+       writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
+       writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
+       if (wait_for_completion_interruptible(&pspim->isr_done)) {
+               dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__);
+               return -EINTR;
+       }
+       writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
+       return 0;
+}
+
+static void sp7021_spi_master_rb(struct sp7021_spi_ctlr *pspim, unsigned int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               pspim->rx_buf[pspim->rx_cur_len] =
+                       readl(pspim->m_base + SP7021_FIFO_REG);
+               pspim->rx_cur_len++;
+       }
+}
+
+static void sp7021_spi_master_wb(struct sp7021_spi_ctlr *pspim, unsigned int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               writel(pspim->tx_buf[pspim->tx_cur_len],
+                      pspim->m_base + SP7021_FIFO_REG);
+               pspim->tx_cur_len++;
+       }
+}
+
+static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
+{
+       struct sp7021_spi_ctlr *pspim = dev;
+       unsigned int tx_cnt, total_len;
+       unsigned int tx_len, rx_cnt;
+       unsigned int fd_status;
+       bool isrdone = false;
+       u32 value;
+
+       fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG);
+       tx_cnt = FIELD_GET(SP7021_TX_CNT_MASK, fd_status);
+       tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status);
+       total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status);
+
+       if ((fd_status & SP7021_TX_EMP_FLAG) && (fd_status & SP7021_RX_EMP_FLAG) && total_len == 0)
+               return IRQ_NONE;
+
+       if (tx_len == 0 && total_len == 0)
+               return IRQ_NONE;
+
+       spin_lock_irq(&pspim->lock);
+
+       rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status);
+       if (fd_status & SP7021_RX_FULL_FLAG)
+               rx_cnt = pspim->data_unit;
+
+       tx_cnt = min(tx_len - pspim->tx_cur_len, pspim->data_unit - tx_cnt);
+       dev_dbg(pspim->dev, "fd_st=0x%x rx_c:%d tx_c:%d tx_l:%d",
+               fd_status, rx_cnt, tx_cnt, tx_len);
+
+       if (rx_cnt > 0)
+               sp7021_spi_master_rb(pspim, rx_cnt);
+       if (tx_cnt > 0)
+               sp7021_spi_master_wb(pspim, tx_cnt);
+
+       fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG);
+       tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status);
+       total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status);
+
+       if (fd_status & SP7021_FINISH_FLAG || tx_len == pspim->tx_cur_len) {
+               while (total_len != pspim->rx_cur_len) {
+                       fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG);
+                       total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status);
+                       if (fd_status & SP7021_RX_FULL_FLAG)
+                               rx_cnt = pspim->data_unit;
+                       else
+                               rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status);
+
+                       if (rx_cnt > 0)
+                               sp7021_spi_master_rb(pspim, rx_cnt);
+               }
+               value = readl(pspim->m_base + SP7021_INT_BUSY_REG);
+               value |= SP7021_CLR_MASTER_INT;
+               writel(value, pspim->m_base + SP7021_INT_BUSY_REG);
+               writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG);
+               isrdone = true;
+       }
+
+       if (isrdone)
+               complete(&pspim->isr_done);
+       spin_unlock_irq(&pspim->lock);
+       return IRQ_HANDLED;
+}
+
+static void sp7021_prep_transfer(struct spi_controller *ctlr, struct spi_device *spi)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       pspim->tx_cur_len = 0;
+       pspim->rx_cur_len = 0;
+       pspim->data_unit = SP7021_FIFO_DATA_LEN;
+}
+
+// preliminary set CS, CPOL, CPHA and LSB
+static int sp7021_spi_controller_prepare_message(struct spi_controller *ctlr,
+                                                struct spi_message *msg)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+       struct spi_device *s = msg->spi;
+       u32 valus, rs = 0;
+
+       valus = readl(pspim->m_base + SP7021_SPI_STATUS_REG);
+       valus |= SP7021_FD_SW_RST;
+       writel(valus, pspim->m_base + SP7021_SPI_STATUS_REG);
+       rs |= SP7021_FD_SEL;
+       if (s->mode & SPI_CPOL)
+               rs |= SP7021_CPOL_FD;
+
+       if (s->mode & SPI_LSB_FIRST)
+               rs |= SP7021_LSB_SEL;
+
+       if (s->mode & SPI_CS_HIGH)
+               rs |= SP7021_CS_POR;
+
+       if (s->mode & SPI_CPHA)
+               rs |=  SP7021_CPHA_R;
+       else
+               rs |=  SP7021_CPHA_W;
+
+       rs |=  FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0);
+       pspim->xfer_conf = rs;
+       if (pspim->xfer_conf & SP7021_CPOL_FD)
+               writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
+
+       return 0;
+}
+
+static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfer *xfer)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+       u32 clk_rate, clk_sel, div;
+
+       clk_rate = clk_get_rate(pspim->spi_clk);
+       div = max(2U, clk_rate / xfer->speed_hz);
+
+       clk_sel = (div / 2) - 1;
+       pspim->xfer_conf &= ~SP7021_CLK_MASK;
+       pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel);
+       writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
+}
+
+static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct spi_device *spi,
+                                      struct spi_transfer *xfer)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+       unsigned long timeout = msecs_to_jiffies(1000);
+       unsigned int xfer_cnt, xfer_len, last_len;
+       unsigned int i, len_temp;
+       u32 reg_temp;
+
+       xfer_cnt = xfer->len / SP7021_SPI_DATA_SIZE;
+       last_len = xfer->len % SP7021_SPI_DATA_SIZE;
+
+       for (i = 0; i <= xfer_cnt; i++) {
+               mutex_lock(&pspim->buf_lock);
+               sp7021_prep_transfer(ctlr, spi);
+               sp7021_spi_setup_clk(ctlr, xfer);
+               reinit_completion(&pspim->isr_done);
+
+               if (i == xfer_cnt)
+                       xfer_len = last_len;
+               else
+                       xfer_len = SP7021_SPI_DATA_SIZE;
+
+               pspim->tx_buf = xfer->tx_buf + i * SP7021_SPI_DATA_SIZE;
+               pspim->rx_buf = xfer->rx_buf + i * SP7021_SPI_DATA_SIZE;
+
+               if (pspim->tx_cur_len < xfer_len) {
+                       len_temp = min(pspim->data_unit, xfer_len);
+                       sp7021_spi_master_wb(pspim, len_temp);
+               }
+               reg_temp = readl(pspim->m_base + SP7021_SPI_CONFIG_REG);
+               reg_temp &= ~SP7021_CLEAN_RW_BYTE;
+               reg_temp &= ~SP7021_CLEAN_FLUG_MASK;
+               reg_temp |= SP7021_FD_SEL | SP7021_FINISH_FLAG_MASK |
+                           SP7021_TX_EMP_FLAG_MASK | SP7021_RX_FULL_FLAG_MASK |
+                           FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0);
+               writel(reg_temp, pspim->m_base + SP7021_SPI_CONFIG_REG);
+
+               reg_temp = FIELD_PREP(SP7021_SET_TX_LEN, xfer_len) |
+                                     FIELD_PREP(SP7021_SET_XFER_LEN, xfer_len) |
+                                     SP7021_SPI_START_FD;
+               writel(reg_temp, pspim->m_base + SP7021_SPI_STATUS_REG);
+
+               if (!wait_for_completion_interruptible_timeout(&pspim->isr_done, timeout)) {
+                       dev_err(&spi->dev, "wait_for_completion err\n");
+                       mutex_unlock(&pspim->buf_lock);
+                       return -ETIMEDOUT;
+               }
+
+               reg_temp = readl(pspim->m_base + SP7021_SPI_STATUS_REG);
+               if (reg_temp & SP7021_FINISH_FLAG) {
+                       writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG);
+                       writel(readl(pspim->m_base + SP7021_SPI_CONFIG_REG) &
+                               SP7021_CLEAN_FLUG_MASK, pspim->m_base + SP7021_SPI_CONFIG_REG);
+               }
+
+               if (pspim->xfer_conf & SP7021_CPOL_FD)
+                       writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG);
+
+               mutex_unlock(&pspim->buf_lock);
+       }
+       return 0;
+}
+
+static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi_device *spi,
+                                      struct spi_transfer *xfer)
+{
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+       struct device *dev = pspim->dev;
+       int ret;
+
+       if (xfer->tx_buf && !xfer->rx_buf) {
+               xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf,
+                                             xfer->len, DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, xfer->tx_dma))
+                       return -ENOMEM;
+               ret = sp7021_spi_slave_tx(spi, xfer);
+               dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE);
+       } else if (xfer->rx_buf && !xfer->tx_buf) {
+               xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, xfer->len,
+                                             DMA_FROM_DEVICE);
+               if (dma_mapping_error(dev, xfer->rx_dma))
+                       return -ENOMEM;
+               ret = sp7021_spi_slave_rx(spi, xfer);
+               dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE);
+       } else {
+               dev_dbg(&ctlr->dev, "%s() wrong command\n", __func__);
+               return -EINVAL;
+       }
+
+       spi_finalize_current_transfer(ctlr);
+       return ret;
+}
+
+static void sp7021_spi_disable_unprepare(void *data)
+{
+       clk_disable_unprepare(data);
+}
+
+static void sp7021_spi_reset_control_assert(void *data)
+{
+       reset_control_assert(data);
+}
+
+static int sp7021_spi_controller_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct sp7021_spi_ctlr *pspim;
+       struct spi_controller *ctlr;
+       int mode, ret;
+
+       pdev->id = of_alias_get_id(pdev->dev.of_node, "sp_spi");
+
+       if (device_property_read_bool(dev, "spi-slave"))
+               mode = SP7021_SLAVE_MODE;
+       else
+               mode = SP7021_MASTER_MODE;
+
+       if (mode == SP7021_SLAVE_MODE)
+               ctlr = devm_spi_alloc_slave(dev, sizeof(*pspim));
+       else
+               ctlr = devm_spi_alloc_master(dev, sizeof(*pspim));
+       if (!ctlr)
+               return -ENOMEM;
+       device_set_node(&ctlr->dev, dev_fwnode(dev));
+       ctlr->bus_num = pdev->id;
+       ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+       ctlr->auto_runtime_pm = true;
+       ctlr->prepare_message = sp7021_spi_controller_prepare_message;
+       if (mode == SP7021_SLAVE_MODE) {
+               ctlr->transfer_one = sp7021_spi_slave_transfer_one;
+               ctlr->slave_abort = sp7021_spi_slave_abort;
+               ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX;
+       } else {
+               ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+               ctlr->min_speed_hz = 40000;
+               ctlr->max_speed_hz = 25000000;
+               ctlr->use_gpio_descriptors = true;
+               ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
+               ctlr->transfer_one = sp7021_spi_master_transfer_one;
+       }
+       platform_set_drvdata(pdev, ctlr);
+       pspim = spi_controller_get_devdata(ctlr);
+       pspim->mode = mode;
+       pspim->ctlr = ctlr;
+       pspim->dev = dev;
+       spin_lock_init(&pspim->lock);
+       mutex_init(&pspim->buf_lock);
+       init_completion(&pspim->isr_done);
+       init_completion(&pspim->slave_isr);
+
+       pspim->m_base = devm_platform_ioremap_resource_byname(pdev, "master");
+       if (IS_ERR(pspim->m_base))
+               return dev_err_probe(dev, PTR_ERR(pspim->m_base), "m_base get fail\n");
+
+       pspim->s_base = devm_platform_ioremap_resource_byname(pdev, "slave");
+       if (IS_ERR(pspim->s_base))
+               return dev_err_probe(dev, PTR_ERR(pspim->s_base), "s_base get fail\n");
+
+       pspim->m_irq = platform_get_irq_byname(pdev, "master_risc");
+       if (pspim->m_irq < 0)
+               return pspim->m_irq;
+
+       pspim->s_irq = platform_get_irq_byname(pdev, "slave_risc");
+       if (pspim->s_irq < 0)
+               return pspim->s_irq;
+
+       pspim->spi_clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(pspim->spi_clk))
+               return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n");
+
+       pspim->rstc = devm_reset_control_get_exclusive(dev, NULL);
+       if (IS_ERR(pspim->rstc))
+               return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n");
+
+       ret = clk_prepare_enable(pspim->spi_clk);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to enable clk\n");
+
+       ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk);
+       if (ret)
+               return ret;
+
+       ret = reset_control_deassert(pspim->rstc);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to deassert reset\n");
+
+       ret = devm_add_action_or_reset(dev, sp7021_spi_reset_control_assert, pspim->rstc);
+       if (ret)
+               return ret;
+
+       ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq,
+                              IRQF_TRIGGER_RISING, pdev->name, pspim);
+       if (ret)
+               return ret;
+
+       ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq,
+                              IRQF_TRIGGER_RISING, pdev->name, pspim);
+       if (ret)
+               return ret;
+
+       pm_runtime_enable(dev);
+       ret = spi_register_controller(ctlr);
+       if (ret) {
+               pm_runtime_disable(dev);
+               return dev_err_probe(dev, ret, "spi_register_master fail\n");
+       }
+       return 0;
+}
+
+static int sp7021_spi_controller_remove(struct platform_device *pdev)
+{
+       struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev);
+
+       spi_unregister_controller(ctlr);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+       return 0;
+}
+
+static int __maybe_unused sp7021_spi_controller_suspend(struct device *dev)
+{
+       struct spi_controller *ctlr = dev_get_drvdata(dev);
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       return reset_control_assert(pspim->rstc);
+}
+
+static int __maybe_unused sp7021_spi_controller_resume(struct device *dev)
+{
+       struct spi_controller *ctlr = dev_get_drvdata(dev);
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       reset_control_deassert(pspim->rstc);
+       return clk_prepare_enable(pspim->spi_clk);
+}
+
+#ifdef CONFIG_PM
+static int sp7021_spi_runtime_suspend(struct device *dev)
+{
+       struct spi_controller *ctlr = dev_get_drvdata(dev);
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       return reset_control_assert(pspim->rstc);
+}
+
+static int sp7021_spi_runtime_resume(struct device *dev)
+{
+       struct spi_controller *ctlr = dev_get_drvdata(dev);
+       struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr);
+
+       return reset_control_deassert(pspim->rstc);
+}
+#endif
+
+static const struct dev_pm_ops sp7021_spi_pm_ops = {
+       SET_RUNTIME_PM_OPS(sp7021_spi_runtime_suspend,
+                          sp7021_spi_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(sp7021_spi_controller_suspend,
+                               sp7021_spi_controller_resume)
+};
+
+static const struct of_device_id sp7021_spi_controller_ids[] = {
+       { .compatible = "sunplus,sp7021-spi" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, sp7021_spi_controller_ids);
+
+static struct platform_driver sp7021_spi_controller_driver = {
+       .probe = sp7021_spi_controller_probe,
+       .remove = sp7021_spi_controller_remove,
+       .driver = {
+               .name = "sunplus,sp7021-spi-controller",
+               .of_match_table = sp7021_spi_controller_ids,
+               .pm     = &sp7021_spi_pm_ops,
+       },
+};
+module_platform_driver(sp7021_spi_controller_driver);
+
+MODULE_AUTHOR("Li-hao Kuo <lhjeff911@gmail.com>");
+MODULE_DESCRIPTION("Sunplus SPI controller driver");
+MODULE_LICENSE("GPL");
index e9de1d958bbd2a0cb595450b5d3ad3fae23e30c8..8f345247a8c3221417c2f9df498b4d39a2727a40 100644 (file)
@@ -1352,6 +1352,10 @@ static int tegra_spi_probe(struct platform_device *pdev)
        tspi->phys = r->start;
 
        spi_irq = platform_get_irq(pdev, 0);
+       if (spi_irq < 0) {
+               ret = spi_irq;
+               goto exit_free_master;
+       }
        tspi->irq = spi_irq;
 
        tspi->clk = devm_clk_get(&pdev->dev, "spi");
index 2a03739a0c609d96d344538a9fd066454a2bdd32..80c3787deea9de60bcd3be5d6aa3369313aa9511 100644 (file)
@@ -1006,14 +1006,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
        struct resource         *r;
        int ret, spi_irq;
        const struct tegra_slink_chip_data *cdata = NULL;
-       const struct of_device_id *match;
 
-       match = of_match_device(tegra_slink_of_match, &pdev->dev);
-       if (!match) {
-               dev_err(&pdev->dev, "Error: No device match found\n");
-               return -ENODEV;
-       }
-       cdata = match->data;
+       cdata = of_device_get_match_data(&pdev->dev);
 
        master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
        if (!master) {
index ce1bdb4767ea38ce58aaf1cbd90aab0c5b1f015f..66f647f32876e34ee5fd752642ea02d4ac500a5d 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/of_device.h>
 #include <linux/reset.h>
 #include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <linux/property.h>
 
 #define QSPI_COMMAND1                          0x000
 #define QSPI_BIT_LENGTH(x)                     (((x) & 0x1f) << 0)
 #define QSPI_NUM_DUMMY_CYCLE(x)                        (((x) & 0xff) << 0)
 #define QSPI_DUMMY_CYCLES_MAX                  0xff
 
+#define QSPI_CMB_SEQ_CMD                       0x19c
+#define QSPI_COMMAND_VALUE_SET(X)              (((x) & 0xFF) << 0)
+
+#define QSPI_CMB_SEQ_CMD_CFG                   0x1a0
+#define QSPI_COMMAND_X1_X2_X4(x)               (((x) & 0x3) << 13)
+#define QSPI_COMMAND_X1_X2_X4_MASK             (0x03 << 13)
+#define QSPI_COMMAND_SDR_DDR                   BIT(12)
+#define QSPI_COMMAND_SIZE_SET(x)               (((x) & 0xFF) << 0)
+
+#define QSPI_GLOBAL_CONFIG                     0X1a4
+#define QSPI_CMB_SEQ_EN                                BIT(0)
+
+#define QSPI_CMB_SEQ_ADDR                      0x1a8
+#define QSPI_ADDRESS_VALUE_SET(X)              (((x) & 0xFFFF) << 0)
+
+#define QSPI_CMB_SEQ_ADDR_CFG                  0x1ac
+#define QSPI_ADDRESS_X1_X2_X4(x)               (((x) & 0x3) << 13)
+#define QSPI_ADDRESS_X1_X2_X4_MASK             (0x03 << 13)
+#define QSPI_ADDRESS_SDR_DDR                   BIT(12)
+#define QSPI_ADDRESS_SIZE_SET(x)               (((x) & 0xFF) << 0)
+
 #define DATA_DIR_TX                            BIT(0)
 #define DATA_DIR_RX                            BIT(1)
 
 #define QSPI_DMA_TIMEOUT                       (msecs_to_jiffies(1000))
 #define DEFAULT_QSPI_DMA_BUF_LEN               (64 * 1024)
+#define CMD_TRANSFER                           0
+#define ADDR_TRANSFER                          1
+#define DATA_TRANSFER                          2
+
+struct tegra_qspi_soc_data {
+       bool has_dma;
+       bool cmb_xfer_capable;
+};
 
 struct tegra_qspi_client_data {
        int tx_clk_tap_delay;
@@ -137,7 +168,6 @@ struct tegra_qspi {
        spinlock_t                              lock;
 
        struct clk                              *clk;
-       struct reset_control                    *rst;
        void __iomem                            *base;
        phys_addr_t                             phys;
        unsigned int                            irq;
@@ -185,6 +215,7 @@ struct tegra_qspi {
        u32                                     *tx_dma_buf;
        dma_addr_t                              tx_dma_phys;
        struct dma_async_tx_descriptor          *tx_dma_desc;
+       const struct tegra_qspi_soc_data        *soc_data;
 };
 
 static inline u32 tegra_qspi_readl(struct tegra_qspi *tqspi, unsigned long offset)
@@ -767,7 +798,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran
        u32 tx_tap = 0, rx_tap = 0;
        int req_mode;
 
-       if (speed != tqspi->cur_speed) {
+       if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) {
                clk_set_rate(tqspi->clk, speed);
                tqspi->cur_speed = speed;
        }
@@ -875,16 +906,16 @@ static int tegra_qspi_start_transfer_one(struct spi_device *spi,
 static struct tegra_qspi_client_data *tegra_qspi_parse_cdata_dt(struct spi_device *spi)
 {
        struct tegra_qspi_client_data *cdata;
-       struct device_node *slave_np = spi->dev.of_node;
 
        cdata = devm_kzalloc(&spi->dev, sizeof(*cdata), GFP_KERNEL);
        if (!cdata)
                return NULL;
 
-       of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay",
-                            &cdata->tx_clk_tap_delay);
-       of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay",
-                            &cdata->rx_clk_tap_delay);
+       device_property_read_u32(&spi->dev, "nvidia,tx-clk-tap-delay",
+                                &cdata->tx_clk_tap_delay);
+       device_property_read_u32(&spi->dev, "nvidia,rx-clk-tap-delay",
+                                &cdata->rx_clk_tap_delay);
+
        return cdata;
 }
 
@@ -906,7 +937,6 @@ static int tegra_qspi_setup(struct spi_device *spi)
                cdata = tegra_qspi_parse_cdata_dt(spi);
                spi->controller_data = cdata;
        }
-
        spin_lock_irqsave(&tqspi->lock, flags);
 
        /* keep default cs state to inactive */
@@ -948,9 +978,8 @@ static void tegra_qspi_handle_error(struct tegra_qspi *tqspi)
        dev_err(tqspi->dev, "error in transfer, fifo status 0x%08x\n", tqspi->status_reg);
        tegra_qspi_dump_regs(tqspi);
        tegra_qspi_flush_fifos(tqspi, true);
-       reset_control_assert(tqspi->rst);
-       udelay(2);
-       reset_control_deassert(tqspi->rst);
+       if (device_reset(tqspi->dev) < 0)
+               dev_warn_once(tqspi->dev, "device reset failed\n");
 }
 
 static void tegra_qspi_transfer_end(struct spi_device *spi)
@@ -966,19 +995,179 @@ static void tegra_qspi_transfer_end(struct spi_device *spi)
        tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1);
 }
 
-static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi_message *msg)
+static u32 tegra_qspi_cmd_config(bool is_ddr, u8 bus_width, u8 len)
+{
+       u32 cmd_config = 0;
+
+       /* Extract Command configuration and value */
+       if (is_ddr)
+               cmd_config |= QSPI_COMMAND_SDR_DDR;
+       else
+               cmd_config &= ~QSPI_COMMAND_SDR_DDR;
+
+       cmd_config |= QSPI_COMMAND_X1_X2_X4(bus_width);
+       cmd_config |= QSPI_COMMAND_SIZE_SET((len * 8) - 1);
+
+       return cmd_config;
+}
+
+static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len)
+{
+       u32 addr_config = 0;
+
+       /* Extract Address configuration and value */
+       is_ddr = 0; //Only SDR mode supported
+       bus_width = 0; //X1 mode
+
+       if (is_ddr)
+               addr_config |= QSPI_ADDRESS_SDR_DDR;
+       else
+               addr_config &= ~QSPI_ADDRESS_SDR_DDR;
+
+       addr_config |= QSPI_ADDRESS_X1_X2_X4(bus_width);
+       addr_config |= QSPI_ADDRESS_SIZE_SET((len * 8) - 1);
+
+       return addr_config;
+}
+
+static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
+                                       struct spi_message *msg)
+{
+       bool is_first_msg = true;
+       struct spi_transfer *xfer;
+       struct spi_device *spi = msg->spi;
+       u8 transfer_phase = 0;
+       u32 cmd1 = 0, dma_ctl = 0;
+       int ret = 0;
+       u32 address_value = 0;
+       u32 cmd_config = 0, addr_config = 0;
+       u8 cmd_value = 0, val = 0;
+
+       /* Enable Combined sequence mode */
+       val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG);
+       val |= QSPI_CMB_SEQ_EN;
+       tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);
+       /* Process individual transfer list */
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               switch (transfer_phase) {
+               case CMD_TRANSFER:
+                       /* X1 SDR mode */
+                       cmd_config = tegra_qspi_cmd_config(false, 0,
+                                                          xfer->len);
+                       cmd_value = *((const u8 *)(xfer->tx_buf));
+                       break;
+               case ADDR_TRANSFER:
+                       /* X1 SDR mode */
+                       addr_config = tegra_qspi_addr_config(false, 0,
+                                                            xfer->len);
+                       address_value = *((const u32 *)(xfer->tx_buf));
+                       break;
+               case DATA_TRANSFER:
+                       /* Program Command, Address value in register */
+                       tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD);
+                       tegra_qspi_writel(tqspi, address_value,
+                                         QSPI_CMB_SEQ_ADDR);
+                       /* Program Command and Address config in register */
+                       tegra_qspi_writel(tqspi, cmd_config,
+                                         QSPI_CMB_SEQ_CMD_CFG);
+                       tegra_qspi_writel(tqspi, addr_config,
+                                         QSPI_CMB_SEQ_ADDR_CFG);
+
+                       reinit_completion(&tqspi->xfer_completion);
+                       cmd1 = tegra_qspi_setup_transfer_one(spi, xfer,
+                                                            is_first_msg);
+                       ret = tegra_qspi_start_transfer_one(spi, xfer,
+                                                           cmd1);
+
+                       if (ret < 0) {
+                               dev_err(tqspi->dev, "Failed to start transfer-one: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       is_first_msg = false;
+                       ret = wait_for_completion_timeout
+                                       (&tqspi->xfer_completion,
+                                       QSPI_DMA_TIMEOUT);
+
+                       if (WARN_ON(ret == 0)) {
+                               dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n",
+                                       ret);
+                               if (tqspi->is_curr_dma_xfer &&
+                                   (tqspi->cur_direction & DATA_DIR_TX))
+                                       dmaengine_terminate_all
+                                               (tqspi->tx_dma_chan);
+
+                               if (tqspi->is_curr_dma_xfer &&
+                                   (tqspi->cur_direction & DATA_DIR_RX))
+                                       dmaengine_terminate_all
+                                               (tqspi->rx_dma_chan);
+
+                               /* Abort transfer by resetting pio/dma bit */
+                               if (!tqspi->is_curr_dma_xfer) {
+                                       cmd1 = tegra_qspi_readl
+                                                       (tqspi,
+                                                        QSPI_COMMAND1);
+                                       cmd1 &= ~QSPI_PIO;
+                                       tegra_qspi_writel
+                                                       (tqspi, cmd1,
+                                                        QSPI_COMMAND1);
+                               } else {
+                                       dma_ctl = tegra_qspi_readl
+                                                       (tqspi,
+                                                        QSPI_DMA_CTL);
+                                       dma_ctl &= ~QSPI_DMA_EN;
+                                       tegra_qspi_writel(tqspi, dma_ctl,
+                                                         QSPI_DMA_CTL);
+                               }
+
+                               /* Reset controller if timeout happens */
+                               if (device_reset(tqspi->dev) < 0)
+                                       dev_warn_once(tqspi->dev,
+                                                     "device reset failed\n");
+                               ret = -EIO;
+                               goto exit;
+                       }
+
+                       if (tqspi->tx_status ||  tqspi->rx_status) {
+                               dev_err(tqspi->dev, "QSPI Transfer failed\n");
+                               tqspi->tx_status = 0;
+                               tqspi->rx_status = 0;
+                               ret = -EIO;
+                               goto exit;
+                       }
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto exit;
+               }
+               msg->actual_length += xfer->len;
+               transfer_phase++;
+       }
+
+exit:
+       msg->status = ret;
+
+       return ret;
+}
+
+static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,
+                                           struct spi_message *msg)
 {
-       struct tegra_qspi *tqspi = spi_master_get_devdata(master);
        struct spi_device *spi = msg->spi;
        struct spi_transfer *transfer;
        bool is_first_msg = true;
-       int ret;
+       int ret = 0, val = 0;
 
        msg->status = 0;
        msg->actual_length = 0;
        tqspi->tx_status = 0;
        tqspi->rx_status = 0;
 
+       /* Disable Combined sequence mode */
+       val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG);
+       val &= ~QSPI_CMB_SEQ_EN;
+       tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);
        list_for_each_entry(transfer, &msg->transfers, transfer_list) {
                struct spi_transfer *xfer = transfer;
                u8 dummy_bytes = 0;
@@ -1016,7 +1205,6 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi
                        goto complete_xfer;
                }
 
-               is_first_msg = false;
                ret = wait_for_completion_timeout(&tqspi->xfer_completion,
                                                  QSPI_DMA_TIMEOUT);
                if (WARN_ON(ret == 0)) {
@@ -1061,7 +1249,48 @@ complete_xfer:
        ret = 0;
 exit:
        msg->status = ret;
+
+       return ret;
+}
+
+static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi,
+                                       struct spi_message *msg)
+{
+       int transfer_count = 0;
+       struct spi_transfer *xfer;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               transfer_count++;
+       }
+       if (!tqspi->soc_data->cmb_xfer_capable || transfer_count != 3)
+               return false;
+       xfer = list_first_entry(&msg->transfers, typeof(*xfer),
+                               transfer_list);
+       if (xfer->len > 2)
+               return false;
+       xfer = list_next_entry(xfer, transfer_list);
+       if (xfer->len > 4 || xfer->len < 3)
+               return false;
+       xfer = list_next_entry(xfer, transfer_list);
+       if (!tqspi->soc_data->has_dma || xfer->len > (QSPI_FIFO_DEPTH << 2))
+               return false;
+
+       return true;
+}
+
+static int tegra_qspi_transfer_one_message(struct spi_master *master,
+                                          struct spi_message *msg)
+{
+       struct tegra_qspi *tqspi = spi_master_get_devdata(master);
+       int ret;
+
+       if (tegra_qspi_validate_cmb_seq(tqspi, msg))
+               ret = tegra_qspi_combined_seq_xfer(tqspi, msg);
+       else
+               ret = tegra_qspi_non_combined_seq_xfer(tqspi, msg);
+
        spi_finalize_current_message(master);
+
        return ret;
 }
 
@@ -1193,15 +1422,58 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data)
        return handle_dma_based_xfer(tqspi);
 }
 
+static struct tegra_qspi_soc_data tegra210_qspi_soc_data = {
+       .has_dma = true,
+       .cmb_xfer_capable = false,
+};
+
+static struct tegra_qspi_soc_data tegra186_qspi_soc_data = {
+       .has_dma = true,
+       .cmb_xfer_capable = true,
+};
+
+static struct tegra_qspi_soc_data tegra234_qspi_soc_data = {
+       .has_dma = false,
+       .cmb_xfer_capable = true,
+};
+
 static const struct of_device_id tegra_qspi_of_match[] = {
-       { .compatible = "nvidia,tegra210-qspi", },
-       { .compatible = "nvidia,tegra186-qspi", },
-       { .compatible = "nvidia,tegra194-qspi", },
+       {
+               .compatible = "nvidia,tegra210-qspi",
+               .data       = &tegra210_qspi_soc_data,
+       }, {
+               .compatible = "nvidia,tegra186-qspi",
+               .data       = &tegra186_qspi_soc_data,
+       }, {
+               .compatible = "nvidia,tegra194-qspi",
+               .data       = &tegra186_qspi_soc_data,
+       }, {
+               .compatible = "nvidia,tegra234-qspi",
+               .data       = &tegra234_qspi_soc_data,
+       },
        {}
 };
 
 MODULE_DEVICE_TABLE(of, tegra_qspi_of_match);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id tegra_qspi_acpi_match[] = {
+       {
+               .id = "NVDA1213",
+               .driver_data = (kernel_ulong_t)&tegra210_qspi_soc_data,
+       }, {
+               .id = "NVDA1313",
+               .driver_data = (kernel_ulong_t)&tegra186_qspi_soc_data,
+       }, {
+               .id = "NVDA1413",
+               .driver_data = (kernel_ulong_t)&tegra234_qspi_soc_data,
+       },
+       {}
+};
+
+MODULE_DEVICE_TABLE(acpi, tegra_qspi_acpi_match);
+#endif
+
 static int tegra_qspi_probe(struct platform_device *pdev)
 {
        struct spi_master       *master;
@@ -1233,6 +1505,7 @@ static int tegra_qspi_probe(struct platform_device *pdev)
        tqspi->dev = &pdev->dev;
        spin_lock_init(&tqspi->lock);
 
+       tqspi->soc_data = device_get_match_data(&pdev->dev);
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        tqspi->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(tqspi->base))
@@ -1240,20 +1513,18 @@ static int tegra_qspi_probe(struct platform_device *pdev)
 
        tqspi->phys = r->start;
        qspi_irq = platform_get_irq(pdev, 0);
+       if (qspi_irq < 0)
+               return qspi_irq;
        tqspi->irq = qspi_irq;
 
-       tqspi->clk = devm_clk_get(&pdev->dev, "qspi");
-       if (IS_ERR(tqspi->clk)) {
-               ret = PTR_ERR(tqspi->clk);
-               dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
-               return ret;
-       }
+       if (!has_acpi_companion(tqspi->dev)) {
+               tqspi->clk = devm_clk_get(&pdev->dev, "qspi");
+               if (IS_ERR(tqspi->clk)) {
+                       ret = PTR_ERR(tqspi->clk);
+                       dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
+                       return ret;
+               }
 
-       tqspi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
-       if (IS_ERR(tqspi->rst)) {
-               ret = PTR_ERR(tqspi->rst);
-               dev_err(&pdev->dev, "failed to get reset control: %d\n", ret);
-               return ret;
        }
 
        tqspi->max_buf_size = QSPI_FIFO_DEPTH << 2;
@@ -1277,9 +1548,8 @@ static int tegra_qspi_probe(struct platform_device *pdev)
                goto exit_pm_disable;
        }
 
-       reset_control_assert(tqspi->rst);
-       udelay(2);
-       reset_control_deassert(tqspi->rst);
+       if (device_reset(tqspi->dev) < 0)
+               dev_warn_once(tqspi->dev, "device reset failed\n");
 
        tqspi->def_command1_reg = QSPI_M_S | QSPI_CS_SW_HW |  QSPI_CS_SW_VAL;
        tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1);
@@ -1358,6 +1628,9 @@ static int __maybe_unused tegra_qspi_runtime_suspend(struct device *dev)
        struct spi_master *master = dev_get_drvdata(dev);
        struct tegra_qspi *tqspi = spi_master_get_devdata(master);
 
+       /* Runtime pm disabled with ACPI */
+       if (has_acpi_companion(tqspi->dev))
+               return 0;
        /* flush all write which are in PPSB queue by reading back */
        tegra_qspi_readl(tqspi, QSPI_COMMAND1);
 
@@ -1372,6 +1645,9 @@ static int __maybe_unused tegra_qspi_runtime_resume(struct device *dev)
        struct tegra_qspi *tqspi = spi_master_get_devdata(master);
        int ret;
 
+       /* Runtime pm disabled with ACPI */
+       if (has_acpi_companion(tqspi->dev))
+               return 0;
        ret = clk_prepare_enable(tqspi->clk);
        if (ret < 0)
                dev_err(tqspi->dev, "failed to enable clock: %d\n", ret);
@@ -1389,6 +1665,7 @@ static struct platform_driver tegra_qspi_driver = {
                .name           = "tegra-qspi",
                .pm             = &tegra_qspi_pm_ops,
                .of_match_table = tegra_qspi_of_match,
+               .acpi_match_table = ACPI_PTR(tegra_qspi_acpi_match),
        },
        .probe =        tegra_qspi_probe,
        .remove =       tegra_qspi_remove,
index f8ad0709d015290a5de2ca67680b6055fff69e67..a565352f63815fc8d8698047c5793545ddd6f1bc 100644 (file)
@@ -288,7 +288,7 @@ static int tle62x0_probe(struct spi_device *spi)
        return ret;
 }
 
-static int tle62x0_remove(struct spi_device *spi)
+static void tle62x0_remove(struct spi_device *spi)
 {
        struct tle62x0_state *st = spi_get_drvdata(spi);
        int ptr;
@@ -298,7 +298,6 @@ static int tle62x0_remove(struct spi_device *spi)
 
        device_remove_file(&spi->dev, &dev_attr_status_show);
        kfree(st);
-       return 0;
 }
 
 static struct spi_driver tle62x0_driver = {
index 8c4615b76339879bc9de125f98efa36ff0a12587..dfaa1d79a78be04e1f8cc4c45b765d7ee95a8ea8 100644 (file)
 static int use_dma = 1;
 
 struct pch_spi_dma_ctrl {
+       struct pci_dev          *dma_dev;
        struct dma_async_tx_descriptor  *desc_tx;
        struct dma_async_tx_descriptor  *desc_rx;
        struct pch_dma_slave            param_tx;
@@ -876,8 +877,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
        if (!chan) {
                dev_err(&data->master->dev,
                        "ERROR: dma_request_channel FAILS(Tx)\n");
-               data->use_dma = 0;
-               return;
+               goto out;
        }
        dma->chan_tx = chan;
 
@@ -893,10 +893,15 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
                        "ERROR: dma_request_channel FAILS(Rx)\n");
                dma_release_channel(dma->chan_tx);
                dma->chan_tx = NULL;
-               data->use_dma = 0;
-               return;
+               goto out;
        }
        dma->chan_rx = chan;
+
+       dma->dma_dev = dma_dev;
+       return;
+out:
+       pci_dev_put(dma_dev);
+       data->use_dma = 0;
 }
 
 static void pch_spi_release_dma(struct pch_spi_data *data)
@@ -912,6 +917,8 @@ static void pch_spi_release_dma(struct pch_spi_data *data)
                dma_release_channel(dma->chan_rx);
                dma->chan_rx = NULL;
        }
+
+       pci_dev_put(dma->dma_dev);
 }
 
 static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
index 328b6559bb19a2f9240f793e58bc746d941e3959..2b5afae8ff7fc457a9c67054436bdaeb796fcf6c 100644 (file)
@@ -1172,7 +1172,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
                goto clk_dis_all;
        }
 
-       dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+       ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+       if (ret)
+               goto clk_dis_all;
+
        ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
        ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;
        ctlr->mem_ops = &zynqmp_qspi_mem_ops;
index d96082dc3340dbc744b1cf83321ff5b68fdc5ad6..c4dd1200fe99166f81285cdd9a0d09bb4a211f01 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-mem.h>
-#include <linux/of_gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
@@ -144,7 +143,7 @@ static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \
        unsigned long flags;                                            \
        ssize_t len;                                                    \
        spin_lock_irqsave(&stat->lock, flags);                          \
-       len = sprintf(buf, format_string, stat->field);                 \
+       len = sysfs_emit(buf, format_string "\n", stat->field);         \
        spin_unlock_irqrestore(&stat->lock, flags);                     \
        return len;                                                     \
 }                                                                      \
@@ -404,15 +403,8 @@ static void spi_remove(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
 
-       if (sdrv->remove) {
-               int ret;
-
-               ret = sdrv->remove(to_spi_device(dev));
-               if (ret)
-                       dev_warn(dev,
-                                "Failed to unbind driver (%pe), ignoring\n",
-                                ERR_PTR(ret));
-       }
+       if (sdrv->remove)
+               sdrv->remove(to_spi_device(dev));
 
        dev_pm_domain_detach(dev, true);
 }
@@ -532,7 +524,7 @@ static DEFINE_MUTEX(board_lock);
  *
  * Return: a pointer to the new device, or NULL.
  */
-static struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
+struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
 {
        struct spi_device       *spi;
 
@@ -549,7 +541,6 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
        spi->dev.parent = &ctlr->dev;
        spi->dev.bus = &spi_bus_type;
        spi->dev.release = spidev_release;
-       spi->cs_gpio = -ENOENT;
        spi->mode = ctlr->buswidth_override_bits;
 
        spin_lock_init(&spi->statistics.lock);
@@ -557,6 +548,7 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
        device_initialize(&spi->dev);
        return spi;
 }
+EXPORT_SYMBOL_GPL(spi_alloc_device);
 
 static void spi_dev_set_name(struct spi_device *spi)
 {
@@ -612,11 +604,8 @@ static int __spi_add_device(struct spi_device *spi)
                return -ENODEV;
        }
 
-       /* Descriptors take precedence */
        if (ctlr->cs_gpiods)
                spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select];
-       else if (ctlr->cs_gpios)
-               spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
 
        /*
         * Drivers may modify this initial i/o setup, but will
@@ -652,7 +641,7 @@ static int __spi_add_device(struct spi_device *spi)
  *
  * Return: 0 on success; negative errno on failure
  */
-static int spi_add_device(struct spi_device *spi)
+int spi_add_device(struct spi_device *spi)
 {
        struct spi_controller *ctlr = spi->controller;
        struct device *dev = ctlr->dev.parent;
@@ -673,6 +662,7 @@ static int spi_add_device(struct spi_device *spi)
        mutex_unlock(&ctlr->add_lock);
        return status;
 }
+EXPORT_SYMBOL_GPL(spi_add_device);
 
 static int spi_add_device_locked(struct spi_device *spi)
 {
@@ -936,48 +926,40 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
         * Avoid calling into the driver (or doing delays) if the chip select
         * isn't actually changing from the last time this was called.
         */
-       if (!force && (spi->controller->last_cs_enable == enable) &&
+       if (!force && ((enable && spi->controller->last_cs == spi->chip_select) ||
+                               (!enable && spi->controller->last_cs != spi->chip_select)) &&
            (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH)))
                return;
 
        trace_spi_set_cs(spi, activate);
 
-       spi->controller->last_cs_enable = enable;
+       spi->controller->last_cs = enable ? spi->chip_select : -1;
        spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
 
-       if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
-           !spi->controller->set_cs_timing) && !activate) {
+       if ((spi->cs_gpiod || !spi->controller->set_cs_timing) && !activate) {
                spi_delay_exec(&spi->cs_hold, NULL);
        }
 
        if (spi->mode & SPI_CS_HIGH)
                enable = !enable;
 
-       if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
+       if (spi->cs_gpiod) {
                if (!(spi->mode & SPI_NO_CS)) {
-                       if (spi->cs_gpiod) {
-                               /*
-                                * Historically ACPI has no means of the GPIO polarity and
-                                * thus the SPISerialBus() resource defines it on the per-chip
-                                * basis. In order to avoid a chain of negations, the GPIO
-                                * polarity is considered being Active High. Even for the cases
-                                * when _DSD() is involved (in the updated versions of ACPI)
-                                * the GPIO CS polarity must be defined Active High to avoid
-                                * ambiguity. That's why we use enable, that takes SPI_CS_HIGH
-                                * into account.
-                                */
-                               if (has_acpi_companion(&spi->dev))
-                                       gpiod_set_value_cansleep(spi->cs_gpiod, !enable);
-                               else
-                                       /* Polarity handled by GPIO library */
-                                       gpiod_set_value_cansleep(spi->cs_gpiod, activate);
-                       } else {
-                               /*
-                                * Invert the enable line, as active low is
-                                * default for SPI.
-                                */
-                               gpio_set_value_cansleep(spi->cs_gpio, !enable);
-                       }
+                       /*
+                        * Historically ACPI has no means of the GPIO polarity and
+                        * thus the SPISerialBus() resource defines it on the per-chip
+                        * basis. In order to avoid a chain of negations, the GPIO
+                        * polarity is considered being Active High. Even for the cases
+                        * when _DSD() is involved (in the updated versions of ACPI)
+                        * the GPIO CS polarity must be defined Active High to avoid
+                        * ambiguity. That's why we use enable, that takes SPI_CS_HIGH
+                        * into account.
+                        */
+                       if (has_acpi_companion(&spi->dev))
+                               gpiod_set_value_cansleep(spi->cs_gpiod, !enable);
+                       else
+                               /* Polarity handled by GPIO library */
+                               gpiod_set_value_cansleep(spi->cs_gpiod, activate);
                }
                /* Some SPI masters need both GPIO CS & slave_select */
                if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
@@ -987,8 +969,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
                spi->controller->set_cs(spi, !enable);
        }
 
-       if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) ||
-           !spi->controller->set_cs_timing) {
+       if (spi->cs_gpiod || !spi->controller->set_cs_timing) {
                if (activate)
                        spi_delay_exec(&spi->cs_setup, NULL);
                else
@@ -1019,10 +1000,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
        int i, ret;
 
        if (vmalloced_buf || kmap_buf) {
-               desc_len = min_t(unsigned int, max_seg_size, PAGE_SIZE);
+               desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE);
                sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
        } else if (virt_addr_valid(buf)) {
-               desc_len = min_t(unsigned int, max_seg_size, ctlr->max_dma_len);
+               desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len);
                sgs = DIV_ROUND_UP(len, desc_len);
        } else {
                return -EINVAL;
@@ -2318,8 +2299,50 @@ struct acpi_spi_lookup {
        int                     irq;
        u8                      bits_per_word;
        u8                      chip_select;
+       int                     n;
+       int                     index;
 };
 
+static int acpi_spi_count(struct acpi_resource *ares, void *data)
+{
+       struct acpi_resource_spi_serialbus *sb;
+       int *count = data;
+
+       if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+               return 1;
+
+       sb = &ares->data.spi_serial_bus;
+       if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_SPI)
+               return 1;
+
+       *count = *count + 1;
+
+       return 1;
+}
+
+/**
+ * acpi_spi_count_resources - Count the number of SpiSerialBus resources
+ * @adev:      ACPI device
+ *
+ * Returns the number of SpiSerialBus resources in the ACPI-device's
+ * resource-list; or a negative error code.
+ */
+int acpi_spi_count_resources(struct acpi_device *adev)
+{
+       LIST_HEAD(r);
+       int count = 0;
+       int ret;
+
+       ret = acpi_dev_get_resources(adev, &r, acpi_spi_count, &count);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&r);
+
+       return count;
+}
+EXPORT_SYMBOL_GPL(acpi_spi_count_resources);
+
 static void acpi_spi_parse_apple_properties(struct acpi_device *dev,
                                            struct acpi_spi_lookup *lookup)
 {
@@ -2349,6 +2372,8 @@ static void acpi_spi_parse_apple_properties(struct acpi_device *dev,
                lookup->mode |= SPI_CPHA;
 }
 
+static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev);
+
 static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
 {
        struct acpi_spi_lookup *lookup = data;
@@ -2362,14 +2387,35 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
                sb = &ares->data.spi_serial_bus;
                if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
 
+                       if (lookup->index != -1 && lookup->n++ != lookup->index)
+                               return 1;
+
+                       if (lookup->index == -1 && !ctlr)
+                               return -ENODEV;
+
                        status = acpi_get_handle(NULL,
                                                 sb->resource_source.string_ptr,
                                                 &parent_handle);
 
-                       if (ACPI_FAILURE(status) ||
-                           ACPI_HANDLE(ctlr->dev.parent) != parent_handle)
+                       if (ACPI_FAILURE(status))
                                return -ENODEV;
 
+                       if (ctlr) {
+                               if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle)
+                                       return -ENODEV;
+                       } else {
+                               struct acpi_device *adev;
+
+                               if (acpi_bus_get_device(parent_handle, &adev))
+                                       return -ENODEV;
+
+                               ctlr = acpi_spi_find_controller_by_adev(adev);
+                               if (!ctlr)
+                                       return -ENODEV;
+
+                               lookup->ctlr = ctlr;
+                       }
+
                        /*
                         * ACPI DeviceSelection numbering is handled by the
                         * host controller driver in Windows and can vary
@@ -2408,8 +2454,25 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
        return 1;
 }
 
-static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
-                                           struct acpi_device *adev)
+/**
+ * acpi_spi_device_alloc - Allocate a spi device, and fill it in with ACPI information
+ * @ctlr: controller to which the spi device belongs
+ * @adev: ACPI Device for the spi device
+ * @index: Index of the spi resource inside the ACPI Node
+ *
+ * This should be used to allocate a new spi device from and ACPI Node.
+ * The caller is responsible for calling spi_add_device to register the spi device.
+ *
+ * If ctlr is set to NULL, the Controller for the spi device will be looked up
+ * using the resource.
+ * If index is set to -1, index is not used.
+ * Note: If index is -1, ctlr must be set.
+ *
+ * Return: a pointer to the new device, or ERR_PTR on error.
+ */
+struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
+                                        struct acpi_device *adev,
+                                        int index)
 {
        acpi_handle parent_handle = NULL;
        struct list_head resource_list;
@@ -2417,12 +2480,13 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
        struct spi_device *spi;
        int ret;
 
-       if (acpi_bus_get_status(adev) || !adev->status.present ||
-           acpi_device_enumerated(adev))
-               return AE_OK;
+       if (!ctlr && index == -1)
+               return ERR_PTR(-EINVAL);
 
        lookup.ctlr             = ctlr;
        lookup.irq              = -1;
+       lookup.index            = index;
+       lookup.n                = 0;
 
        INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list,
@@ -2431,26 +2495,25 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
 
        if (ret < 0)
                /* found SPI in _CRS but it points to another controller */
-               return AE_OK;
+               return ERR_PTR(-ENODEV);
 
        if (!lookup.max_speed_hz &&
            ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) &&
-           ACPI_HANDLE(ctlr->dev.parent) == parent_handle) {
+           ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) {
                /* Apple does not use _CRS but nested devices for SPI slaves */
                acpi_spi_parse_apple_properties(adev, &lookup);
        }
 
        if (!lookup.max_speed_hz)
-               return AE_OK;
+               return ERR_PTR(-ENODEV);
 
-       spi = spi_alloc_device(ctlr);
+       spi = spi_alloc_device(lookup.ctlr);
        if (!spi) {
-               dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n",
+               dev_err(&lookup.ctlr->dev, "failed to allocate SPI device for %s\n",
                        dev_name(&adev->dev));
-               return AE_NO_MEMORY;
+               return ERR_PTR(-ENOMEM);
        }
 
-
        ACPI_COMPANION_SET(&spi->dev, adev);
        spi->max_speed_hz       = lookup.max_speed_hz;
        spi->mode               |= lookup.mode;
@@ -2458,6 +2521,27 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
        spi->bits_per_word      = lookup.bits_per_word;
        spi->chip_select        = lookup.chip_select;
 
+       return spi;
+}
+EXPORT_SYMBOL_GPL(acpi_spi_device_alloc);
+
+static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
+                                           struct acpi_device *adev)
+{
+       struct spi_device *spi;
+
+       if (acpi_bus_get_status(adev) || !adev->status.present ||
+           acpi_device_enumerated(adev))
+               return AE_OK;
+
+       spi = acpi_spi_device_alloc(ctlr, adev, -1);
+       if (IS_ERR(spi)) {
+               if (PTR_ERR(spi) == -ENOMEM)
+                       return AE_NO_MEMORY;
+               else
+                       return AE_OK;
+       }
+
        acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
                          sizeof(spi->modalias));
 
@@ -2480,10 +2564,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
 static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
                                       void *data, void **return_value)
 {
+       struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
        struct spi_controller *ctlr = data;
-       struct acpi_device *adev;
 
-       if (acpi_bus_get_device(handle, &adev))
+       if (!adev)
                return AE_OK;
 
        return acpi_register_spi_device(ctlr, adev);
@@ -2729,46 +2813,6 @@ struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller);
 
-#ifdef CONFIG_OF
-static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
-{
-       int nb, i, *cs;
-       struct device_node *np = ctlr->dev.of_node;
-
-       if (!np)
-               return 0;
-
-       nb = of_gpio_named_count(np, "cs-gpios");
-       ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect);
-
-       /* Return error only for an incorrectly formed cs-gpios property */
-       if (nb == 0 || nb == -ENOENT)
-               return 0;
-       else if (nb < 0)
-               return nb;
-
-       cs = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect, sizeof(int),
-                         GFP_KERNEL);
-       ctlr->cs_gpios = cs;
-
-       if (!ctlr->cs_gpios)
-               return -ENOMEM;
-
-       for (i = 0; i < ctlr->num_chipselect; i++)
-               cs[i] = -ENOENT;
-
-       for (i = 0; i < nb; i++)
-               cs[i] = of_get_named_gpio(np, "cs-gpios", i);
-
-       return 0;
-}
-#else
-static int of_spi_get_gpio_numbers(struct spi_controller *ctlr)
-{
-       return 0;
-}
-#endif
-
 /**
  * spi_get_gpio_descs() - grab chip select GPIOs for the master
  * @ctlr: The SPI master to grab GPIO descriptors for
@@ -2953,22 +2997,15 @@ int spi_register_controller(struct spi_controller *ctlr)
         */
        dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
 
-       if (!spi_controller_is_slave(ctlr)) {
-               if (ctlr->use_gpio_descriptors) {
-                       status = spi_get_gpio_descs(ctlr);
-                       if (status)
-                               goto free_bus_id;
-                       /*
-                        * A controller using GPIO descriptors always
-                        * supports SPI_CS_HIGH if need be.
-                        */
-                       ctlr->mode_bits |= SPI_CS_HIGH;
-               } else {
-                       /* Legacy code path for GPIOs from DT */
-                       status = of_spi_get_gpio_numbers(ctlr);
-                       if (status)
-                               goto free_bus_id;
-               }
+       if (!spi_controller_is_slave(ctlr) && ctlr->use_gpio_descriptors) {
+               status = spi_get_gpio_descs(ctlr);
+               if (status)
+                       goto free_bus_id;
+               /*
+                * A controller using GPIO descriptors always
+                * supports SPI_CS_HIGH if need be.
+                */
+               ctlr->mode_bits |= SPI_CS_HIGH;
        }
 
        /*
@@ -2980,6 +3017,9 @@ int spi_register_controller(struct spi_controller *ctlr)
                goto free_bus_id;
        }
 
+       /* setting last_cs to -1 means no chip selected */
+       ctlr->last_cs = -1;
+
        status = device_add(&ctlr->dev);
        if (status < 0)
                goto free_bus_id;
@@ -3457,12 +3497,6 @@ int spi_setup(struct spi_device *spi)
         */
        bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD |
                                 SPI_NO_TX | SPI_NO_RX);
-       /*
-        * Nothing prevents from working with active-high CS in case if it
-        * is driven by GPIO.
-        */
-       if (gpio_is_valid(spi->cs_gpio))
-               bad_bits &= ~SPI_CS_HIGH;
        ugly_bits = bad_bits &
                    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL |
                     SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL);
@@ -3588,8 +3622,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
         * cs_change is set for each transfer.
         */
        if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) ||
-                                         spi->cs_gpiod ||
-                                         gpio_is_valid(spi->cs_gpio))) {
+                                         spi->cs_gpiod)) {
                size_t maxsize;
                int ret;
 
index a5cceca8b82b6c61891346fbeeee41cb5474df3c..53a55171426530cbada4894a4d083c5b49b2fe29 100644 (file)
@@ -453,22 +453,29 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                dev_dbg(&spi->dev, "%d bits per word\n", tmp);
                }
                break;
-       case SPI_IOC_WR_MAX_SPEED_HZ:
+       case SPI_IOC_WR_MAX_SPEED_HZ: {
+               u32 save;
+
                retval = get_user(tmp, (__u32 __user *)arg);
-               if (retval == 0) {
-                       u32     save = spi->max_speed_hz;
+               if (retval)
+                       break;
+               if (tmp == 0) {
+                       retval = -EINVAL;
+                       break;
+               }
 
-                       spi->max_speed_hz = tmp;
-                       retval = spi_setup(spi);
-                       if (retval == 0) {
-                               spidev->speed_hz = tmp;
-                               dev_dbg(&spi->dev, "%d Hz (max)\n",
-                                       spidev->speed_hz);
-                       }
-                       spi->max_speed_hz = save;
+               save = spi->max_speed_hz;
+
+               spi->max_speed_hz = tmp;
+               retval = spi_setup(spi);
+               if (retval == 0) {
+                       spidev->speed_hz = tmp;
+                       dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz);
                }
-               break;
 
+               spi->max_speed_hz = save;
+               break;
+       }
        default:
                /* segmented and/or full-duplex I/O request */
                /* Check message and copy into scratch area */
@@ -803,7 +810,7 @@ static int spidev_probe(struct spi_device *spi)
        return status;
 }
 
-static int spidev_remove(struct spi_device *spi)
+static void spidev_remove(struct spi_device *spi)
 {
        struct spidev_data      *spidev = spi_get_drvdata(spi);
 
@@ -820,8 +827,6 @@ static int spidev_remove(struct spi_device *spi)
        if (spidev->users == 0)
                kfree(spidev);
        mutex_unlock(&device_list_lock);
-
-       return 0;
 }
 
 static struct spi_driver spidev_spi_driver = {
index 55677efc01380a78f576be27af41a9825bc2279c..b68f5f9b7c78cc0ba36e1600217c2d6360b33e9f 100644 (file)
@@ -272,21 +272,39 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
 void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
 void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
 
+#define FBTFT_DT_TABLE(_compatible)                                            \
+static const struct of_device_id dt_ids[] = {                                  \
+       { .compatible = _compatible },                                          \
+       {},                                                                     \
+};                                                                             \
+MODULE_DEVICE_TABLE(of, dt_ids);
+
+#define FBTFT_SPI_DRIVER(_name, _compatible, _display, _spi_ids)               \
+                                                                               \
+static int fbtft_driver_probe_spi(struct spi_device *spi)                      \
+{                                                                              \
+       return fbtft_probe_common(_display, spi, NULL);                         \
+}                                                                              \
+                                                                               \
+static void fbtft_driver_remove_spi(struct spi_device *spi)                    \
+{                                                                              \
+       struct fb_info *info = spi_get_drvdata(spi);                            \
+                                                                               \
+       fbtft_remove_common(&spi->dev, info);                                   \
+}                                                                              \
+                                                                               \
+static struct spi_driver fbtft_driver_spi_driver = {                           \
+       .driver = {                                                             \
+               .name = _name,                                                  \
+               .of_match_table = dt_ids,                                       \
+       },                                                                      \
+       .id_table = _spi_ids,                                                   \
+       .probe = fbtft_driver_probe_spi,                                        \
+       .remove = fbtft_driver_remove_spi,                                      \
+};
+
 #define FBTFT_REGISTER_DRIVER(_name, _compatible, _display)                \
                                                                           \
-static int fbtft_driver_probe_spi(struct spi_device *spi)                  \
-{                                                                          \
-       return fbtft_probe_common(_display, spi, NULL);                    \
-}                                                                          \
-                                                                          \
-static int fbtft_driver_remove_spi(struct spi_device *spi)                 \
-{                                                                          \
-       struct fb_info *info = spi_get_drvdata(spi);                       \
-                                                                          \
-       fbtft_remove_common(&spi->dev, info);                              \
-       return 0;                                                          \
-}                                                                          \
-                                                                          \
 static int fbtft_driver_probe_pdev(struct platform_device *pdev)           \
 {                                                                          \
        return fbtft_probe_common(_display, NULL, pdev);                   \
@@ -300,22 +318,9 @@ static int fbtft_driver_remove_pdev(struct platform_device *pdev)          \
        return 0;                                                          \
 }                                                                          \
                                                                           \
-static const struct of_device_id dt_ids[] = {                              \
-       { .compatible = _compatible },                                     \
-       {},                                                                \
-};                                                                         \
-                                                                          \
-MODULE_DEVICE_TABLE(of, dt_ids);                                           \
+FBTFT_DT_TABLE(_compatible)                                               \
                                                                           \
-                                                                          \
-static struct spi_driver fbtft_driver_spi_driver = {                       \
-       .driver = {                                                        \
-               .name   = _name,                                           \
-               .of_match_table = dt_ids,                                  \
-       },                                                                 \
-       .probe  = fbtft_driver_probe_spi,                                  \
-       .remove = fbtft_driver_remove_spi,                                 \
-};                                                                         \
+FBTFT_SPI_DRIVER(_name, _compatible, _display, NULL)                      \
                                                                           \
 static struct platform_driver fbtft_driver_platform_driver = {             \
        .driver = {                                                        \
@@ -351,42 +356,15 @@ module_exit(fbtft_driver_module_exit);
 
 #define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display)      \
                                                                                \
-static int fbtft_driver_probe_spi(struct spi_device *spi)                      \
-{                                                                              \
-       return fbtft_probe_common(_display, spi, NULL);                         \
-}                                                                              \
-                                                                               \
-static int fbtft_driver_remove_spi(struct spi_device *spi)                     \
-{                                                                              \
-       struct fb_info *info = spi_get_drvdata(spi);                            \
-                                                                               \
-       fbtft_remove_common(&spi->dev, info);                                   \
-       return 0;                                                               \
-}                                                                              \
-                                                                               \
-static const struct of_device_id dt_ids[] = {                                  \
-       { .compatible = _comp_vend "," _comp_dev },                             \
-       {},                                                                     \
-};                                                                             \
-                                                                               \
-MODULE_DEVICE_TABLE(of, dt_ids);                                               \
+FBTFT_DT_TABLE(_comp_vend "," _comp_dev)                                       \
                                                                                \
 static const struct spi_device_id spi_ids[] = {                                        \
        { .name = _comp_dev },                                                  \
        {},                                                                     \
 };                                                                             \
-                                                                               \
 MODULE_DEVICE_TABLE(spi, spi_ids);                                             \
                                                                                \
-static struct spi_driver fbtft_driver_spi_driver = {                           \
-       .driver = {                                                             \
-               .name  = _name,                                                 \
-               .of_match_table = dt_ids,                                       \
-       },                                                                      \
-       .id_table = spi_ids,                                                    \
-       .probe  = fbtft_driver_probe_spi,                                       \
-       .remove = fbtft_driver_remove_spi,                                      \
-};                                                                             \
+FBTFT_SPI_DRIVER(_name, _comp_vend "," _comp_dev, _display, spi_ids)           \
                                                                                \
 module_spi_driver(fbtft_driver_spi_driver);
 
index 68c09fa016ed335e7722bf0a463a8467207901cc..1d31c35875e335b43c0ab2a019546c8d35de6cbc 100644 (file)
@@ -1264,7 +1264,7 @@ RX_failed:
        return retval;
 }
 
-static int pi433_remove(struct spi_device *spi)
+static void pi433_remove(struct spi_device *spi)
 {
        struct pi433_device     *device = spi_get_drvdata(spi);
 
@@ -1284,8 +1284,6 @@ static int pi433_remove(struct spi_device *spi)
 
        kfree(device->rx_buffer);
        kfree(device);
-
-       return 0;
 }
 
 static const struct of_device_id pi433_dt_ids[] = {
index 55ffcd7c42e27aff526eeef371f627ec4c50faf9..fa0ff66a457df6f7e0ff2e8de668c6f50ecba1c7 100644 (file)
@@ -232,12 +232,11 @@ static int wfx_spi_probe(struct spi_device *func)
        return wfx_probe(bus->core);
 }
 
-static int wfx_spi_remove(struct spi_device *func)
+static void wfx_spi_remove(struct spi_device *func)
 {
        struct wfx_spi_priv *bus = spi_get_drvdata(func);
 
        wfx_release(bus->core);
-       return 0;
 }
 
 /* For dynamic driver binding, kernel does not use OF to match driver. It only
index 3c92d4e014887f15f553da1a4fb2d6a3b3758eb7..516cff362434d51c2548a19c2cefa5866f720abf 100644 (file)
@@ -805,7 +805,7 @@ static int max3100_probe(struct spi_device *spi)
        return 0;
 }
 
-static int max3100_remove(struct spi_device *spi)
+static void max3100_remove(struct spi_device *spi)
 {
        struct max3100_port *s = spi_get_drvdata(spi);
        int i;
@@ -828,13 +828,12 @@ static int max3100_remove(struct spi_device *spi)
        for (i = 0; i < MAX_MAX3100; i++)
                if (max3100s[i]) {
                        mutex_unlock(&max3100s_lock);
-                       return 0;
+                       return;
                }
        pr_debug("removing max3100 driver\n");
        uart_unregister_driver(&max3100_uart_driver);
 
        mutex_unlock(&max3100s_lock);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index dde0824b2fa527216e65b14b45eed3c64a23083c..3112b4a054485f78ce82766b02974d2af89472c0 100644 (file)
@@ -1487,10 +1487,9 @@ static int max310x_spi_probe(struct spi_device *spi)
        return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
 }
 
-static int max310x_spi_remove(struct spi_device *spi)
+static void max310x_spi_remove(struct spi_device *spi)
 {
        max310x_remove(&spi->dev);
-       return 0;
 }
 
 static const struct spi_device_id max310x_id_table[] = {
index 38d1c0748533cdc951022d6d61d1e07b8814d974..3a6c68e19c80d20088e79f67278f8474e78e8b40 100644 (file)
@@ -1443,11 +1443,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
        return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);
 }
 
-static int sc16is7xx_spi_remove(struct spi_device *spi)
+static void sc16is7xx_spi_remove(struct spi_device *spi)
 {
        sc16is7xx_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id sc16is7xx_spi_id_table[] = {
index d2a2b20cc1ad457e7d8352b502f143a850440cac..7d9bd16190c09faaf120c2dadd307b5dd0646d87 100644 (file)
@@ -1292,7 +1292,7 @@ del_gadget:
        return err;
 }
 
-static int max3420_remove(struct spi_device *spi)
+static void max3420_remove(struct spi_device *spi)
 {
        struct max3420_udc *udc = spi_get_drvdata(spi);
        unsigned long flags;
@@ -1304,8 +1304,6 @@ static int max3420_remove(struct spi_device *spi)
        kthread_stop(udc->thread_task);
 
        spin_unlock_irqrestore(&udc->lock, flags);
-
-       return 0;
 }
 
 static const struct of_device_id max3420_udc_of_match[] = {
index 30de85a707fef503d1f66f38712e33a5607313e0..99a5523a79fb9a3afe1224fd4ceac9ad05d9a20d 100644 (file)
@@ -1926,7 +1926,7 @@ error:
        return retval;
 }
 
-static int
+static void
 max3421_remove(struct spi_device *spi)
 {
        struct max3421_hcd *max3421_hcd;
@@ -1947,7 +1947,6 @@ max3421_remove(struct spi_device *spi)
        free_irq(spi->irq, hcd);
 
        usb_put_hcd(hcd);
-       return 0;
 }
 
 static const struct of_device_id max3421_of_match_table[] = {
index 8a4361e95a1143be5658ca7a515e9868243821a6..522dd81110b8e7f5b945d10793327f0d1814d1d5 100644 (file)
@@ -506,12 +506,11 @@ static int ams369fg06_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ams369fg06_remove(struct spi_device *spi)
+static void ams369fg06_remove(struct spi_device *spi)
 {
        struct ams369fg06 *lcd = spi_get_drvdata(spi);
 
        ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 33f5d80495e6f46f7b30cec6c72fba41d5b79f86..0a57033ae31d1dc2253f310ac37bd5c6e2f559ea 100644 (file)
@@ -542,7 +542,7 @@ static int corgi_lcd_probe(struct spi_device *spi)
        return 0;
 }
 
-static int corgi_lcd_remove(struct spi_device *spi)
+static void corgi_lcd_remove(struct spi_device *spi)
 {
        struct corgi_lcd *lcd = spi_get_drvdata(spi);
 
@@ -550,7 +550,6 @@ static int corgi_lcd_remove(struct spi_device *spi)
        lcd->bl_dev->props.brightness = 0;
        backlight_update_status(lcd->bl_dev);
        corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 static struct spi_driver corgi_lcd_driver = {
index 328aba9cddad191d45ecb9258e719022f2f3a31e..e7b6bd827986fa931de3d3e6c22565e8227afd35 100644 (file)
@@ -526,10 +526,9 @@ static int ili922x_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ili922x_remove(struct spi_device *spi)
+static void ili922x_remove(struct spi_device *spi)
 {
        ili922x_poweroff(spi);
-       return 0;
 }
 
 static struct spi_driver ili922x_driver = {
index 46f97d1c3d2190503343caa99a467d54c0a59efb..cc763cf15f53e695c541bd28df5f4e111af627a6 100644 (file)
@@ -223,12 +223,11 @@ static int l4f00242t03_probe(struct spi_device *spi)
        return 0;
 }
 
-static int l4f00242t03_remove(struct spi_device *spi)
+static void l4f00242t03_remove(struct spi_device *spi)
 {
        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
 
        l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 static void l4f00242t03_shutdown(struct spi_device *spi)
index f949b66dce1bed3378725fa062d7b26fc34d738c..5c46df8022bf4d3bf15ccb94e4d13c4c95ae0d3a 100644 (file)
@@ -364,12 +364,11 @@ static int lms501kf03_probe(struct spi_device *spi)
        return 0;
 }
 
-static int lms501kf03_remove(struct spi_device *spi)
+static void lms501kf03_remove(struct spi_device *spi)
 {
        struct lms501kf03 *lcd = spi_get_drvdata(spi);
 
        lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 5cbf621e48bd3be2e7e71ef8534a3b9ee52f45b2..b6d373af6e3f1fcd4b8f78cac6343a17a6f024c8 100644 (file)
@@ -255,12 +255,11 @@ static int ltv350qv_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ltv350qv_remove(struct spi_device *spi)
+static void ltv350qv_remove(struct spi_device *spi)
 {
        struct ltv350qv *lcd = spi_get_drvdata(spi);
 
        ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 0de044dcafd5050dbf07a1dcd422071b5ccbc119..fc6fbaf855943780fd493d056893bcd78b184629 100644 (file)
@@ -397,12 +397,11 @@ static int tdo24m_probe(struct spi_device *spi)
        return 0;
 }
 
-static int tdo24m_remove(struct spi_device *spi)
+static void tdo24m_remove(struct spi_device *spi)
 {
        struct tdo24m *lcd = spi_get_drvdata(spi);
 
        tdo24m_power(lcd, FB_BLANK_POWERDOWN);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 38765544345b8d76f07aacfd6038f1855ad082e2..23d6c6bf0f54311d66938669f1156cf83162b5d2 100644 (file)
@@ -232,15 +232,13 @@ err_register:
        return ret;
 }
 
-static int tosa_lcd_remove(struct spi_device *spi)
+static void tosa_lcd_remove(struct spi_device *spi)
 {
        struct tosa_lcd_data *data = spi_get_drvdata(spi);
 
        i2c_unregister_device(data->i2c);
 
        tosa_lcd_tg_off(data);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 3567b45f9ba9f270cf86901815cc8ce5c10c3ed9..bfc1913e8b55e3b60946624d3565d37aad5801cd 100644 (file)
@@ -233,11 +233,9 @@ static int vgg2432a4_probe(struct spi_device *spi)
        return 0;
 }
 
-static int vgg2432a4_remove(struct spi_device *spi)
+static void vgg2432a4_remove(struct spi_device *spi)
 {
        ili9320_remove(spi_get_drvdata(spi));
-
-       return 0;
 }
 
 static void vgg2432a4_shutdown(struct spi_device *spi)
index a75ae0c9b14c7d4c1ba3fd966359461f1384e8c4..03cff39d392db3f67e77f9790ca63d02a3dd29f9 100644 (file)
@@ -570,14 +570,12 @@ static int mipid_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int mipid_spi_remove(struct spi_device *spi)
+static void mipid_spi_remove(struct spi_device *spi)
 {
        struct mipid_device *md = dev_get_drvdata(&spi->dev);
 
        mipid_disable(&md->panel);
        kfree(md);
-
-       return 0;
 }
 
 static struct spi_driver mipid_spi_driver = {
index 1bec7a4422e8056b468455ed12889ffb1e372be1..aab67721263d8df51b58a01bb71fadcbd4b79940 100644 (file)
@@ -316,7 +316,7 @@ err_gpio:
        return r;
 }
 
-static int lb035q02_panel_spi_remove(struct spi_device *spi)
+static void lb035q02_panel_spi_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = spi_get_drvdata(spi);
        struct omap_dss_device *dssdev = &ddata->dssdev;
@@ -328,8 +328,6 @@ static int lb035q02_panel_spi_remove(struct spi_device *spi)
        lb035q02_disconnect(dssdev);
 
        omap_dss_put_device(in);
-
-       return 0;
 }
 
 static const struct of_device_id lb035q02_of_match[] = {
index dff9ebbadfc0f80f27e9db46751edde663cac1b0..be9910ff6e62d410b90d77a39337083317443c85 100644 (file)
@@ -327,7 +327,7 @@ err_gpio:
        return r;
 }
 
-static int nec_8048_remove(struct spi_device *spi)
+static void nec_8048_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
@@ -341,8 +341,6 @@ static int nec_8048_remove(struct spi_device *spi)
        nec_8048_disconnect(dssdev);
 
        omap_dss_put_device(in);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 8d8b5ff7d43c8e0bb635132667e8f57f86b2824b..a909b5385ca5b0486e86174a3fd68aeab50280cf 100644 (file)
@@ -857,7 +857,7 @@ err_gpio:
        return r;
 }
 
-static int acx565akm_remove(struct spi_device *spi)
+static void acx565akm_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
@@ -874,8 +874,6 @@ static int acx565akm_remove(struct spi_device *spi)
        acx565akm_disconnect(dssdev);
 
        omap_dss_put_device(in);
-
-       return 0;
 }
 
 static const struct of_device_id acx565akm_of_match[] = {
index 595ebd8bd5dcb98dd29e1c3ee6beb00337fff6b4..3c0f887d3092627aa7a13bb71ea041df515ed1aa 100644 (file)
@@ -425,7 +425,7 @@ err_reg:
        return r;
 }
 
-static int td028ttec1_panel_remove(struct spi_device *spi)
+static void td028ttec1_panel_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
@@ -439,8 +439,6 @@ static int td028ttec1_panel_remove(struct spi_device *spi)
        td028ttec1_panel_disconnect(dssdev);
 
        omap_dss_put_device(in);
-
-       return 0;
 }
 
 static const struct of_device_id td028ttec1_of_match[] = {
index afac1d9445aa27f08d146839cc7ecb60c7d1a871..58bbba7c037fa3fa6d5cedcf0e28d6e59e81abc2 100644 (file)
@@ -564,7 +564,7 @@ err_regulator:
        return r;
 }
 
-static int tpo_td043_remove(struct spi_device *spi)
+static void tpo_td043_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
@@ -580,8 +580,6 @@ static int tpo_td043_remove(struct spi_device *spi)
        omap_dss_put_device(in);
 
        sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 39967a5eca6d6f9754293c3afe2df8ea895fd3db..ea4a4b1b246a29e494036ad5a885ba2854e5a09a 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef LPC_ICH_H
 #define LPC_ICH_H
 
-#include <linux/platform_data/x86/intel-spi.h>
+#include <linux/platform_data/x86/spi-intel.h>
 
 /* GPIO resources */
 #define ICH_RES_GPIO   0
index 773daf7915a374d214c9154132e93256c038c320..5df1ace6d2c98e1ea585ec8daa01e99da7db5f4d 100644 (file)
@@ -16,7 +16,6 @@ struct platform_device;
  * struct s3c64xx_spi_csinfo - ChipSelect description
  * @fb_delay: Slave specific feedback delay.
  *            Refer to FB_CLK_SEL register definition in SPI chapter.
- * @line: Custom 'identity' of the CS line.
  *
  * This is per SPI-Slave Chipselect information.
  * Allocate and initialize one in machine init code and make the
@@ -24,7 +23,6 @@ struct platform_device;
  */
 struct s3c64xx_spi_csinfo {
        u8 fb_delay;
-       unsigned line;
 };
 
 /**
@@ -43,26 +41,16 @@ struct s3c64xx_spi_info {
 /**
  * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
  *                             initialization code.
- * @cfg_gpio: Pointer to gpio setup function.
  * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
  * @num_cs: Number of elements in the 'cs' array.
  *
  * Call this from machine init code for each SPI Controller that
  * has some chips attached to it.
  */
-extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs);
-extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs);
-extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-                                               int num_cs);
+extern void s3c64xx_spi0_set_platdata(int src_clk_nr, int num_cs);
 
 /* defined by architecture to configure gpio */
 extern int s3c64xx_spi0_cfg_gpio(void);
-extern int s3c64xx_spi1_cfg_gpio(void);
-extern int s3c64xx_spi2_cfg_gpio(void);
 
 extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
-extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
-extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
 #endif /*__SPI_S3C64XX_H */
diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/intel-spi.h
deleted file mode 100644 (file)
index 7f53a5c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel PCH/PCU SPI flash driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#ifndef INTEL_SPI_PDATA_H
-#define INTEL_SPI_PDATA_H
-
-enum intel_spi_type {
-       INTEL_SPI_BYT = 1,
-       INTEL_SPI_LPT,
-       INTEL_SPI_BXT,
-       INTEL_SPI_CNL,
-};
-
-/**
- * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
- * @type: Type which this controller is compatible with
- * @writeable: The chip is writeable
- */
-struct intel_spi_boardinfo {
-       enum intel_spi_type type;
-       bool writeable;
-};
-
-#endif /* INTEL_SPI_PDATA_H */
diff --git a/include/linux/platform_data/x86/spi-intel.h b/include/linux/platform_data/x86/spi-intel.h
new file mode 100644 (file)
index 0000000..a512ec3
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Intel PCH/PCU SPI flash driver.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#ifndef SPI_INTEL_PDATA_H
+#define SPI_INTEL_PDATA_H
+
+enum intel_spi_type {
+       INTEL_SPI_BYT = 1,
+       INTEL_SPI_LPT,
+       INTEL_SPI_BXT,
+       INTEL_SPI_CNL,
+};
+
+/**
+ * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
+ * @type: Type which this controller is compatible with
+ * @set_writeable: Try to make the chip writeable (optional)
+ * @data: Data to be passed to @set_writeable can be %NULL
+ */
+struct intel_spi_boardinfo {
+       enum intel_spi_type type;
+       bool (*set_writeable)(void __iomem *base, void *data);
+       void *data;
+};
+
+#endif /* SPI_INTEL_PDATA_H */
index ca74dce3670653c47a5a95fbc3b67b9d1599a650..4658e7801b42e134c60e5bab9714bd62d7af9fcf 100644 (file)
@@ -42,7 +42,6 @@ struct pxa2xx_spi_chip {
        u8 rx_threshold;
        u8 dma_burst_size;
        u32 timeout;
-       int gpio_cs;
 };
 
 #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
index 440a715931629be5fee609b9040f30b6133ab1c7..9b8bb22d5b0cf499f2cab12d435f6683f083a842 100644 (file)
 #define __LINUX_SPI_S3C24XX_H __FILE__
 
 struct s3c2410_spi_info {
-       int                      pin_cs;        /* simple gpio cs */
        unsigned int             num_cs;        /* total chipselects */
        int                      bus_num;       /* bus number to use. */
-
        unsigned int             use_fiq:1;     /* use fiq */
-
-       void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
-       void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
 
 extern int s3c24xx_set_fiq(unsigned int irq, u32 *ack_ptr, bool on);
index 7ab3fed7b8043e61a2b80050ff75ec5a623d6814..7d005fa4631c301804d528cf9407226f57065b03 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/gpio/consumer.h>
 
 #include <uapi/linux/spi/spi.h>
+#include <linux/acpi.h>
 
 struct dma_chan;
 struct software_node;
@@ -136,9 +137,6 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
  *     for driver coldplugging, and in uevents used for hotplugging
  * @driver_override: If the name of a driver is written to this attribute, then
  *     the device will bind to the named driver and only the named driver.
- * @cs_gpio: LEGACY: gpio number of the chipselect line (optional, -ENOENT when
- *     not using a GPIO line) use cs_gpiod in new drivers by opting in on
- *     the spi_master.
  * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when
  *     not using a GPIO line)
  * @word_delay: delay to be inserted between consecutive
@@ -185,7 +183,6 @@ struct spi_device {
        void                    *controller_data;
        char                    modalias[SPI_NAME_SIZE];
        const char              *driver_override;
-       int                     cs_gpio;        /* LEGACY: chip select gpio */
        struct gpio_desc        *cs_gpiod;      /* chip select gpio desc */
        struct spi_delay        word_delay; /* inter-word delay */
        /* CS delays */
@@ -280,7 +277,7 @@ struct spi_message;
 struct spi_driver {
        const struct spi_device_id *id_table;
        int                     (*probe)(struct spi_device *spi);
-       int                     (*remove)(struct spi_device *spi);
+       void                    (*remove)(struct spi_device *spi);
        void                    (*shutdown)(struct spi_device *spi);
        struct device_driver    driver;
 };
@@ -373,7 +370,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
  * @cur_msg_prepared: spi_prepare_message was called for the currently
  *                    in-flight message
  * @cur_msg_mapped: message has been mapped for DMA
- * @last_cs_enable: was enable true on the last call to set_cs.
+ * @last_cs: the last chip_select that is recorded by set_cs, -1 on non chip
+ *           selected
  * @last_cs_mode_high: was (mode & SPI_CS_HIGH) true on the last call to set_cs.
  * @xfer_completion: used by core transfer_one_message()
  * @busy: message pump is busy
@@ -417,17 +415,12 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
  *          controller has native support for memory like operations.
  * @unprepare_message: undo any work done by prepare_message().
  * @slave_abort: abort the ongoing transfer request on an SPI slave controller
- * @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per
- *     CS number. Any individual value may be -ENOENT for CS lines that
- *     are not GPIOs (driven by the SPI controller itself). Use the cs_gpiods
- *     in new drivers.
  * @cs_gpiods: Array of GPIO descs to use as chip select lines; one per CS
  *     number. Any individual value may be NULL for CS lines that
  *     are not GPIOs (driven by the SPI controller itself).
  * @use_gpio_descriptors: Turns on the code in the SPI core to parse and grab
- *     GPIO descriptors rather than using global GPIO numbers grabbed by the
- *     driver. This will fill in @cs_gpiods and @cs_gpios should not be used,
- *     and SPI devices will have the cs_gpiod assigned rather than cs_gpio.
+ *     GPIO descriptors. This will fill in @cs_gpiods and SPI devices will have
+ *     the cs_gpiod assigned if a GPIO line is found for the chipselect.
  * @unused_native_cs: When cs_gpiods is used, spi_register_controller() will
  *     fill in this field with the first unused native CS, to be used by SPI
  *     controller drivers that need to drive a native CS when using GPIO CS.
@@ -611,7 +604,7 @@ struct spi_controller {
        bool                            auto_runtime_pm;
        bool                            cur_msg_prepared;
        bool                            cur_msg_mapped;
-       bool                            last_cs_enable;
+       char                            last_cs;
        bool                            last_cs_mode_high;
        bool                            fallback;
        struct completion               xfer_completion;
@@ -641,7 +634,6 @@ struct spi_controller {
        const struct spi_controller_mem_ops *mem_ops;
 
        /* gpio chip select */
-       int                     *cs_gpios;
        struct gpio_desc        **cs_gpiods;
        bool                    use_gpio_descriptors;
        s8                      unused_native_cs;
@@ -759,6 +751,13 @@ extern int devm_spi_register_controller(struct device *dev,
                                        struct spi_controller *ctlr);
 extern void spi_unregister_controller(struct spi_controller *ctlr);
 
+#if IS_ENABLED(CONFIG_ACPI)
+extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
+                                               struct acpi_device *adev,
+                                               int index);
+int acpi_spi_count_resources(struct acpi_device *adev);
+#endif
+
 /*
  * SPI resource management while processing a SPI message
  */
@@ -1452,7 +1451,19 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
  * use spi_new_device() to describe each device.  You can also call
  * spi_unregister_device() to start making that device vanish, but
  * normally that would be handled by spi_unregister_controller().
+ *
+ * You can also use spi_alloc_device() and spi_add_device() to use a two
+ * stage registration sequence for each spi_device. This gives the caller
+ * some more control over the spi_device structure before it is registered,
+ * but requires that caller to initialize fields that would otherwise
+ * be defined using the board info.
  */
+extern struct spi_device *
+spi_alloc_device(struct spi_controller *ctlr);
+
+extern int
+spi_add_device(struct spi_device *spi);
+
 extern struct spi_device *
 spi_new_device(struct spi_controller *, struct spi_board_info *);
 
index 9f8123893cc864d98084fe1259518c37d7f9cc1a..50eb6c0e66588fb5f43d6a31e12d24a4168d6837 100644 (file)
@@ -28,11 +28,9 @@ static int cs35l41_hda_spi_probe(struct spi_device *spi)
                                 devm_regmap_init_spi(spi, &cs35l41_regmap_spi));
 }
 
-static int cs35l41_hda_spi_remove(struct spi_device *spi)
+static void cs35l41_hda_spi_remove(struct spi_device *spi)
 {
        cs35l41_hda_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id cs35l41_hda_spi_id[] = {
index 655689c9778ac7be23477bc229e1ddbeab7327da..7c9242c2ff94b638f41f8d9bed77b0d24be74f2c 100644 (file)
@@ -45,10 +45,9 @@ static int adau1761_spi_probe(struct spi_device *spi)
                id->driver_data, adau1761_spi_switch_mode);
 }
 
-static int adau1761_spi_remove(struct spi_device *spi)
+static void adau1761_spi_remove(struct spi_device *spi)
 {
        adau17x1_remove(&spi->dev);
-       return 0;
 }
 
 static const struct spi_device_id adau1761_spi_id[] = {
index bb5613574786b2489531b47b3ffeac38e1746a64..1a09633d5a88580725c43d39ab61f835c5ec64a5 100644 (file)
@@ -45,10 +45,9 @@ static int adau1781_spi_probe(struct spi_device *spi)
                id->driver_data, adau1781_spi_switch_mode);
 }
 
-static int adau1781_spi_remove(struct spi_device *spi)
+static void adau1781_spi_remove(struct spi_device *spi)
 {
        adau17x1_remove(&spi->dev);
-       return 0;
 }
 
 static const struct spi_device_id adau1781_spi_id[] = {
index 6dfd5459aa2076dc4029c1c217b1760e569085a8..169221a5b09f7c0f64ca4e14e102acee60d2bf4d 100644 (file)
@@ -55,13 +55,11 @@ static int cs35l41_spi_probe(struct spi_device *spi)
        return cs35l41_probe(cs35l41, pdata);
 }
 
-static int cs35l41_spi_remove(struct spi_device *spi)
+static void cs35l41_spi_remove(struct spi_device *spi)
 {
        struct cs35l41_private *cs35l41 = spi_get_drvdata(spi);
 
        cs35l41_remove(cs35l41);
-
-       return 0;
 }
 
 #ifdef CONFIG_OF
index ecd379f308e6b591ed5a17e852ae8c8c834f0b2e..b5b08046f5454a56dd6ea5ef2e5f8e1fbf3bb717 100644 (file)
@@ -26,11 +26,9 @@ static int pcm3168a_spi_probe(struct spi_device *spi)
        return pcm3168a_probe(&spi->dev, regmap);
 }
 
-static int pcm3168a_spi_remove(struct spi_device *spi)
+static void pcm3168a_spi_remove(struct spi_device *spi)
 {
        pcm3168a_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id pcm3168a_spi_id[] = {
index 7cf559b47e1c371038ca8113eb5672ff0f10122c..4d29e71963800b1dd80aca3af4785b5f4a9ef3a0 100644 (file)
@@ -26,10 +26,9 @@ static int pcm512x_spi_probe(struct spi_device *spi)
        return pcm512x_probe(&spi->dev, regmap);
 }
 
-static int pcm512x_spi_remove(struct spi_device *spi)
+static void pcm512x_spi_remove(struct spi_device *spi)
 {
        pcm512x_remove(&spi->dev);
-       return 0;
 }
 
 static const struct spi_device_id pcm512x_spi_id[] = {
index a8958cd1c69211f208d7061b936c574a51864a7b..03cce8d6404f844c361062e9ef1e5f0c3de5ff6d 100644 (file)
@@ -46,11 +46,9 @@ static int aic32x4_spi_probe(struct spi_device *spi)
        return aic32x4_probe(&spi->dev, regmap);
 }
 
-static int aic32x4_spi_remove(struct spi_device *spi)
+static void aic32x4_spi_remove(struct spi_device *spi)
 {
        aic32x4_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id aic32x4_spi_id[] = {
index 494e844022321c337551fc53c37db0ac1b0de0c7..deed6ec7e0816e29e5d09de8790fe2adb7956b77 100644 (file)
@@ -35,11 +35,9 @@ static int aic3x_spi_probe(struct spi_device *spi)
        return aic3x_probe(&spi->dev, regmap, id->driver_data);
 }
 
-static int aic3x_spi_remove(struct spi_device *spi)
+static void aic3x_spi_remove(struct spi_device *spi)
 {
        aic3x_remove(&spi->dev);
-
-       return 0;
 }
 
 static const struct spi_device_id aic3x_spi_id[] = {
index 28b4656c4e1491603d9dfa5478b5e20138328656..1bef1c500c8e32a114b18a6345a5b28a954d6632 100644 (file)
@@ -969,7 +969,7 @@ static int wm0010_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int wm0010_spi_remove(struct spi_device *spi)
+static void wm0010_spi_remove(struct spi_device *spi)
 {
        struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
 
@@ -980,8 +980,6 @@ static int wm0010_spi_remove(struct spi_device *spi)
 
        if (wm0010->irq)
                free_irq(wm0010->irq, wm0010);
-
-       return 0;
 }
 
 static struct spi_driver wm0010_spi_driver = {
index 9a8da1511c34bb88a2dd6b91432299456b46557f..628568724c200a63ba02282957f02406378012d5 100644 (file)
@@ -24,10 +24,9 @@ static int wm8804_spi_probe(struct spi_device *spi)
        return wm8804_probe(&spi->dev, regmap);
 }
 
-static int wm8804_spi_remove(struct spi_device *spi)
+static void wm8804_spi_remove(struct spi_device *spi)
 {
        wm8804_remove(&spi->dev);
-       return 0;
 }
 
 static const struct of_device_id wm8804_of_match[] = {
index 76c0e37a838cf430f1fdec54b07368c11a05c010..56d2c712e2571e0c5eaf632937c7151be40acdd7 100644 (file)
@@ -1001,7 +1001,7 @@ out:
        return retval;
 }
 
-static int snd_at73c213_remove(struct spi_device *spi)
+static void snd_at73c213_remove(struct spi_device *spi)
 {
        struct snd_card *card = dev_get_drvdata(&spi->dev);
        struct snd_at73c213 *chip = card->private_data;
@@ -1066,8 +1066,6 @@ out:
 
        ssc_free(chip->ssc);
        snd_card_free(card);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP