Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Nov 2017 07:18:46 +0000 (21:18 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Nov 2017 07:18:46 +0000 (21:18 -1000)
Pull networking fixes from David Miller:

 1) Fix PCI IDs of 9000 series iwlwifi devices, from Luca Coelho.

 2) bpf offload bug fixes from Jakub Kicinski.

 3) Fix bpf verifier to NOP out code which is dead at run time because
    due to branch pruning the verifier will not explore such
    instructions. From Alexei Starovoitov.

 4) Fix crash when deleting secondary chains in packet scheduler
    classifier. From Roman Kapl.

 5) Fix buffer management bugs in smc, from Ursula Braun.

 6) Fix regression in anycast route handling, from David Ahern.

 7) Fix link settings regression in r8169, from Tobias Jakobi.

 8) Add back enough UFO support so that live migration still works, from
    Willem de Bruijn.

 9) Linearize enough packet data for the full extent to which the ipvlan
    code will inspect the packet headers, from Gao Feng.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (46 commits)
  ipvlan: Fix insufficient skb linear check for ipv6 icmp
  ipvlan: Fix insufficient skb linear check for arp
  geneve: only configure or fill UDP_ZERO_CSUM6_RX/TX info when CONFIG_IPV6
  net: dsa: bcm_sf2: Clear IDDQ_GLOBAL_PWR bit for PHY
  net: accept UFO datagrams from tuntap and packet
  net: realtek: r8169: implement set_link_ksettings()
  net: ipv6: Fixup device for anycast routes during copy
  net/smc: Fix preinitialization of buf_desc in __smc_buf_create()
  net/smc: use sk_rcvbuf as start for rmb creation
  ipv6: Do not consider linkdown nexthops during multipath
  net: sched: fix crash when deleting secondary chains
  net: phy: cortina: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
  bpf: fix branch pruning logic
  bpf: change bpf_perf_event_output arg5 type to ARG_CONST_SIZE_OR_ZERO
  bpf: change bpf_probe_read_str arg2 type to ARG_CONST_SIZE_OR_ZERO
  bpf: remove explicit handling of 0 for arg2 in bpf_probe_read
  bpf: introduce ARG_PTR_TO_MEM_OR_NULL
  i40evf: Use smp_rmb rather than read_barrier_depends
  fm10k: Use smp_rmb rather than read_barrier_depends
  igb: Use smp_rmb rather than read_barrier_depends
  ...

205 files changed:
Documentation/admin-guide/kernel-parameters.txt
Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
Documentation/devicetree/bindings/mtd/cadence-quadspi.txt
Documentation/devicetree/bindings/mtd/denali-nand.txt
Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
Documentation/devicetree/bindings/mtd/mtk-quadspi.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
Documentation/devicetree/bindings/rtc/imxdi-rtc.txt
Documentation/devicetree/bindings/rtc/pcf85363.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-mt7622.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/sprd,sc27xx-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/trivial-devices.txt
Documentation/process/5.Posting.rst
Documentation/security/keys/core.rst
Documentation/svga.txt
Documentation/translations/ko_KR/memory-barriers.txt
MAINTAINERS
arch/arm/mach-pxa/cm-x255.c
arch/um/Kconfig.common
crypto/asymmetric_keys/pkcs7_key_type.c
crypto/asymmetric_keys/pkcs7_parser.c
crypto/asymmetric_keys/public_key.c
crypto/asymmetric_keys/x509_public_key.c
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/drm/tilcdc/Makefile
drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c [deleted file]
drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts [deleted file]
drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h [deleted file]
drivers/gpu/ipu-v3/ipu-dc.c
drivers/mtd/Kconfig
drivers/mtd/chips/map_ram.c
drivers/mtd/chips/map_rom.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/slram.c
drivers/mtd/maps/cfi_flagadm.c
drivers/mtd/maps/impa7.c
drivers/mtd/maps/netsc520.c
drivers/mtd/maps/nettel.c
drivers/mtd/maps/plat-ram.c
drivers/mtd/maps/sbc_gxx.c
drivers/mtd/maps/ts5500_flash.c
drivers/mtd/maps/uclinux.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/mtdswap.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/ams-delta.c
drivers/mtd/nand/atmel/nand-controller.c
drivers/mtd/nand/atmel/pmecc.c
drivers/mtd/nand/atmel/pmecc.h
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c
drivers/mtd/nand/denali_pci.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/hisi504_nand.c
drivers/mtd/nand/mtk_ecc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/nuc900_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/qcom_nandc.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/parsers/Kconfig
drivers/mtd/parsers/Makefile
drivers/mtd/parsers/sharpslpart.c [new file with mode: 0644]
drivers/mtd/spi-nor/Kconfig
drivers/mtd/spi-nor/cadence-quadspi.c
drivers/mtd/spi-nor/intel-spi-pci.c
drivers/mtd/spi-nor/intel-spi.c
drivers/mtd/spi-nor/mtk-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/spi-nor/stm32-quadspi.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-smbios-wmi.c
drivers/platform/x86/dell-wmi-descriptor.c
drivers/platform/x86/dell-wmi-descriptor.h
drivers/pwm/pwm-atmel-tcb.c
drivers/pwm/pwm-img.c
drivers/pwm/pwm-mediatek.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-sun4i.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/interface.c
drivers/rtc/rtc-abx80x.c
drivers/rtc/rtc-armada38x.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1390.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-jz4740.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-mt7622.c [new file with mode: 0644]
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf8523.c
drivers/rtc/rtc-pcf85363.c [new file with mode: 0644]
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rx8010.c
drivers/rtc/rtc-sc27xx.c [new file with mode: 0644]
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-xgene.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/proc/base.c
fs/proc/internal.h
fs/xfs/libxfs/xfs_iext_tree.c
fs/xfs/libxfs/xfs_inode_fork.c
fs/xfs/xfs_linux.h
include/drm/drm_connector.h
include/drm/drm_mode_config.h
include/dt-bindings/msm/msm-bus-ids.h [deleted file]
include/linux/key-type.h
include/linux/key.h
include/linux/mtd/mtd.h
include/linux/mtd/nand-gpio.h
include/linux/mtd/rawnand.h
include/linux/mtd/spi-nor.h
include/linux/platform_data/mtd-nand-omap2.h
include/scsi/scsi_device.h
include/scsi/scsi_devinfo.h
include/sound/control.h
lib/Kconfig
net/9p/client.c
net/9p/trans_fd.c
net/9p/trans_virtio.c
net/9p/trans_xen.c
scripts/Makefile.build
scripts/kernel-doc
security/apparmor/apparmorfs.c
security/apparmor/domain.c
security/apparmor/file.c
security/apparmor/label.c
security/apparmor/lib.c
security/apparmor/lsm.c
security/apparmor/mount.c
security/apparmor/policy.c
security/apparmor/policy_ns.c
security/apparmor/policy_unpack.c
security/apparmor/resource.c
security/keys/gc.c
security/keys/internal.h
security/keys/key.c
security/keys/keyring.c
security/keys/permission.c
security/keys/proc.c
security/keys/process_keys.c
sound/core/pcm_lib.c
sound/core/timer_compat.c
sound/core/vmaster.c
sound/hda/hdmi_chmap.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/intel/Kconfig
sound/usb/clock.c
sound/usb/mixer.c

index 62436bd5f34a730b5e0c15e38138970605d9f8c0..b44217290e5776ee616437bf8f1b86be93adac0a 100644 (file)
                        instead using the legacy FADT method
 
        profile=        [KNL] Enable kernel profiling via /proc/profile
-                       Format: [schedule,]<number>
+                       Format: [<profiletype>,]<number>
+                       Param: <profiletype>: "schedule", "sleep", or "kvm"
+                               [defaults to kernel profiling]
                        Param: "schedule" - profile schedule points.
-                       Param: <number> - step/bucket size as a power of 2 for
-                               statistical time based profiling.
                        Param: "sleep" - profile D-state sleeping (millisecs).
                                Requires CONFIG_SCHEDSTATS
                        Param: "kvm" - profile VM exits.
+                       Param: <number> - step/bucket size as a power of 2 for
+                               statistical time based profiling.
 
        prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
                        before loading.
index f79854783c2c342655b37e1ffc31cb3cb3f2a02e..5bf77f6dd19db0ea3eab3cb3f837f54089c2a547 100644 (file)
@@ -129,7 +129,7 @@ Optional properties:
 
 example:
 
-display@di0 {
+disp0 {
        compatible = "fsl,imx-parallel-display";
        edid = [edid-data];
        interface-pix-fmt = "rgb24";
index f248056da24cf87009861f9db7650955049278d6..bb2075df9b3826dd813dd23567ac470ffed5144e 100644 (file)
@@ -1,7 +1,9 @@
 * Cadence Quad SPI controller
 
 Required properties:
-- compatible : Should be "cdns,qspi-nor".
+- compatible : should be one of the following:
+       Generic default - "cdns,qspi-nor".
+       For TI 66AK2G SoC - "ti,k2g-qspi", "cdns,qspi-nor".
 - reg : Contains two entries, each of which is a tuple consisting of a
        physical address and length. The first entry is the address and
        length of the controller register set. The second entry is the
@@ -14,6 +16,9 @@ Required properties:
 
 Optional properties:
 - cdns,is-decoded-cs : Flag to indicate whether decoder is used or not.
+- cdns,rclk-en : Flag to indicate that QSPI return clock is used to latch
+  the read data rather than the QSPI clock. Make sure that QSPI return
+  clock is populated on the board before using this property.
 
 Optional subnodes:
 Subnodes of the Cadence Quad SPI controller are spi slave nodes with additional
index 504291d2e5c2e5e02b880738c7f453b527dee63c..0ee8edb60efc6d07e106314b57fa1cbaa943ed4d 100644 (file)
@@ -29,7 +29,7 @@ nand: nand@ff900000 {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "altr,socfpga-denali-nand";
-       reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
+       reg = <0xff900000 0x20>, <0xffb80000 0x1000>;
        reg-names = "nand_data", "denali_reg";
        interrupts = <0 144 4>;
 };
index 4cab5d85cf6f8eaf11cdf5b90b18cdcc3def4626..376fa2f50e6bc9b41052928037acd4b3a382d380 100644 (file)
@@ -14,6 +14,7 @@ Required properties:
                  at25df641
                  at26df081a
                  en25s64
+                 mr25h128
                  mr25h256
                  mr25h10
                  mr25h40
index 840f9405dcf0736cc294c6432b8176421e34d609..56d3668e2c50e808fca1274436d151951f4ee6a1 100644 (file)
@@ -1,13 +1,16 @@
 * Serial NOR flash controller for MTK MT81xx (and similar)
 
 Required properties:
-- compatible:    The possible values are:
-                 "mediatek,mt2701-nor"
-                 "mediatek,mt7623-nor"
+- compatible:    For mt8173, compatible should be "mediatek,mt8173-nor",
+                 and it's the fallback compatible for other Soc.
+                 For every other SoC, should contain both the SoC-specific compatible
+                 string and "mediatek,mt8173-nor".
+                 The possible values are:
+                 "mediatek,mt2701-nor", "mediatek,mt8173-nor"
+                 "mediatek,mt2712-nor", "mediatek,mt8173-nor"
+                 "mediatek,mt7622-nor", "mediatek,mt8173-nor"
+                 "mediatek,mt7623-nor", "mediatek,mt8173-nor"
                  "mediatek,mt8173-nor"
-                 For mt8173, compatible should be "mediatek,mt8173-nor".
-                 For every other SoC, should contain both the SoC-specific compatible string
-                 and "mediatek,mt8173-nor".
 - reg:                   physical base address and length of the controller's register
 - clocks:        the phandle of the clocks needed by the nor controller
 - clock-names:           the names of the clocks
index d9b655f110489ba0be1877d6b0338066a1a767a6..d4ee4da584633c95e8ec584ae8e0644d5d05039b 100644 (file)
@@ -5,9 +5,13 @@ Required properties:
  - compatible:         Should be set to one of the following:
                        marvell,pxa3xx-nand
                        marvell,armada370-nand
+                       marvell,armada-8k-nand
  - reg:                The register base for the controller
  - interrupts:         The interrupt to map
  - #address-cells:     Set to <1> if the node includes partitions
+ - marvell,system-controller: Set to retrieve the syscon node that handles
+                       NAND controller related registers (only required
+                       with marvell,armada-8k-nand compatible).
 
 Optional properties:
 
index 7e94b802395d677ec946c874ffaf58969d209a41..74c1180159809e3886caacabef528da0578256a0 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
  - "renesas,pwm-r8a7794": for R-Car E2
  - "renesas,pwm-r8a7795": for R-Car H3
  - "renesas,pwm-r8a7796": for R-Car M3-W
+ - "renesas,pwm-r8a77995": for R-Car D3
 - reg: base address and length of the registers block for the PWM.
 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
   the cells format.
index 323cf26374cb14dff4284fb8cdbe4e27270b8107..c797bc9d77d2296a225c8d6da9922fb187243f9a 100644 (file)
@@ -1,20 +1,20 @@
 * i.MX25 Real Time Clock controller
 
-This binding supports the following chips: i.MX25, i.MX53
-
 Required properties:
 - compatible: should be: "fsl,imx25-rtc"
 - reg: physical base address of the controller and length of memory mapped
   region.
+- clocks: should contain the phandle for the rtc clock
 - interrupts: rtc alarm interrupt
 
 Optional properties:
-- interrupts: dryice security violation interrupt
+- interrupts: dryice security violation interrupt (second entry)
 
 Example:
 
-rtc@80056000 {
-       compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
-       reg = <0x80056000 2000>;
-       interrupts = <29 56>;
+rtc@53ffc000 {
+       compatible = "fsl,imx25-rtc";
+       reg = <0x53ffc000 0x4000>;
+       clocks = <&clks 81>;
+       interrupts = <25 56>;
 };
diff --git a/Documentation/devicetree/bindings/rtc/pcf85363.txt b/Documentation/devicetree/bindings/rtc/pcf85363.txt
new file mode 100644 (file)
index 0000000..76fdabc
--- /dev/null
@@ -0,0 +1,17 @@
+NXP PCF85363 Real Time Clock
+============================
+
+Required properties:
+- compatible: Should contain "nxp,pcf85363".
+- reg: I2C address for chip.
+
+Optional properties:
+- interrupts: IRQ line for the RTC (not implemented).
+
+Example:
+
+pcf85363: pcf85363@51 {
+       compatible = "nxp,pcf85363";
+       reg = <0x51>;
+};
+
diff --git a/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt b/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
new file mode 100644 (file)
index 0000000..09fe8f5
--- /dev/null
@@ -0,0 +1,21 @@
+Device-Tree bindings for MediaTek SoC based RTC
+
+Required properties:
+- compatible       : Should be
+                       "mediatek,mt7622-rtc", "mediatek,soc-rtc" : for MT7622 SoC
+- reg              : Specifies base physical address and size of the registers;
+- interrupts       : Should contain the interrupt for RTC alarm;
+- clocks           : Specifies list of clock specifiers, corresponding to
+                     entries in clock-names property;
+- clock-names      : Should contain "rtc" entries
+
+Example:
+
+rtc: rtc@10212800 {
+       compatible = "mediatek,mt7622-rtc",
+                    "mediatek,soc-rtc";
+       reg = <0 0x10212800 0 0x200>;
+       interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
+       clocks = <&topckgen CLK_TOP_RTC>;
+       clock-names = "rtc";
+};
diff --git a/Documentation/devicetree/bindings/rtc/sprd,sc27xx-rtc.txt b/Documentation/devicetree/bindings/rtc/sprd,sc27xx-rtc.txt
new file mode 100644 (file)
index 0000000..7c170da
--- /dev/null
@@ -0,0 +1,27 @@
+Spreadtrum SC27xx Real Time Clock
+
+Required properties:
+- compatible: should be "sprd,sc2731-rtc".
+- reg: address offset of rtc register.
+- interrupt-parent: phandle for the interrupt controller.
+- interrupts: rtc alarm interrupt.
+
+Example:
+
+       sc2731_pmic: pmic@0 {
+               compatible = "sprd,sc2731";
+               reg = <0>;
+               spi-max-frequency = <26000000>;
+               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rtc@280 {
+                       compatible = "sprd,sc2731-rtc";
+                       reg = <0x280>;
+                       interrupt-parent = <&sc2731_pmic>;
+                       interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+               };
+       };
index 678039d4d5e57f96eacd9c9b5a0e8ce72a1d4dd4..5f3143f970983ca92ce1024eaed87f03fa494877 100644 (file)
@@ -72,7 +72,6 @@ maxim,ds1050          5 Bit Programmable, Pulse-Width Modulator
 maxim,max1237          Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
 maxim,max6621          PECI-to-I2C translator for PECI-to-SMBus/I2C protocol conversion
 maxim,max6625          9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
-mc,rv3029c2            Real Time Clock Module with I2C-Bus
 mcube,mc3230           mCube 3-axis 8-bit digital accelerometer
 memsic,mxc6225         MEMSIC 2-axis 8-bit digital accelerometer
 microchip,mcp4531-502  Microchip 7-bit Single I2C Digital Potentiometer (5k)
@@ -141,6 +140,7 @@ microchip,mcp4662-503       Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
 microchip,mcp4662-104  Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
 microchip,tc654                PWM Fan Speed Controller With Fan Fault Detection
 microchip,tc655                PWM Fan Speed Controller With Fan Fault Detection
+microcrystal,rv3029    Real Time Clock Module with I2C-Bus
 miramems,da226         MiraMEMS DA226 2-axis 14-bit digital accelerometer
 miramems,da280         MiraMEMS DA280 3-axis 14-bit digital accelerometer
 miramems,da311         MiraMEMS DA311 3-axis 12-bit digital accelerometer
index 1b7728b19ea7aaef7ca77fa5532a8065e66d414d..645fa9c7388a857607685047a547c1e9ede4a4be 100644 (file)
@@ -213,6 +213,11 @@ The tags in common use are:
    which can be found in Documentation/process/submitting-patches.rst.  Code without a
    proper signoff cannot be merged into the mainline.
 
+ - Co-Developed-by: states that the patch was also created by another developer
+   along with the original author.  This is useful at times when multiple
+   people work on a single patch.  Note, this person also needs to have a
+   Signed-off-by: line in the patch as well.
+
  - Acked-by: indicates an agreement by another developer (often a
    maintainer of the relevant code) that the patch is appropriate for
    inclusion into the kernel.
index 1266eeae45f69caeed72902d2507c3131de9a08f..9ce7256c6edba8b605e9928a42159d717f6d7cf5 100644 (file)
@@ -628,12 +628,12 @@ The keyctl syscall functions are:
      defined key type will return its data as is. If a key type does not
      implement this function, error EOPNOTSUPP will result.
 
-     As much of the data as can be fitted into the buffer will be copied to
-     userspace if the buffer pointer is not NULL.
-
-     On a successful return, the function will always return the amount of data
-     available rather than the amount copied.
+     If the specified buffer is too small, then the size of the buffer required
+     will be returned.  Note that in this case, the contents of the buffer may
+     have been overwritten in some undefined way.
 
+     Otherwise, on success, the function will return the amount of data copied
+     into the buffer.
 
   *  Instantiate a partially constructed key::
 
index 119f1515b1acbe693386bf816af524436fa27358..b6c2f9acca92b4f49582934eba45c2b24aeace2c 100644 (file)
@@ -67,8 +67,7 @@ The menu looks like::
 <name-of-detected-video-adapter> tells what video adapter did Linux detect
 -- it's either a generic adapter name (MDA, CGA, HGC, EGA, VGA, VESA VGA [a VGA
 with VESA-compliant BIOS]) or a chipset name (e.g., Trident). Direct detection
-of chipsets is turned off by default (see CONFIG_VIDEO_SVGA in chapter 4 to see
-how to enable it if you really want) as it's inherently unreliable due to
+of chipsets is turned off by default as it's inherently unreliable due to
 absolutely insane PC design.
 
 "0  0F00  80x25" means that the first menu item (the menu items are numbered
@@ -138,7 +137,7 @@ The ID numbers can be divided to those regions::
        0x0f05  VGA 80x30 (480 scans, 16-point font)
        0x0f06  VGA 80x34 (480 scans, 14-point font)
        0x0f07  VGA 80x60 (480 scans, 8-point font)
-       0x0f08  Graphics hack (see the CONFIG_VIDEO_HACK paragraph below)
+       0x0f08  Graphics hack (see the VIDEO_GFX_HACK paragraph below)
 
    0x1000 to 0x7fff - modes specified by resolution. The code has a "0xRRCC"
        form where RR is a number of rows and CC is a number of columns.
@@ -160,58 +159,22 @@ end of the display.
 Options
 ~~~~~~~
 
-Some options can be set in the source text (in arch/i386/boot/video.S).
-All of them are simple #define's -- change them to #undef's when you want to
-switch them off. Currently supported:
-
-CONFIG_VIDEO_SVGA - enables autodetection of SVGA cards. This is switched
-off by default as it's a bit unreliable due to terribly bad PC design. If you
-really want to have the adapter autodetected (maybe in case the ``scan`` feature
-doesn't work on your machine), switch this on and don't cry if the results
-are not completely sane. In case you really need this feature, please drop me
-a mail as I think of removing it some day.
-
-CONFIG_VIDEO_VESA - enables autodetection of VESA modes. If it doesn't work
-on your machine (or displays a "Error: Scanning of VESA modes failed" message),
-you can switch it off and report as a bug.
-
-CONFIG_VIDEO_COMPACT - enables compacting of the video mode list. If there
-are more modes with the same screen size, only the first one is kept (see above
-for more info on mode ordering). However, in very strange cases it's possible
-that the first "version" of the mode doesn't work although some of the others
-do -- in this case turn this switch off to see the rest.
-
-CONFIG_VIDEO_RETAIN - enables retaining of screen contents when switching
-video modes. Works only with some boot loaders which leave enough room for the
-buffer. (If you have old LILO, you can adjust heap_end_ptr and loadflags
-in setup.S, but it's better to upgrade the boot loader...)
-
-CONFIG_VIDEO_LOCAL - enables inclusion of "local modes" in the list. The
-local modes are added automatically to the beginning of the list not depending
-on hardware configuration. The local modes are listed in the source text after
-the "local_mode_table:" line. The comment before this line describes the format
-of the table (which also includes a video card name to be displayed on the
-top of the menu).
-
-CONFIG_VIDEO_400_HACK - force setting of 400 scan lines for standard VGA
-modes. This option is intended to be used on certain buggy BIOSes which draw
-some useless logo using font download and then fail to reset the correct mode.
-Don't use unless needed as it forces resetting the video card.
-
-CONFIG_VIDEO_GFX_HACK - includes special hack for setting of graphics modes
-to be used later by special drivers (e.g., 800x600 on IBM ThinkPad -- see
-ftp://ftp.phys.keio.ac.jp/pub/XFree86/800x600/XF86Configs/XF86Config.IBM_TP560).
+Build options for arch/x86/boot/* are selected by the kernel kconfig
+utility and the kernel .config file.
+
+VIDEO_GFX_HACK - includes special hack for setting of graphics modes
+to be used later by special drivers.
 Allows to set _any_ BIOS mode including graphic ones and forcing specific
 text screen resolution instead of peeking it from BIOS variables. Don't use
 unless you think you know what you're doing. To activate this setup, use
-mode number 0x0f08 (see section 3).
+mode number 0x0f08 (see the Mode IDs section above).
 
 Still doesn't work?
 ~~~~~~~~~~~~~~~~~~~
 
 When the mode detection doesn't work (e.g., the mode list is incorrect or
 the machine hangs instead of displaying the menu), try to switch off some of
-the configuration options listed in section 4. If it fails, you can still use
+the configuration options listed under "Options". If it fails, you can still use
 your kernel with the video mode set directly via the kernel parameter.
 
 In either case, please send me a bug report containing what _exactly_
@@ -228,10 +191,6 @@ contains the most common video BIOS bug called "incorrect vertical display
 end setting". Adding 0x8000 to the mode ID might fix the problem. Unfortunately,
 this must be done manually -- no autodetection mechanisms are available.
 
-If you have a VGA card and your display still looks as on EGA, your BIOS
-is probably broken and you need to set the CONFIG_VIDEO_400_HACK switch to
-force setting of the correct mode.
-
 History
 ~~~~~~~
 
index ec3b46e27b7aa3aeca361d169bfda8ea09bf91fb..0a0930ab415668a97ef649931f4af58c6fb2e2c1 100644 (file)
@@ -82,7 +82,7 @@ Documentation/memory-barriers.txt
      - SMP 배리어 짝맞추기.
      - 메모리 배리어 시퀀스의 예.
      - 읽기 메모리 배리어 vs 로드 예측.
-     - 이행성
+     - Multicopy 원자성.
 
  (*) 명시적 커널 배리어.
 
@@ -656,6 +656,11 @@ Documentation/RCU/rcu_dereference.txt 파일을 주의 깊게 읽어 주시기 
 해줍니다.
 
 
+데이터 의존성에 의해 제공되는 이 순서규칙은 이를 포함하고 있는 CPU 에
+지역적임을 알아두시기 바랍니다.  더 많은 정보를 위해선 "Multicopy 원자성"
+섹션을 참고하세요.
+
+
 데이터 의존성 배리어는 매우 중요한데, 예를 들어 RCU 시스템에서 그렇습니다.
 include/linux/rcupdate.h 의 rcu_assign_pointer() 와 rcu_dereference() 를
 참고하세요.  여기서 데이터 의존성 배리어는 RCU 로 관리되는 포인터의 타겟을 현재
@@ -864,38 +869,10 @@ CPU 는 b 로부터의 로드 오퍼레이션이 a 로부터의 로드 오퍼레
 주어진 if 문의 then 절과 else 절에게만 (그리고 이 두 절 내에서 호출되는
 함수들에게까지) 적용되지, 이 if 문을 뒤따르는 코드에는 적용되지 않습니다.
 
-마지막으로, 컨트롤 의존성은 이행성 (transitivity) 을 제공하지 -않습니다-.  이건
-'x' 와 'y' 가 둘 다 0 이라는 초기값을 가졌다는 가정 하의 두개의 예제로
-보이겠습니다:
-
-       CPU 0                     CPU 1
-       =======================   =======================
-       r1 = READ_ONCE(x);        r2 = READ_ONCE(y);
-       if (r1 > 0)               if (r2 > 0)
-         WRITE_ONCE(y, 1);         WRITE_ONCE(x, 1);
-
-       assert(!(r1 == 1 && r2 == 1));
-
-이 두 CPU 예제에서 assert() 의 조건은 항상 참일 것입니다.  그리고, 만약 컨트롤
-의존성이 이행성을 (실제로는 그러지 않지만) 보장한다면, 다음의 CPU 가 추가되어도
-아래의 assert() 조건은 참이 될것입니다:
 
-       CPU 2
-       =====================
-       WRITE_ONCE(x, 2);
+컨트롤 의존성에 의해 제공되는 이 순서규칙은 이를 포함하고 있는 CPU 에
+지역적입니다.  더 많은 정보를 위해선 "Multicopy 원자성" 섹션을 참고하세요.
 
-       assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */
-
-하지만 컨트롤 의존성은 이행성을 제공하지 -않기- 때문에, 세개의 CPU 예제가 실행
-완료된 후에 위의 assert() 의 조건은 거짓으로 평가될 수 있습니다.  세개의 CPU
-예제가 순서를 지키길 원한다면, CPU 0 와 CPU 1 코드의 로드와 스토어 사이, "if"
-문 바로 다음에 smp_mb()를 넣어야 합니다.  더 나아가서, 최초의 두 CPU 예제는
-매우 위험하므로 사용되지 않아야 합니다.
-
-이 두개의 예제는 다음 논문:
-http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf 와
-이 사이트: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html 에 나온 LB 와 WWC
-리트머스 테스트입니다.
 
 요약하자면:
 
@@ -930,8 +907,8 @@ http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf 와
 
   (*) 컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다.
 
-  (*) 컨트롤 의존성은 이행성을 제공하지 -않습니다-.  이행성이 필요하다면,
-      smp_mb() 를 사용하세요.
+  (*) 컨트롤 의존성은 multicopy 원자성을 제공하지 -않습니다-.  모든 CPU 들이
+      특정 스토어를 동시에 보길 원한다면, smp_mb() 를 사용하세요.
 
   (*) 컴파일러는 컨트롤 의존성을 이해하고 있지 않습니다.  따라서 컴파일러가
       여러분의 코드를 망가뜨리지 않도록 하는건 여러분이 해야 하는 일입니다.
@@ -943,13 +920,14 @@ SMP 배리어 짝맞추기
 CPU 간 상호작용을 다룰 때에 일부 타입의 메모리 배리어는 항상 짝을 맞춰
 사용되어야 합니다.  적절하게 짝을 맞추지 않은 코드는 사실상 에러에 가깝습니다.
 
-범용 배리어들은 범용 배리어끼리도 짝을 맞추지만 이행성이 없는 대부분의 다른
-타입의 배리어들과도 짝을 맞춥니다.  ACQUIRE 배리어는 RELEASE 배리어와 짝을
-맞춥니다만, 둘 다 범용 배리어를 포함해 다른 배리어들과도 짝을 맞출 수 있습니다.
-쓰기 배리어는 데이터 의존성 배리어나 컨트롤 의존성, ACQUIRE 배리어, RELEASE
-배리어, 읽기 배리어, 또는 범용 배리어와 짝을 맞춥니다.  비슷하게 읽기 배리어나
-컨트롤 의존성, 또는 데이터 의존성 배리어는 쓰기 배리어나 ACQUIRE 배리어,
-RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과 같습니다:
+범용 배리어들은 범용 배리어끼리도 짝을 맞추지만 multicopy 원자성이 없는
+대부분의 다른 타입의 배리어들과도 짝을 맞춥니다.  ACQUIRE 배리어는 RELEASE
+배리어와 짝을 맞춥니다만, 둘 다 범용 배리어를 포함해 다른 배리어들과도 짝을
+맞출 수 있습니다.  쓰기 배리어는 데이터 의존성 배리어나 컨트롤 의존성, ACQUIRE
+배리어, RELEASE 배리어, 읽기 배리어, 또는 범용 배리어와 짝을 맞춥니다.
+비슷하게 읽기 배리어나 컨트롤 의존성, 또는 데이터 의존성 배리어는 쓰기 배리어나
+ACQUIRE 배리어, RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과
+같습니다:
 
        CPU 1                 CPU 2
        ===============       ===============
@@ -975,7 +953,7 @@ RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과 같
        ===============       ===============================
        r1 = READ_ONCE(y);
        <범용 배리어>
-       WRITE_ONCE(y, 1);     if (r2 = READ_ONCE(x)) {
+       WRITE_ONCE(x, 1);     if (r2 = READ_ONCE(x)) {
                                 <묵시적 컨트롤 의존성>
                                 WRITE_ONCE(y, 1);
                              }
@@ -1361,57 +1339,74 @@ A 의 로드 두개가 모두 B 의 로드 뒤에 있지만, 서로 다른 값
                                                :       :       +-------+
 
 
-이행
-------
+MULTICOPY 원자
+----------------
 
-이행성(transitivity)은 실제의 컴퓨터 시스템에서 항상 제공되지는 않는, 순서
-맞추기에 대한 상당히 직관적인 개념입니다.  다음의 예가 이행성을 보여줍니다:
+Multicopy 원자성은 실제의 컴퓨터 시스템에서 항상 제공되지는 않는, 순서 맞추기에
+대한 상당히 직관적인 개념으로, 특정 스토어가 모든 CPU 들에게 동시에 보여지게
+됨을, 달리 말하자면 모든 CPU 들이 모든 스토어들이 보여지는 순서를 동의하게 되는
+것입니다.  하지만, 완전한 multicopy 원자성의 사용은 가치있는 하드웨어
+최적화들을 무능하게 만들어버릴 수 있어서, 보다 완화된 형태의 ``다른 multicopy
+원자성'' 라는 이름의, 특정 스토어가 모든 -다른- CPU 들에게는 동시에 보여지게
+하는 보장을 대신 제공합니다.  이 문서의 뒷부분들은 이 완화된 형태에 대해 논하게
+됩니다만, 단순히 ``multicopy 원자성'' 이라고 부르겠습니다.
+
+다음의 예가 multicopy 원자성을 보입니다:
 
        CPU 1                   CPU 2                   CPU 3
        ======================= ======================= =======================
                { X = 0, Y = 0 }
-       STORE X=1               LOAD X                  STORE Y=1
-                               <범용 배리어>              <범용 배리어>
-                               LOAD Y                  LOAD X
-
-CPU 2 의 X 로드가 1을 리턴했고 Y 로드가 0을 리턴했다고 해봅시다.  이는 CPU 2 의
-X 로드가 CPU 1 의 X 스토어 뒤에 이루어졌고 CPU 2 의 Y 로드는 CPU 3 의 Y 스토어
-전에 이루어졌음을 의미합니다.  그럼 "CPU 3 의 X 로드는 0을 리턴할 수 있나요?"
-
-CPU 2 의 X 로드는 CPU 1 의 스토어 후에 이루어졌으니, CPU 3 의 X 로드는 1을
-리턴하는게 자연스럽습니다.  이런 생각이 이행성의 한 예입니다: CPU A 에서 실행된
-로드가 CPU B 에서의 같은 변수에 대한 로드를 뒤따른다면, CPU A 의 로드는 CPU B
-의 로드가 내놓은 값과 같거나 그 후의 값을 내놓아야 합니다.
-
-리눅스 커널에서 범용 배리어의 사용은 이행성을 보장합니다.  따라서, 앞의 예에서
-CPU 2 의 X 로드가 1을, Y 로드는 0을 리턴했다면, CPU 3 의 X 로드는 반드시 1을
-리턴합니다.
-
-하지만, 읽기나 쓰기 배리어에 대해서는 이행성이 보장되지 -않습니다-.  예를 들어,
-앞의 예에서 CPU 2 의 범용 배리어가 아래처럼 읽기 배리어로 바뀐 경우를 생각해
-봅시다:
+       STORE X=1               r1=LOAD X (reads 1)     LOAD Y (reads 1)
+                               <범용 배리어>              <읽기 배리어>
+                               STORE Y=r1              LOAD X
+
+CPU 2 의 Y 로의 스토어에 사용되는 X 로드의 결과가 1 이었고 CPU 3 의 Y 로드가
+1을 리턴했다고 해봅시다.  이는 CPU 1 의 X 로의 스토어가 CPU 2 의 X 로부터의
+로드를 앞서고 CPU 2 의 Y 로의 스토어가 CPU 3 의 Y 로부터의 로드를 앞섬을
+의미합니다.  또한, 여기서의 메모리 배리어들은 CPU 2 가 자신의 로드를 자신의
+스토어 전에 수행하고, CPU 3 가 Y 로부터의 로드를 X 로부터의 로드 전에 수행함을
+보장합니다.  그럼 "CPU 3 의 X 로부터의 로드는 0 을 리턴할 수 있을까요?"
+
+CPU 3 의 X 로드가 CPU 2 의 로드보다 뒤에 이루어졌으므로, CPU 3 의 X 로부터의
+로드는 1 을 리턴한다고 예상하는게 당연합니다.  이런 예상은 multicopy
+원자성으로부터 나옵니다: CPU B 에서 수행된 로드가 CPU A 의 같은 변수로부터의
+로드를 뒤따른다면 (그리고 CPU A 가 자신이 읽은 값으로 먼저 해당 변수에 스토어
+하지 않았다면) multicopy 원자성을 제공하는 시스템에서는, CPU B 의 로드가 CPU A
+의 로드와 같은 값 또는 그 나중 값을 리턴해야만 합니다.  하지만, 리눅스 커널은
+시스템들이 multicopy 원자성을 제공할 것을 요구하지 않습니다.
+
+앞의 범용 메모리 배리어의 사용은 모든 multicopy 원자성의 부족을 보상해줍니다.
+앞의 예에서, CPU 2 의 X 로부터의 로드가 1 을 리턴했고 CPU 3 의 Y 로부터의
+로드가 1 을 리턴했다면, CPU 3 의 X 로부터의 로드는 1을 리턴해야만 합니다.
+
+하지만, 의존성, 읽기 배리어, 쓰기 배리어는 항상 non-multicopy 원자성을 보상해
+주지는 않습니다.  예를 들어, CPU 2 의 범용 배리어가 앞의 예에서 사라져서
+아래처럼 데이터 의존성만 남게 되었다고 해봅시다:
 
        CPU 1                   CPU 2                   CPU 3
        ======================= ======================= =======================
                { X = 0, Y = 0 }
-       STORE X=1               LOAD X                  STORE Y=1
-                               <읽기 배리어>              <범용 배리어>
-                               LOAD Y                  LOAD X
-
-이 코드는 이행성을 갖지 않습니다: 이 예에서는, CPU 2 의 X 로드가 1을
-리턴하고, Y 로드는 0을 리턴하지만 CPU 3 의 X 로드가 0을 리턴하는 것도 완전히
-합법적입니다.
-
-CPU 2 의 읽기 배리어가 자신의 읽기는 순서를 맞춰줘도, CPU 1 의 스토어와의
-순서를 맞춰준다고는 보장할 수 없다는게 핵심입니다.  따라서, CPU 1 과 CPU 2 가
-버퍼나 캐시를 공유하는 시스템에서 이 예제 코드가 실행된다면, CPU 2 는 CPU 1 이
-쓴 값에 좀 빨리 접근할 수 있을 것입니다.  따라서 CPU 1 과 CPU 2 의 접근으로
-조합된 순서를 모든 CPU 가 동의할 수 있도록 하기 위해 범용 배리어가 필요합니다.
-
-범용 배리어는 "글로벌 이행성"을 제공해서, 모든 CPU 들이 오퍼레이션들의 순서에
-동의하게 할 것입니다.  반면, release-acquire 조합은 "로컬 이행성" 만을
-제공해서, 해당 조합이 사용된 CPU 들만이 해당 액세스들의 조합된 순서에 동의함이
-보장됩니다.  예를 들어, 존경스런 Herman Hollerith 의 C 코드로 보면:
+       STORE X=1               r1=LOAD X (reads 1)     LOAD Y (reads 1)
+                               <데이터 의존성>           <읽기 배리어>
+                               STORE Y=r1              LOAD X (reads 0)
+
+이 변화는 non-multicopy 원자성이 만연하게 합니다: 이 예에서, CPU 2 의 X
+로부터의 로드가 1을 리턴하고, CPU 3 의 Y 로부터의 로드가 1 을 리턴하는데, CPU 3
+의 X 로부터의 로드가 0 을 리턴하는게 완전히 합법적입니다.
+
+핵심은, CPU 2 의 데이터 의존성이 자신의 로드와 스토어를 순서짓지만, CPU 1 의
+스토어에 대한 순서는 보장하지 않는다는 것입니다.  따라서, 이 예제가 CPU 1 과
+CPU 2 가 스토어 버퍼나 한 수준의 캐시를 공유하는, multicopy 원자성을 제공하지
+않는 시스템에서 수행된다면 CPU 2 는 CPU 1 의 쓰기에 이른 접근을 할 수도
+있습니다.  따라서, 모든 CPU 들이 여러 접근들의 조합된 순서에 대해서 동의하게
+하기 위해서는 범용 배리어가 필요합니다.
+
+범용 배리어는 non-multicopy 원자성만 보상할 수 있는게 아니라, -모든- CPU 들이
+-모든- 오퍼레이션들의 순서를 동일하게 인식하게 하는 추가적인 순서 보장을
+만들어냅니다.  반대로, release-acquire 짝의 연결은 이런 추가적인 순서는
+제공하지 않는데, 해당 연결에 들어있는 CPU 들만이 메모리 접근의 조합된 순서에
+대해 동의할 것으로 보장됨을 의미합니다.  예를 들어, 존경스런 Herman Hollerith
+의 코드를 C 코드로 변환하면:
 
        int u, v, x, y, z;
 
@@ -1444,8 +1439,7 @@ CPU 2 의 읽기 배리어가 자신의 읽기는 순서를 맞춰줘도, CPU 1
        }
 
 cpu0(), cpu1(), 그리고 cpu2() 는 smp_store_release()/smp_load_acquire() 쌍의
-연결을 통한 로컬 이행성에 동참하고 있으므로, 다음과 같은 결과는 나오지 않을
-겁니다:
+연결에 참여되어 있으므로, 다음과 같은 결과는 나오지 않을 겁니다:
 
        r0 == 1 && r1 == 1 && r2 == 1
 
@@ -1454,8 +1448,9 @@ cpu0() 의 쓰기를 봐야만 하므로, 다음과 같은 결과도 없을 겁
 
        r1 == 1 && r5 == 0
 
-하지만, release-acquire 타동성은 동참한 CPU 들에만 적용되므로 cpu3() 에는
-적용되지 않습니다.  따라서, 다음과 같은 결과가 가능합니다:
+하지만, release-acquire 에 의해 제공되는 순서는 해당 연결에 동참한 CPU 들에만
+적용되므로 cpu3() 에, 적어도 스토어들 외에는 적용되지 않습니다.  따라서, 다음과
+같은 결과가 가능합니다:
 
        r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
 
@@ -1482,8 +1477,8 @@ u 로의 스토어를 cpu1() 의 v 로부터의 로드 뒤에 일어난 것으
 이런 결과는 어떤 것도 재배치 되지 않는, 순차적 일관성을 가진 가상의
 시스템에서도 일어날 수 있음을 기억해 두시기 바랍니다.
 
-다시 말하지만, 당신의 코드가 글로벌 이행성을 필요로 한다면, 범용 배리어를
-사용하십시오.
+다시 말하지만, 당신의 코드가 모든 오퍼레이션들의 완전한 순서를 필요로 한다면,
+범용 배리어를 사용하십시오.
 
 
 ==================
@@ -3046,6 +3041,9 @@ AMD64 Architecture Programmer's Manual Volume 2: System Programming
        Chapter 7.1: Memory-Access Ordering
        Chapter 7.4: Buffering and Combining Memory Writes
 
+ARM Architecture Reference Manual (ARMv8, for ARMv8-A architecture profile)
+       Chapter B2: The AArch64 Application Level Memory Model
+
 IA-32 Intel Architecture Software Developer's Manual, Volume 3:
 System Programming Guide
        Chapter 7.1: Locked Atomic Operations
@@ -3057,6 +3055,8 @@ The SPARC Architecture Manual, Version 9
        Appendix D: Formal Specification of the Memory Models
        Appendix J: Programming with the Memory Models
 
+Storage in the PowerPC (Stone and Fitzgerald)
+
 UltraSPARC Programmer Reference Manual
        Chapter 5: Memory Accesses and Cacheability
        Chapter 15: Sparc-V9 Memory Models
index 44512c346206708bfc9b90e14e8e733a8aa81018..aa71ab52fd76d1607b36f476dde8e0060f500070 100644 (file)
@@ -1590,10 +1590,13 @@ F:      drivers/rtc/rtc-armada38x.c
 
 ARM/Mediatek RTC DRIVER
 M:     Eddie Huang <eddie.huang@mediatek.com>
+M:     Sean Wang <sean.wang@mediatek.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
 F:     drivers/rtc/rtc-mt6397.c
+F:     drivers/rtc/rtc-mt7622.c
 
 ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
index b592f79a1742d7eab4f2315a41ebbdacf595bdda..fa8e7dd4d898aab839c67cfd5f4ecd90bc90e2ac 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand-gpio.h>
-
+#include <linux/gpio/machine.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 
@@ -176,6 +176,17 @@ static inline void cmx255_init_nor(void) {}
 #endif
 
 #if defined(CONFIG_MTD_NAND_GPIO) || defined(CONFIG_MTD_NAND_GPIO_MODULE)
+
+static struct gpiod_lookup_table cmx255_nand_gpiod_table = {
+       .dev_id         = "gpio-nand",
+       .table          = {
+               GPIO_LOOKUP("gpio-pxa", GPIO_NAND_CS, "nce", GPIO_ACTIVE_HIGH),
+               GPIO_LOOKUP("gpio-pxa", GPIO_NAND_CLE, "cle", GPIO_ACTIVE_HIGH),
+               GPIO_LOOKUP("gpio-pxa", GPIO_NAND_ALE, "ale", GPIO_ACTIVE_HIGH),
+               GPIO_LOOKUP("gpio-pxa", GPIO_NAND_RB, "rdy", GPIO_ACTIVE_HIGH),
+       },
+};
+
 static struct resource cmx255_nand_resource[] = {
        [0] = {
                .start = PXA_CS1_PHYS,
@@ -198,11 +209,6 @@ static struct mtd_partition cmx255_nand_parts[] = {
 };
 
 static struct gpio_nand_platdata cmx255_nand_platdata = {
-       .gpio_nce = GPIO_NAND_CS,
-       .gpio_cle = GPIO_NAND_CLE,
-       .gpio_ale = GPIO_NAND_ALE,
-       .gpio_rdy = GPIO_NAND_RB,
-       .gpio_nwp = -1,
        .parts = cmx255_nand_parts,
        .num_parts = ARRAY_SIZE(cmx255_nand_parts),
        .chip_delay = 25,
@@ -220,6 +226,7 @@ static struct platform_device cmx255_nand = {
 
 static void __init cmx255_init_nand(void)
 {
+       gpiod_add_lookup_table(&cmx255_nand_gpiod_table);
        platform_device_register(&cmx255_nand);
 }
 #else
index d9280482a2f89c7c559b76448c6da8358ccda82c..c68add8df3aef6232976dccbb2399270495e5814 100644 (file)
@@ -10,7 +10,6 @@ config UML
        select HAVE_DEBUG_KMEMLEAK
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
-       select GENERIC_IO
        select GENERIC_CLOCKEVENTS
        select HAVE_GCC_PLUGINS
        select TTY # Needed for line.c
index 1063b644efcdb3b2cbde33483207b7fc06e4eb5b..e284d9cb9237bfff0e86ebc7370c35fb7b58fee4 100644 (file)
@@ -19,6 +19,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PKCS#7 testing key type");
+MODULE_AUTHOR("Red Hat, Inc.");
 
 static unsigned pkcs7_usage;
 module_param_named(usage, pkcs7_usage, uint, S_IWUSR | S_IRUGO);
index d140d8bb2c96140c408b1e3450f288e562372743..c1ca1e86f5c4f86d1110343aa5194e2c3147f4d5 100644 (file)
@@ -11,6 +11,7 @@
 
 #define pr_fmt(fmt) "PKCS7: "fmt
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include "pkcs7_parser.h"
 #include "pkcs7-asn1.h"
 
+MODULE_DESCRIPTION("PKCS#7 parser");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
 struct pkcs7_parse_context {
        struct pkcs7_message    *msg;           /* Message being constructed */
        struct pkcs7_signed_info *sinfo;        /* SignedInfo being constructed */
index d916235d6cf512093bd2027c1f6f633775c3f19c..bc3035ef27a22b3ca593532dedc8020bb2773a2a 100644 (file)
@@ -22,6 +22,8 @@
 #include <crypto/public_key.h>
 #include <crypto/akcipher.h>
 
+MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
+MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
 /*
index eea71dc9686c29fd2c3fe07d2c9fc0b213bc99b7..c9013582c026748a10b09eeb09d5c71f0571ea7a 100644 (file)
@@ -275,4 +275,5 @@ module_init(x509_key_init);
 module_exit(x509_key_exit);
 
 MODULE_DESCRIPTION("X.509 certificate parser");
+MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
index c21adf60a7f200ba6a4faaa32c163157d00da9ce..057e1ecd83cec5746319adb88602eb95111104c6 100644 (file)
@@ -59,12 +59,6 @@ static bool check_atom_bios(uint8_t *bios, size_t size)
                return false;
        }
 
-       tmp = bios[0x18] | (bios[0x19] << 8);
-       if (bios[tmp + 0x14] != 0x0) {
-               DRM_INFO("Not an x86 BIOS ROM\n");
-               return false;
-       }
-
        bios_header_start = bios[0x48] | (bios[0x49] << 8);
        if (!bios_header_start) {
                DRM_INFO("Can't locate bios header\n");
index 6c78623e13863c6773d9dd4f7c4444de045f9f2b..a57cec737c18ab1b8db405607042a4363493205b 100644 (file)
@@ -1495,8 +1495,11 @@ out:
        memset(wait, 0, sizeof(*wait));
        wait->out.status = (r > 0);
        wait->out.first_signaled = first;
-       /* set return value 0 to indicate success */
-       r = array[first]->error;
+
+       if (first < fence_count && array[first])
+               r = array[first]->error;
+       else
+               r = 0;
 
 err_free_fence_array:
        for (i = 0; i < fence_count; i++)
index 2d792cdc094cd60e86542c0ed5380c3590198fc2..2c574374d9b6884e6c4473f2dd3ede86b7a612df 100644 (file)
@@ -1837,6 +1837,9 @@ static int amdgpu_fini(struct amdgpu_device *adev)
                adev->ip_blocks[i].status.hw = false;
        }
 
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
+               amdgpu_ucode_fini_bo(adev);
+
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.sw)
                        continue;
@@ -3261,9 +3264,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
        pm_pg_lock = (*pos >> 23) & 1;
 
        if (*pos & (1ULL << 62)) {
-               se_bank = (*pos >> 24) & 0x3FF;
-               sh_bank = (*pos >> 34) & 0x3FF;
-               instance_bank = (*pos >> 44) & 0x3FF;
+               se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24;
+               sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34;
+               instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44;
 
                if (se_bank == 0x3FF)
                        se_bank = 0xFFFFFFFF;
@@ -3337,9 +3340,9 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
        pm_pg_lock = (*pos >> 23) & 1;
 
        if (*pos & (1ULL << 62)) {
-               se_bank = (*pos >> 24) & 0x3FF;
-               sh_bank = (*pos >> 34) & 0x3FF;
-               instance_bank = (*pos >> 44) & 0x3FF;
+               se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24;
+               sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34;
+               instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44;
 
                if (se_bank == 0x3FF)
                        se_bank = 0xFFFFFFFF;
@@ -3687,12 +3690,12 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
                return -EINVAL;
 
        /* decode offset */
-       offset = (*pos & 0x7F);
-       se = ((*pos >> 7) & 0xFF);
-       sh = ((*pos >> 15) & 0xFF);
-       cu = ((*pos >> 23) & 0xFF);
-       wave = ((*pos >> 31) & 0xFF);
-       simd = ((*pos >> 37) & 0xFF);
+       offset = (*pos & GENMASK_ULL(6, 0));
+       se = (*pos & GENMASK_ULL(14, 7)) >> 7;
+       sh = (*pos & GENMASK_ULL(22, 15)) >> 15;
+       cu = (*pos & GENMASK_ULL(30, 23)) >> 23;
+       wave = (*pos & GENMASK_ULL(36, 31)) >> 31;
+       simd = (*pos & GENMASK_ULL(44, 37)) >> 37;
 
        /* switch to the specific se/sh/cu */
        mutex_lock(&adev->grbm_idx_mutex);
@@ -3737,14 +3740,14 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
                return -EINVAL;
 
        /* decode offset */
-       offset = (*pos & 0xFFF);       /* in dwords */
-       se = ((*pos >> 12) & 0xFF);
-       sh = ((*pos >> 20) & 0xFF);
-       cu = ((*pos >> 28) & 0xFF);
-       wave = ((*pos >> 36) & 0xFF);
-       simd = ((*pos >> 44) & 0xFF);
-       thread = ((*pos >> 52) & 0xFF);
-       bank = ((*pos >> 60) & 1);
+       offset = *pos & GENMASK_ULL(11, 0);
+       se = (*pos & GENMASK_ULL(19, 12)) >> 12;
+       sh = (*pos & GENMASK_ULL(27, 20)) >> 20;
+       cu = (*pos & GENMASK_ULL(35, 28)) >> 28;
+       wave = (*pos & GENMASK_ULL(43, 36)) >> 36;
+       simd = (*pos & GENMASK_ULL(51, 44)) >> 44;
+       thread = (*pos & GENMASK_ULL(59, 52)) >> 52;
+       bank = (*pos & GENMASK_ULL(61, 60)) >> 60;
 
        data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);
        if (!data)
index a418df1b942274579e4da7a767e0138d95c38c90..e87eedcc0da9d5363d7742782281683d6bb842dd 100644 (file)
@@ -63,6 +63,11 @@ retry:
                             flags, NULL, resv, 0, &bo);
        if (r) {
                if (r != -ERESTARTSYS) {
+                       if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
+                               flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+                               goto retry;
+                       }
+
                        if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
                                initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
                                goto retry;
@@ -323,7 +328,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
                r = amdgpu_ttm_tt_get_user_pages(bo->tbo.ttm,
                                                 bo->tbo.ttm->pages);
                if (r)
-                       goto unlock_mmap_sem;
+                       goto release_object;
 
                r = amdgpu_bo_reserve(bo, true);
                if (r)
@@ -348,9 +353,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
 free_pages:
        release_pages(bo->tbo.ttm->pages, bo->tbo.ttm->num_pages);
 
-unlock_mmap_sem:
-       up_read(&current->mm->mmap_sem);
-
 release_object:
        drm_gem_object_put_unlocked(gobj);
 
@@ -556,9 +558,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 
        if (args->va_address < AMDGPU_VA_RESERVED_SIZE) {
                dev_err(&dev->pdev->dev,
-                       "va_address 0x%lX is in reserved area 0x%X\n",
-                       (unsigned long)args->va_address,
-                       AMDGPU_VA_RESERVED_SIZE);
+                       "va_address 0x%LX is in reserved area 0x%LX\n",
+                       args->va_address, AMDGPU_VA_RESERVED_SIZE);
                return -EINVAL;
        }
 
index 33535d3477343bab044dba5c1cb171ed6befa475..00e0ce10862f7275655710c2559b2286dacb136b 100644 (file)
@@ -71,12 +71,6 @@ static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man)
 {
        struct amdgpu_gtt_mgr *mgr = man->priv;
 
-       spin_lock(&mgr->lock);
-       if (!drm_mm_clean(&mgr->mm)) {
-               spin_unlock(&mgr->lock);
-               return -EBUSY;
-       }
-
        drm_mm_takedown(&mgr->mm);
        spin_unlock(&mgr->lock);
        kfree(mgr);
index d6df5728df7fca04648daa9677bc03d8dafd830f..6c570d4e4516488b81cd385353b8d02c7e428912 100644 (file)
@@ -946,6 +946,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct amdgpu_device *adev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
+       /* no skipping for powerplay */
+       if (adev->powerplay.cgs_device)
+               return effective_mode;
+
        /* Skip limit attributes if DPM is not enabled */
        if (!adev->pm.dpm_enabled &&
            (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
index 5f5aa5fddc169355077a4e61665563c087d860f5..033fba2def6f775b35f4f840f7032477c4403ad3 100644 (file)
@@ -164,9 +164,6 @@ static int amdgpu_pp_hw_fini(void *handle)
                ret = adev->powerplay.ip_funcs->hw_fini(
                                        adev->powerplay.pp_handle);
 
-       if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
-               amdgpu_ucode_fini_bo(adev);
-
        return ret;
 }
 
index 90af8e82b16af3f97990b7e71bb672de4b6d0b72..ae9c106979d7de51ce3ec1027593d80d7a897e34 100644 (file)
@@ -169,10 +169,14 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
                                        int flags)
 {
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
+       struct dma_buf *buf;
 
        if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
            bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)
                return ERR_PTR(-EPERM);
 
-       return drm_gem_prime_export(dev, gobj, flags);
+       buf = drm_gem_prime_export(dev, gobj, flags);
+       if (!IS_ERR(buf))
+               buf->file->f_mapping = dev->anon_inode->i_mapping;
+       return buf;
 }
index 447d446b50150d475cb9a01945706b17bbfc2e78..7714f4a6c8b000072c2b7c3d8691884b3d902a35 100644 (file)
@@ -442,8 +442,6 @@ static int psp_hw_fini(void *handle)
        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
                return 0;
 
-       amdgpu_ucode_fini_bo(adev);
-
        psp_ring_destroy(psp, PSP_RING_TYPE__KM);
 
        amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
index aa914256b4bc75d98015ced2bbe413799f8d3466..bae77353447b793fbcb9ed9b710d923524d4f4f1 100644 (file)
@@ -94,7 +94,8 @@ struct amdgpu_bo_list_entry;
 #define AMDGPU_MMHUB                           1
 
 /* hardcode that limit for now */
-#define AMDGPU_VA_RESERVED_SIZE                        (8 << 20)
+#define AMDGPU_VA_RESERVED_SIZE                        (8ULL << 20)
+
 /* max vmids dedicated for process */
 #define AMDGPU_VM_MAX_RESERVED_VMID    1
 
index 26e90062797173d772b4c71c2f3229ebb1bfbbbc..4acca92f6a52da27b460cfb28bef9a05c571acfa 100644 (file)
@@ -68,11 +68,6 @@ static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man)
        struct amdgpu_vram_mgr *mgr = man->priv;
 
        spin_lock(&mgr->lock);
-       if (!drm_mm_clean(&mgr->mm)) {
-               spin_unlock(&mgr->lock);
-               return -EBUSY;
-       }
-
        drm_mm_takedown(&mgr->mm);
        spin_unlock(&mgr->lock);
        kfree(mgr);
index 00868764a0dd2cfedbc0317a3f1b7e6216d88424..5c8a7a48a4adb16834ab5893e2341c03a5899d7d 100644 (file)
@@ -4670,6 +4670,14 @@ static int gfx_v7_0_sw_fini(void *handle)
        gfx_v7_0_cp_compute_fini(adev);
        gfx_v7_0_rlc_fini(adev);
        gfx_v7_0_mec_fini(adev);
+       amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
+                               &adev->gfx.rlc.clear_state_gpu_addr,
+                               (void **)&adev->gfx.rlc.cs_ptr);
+       if (adev->gfx.rlc.cp_table_size) {
+               amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
+                               &adev->gfx.rlc.cp_table_gpu_addr,
+                               (void **)&adev->gfx.rlc.cp_table_ptr);
+       }
        gfx_v7_0_free_microcode(adev);
 
        return 0;
index b8002ac3e53691d159050159cb03c5b0ec009e61..9ecdf621a74a14994e9f657d161e8aa9c5cc3a52 100644 (file)
@@ -2118,6 +2118,15 @@ static int gfx_v8_0_sw_fini(void *handle)
 
        gfx_v8_0_mec_fini(adev);
        gfx_v8_0_rlc_fini(adev);
+       amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
+                               &adev->gfx.rlc.clear_state_gpu_addr,
+                               (void **)&adev->gfx.rlc.cs_ptr);
+       if ((adev->asic_type == CHIP_CARRIZO) ||
+           (adev->asic_type == CHIP_STONEY)) {
+               amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
+                               &adev->gfx.rlc.cp_table_gpu_addr,
+                               (void **)&adev->gfx.rlc.cp_table_ptr);
+       }
        gfx_v8_0_free_microcode(adev);
 
        return 0;
index 7f15bb2c5233566b771afc111ac17a5cbfe4ccc8..da43813d67a4ad56ddecb79ac0a749afe29abc43 100644 (file)
@@ -207,6 +207,12 @@ static const u32 golden_settings_gc_9_1_rv1[] =
        SOC15_REG_OFFSET(GC, 0, mmTD_CNTL), 0x01bd9f33, 0x00000800
 };
 
+static const u32 golden_settings_gc_9_x_common[] =
+{
+       SOC15_REG_OFFSET(GC, 0, mmGRBM_CAM_INDEX), 0xffffffff, 0x00000000,
+       SOC15_REG_OFFSET(GC, 0, mmGRBM_CAM_DATA), 0xffffffff, 0x2544c382
+};
+
 #define VEGA10_GB_ADDR_CONFIG_GOLDEN 0x2a114042
 #define RAVEN_GB_ADDR_CONFIG_GOLDEN 0x24000042
 
@@ -242,6 +248,9 @@ static void gfx_v9_0_init_golden_registers(struct amdgpu_device *adev)
        default:
                break;
        }
+
+       amdgpu_program_register_sequence(adev, golden_settings_gc_9_x_common,
+                                       (const u32)ARRAY_SIZE(golden_settings_gc_9_x_common));
 }
 
 static void gfx_v9_0_scratch_init(struct amdgpu_device *adev)
@@ -988,12 +997,22 @@ static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
                start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
 }
 
+static void gfx_v9_0_read_wave_vgprs(struct amdgpu_device *adev, uint32_t simd,
+                                    uint32_t wave, uint32_t thread,
+                                    uint32_t start, uint32_t size,
+                                    uint32_t *dst)
+{
+       wave_read_regs(
+               adev, simd, wave, thread,
+               start + SQIND_WAVE_VGPRS_OFFSET, size, dst);
+}
 
 static const struct amdgpu_gfx_funcs gfx_v9_0_gfx_funcs = {
        .get_gpu_clock_counter = &gfx_v9_0_get_gpu_clock_counter,
        .select_se_sh = &gfx_v9_0_select_se_sh,
        .read_wave_data = &gfx_v9_0_read_wave_data,
        .read_wave_sgprs = &gfx_v9_0_read_wave_sgprs,
+       .read_wave_vgprs = &gfx_v9_0_read_wave_vgprs,
 };
 
 static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
@@ -1449,6 +1468,14 @@ static int gfx_v9_0_sw_fini(void *handle)
 
        gfx_v9_0_mec_fini(adev);
        gfx_v9_0_ngg_fini(adev);
+       amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
+                               &adev->gfx.rlc.clear_state_gpu_addr,
+                               (void **)&adev->gfx.rlc.cs_ptr);
+       if (adev->asic_type == CHIP_RAVEN) {
+               amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
+                               &adev->gfx.rlc.cp_table_gpu_addr,
+                               (void **)&adev->gfx.rlc.cp_table_ptr);
+       }
        gfx_v9_0_free_microcode(adev);
 
        return 0;
index 621699331e090d745194a3ea0fb5407d5140ae65..c8f1aebeac7a90d934f0793535c9e5fa656916e6 100644 (file)
@@ -392,7 +392,16 @@ static int gmc_v9_0_early_init(void *handle)
 static int gmc_v9_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 3, 3 };
+       /*
+        * The latest engine allocation on gfx9 is:
+        * Engine 0, 1: idle
+        * Engine 2, 3: firmware
+        * Engine 4~13: amdgpu ring, subject to change when ring number changes
+        * Engine 14~15: idle
+        * Engine 16: kfd tlb invalidation
+        * Engine 17: Gart flushes
+        */
+       unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 4, 4 };
        unsigned i;
 
        for(i = 0; i < adev->num_rings; ++i) {
@@ -405,9 +414,9 @@ static int gmc_v9_0_late_init(void *handle)
                         ring->funcs->vmhub);
        }
 
-       /* Engine 17 is used for GART flushes */
+       /* Engine 16 is used for KFD and 17 for GART flushes */
        for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)
-               BUG_ON(vm_inv_eng[i] > 17);
+               BUG_ON(vm_inv_eng[i] > 16);
 
        return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
 }
index a129bc5b18442a3b20743506f852f7e97938dd74..c6febbf0bf693354e5af19fecd18e4047b82cc80 100644 (file)
@@ -1486,7 +1486,7 @@ int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr,
                                if (vddci_id_buf[i] == virtual_voltage_id) {
                                        for (j = 0; j < profile->ucLeakageBinNum; j++) {
                                                if (efuse_voltage_id <= leakage_bin[j]) {
-                                                       *vddci = vddci_buf[j * profile->ucElbVDDC_Num + i];
+                                                       *vddci = vddci_buf[j * profile->ucElbVDDCI_Num + i];
                                                        break;
                                                }
                                        }
index d1af1483c69bafe427f4835c55a4bea93f31a66c..a651ebcf44fdccbca6e90ed31bcbd62bdbbca38c 100644 (file)
@@ -830,9 +830,9 @@ static int init_over_drive_limits(
                const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
 {
        hwmgr->platform_descriptor.overdriveLimit.engineClock =
-               le16_to_cpu(powerplay_table->ulMaxODEngineClock);
+               le32_to_cpu(powerplay_table->ulMaxODEngineClock);
        hwmgr->platform_descriptor.overdriveLimit.memoryClock =
-               le16_to_cpu(powerplay_table->ulMaxODMemoryClock);
+               le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
 
        hwmgr->platform_descriptor.minOverdriveVDDC = 0;
        hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
index 4466469cf8ab816d8d5e0eca6a4ec29358e6cfe4..e33ec7fc5d09a11a0eb654564158edbaf2433f50 100644 (file)
@@ -3778,7 +3778,7 @@ static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
                                "Trying to Unfreeze MCLK DPM when DPM is disabled",
                                );
                PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
-                               PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+                               PPSMC_MSG_MCLKDPM_UnfreezeLevel),
                    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
                    return -EINVAL);
        }
index 4f79c21f27ed451451280156afbe9e0ec0c72409..f8d838c2c8eea5f0e86c692510b86d5cd318a1b2 100644 (file)
@@ -753,6 +753,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        uint32_t config_telemetry = 0;
        struct pp_atomfwctrl_voltage_table vol_table;
        struct cgs_system_info sys_info = {0};
+       uint32_t reg;
 
        data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
        if (data == NULL)
@@ -859,6 +860,16 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
                        advanceFanControlParameters.usFanPWMMinLimit *
                        hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
 
+       reg = soc15_get_register_offset(DF_HWID, 0,
+                       mmDF_CS_AON0_DramBaseAddress0_BASE_IDX,
+                       mmDF_CS_AON0_DramBaseAddress0);
+       data->mem_channels = (cgs_read_register(hwmgr->device, reg) &
+                       DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
+                       DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
+       PP_ASSERT_WITH_CODE(data->mem_channels < ARRAY_SIZE(channel_number),
+                       "Mem Channel Index Exceeded maximum!",
+                       return -EINVAL);
+
        return result;
 }
 
@@ -1777,7 +1788,7 @@ static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *dpm_table =
                        &(data->dpm_table.mem_table);
        int result = 0;
-       uint32_t i, j, reg, mem_channels;
+       uint32_t i, j;
 
        for (i = 0; i < dpm_table->count; i++) {
                result = vega10_populate_single_memory_level(hwmgr,
@@ -1801,20 +1812,10 @@ static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
                i++;
        }
 
-       reg = soc15_get_register_offset(DF_HWID, 0,
-                       mmDF_CS_AON0_DramBaseAddress0_BASE_IDX,
-                       mmDF_CS_AON0_DramBaseAddress0);
-       mem_channels = (cgs_read_register(hwmgr->device, reg) &
-                       DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
-                       DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
-       PP_ASSERT_WITH_CODE(mem_channels < ARRAY_SIZE(channel_number),
-                       "Mem Channel Index Exceeded maximum!",
-                       return -1);
-
-       pp_table->NumMemoryChannels = cpu_to_le16(mem_channels);
+       pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels);
        pp_table->MemoryChannelWidth =
-                       cpu_to_le16(HBM_MEMORY_CHANNEL_WIDTH *
-                                       channel_number[mem_channels]);
+                       (uint16_t)(HBM_MEMORY_CHANNEL_WIDTH *
+                                       channel_number[data->mem_channels]);
 
        pp_table->LowestUclkReservedForUlv =
                        (uint8_t)(data->lowest_uclk_reserved_for_ulv);
index b4b461c3b8ee88b1e3a6fededc8b5b127cd3305e..8f7358cc3327b779a8000d052da6e6e79d622ac3 100644 (file)
@@ -389,6 +389,7 @@ struct vega10_hwmgr {
        uint32_t                       config_telemetry;
        uint32_t                       smu_version;
        uint32_t                       acg_loop_state;
+       uint32_t                       mem_channels;
 };
 
 #define VEGA10_DPM2_NEAR_TDP_DEC                      10
index 704fc893461629d71955e513f61c9e34c2f2a057..25f4b2e9a44fcdd5cef668df014001e1c1b1c90e 100644 (file)
@@ -234,6 +234,10 @@ int drm_connector_init(struct drm_device *dev,
                                   config->link_status_property,
                                   0);
 
+       drm_object_attach_property(&connector->base,
+                                  config->non_desktop_property,
+                                  0);
+
        if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
                drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
        }
@@ -763,6 +767,10 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
  *      value of link-status is "GOOD". If something fails during or after modeset,
  *      the kernel driver may set this to "BAD" and issue a hotplug uevent. Drivers
  *      should update this value using drm_mode_connector_set_link_status_property().
+ * non_desktop:
+ *     Indicates the output should be ignored for purposes of displaying a
+ *     standard desktop environment or console. This is most likely because
+ *     the output device is not rectilinear.
  *
  * Connectors also have one standardized atomic property:
  *
@@ -811,6 +819,11 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
                return -ENOMEM;
        dev->mode_config.link_status_property = prop;
 
+       prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, "non-desktop");
+       if (!prop)
+               return -ENOMEM;
+       dev->mode_config.non_desktop_property = prop;
+
        return 0;
 }
 
@@ -1194,6 +1207,10 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
        if (edid)
                size = EDID_LENGTH * (1 + edid->extensions);
 
+       drm_object_property_set_value(&connector->base,
+                                     dev->mode_config.non_desktop_property,
+                                     connector->display_info.non_desktop);
+
        ret = drm_property_replace_global_blob(dev,
                                               &connector->edid_blob_ptr,
                                               size,
index 00ddabfbf980401f8d58a4d46eff8ee60282ee5f..2e8fb51282ef36813873a18017a69f0c5abc3c47 100644 (file)
@@ -82,6 +82,8 @@
 #define EDID_QUIRK_FORCE_6BPC                  (1 << 10)
 /* Force 10bpc */
 #define EDID_QUIRK_FORCE_10BPC                 (1 << 11)
+/* Non desktop display (i.e. HMD) */
+#define EDID_QUIRK_NON_DESKTOP                 (1 << 12)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -157,6 +159,9 @@ static const struct edid_quirk {
 
        /* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
        { "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
+
+       /* HTC Vive VR Headset */
+       { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
 };
 
 /*
@@ -4393,7 +4398,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
 }
 
 static void drm_add_display_info(struct drm_connector *connector,
-                                struct edid *edid)
+                                struct edid *edid, u32 quirks)
 {
        struct drm_display_info *info = &connector->display_info;
 
@@ -4407,6 +4412,8 @@ static void drm_add_display_info(struct drm_connector *connector,
        info->max_tmds_clock = 0;
        info->dvi_dual = false;
 
+       info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
+
        if (edid->revision < 3)
                return;
 
@@ -4627,7 +4634,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
         * To avoid multiple parsing of same block, lets parse that map
         * from sink info, before parsing CEA modes.
         */
-       drm_add_display_info(connector, edid);
+       drm_add_display_info(connector, edid, quirks);
 
        /*
         * EDID spec says modes should be preferred in this order:
index 116d1f1337c7e36da1622ffc88bfc6e218d461a3..07374008f146fa946750b1cfd3bf13bfd1b9c47d 100644 (file)
@@ -2033,6 +2033,9 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
 {
        bool enable;
 
+       if (connector->display_info.non_desktop)
+               return false;
+
        if (strict)
                enable = connector->status == connector_status_connected;
        else
@@ -2052,7 +2055,8 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
                connector = fb_helper->connector_info[i]->connector;
                enabled[i] = drm_connector_enabled(connector, true);
                DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
-                         enabled[i] ? "yes" : "no");
+                             connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no");
+
                any_enabled |= enabled[i];
        }
 
index 58e9e0601a616b86bc910dc606ea7229c79fa52b..faf17b83b910df4f38202a1a453f9bd48ac82fd7 100644 (file)
@@ -210,7 +210,6 @@ static int fsl_dcu_drm_pm_suspend(struct device *dev)
                return PTR_ERR(fsl_dev->state);
        }
 
-       clk_disable_unprepare(fsl_dev->pix_clk);
        clk_disable_unprepare(fsl_dev->clk);
 
        return 0;
@@ -233,6 +232,7 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
        if (fsl_dev->tcon)
                fsl_tcon_bypass_enable(fsl_dev->tcon);
        fsl_dcu_drm_init_planes(fsl_dev->drm);
+       enable_irq(fsl_dev->irq);
        drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state);
 
        console_lock();
@@ -240,7 +240,6 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
        console_unlock();
 
        drm_kms_helper_poll_enable(fsl_dev->drm);
-       enable_irq(fsl_dev->irq);
 
        return 0;
 }
index edd7d8127d194d87440d721fcce53026fd319592..c54806d08dd78d0080ef42a314fe5ac2db40d7b6 100644 (file)
@@ -102,7 +102,6 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
 {
        struct drm_encoder *encoder = &fsl_dev->encoder;
        struct drm_connector *connector = &fsl_dev->connector.base;
-       struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config;
        int ret;
 
        fsl_dev->connector.encoder = encoder;
@@ -122,10 +121,6 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
        if (ret < 0)
                goto err_sysfs;
 
-       drm_object_property_set_value(&connector->base,
-                                     mode_config->dpms_property,
-                                     DRM_MODE_DPMS_OFF);
-
        ret = drm_panel_attach(panel, connector);
        if (ret) {
                dev_err(fsl_dev->dev, "failed to attach panel\n");
index 53e0b24beda6e0e2ee44c57550d5c752393b5863..9a9961802f5c39ce7270217903c550b2f01ed92d 100644 (file)
@@ -115,7 +115,7 @@ static void imx_drm_crtc_reset(struct drm_crtc *crtc)
 
        if (crtc->state) {
                if (crtc->state->mode_blob)
-                       drm_property_unreference_blob(crtc->state->mode_blob);
+                       drm_property_blob_put(crtc->state->mode_blob);
 
                state = to_imx_crtc_state(crtc->state);
                memset(state, 0, sizeof(*state));
index 8def97d75030c8c49a64ef63764769bb7d44bf42..aedecda9728a9847d1762cd1e35d4c6fe19c8991 100644 (file)
@@ -183,7 +183,7 @@ static int imx_pd_register(struct drm_device *drm,
                                &imx_pd_connector_helper_funcs);
                drm_connector_init(drm, &imxpd->connector,
                                   &imx_pd_connector_funcs,
-                                  DRM_MODE_CONNECTOR_VGA);
+                                  DRM_MODE_CONNECTOR_DPI);
        }
 
        if (imxpd->panel)
index 2fcf805d3a169e9776634fc4f5ddfcbd4b9fbee7..33b821d6d018f37ba1ccf9cf86be81be0f4e11da 100644 (file)
@@ -245,7 +245,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        }
 
        info->par = rfbdev;
-       info->skip_vt_switch = true;
 
        ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
        if (ret) {
index 4bcacd3f48613d416deea7a32cff7f58c97709b3..b0a1dedac8026e0ad89ee1227cb7b7881d3fee7d 100644 (file)
@@ -174,9 +174,9 @@ struct tegra_sor {
 
        struct reset_control *rst;
        struct clk *clk_parent;
-       struct clk *clk_brick;
        struct clk *clk_safe;
-       struct clk *clk_src;
+       struct clk *clk_out;
+       struct clk *clk_pad;
        struct clk *clk_dp;
        struct clk *clk;
 
@@ -255,7 +255,7 @@ static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
 
        clk_disable_unprepare(sor->clk);
 
-       err = clk_set_parent(sor->clk, parent);
+       err = clk_set_parent(sor->clk_out, parent);
        if (err < 0)
                return err;
 
@@ -266,24 +266,24 @@ static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
        return 0;
 }
 
-struct tegra_clk_sor_brick {
+struct tegra_clk_sor_pad {
        struct clk_hw hw;
        struct tegra_sor *sor;
 };
 
-static inline struct tegra_clk_sor_brick *to_brick(struct clk_hw *hw)
+static inline struct tegra_clk_sor_pad *to_pad(struct clk_hw *hw)
 {
-       return container_of(hw, struct tegra_clk_sor_brick, hw);
+       return container_of(hw, struct tegra_clk_sor_pad, hw);
 }
 
-static const char * const tegra_clk_sor_brick_parents[] = {
+static const char * const tegra_clk_sor_pad_parents[] = {
        "pll_d2_out0", "pll_dp"
 };
 
-static int tegra_clk_sor_brick_set_parent(struct clk_hw *hw, u8 index)
+static int tegra_clk_sor_pad_set_parent(struct clk_hw *hw, u8 index)
 {
-       struct tegra_clk_sor_brick *brick = to_brick(hw);
-       struct tegra_sor *sor = brick->sor;
+       struct tegra_clk_sor_pad *pad = to_pad(hw);
+       struct tegra_sor *sor = pad->sor;
        u32 value;
 
        value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
@@ -304,10 +304,10 @@ static int tegra_clk_sor_brick_set_parent(struct clk_hw *hw, u8 index)
        return 0;
 }
 
-static u8 tegra_clk_sor_brick_get_parent(struct clk_hw *hw)
+static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw)
 {
-       struct tegra_clk_sor_brick *brick = to_brick(hw);
-       struct tegra_sor *sor = brick->sor;
+       struct tegra_clk_sor_pad *pad = to_pad(hw);
+       struct tegra_sor *sor = pad->sor;
        u8 parent = U8_MAX;
        u32 value;
 
@@ -328,33 +328,33 @@ static u8 tegra_clk_sor_brick_get_parent(struct clk_hw *hw)
        return parent;
 }
 
-static const struct clk_ops tegra_clk_sor_brick_ops = {
-       .set_parent = tegra_clk_sor_brick_set_parent,
-       .get_parent = tegra_clk_sor_brick_get_parent,
+static const struct clk_ops tegra_clk_sor_pad_ops = {
+       .set_parent = tegra_clk_sor_pad_set_parent,
+       .get_parent = tegra_clk_sor_pad_get_parent,
 };
 
-static struct clk *tegra_clk_sor_brick_register(struct tegra_sor *sor,
-                                               const char *name)
+static struct clk *tegra_clk_sor_pad_register(struct tegra_sor *sor,
+                                             const char *name)
 {
-       struct tegra_clk_sor_brick *brick;
+       struct tegra_clk_sor_pad *pad;
        struct clk_init_data init;
        struct clk *clk;
 
-       brick = devm_kzalloc(sor->dev, sizeof(*brick), GFP_KERNEL);
-       if (!brick)
+       pad = devm_kzalloc(sor->dev, sizeof(*pad), GFP_KERNEL);
+       if (!pad)
                return ERR_PTR(-ENOMEM);
 
-       brick->sor = sor;
+       pad->sor = sor;
 
        init.name = name;
        init.flags = 0;
-       init.parent_names = tegra_clk_sor_brick_parents;
-       init.num_parents = ARRAY_SIZE(tegra_clk_sor_brick_parents);
-       init.ops = &tegra_clk_sor_brick_ops;
+       init.parent_names = tegra_clk_sor_pad_parents;
+       init.num_parents = ARRAY_SIZE(tegra_clk_sor_pad_parents);
+       init.ops = &tegra_clk_sor_pad_ops;
 
-       brick->hw.init = &init;
+       pad->hw.init = &init;
 
-       clk = devm_clk_register(sor->dev, &brick->hw);
+       clk = devm_clk_register(sor->dev, &pad->hw);
 
        return clk;
 }
@@ -998,8 +998,10 @@ static int tegra_sor_power_down(struct tegra_sor *sor)
 
        /* switch to safe parent clock */
        err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
-       if (err < 0)
+       if (err < 0) {
                dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
+               return err;
+       }
 
        value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
        value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
@@ -2007,8 +2009,10 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
 
        /* switch to safe parent clock */
        err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
-       if (err < 0)
+       if (err < 0) {
                dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
+               return;
+       }
 
        div = clk_get_rate(sor->clk) / 1000000 * 4;
 
@@ -2111,13 +2115,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
        tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
 
        /* switch to parent clock */
-       err = clk_set_parent(sor->clk_src, sor->clk_parent);
-       if (err < 0)
-               dev_err(sor->dev, "failed to set source clock: %d\n", err);
-
-       err = tegra_sor_set_parent_clock(sor, sor->clk_src);
-       if (err < 0)
+       err = clk_set_parent(sor->clk, sor->clk_parent);
+       if (err < 0) {
                dev_err(sor->dev, "failed to set parent clock: %d\n", err);
+               return;
+       }
+
+       err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
+       if (err < 0) {
+               dev_err(sor->dev, "failed to set pad clock: %d\n", err);
+               return;
+       }
 
        value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
 
@@ -2628,11 +2636,24 @@ static int tegra_sor_probe(struct platform_device *pdev)
        }
 
        if (sor->soc->supports_hdmi || sor->soc->supports_dp) {
-               sor->clk_src = devm_clk_get(&pdev->dev, "source");
-               if (IS_ERR(sor->clk_src)) {
-                       err = PTR_ERR(sor->clk_src);
-                       dev_err(sor->dev, "failed to get source clock: %d\n",
-                               err);
+               struct device_node *np = pdev->dev.of_node;
+               const char *name;
+
+               /*
+                * For backwards compatibility with Tegra210 device trees,
+                * fall back to the old clock name "source" if the new "out"
+                * clock is not available.
+                */
+               if (of_property_match_string(np, "clock-names", "out") < 0)
+                       name = "source";
+               else
+                       name = "out";
+
+               sor->clk_out = devm_clk_get(&pdev->dev, name);
+               if (IS_ERR(sor->clk_out)) {
+                       err = PTR_ERR(sor->clk_out);
+                       dev_err(sor->dev, "failed to get %s clock: %d\n",
+                               name, err);
                        goto remove;
                }
        }
@@ -2658,16 +2679,60 @@ static int tegra_sor_probe(struct platform_device *pdev)
                goto remove;
        }
 
+       /*
+        * Starting with Tegra186, the BPMP provides an implementation for
+        * the pad output clock, so we have to look it up from device tree.
+        */
+       sor->clk_pad = devm_clk_get(&pdev->dev, "pad");
+       if (IS_ERR(sor->clk_pad)) {
+               if (sor->clk_pad != ERR_PTR(-ENOENT)) {
+                       err = PTR_ERR(sor->clk_pad);
+                       goto remove;
+               }
+
+               /*
+                * If the pad output clock is not available, then we assume
+                * we're on Tegra210 or earlier and have to provide our own
+                * implementation.
+                */
+               sor->clk_pad = NULL;
+       }
+
+       /*
+        * The bootloader may have set up the SOR such that it's module clock
+        * is sourced by one of the display PLLs. However, that doesn't work
+        * without properly having set up other bits of the SOR.
+        */
+       err = clk_set_parent(sor->clk_out, sor->clk_safe);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to use safe clock: %d\n", err);
+               goto remove;
+       }
+
        platform_set_drvdata(pdev, sor);
        pm_runtime_enable(&pdev->dev);
 
-       pm_runtime_get_sync(&pdev->dev);
-       sor->clk_brick = tegra_clk_sor_brick_register(sor, "sor1_brick");
-       pm_runtime_put(&pdev->dev);
+       /*
+        * On Tegra210 and earlier, provide our own implementation for the
+        * pad output clock.
+        */
+       if (!sor->clk_pad) {
+               err = pm_runtime_get_sync(&pdev->dev);
+               if (err < 0) {
+                       dev_err(&pdev->dev, "failed to get runtime PM: %d\n",
+                               err);
+                       goto remove;
+               }
+
+               sor->clk_pad = tegra_clk_sor_pad_register(sor,
+                                                         "sor1_pad_clkout");
+               pm_runtime_put(&pdev->dev);
+       }
 
-       if (IS_ERR(sor->clk_brick)) {
-               err = PTR_ERR(sor->clk_brick);
-               dev_err(&pdev->dev, "failed to register SOR clock: %d\n", err);
+       if (IS_ERR(sor->clk_pad)) {
+               err = PTR_ERR(sor->clk_pad);
+               dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n",
+                       err);
                goto remove;
        }
 
index 28fed7e206d030abb23eb1141a7eac672fc702a7..81ac82455ce4d649aadfc99eb85e53a37f74f683 100644 (file)
@@ -12,14 +12,3 @@ config DRM_TILCDC
          controller, for example AM33xx in beagle-bone, DA8xx, or
          OMAP-L1xx.  This driver replaces the FB_DA8XX fbdev driver.
 
-config DRM_TILCDC_SLAVE_COMPAT
-       bool "Support device tree blobs using TI LCDC Slave binding"
-       depends on DRM_TILCDC
-       default y
-       select OF_RESOLVE
-       select OF_OVERLAY
-       help
-         Choose this option if you need a kernel that is compatible
-         with device tree blobs using the obsolete "ti,tilcdc,slave"
-         binding. If you find "ti,tilcdc,slave"-string from your DTB,
-         you probably need this. Otherwise you do not.
index b9e1108e5b4e81e8c6a9926361abff0c5226248a..87f9480e43b05f0fa707f2e84c3fe6f5774fb56d 100644 (file)
@@ -3,9 +3,6 @@ ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
        ccflags-y += -Werror
 endif
 
-obj-$(CONFIG_DRM_TILCDC_SLAVE_COMPAT) += tilcdc_slave_compat.o \
-                                        tilcdc_slave_compat.dtb.o
-
 tilcdc-y := \
        tilcdc_plane.o \
        tilcdc_crtc.o \
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c
deleted file mode 100644 (file)
index d2b9e5f..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2015 Texas Instruments
- * Author: Jyri Sarha <jsarha@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- */
-
-/*
- * To support the old "ti,tilcdc,slave" binding the binding has to be
- * transformed to the new external encoder binding.
- */
-
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-#include <linux/of_fdt.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-
-#include "tilcdc_slave_compat.h"
-
-struct kfree_table {
-       int total;
-       int num;
-       void **table;
-};
-
-static int __init kfree_table_init(struct kfree_table *kft)
-{
-       kft->total = 32;
-       kft->num = 0;
-       kft->table = kmalloc(kft->total * sizeof(*kft->table),
-                            GFP_KERNEL);
-       if (!kft->table)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static int __init kfree_table_add(struct kfree_table *kft, void *p)
-{
-       if (kft->num == kft->total) {
-               void **old = kft->table;
-
-               kft->total *= 2;
-               kft->table = krealloc(old, kft->total * sizeof(*kft->table),
-                                     GFP_KERNEL);
-               if (!kft->table) {
-                       kft->table = old;
-                       kfree(p);
-                       return -ENOMEM;
-               }
-       }
-       kft->table[kft->num++] = p;
-       return 0;
-}
-
-static void __init kfree_table_free(struct kfree_table *kft)
-{
-       int i;
-
-       for (i = 0; i < kft->num; i++)
-               kfree(kft->table[i]);
-
-       kfree(kft->table);
-}
-
-static
-struct property * __init tilcdc_prop_dup(const struct property *prop,
-                                        struct kfree_table *kft)
-{
-       struct property *nprop;
-
-       nprop = kzalloc(sizeof(*nprop), GFP_KERNEL);
-       if (!nprop || kfree_table_add(kft, nprop))
-               return NULL;
-
-       nprop->name = kstrdup(prop->name, GFP_KERNEL);
-       if (!nprop->name || kfree_table_add(kft, nprop->name))
-               return NULL;
-
-       nprop->value = kmemdup(prop->value, prop->length, GFP_KERNEL);
-       if (!nprop->value || kfree_table_add(kft, nprop->value))
-               return NULL;
-
-       nprop->length = prop->length;
-
-       return nprop;
-}
-
-static void __init tilcdc_copy_props(struct device_node *from,
-                                    struct device_node *to,
-                                    const char * const props[],
-                                    struct kfree_table *kft)
-{
-       struct property *prop;
-       int i;
-
-       for (i = 0; props[i]; i++) {
-               prop = of_find_property(from, props[i], NULL);
-               if (!prop)
-                       continue;
-
-               prop = tilcdc_prop_dup(prop, kft);
-               if (!prop)
-                       continue;
-
-               prop->next = to->properties;
-               to->properties = prop;
-       }
-}
-
-static int __init tilcdc_prop_str_update(struct property *prop,
-                                         const char *str,
-                                         struct kfree_table *kft)
-{
-       prop->value = kstrdup(str, GFP_KERNEL);
-       if (kfree_table_add(kft, prop->value) || !prop->value)
-               return -ENOMEM;
-       prop->length = strlen(str)+1;
-       return 0;
-}
-
-static void __init tilcdc_node_disable(struct device_node *node)
-{
-       struct property *prop;
-
-       prop = kzalloc(sizeof(*prop), GFP_KERNEL);
-       if (!prop)
-               return;
-
-       prop->name = "status";
-       prop->value = "disabled";
-       prop->length = strlen((char *)prop->value)+1;
-
-       of_update_property(node, prop);
-}
-
-static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft)
-{
-       const int size = __dtb_tilcdc_slave_compat_end -
-               __dtb_tilcdc_slave_compat_begin;
-       static void *overlay_data;
-       struct device_node *overlay;
-
-       if (!size) {
-               pr_warn("%s: No overlay data\n", __func__);
-               return NULL;
-       }
-
-       overlay_data = kmemdup(__dtb_tilcdc_slave_compat_begin,
-                              size, GFP_KERNEL);
-       if (!overlay_data || kfree_table_add(kft, overlay_data))
-               return NULL;
-
-       of_fdt_unflatten_tree(overlay_data, NULL, &overlay);
-       if (!overlay) {
-               pr_warn("%s: Unfattening overlay tree failed\n", __func__);
-               return NULL;
-       }
-
-       return overlay;
-}
-
-static const struct of_device_id tilcdc_slave_of_match[] __initconst = {
-       { .compatible = "ti,tilcdc,slave", },
-       {},
-};
-
-static const struct of_device_id tilcdc_of_match[] __initconst = {
-       { .compatible = "ti,am33xx-tilcdc", },
-       {},
-};
-
-static const struct of_device_id tilcdc_tda998x_of_match[] __initconst = {
-       { .compatible = "nxp,tda998x", },
-       {},
-};
-
-static const char * const tilcdc_slave_props[] __initconst = {
-       "pinctrl-names",
-       "pinctrl-0",
-       "pinctrl-1",
-       NULL
-};
-
-static void __init tilcdc_convert_slave_node(void)
-{
-       struct device_node *slave = NULL, *lcdc = NULL;
-       struct device_node *i2c = NULL, *fragment = NULL;
-       struct device_node *overlay, *encoder;
-       struct property *prop;
-       /* For all memory needed for the overlay tree. This memory can
-          be freed after the overlay has been applied. */
-       struct kfree_table kft;
-       int ovcs_id, ret;
-
-       if (kfree_table_init(&kft))
-               return;
-
-       lcdc = of_find_matching_node(NULL, tilcdc_of_match);
-       slave = of_find_matching_node(NULL, tilcdc_slave_of_match);
-
-       if (!slave || !of_device_is_available(lcdc))
-               goto out;
-
-       i2c = of_parse_phandle(slave, "i2c", 0);
-       if (!i2c) {
-               pr_err("%s: Can't find i2c node trough phandle\n", __func__);
-               goto out;
-       }
-
-       overlay = tilcdc_get_overlay(&kft);
-       if (!overlay)
-               goto out;
-
-       encoder = of_find_matching_node(overlay, tilcdc_tda998x_of_match);
-       if (!encoder) {
-               pr_err("%s: Failed to find tda998x node\n", __func__);
-               goto out;
-       }
-
-       tilcdc_copy_props(slave, encoder, tilcdc_slave_props, &kft);
-
-       for_each_child_of_node(overlay, fragment) {
-               prop = of_find_property(fragment, "target-path", NULL);
-               if (!prop)
-                       continue;
-               if (!strncmp("i2c", (char *)prop->value, prop->length))
-                       if (tilcdc_prop_str_update(prop, i2c->full_name, &kft))
-                               goto out;
-               if (!strncmp("lcdc", (char *)prop->value, prop->length))
-                       if (tilcdc_prop_str_update(prop, lcdc->full_name, &kft))
-                               goto out;
-       }
-
-       tilcdc_node_disable(slave);
-
-       ovcs_id = 0;
-       ret = of_overlay_apply(overlay, &ovcs_id);
-       if (ret)
-               pr_err("%s: Applying overlay changeset failed: %d\n",
-                       __func__, ret);
-       else
-               pr_info("%s: ti,tilcdc,slave node successfully converted\n",
-                       __func__);
-out:
-       kfree_table_free(&kft);
-       of_node_put(i2c);
-       of_node_put(slave);
-       of_node_put(lcdc);
-       of_node_put(fragment);
-}
-
-static int __init tilcdc_slave_compat_init(void)
-{
-       tilcdc_convert_slave_node();
-       return 0;
-}
-
-subsys_initcall(tilcdc_slave_compat_init);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts
deleted file mode 100644 (file)
index 693f8b0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * DTS overlay for converting ti,tilcdc,slave binding to new binding.
- *
- * Copyright (C) 2015 Texas Instruments Inc.
- * Author: Jyri Sarha <jsarha@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- */
-
-/*
- * target-path property values are simple tags that are replaced with
- * correct values in tildcdc_slave_compat.c. Some properties are also
- * copied over from the ti,tilcdc,slave node.
- */
-
-/dts-v1/;
-/ {
-       fragment@0 {
-               target-path = "i2c";
-               __overlay__ {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       tda19988 {
-                               compatible = "nxp,tda998x";
-                               reg = <0x70>;
-                               status = "okay";
-
-                               port {
-                                       hdmi_0: endpoint@0 {
-                                               remote-endpoint = <&lcd_0>;
-                                       };
-                               };
-                       };
-               };
-       };
-
-       fragment@1 {
-               target-path = "lcdc";
-               __overlay__ {
-                       port {
-                               lcd_0: endpoint@0 {
-                                       remote-endpoint = <&hdmi_0>;
-                               };
-                       };
-               };
-       };
-
-       __local_fixups__ {
-               fragment@0 {
-                       __overlay__ {
-                               tda19988 {
-                                       port {
-                                               endpoint@0 {
-                                                       remote-endpoint = <0>;
-                                               };
-                                       };
-                               };
-                       };
-               };
-               fragment@1 {
-                       __overlay__ {
-                               port {
-                                       endpoint@0 {
-                                               remote-endpoint = <0>;
-                                       };
-                               };
-                       };
-               };
-       };
-};
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h
deleted file mode 100644 (file)
index 403d35d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2015 Texas Instruments
- * Author: Jyri Sarha <jsarha@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-/* This header declares the symbols defined in tilcdc_slave_compat.dts */
-
-#ifndef __TILCDC_SLAVE_COMPAT_H__
-#define __TILCDC_SLAVE_COMPAT_H__
-
-extern uint8_t __dtb_tilcdc_slave_compat_begin[];
-extern uint8_t __dtb_tilcdc_slave_compat_end[];
-
-#endif /* __TILCDC_SLAVE_COMPAT_H__ */
index 7a4b8362dda8f4c2691575550b383455c2aadfdb..49bfe6e7d0052937b3b2189420350c226985f7ba 100644 (file)
@@ -249,11 +249,8 @@ EXPORT_SYMBOL_GPL(ipu_dc_enable);
 
 void ipu_dc_enable_channel(struct ipu_dc *dc)
 {
-       int di;
        u32 reg;
 
-       di = dc->di;
-
        reg = readl(dc->base + DC_WR_CH_CONF);
        reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
        writel(reg, dc->base + DC_WR_CH_CONF);
index 5a2d71729b9ace7a67e8216f7d5ba61fddb471d7..2a8ac6829d42b187e20f6f2a7c80b400d19a423b 100644 (file)
@@ -1,6 +1,5 @@
 menuconfig MTD
        tristate "Memory Technology Device (MTD) support"
-       depends on GENERIC_IO
        help
          Memory Technology Devices are flash, RAM and similar chips, often
          used for solid state file systems on embedded devices. This option
index afb43d5e178269d33443a59a439245263cb263c0..1cd0fff0e9402d9c1ee477674be5b90611dcb561 100644 (file)
@@ -20,8 +20,9 @@ static int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_ch
 static int mapram_erase (struct mtd_info *, struct erase_info *);
 static void mapram_nop (struct mtd_info *);
 static struct mtd_info *map_ram_probe(struct map_info *map);
-static unsigned long mapram_unmapped_area(struct mtd_info *, unsigned long,
-                                         unsigned long, unsigned long);
+static int mapram_point (struct mtd_info *mtd, loff_t from, size_t len,
+                        size_t *retlen, void **virt, resource_size_t *phys);
+static int mapram_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
 
 
 static struct mtd_chip_driver mapram_chipdrv = {
@@ -65,11 +66,12 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
        mtd->type = MTD_RAM;
        mtd->size = map->size;
        mtd->_erase = mapram_erase;
-       mtd->_get_unmapped_area = mapram_unmapped_area;
        mtd->_read = mapram_read;
        mtd->_write = mapram_write;
        mtd->_panic_write = mapram_write;
+       mtd->_point = mapram_point;
        mtd->_sync = mapram_nop;
+       mtd->_unpoint = mapram_unpoint;
        mtd->flags = MTD_CAP_RAM;
        mtd->writesize = 1;
 
@@ -81,19 +83,23 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
        return mtd;
 }
 
-
-/*
- * Allow NOMMU mmap() to directly map the device (if not NULL)
- * - return the address to which the offset maps
- * - return -ENOSYS to indicate refusal to do the mapping
- */
-static unsigned long mapram_unmapped_area(struct mtd_info *mtd,
-                                         unsigned long len,
-                                         unsigned long offset,
-                                         unsigned long flags)
+static int mapram_point(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, void **virt, resource_size_t *phys)
 {
        struct map_info *map = mtd->priv;
-       return (unsigned long) map->virt + offset;
+
+       if (!map->virt)
+               return -EINVAL;
+       *virt = map->virt + from;
+       if (phys)
+               *phys = map->phys + from;
+       *retlen = len;
+       return 0;
+}
+
+static int mapram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
+{
+       return 0;
 }
 
 static int mapram_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
index e67f73ab44c9db23eae052c206139a03aafe15b9..20e3604b4d7169fef2c65daeba87dbe74b502baf 100644 (file)
@@ -20,8 +20,10 @@ static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_ch
 static void maprom_nop (struct mtd_info *);
 static struct mtd_info *map_rom_probe(struct map_info *map);
 static int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
-static unsigned long maprom_unmapped_area(struct mtd_info *, unsigned long,
-                                         unsigned long, unsigned long);
+static int maprom_point (struct mtd_info *mtd, loff_t from, size_t len,
+                        size_t *retlen, void **virt, resource_size_t *phys);
+static int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
+
 
 static struct mtd_chip_driver maprom_chipdrv = {
        .probe  = map_rom_probe,
@@ -51,7 +53,8 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
        mtd->name = map->name;
        mtd->type = MTD_ROM;
        mtd->size = map->size;
-       mtd->_get_unmapped_area = maprom_unmapped_area;
+       mtd->_point = maprom_point;
+       mtd->_unpoint = maprom_unpoint;
        mtd->_read = maprom_read;
        mtd->_write = maprom_write;
        mtd->_sync = maprom_nop;
@@ -66,18 +69,23 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
 }
 
 
-/*
- * Allow NOMMU mmap() to directly map the device (if not NULL)
- * - return the address to which the offset maps
- * - return -ENOSYS to indicate refusal to do the mapping
- */
-static unsigned long maprom_unmapped_area(struct mtd_info *mtd,
-                                         unsigned long len,
-                                         unsigned long offset,
-                                         unsigned long flags)
+static int maprom_point(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, void **virt, resource_size_t *phys)
 {
        struct map_info *map = mtd->priv;
-       return (unsigned long) map->virt + offset;
+
+       if (!map->virt)
+               return -EINVAL;
+       *virt = map->virt + from;
+       if (phys)
+               *phys = map->phys + from;
+       *retlen = len;
+       return 0;
+}
+
+static int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
+{
+       return 0;
 }
 
 static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
index 84b16133554bebf60f4e42c84bc1fd4274c477a8..0806f72102c09d03469c8124b75e699333fca652 100644 (file)
@@ -1814,8 +1814,13 @@ static void __init doc_dbg_register(struct mtd_info *floor)
        struct dentry *root = floor->dbg.dfs_dir;
        struct docg3 *docg3 = floor->priv;
 
-       if (IS_ERR_OR_NULL(root))
+       if (IS_ERR_OR_NULL(root)) {
+               if (IS_ENABLED(CONFIG_DEBUG_FS) &&
+                   !IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
+                       dev_warn(floor->dev.parent,
+                                "CONFIG_MTD_PARTITIONED_MASTER must be enabled to expose debugfs stuff\n");
                return;
+       }
 
        debugfs_create_file("docg3_flashcontrol", S_IRUSR, root, docg3,
                            &flashcontrol_fops);
index 268aae45b5149de12ff77e59df776790724dede8..555b94406e0bb31a83c92fd03a70250cce015842 100644 (file)
@@ -583,7 +583,7 @@ static struct mtd_erase_region_info erase_regions[] = {
        }
 };
 
-static struct mtd_partition lart_partitions[] = {
+static const struct mtd_partition lart_partitions[] = {
        /* blob */
        {
                .name   = "blob",
index 00eea6fd379cc68d51dbe197eec9b8b310341fdb..dbe6a1de2bb822fda74d0af92a9d08ebc7eb30ea 100644 (file)
@@ -359,6 +359,7 @@ static const struct spi_device_id m25p_ids[] = {
        {"m25p32-nonjedec"},    {"m25p64-nonjedec"},    {"m25p128-nonjedec"},
 
        /* Everspin MRAMs (non-JEDEC) */
+       { "mr25h128" }, /* 128 Kib, 40 MHz */
        { "mr25h256" }, /* 256 Kib, 40 MHz */
        { "mr25h10" },  /*   1 Mib, 40 MHz */
        { "mr25h40" },  /*   4 Mib, 40 MHz */
index cbd8547d7aad8654b14ae20e8d00a69b2c861463..0bf4aeaf0cb8cf14665ee8474c3faeb68479fd88 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtdram.h>
@@ -69,6 +70,27 @@ static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
 {
        *virt = mtd->priv + from;
        *retlen = len;
+
+       if (phys) {
+               /* limit retlen to the number of contiguous physical pages */
+               unsigned long page_ofs = offset_in_page(*virt);
+               void *addr = *virt - page_ofs;
+               unsigned long pfn1, pfn0 = vmalloc_to_pfn(addr);
+
+               *phys = __pfn_to_phys(pfn0) + page_ofs;
+               len += page_ofs;
+               while (len > PAGE_SIZE) {
+                       len -= PAGE_SIZE;
+                       addr += PAGE_SIZE;
+                       pfn0++;
+                       pfn1 = vmalloc_to_pfn(addr);
+                       if (pfn1 != pfn0) {
+                               *retlen = addr - *virt;
+                               break;
+                       }
+               }
+       }
+
        return 0;
 }
 
@@ -77,19 +99,6 @@ static int ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
        return 0;
 }
 
-/*
- * Allow NOMMU mmap() to directly map the device (if not NULL)
- * - return the address to which the offset maps
- * - return -ENOSYS to indicate refusal to do the mapping
- */
-static unsigned long ram_get_unmapped_area(struct mtd_info *mtd,
-                                          unsigned long len,
-                                          unsigned long offset,
-                                          unsigned long flags)
-{
-       return (unsigned long) mtd->priv + offset;
-}
-
 static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
                size_t *retlen, u_char *buf)
 {
@@ -134,7 +143,6 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
        mtd->_erase = ram_erase;
        mtd->_point = ram_point;
        mtd->_unpoint = ram_unpoint;
-       mtd->_get_unmapped_area = ram_get_unmapped_area;
        mtd->_read = ram_read;
        mtd->_write = ram_write;
 
index 8087c36dc6935a8d6caf6d4b770be4fba60e1319..0ec85f316d24c04e8503c8ca7625a3c16399a97b 100644 (file)
@@ -163,8 +163,9 @@ static int register_device(char *name, unsigned long start, unsigned long length
        }
 
        if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start =
-                               ioremap(start, length))) {
-               E("slram: ioremap failed\n");
+               memremap(start, length,
+                        MEMREMAP_WB | MEMREMAP_WT | MEMREMAP_WC))) {
+               E("slram: memremap failed\n");
                return -EIO;
        }
        ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end =
@@ -186,7 +187,7 @@ static int register_device(char *name, unsigned long start, unsigned long length
 
        if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0))   {
                E("slram: Failed to register new device\n");
-               iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
+               memunmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
                kfree((*curmtd)->mtdinfo->priv);
                kfree((*curmtd)->mtdinfo);
                return(-EAGAIN);
@@ -206,7 +207,7 @@ static void unregister_devices(void)
        while (slram_mtdlist) {
                nextitem = slram_mtdlist->next;
                mtd_device_unregister(slram_mtdlist->mtdinfo);
-               iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start);
+               memunmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start);
                kfree(slram_mtdlist->mtdinfo->priv);
                kfree(slram_mtdlist->mtdinfo);
                kfree(slram_mtdlist);
index d504b3d1791da8ef70076d2b936c6afba7cc863c..70f488628464d41682b2392c5d677cdbbde55b92 100644 (file)
@@ -61,7 +61,7 @@ static struct map_info flagadm_map = {
                .bankwidth =    2,
 };
 
-static struct mtd_partition flagadm_parts[] = {
+static const struct mtd_partition flagadm_parts[] = {
        {
                .name =         "Bootloader",
                .offset =       FLASH_PARTITION0_ADDR,
index 15bbda03be6542cd860759a79a914387c842301d..a0b8fa7849a956c31250fd6946638f3423a9b58e 100644 (file)
@@ -47,7 +47,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = {
 /*
  * MTD partitioning stuff
  */
-static struct mtd_partition partitions[] =
+static const struct mtd_partition partitions[] =
 {
        {
                .name = "FileSystem",
index 81dc2598bc0ac9085cadf7b332543e7752be5ade..3528497f96c779e8ce059471178bb771f895c216 100644 (file)
@@ -52,7 +52,7 @@
 /* partition_info gives details on the logical partitions that the split the
  * single flash device into. If the size if zero we use up to the end of the
  * device. */
-static struct mtd_partition partition_info[]={
+static const struct mtd_partition partition_info[] = {
     {
            .name = "NetSc520 boot kernel",
            .offset = 0,
index a577ef8553d076fb01a13b01de55fb5a672e9e77..729579fb654ffcaea4cc6afb698ff43ce337f7de 100644 (file)
@@ -107,7 +107,7 @@ static struct map_info nettel_amd_map = {
        .bankwidth = AMD_BUSWIDTH,
 };
 
-static struct mtd_partition nettel_amd_partitions[] = {
+static const struct mtd_partition nettel_amd_partitions[] = {
        {
                .name = "SnapGear BIOS config",
                .offset = 0x000e0000,
index 51572895c02cc42f8d3ad0d153625c8d3e7263ee..6d9a4d6f983949cf11692d1164b7e3456d867627 100644 (file)
@@ -43,7 +43,6 @@ struct platram_info {
        struct device           *dev;
        struct mtd_info         *mtd;
        struct map_info          map;
-       struct resource         *area;
        struct platdata_mtd_ram *pdata;
 };
 
@@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev)
 
        platram_setrw(info, PLATRAM_RO);
 
-       /* release resources */
-
-       if (info->area) {
-               release_resource(info->area);
-               kfree(info->area);
-       }
-
-       if (info->map.virt != NULL)
-               iounmap(info->map.virt);
-
        kfree(info);
 
        return 0;
@@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev)
        info->pdata = pdata;
 
        /* get the resource for the memory mapping */
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       if (res == NULL) {
-               dev_err(&pdev->dev, "no memory resource specified\n");
-               err = -ENOENT;
+       info->map.virt = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(info->map.virt)) {
+               err = PTR_ERR(info->map.virt);
+               dev_err(&pdev->dev, "failed to ioremap() region\n");
                goto exit_free;
        }
 
@@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev)
                        (char *)pdata->mapname : (char *)pdev->name;
        info->map.bankwidth = pdata->bankwidth;
 
-       /* register our usage of the memory area */
-
-       info->area = request_mem_region(res->start, info->map.size, pdev->name);
-       if (info->area == NULL) {
-               dev_err(&pdev->dev, "failed to request memory region\n");
-               err = -EIO;
-               goto exit_free;
-       }
-
-       /* remap the memory area */
-
-       info->map.virt = ioremap(res->start, info->map.size);
        dev_dbg(&pdev->dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size);
 
-       if (info->map.virt == NULL) {
-               dev_err(&pdev->dev, "failed to ioremap() region\n");
-               err = -EIO;
-               goto exit_free;
-       }
-
        simple_map_init(&info->map);
 
        dev_dbg(&pdev->dev, "initialised map, probing for mtd\n");
index 556a2dfe94c586e03b363f5c2056992346df72b1..4337d279ad83629d23a4c8890176fbc30a1f4509 100644 (file)
@@ -87,7 +87,7 @@ static DEFINE_SPINLOCK(sbc_gxx_spin);
 /* partition_info gives details on the logical partitions that the split the
  * single flash device into. If the size if zero we use up to the end of the
  * device. */
-static struct mtd_partition partition_info[]={
+static const struct mtd_partition partition_info[] = {
     { .name = "SBC-GXx flash boot partition",
       .offset = 0,
       .size =   BOOT_PARTITION_SIZE_KiB*1024 },
index 9969fedb1f13c2be53859df396823260bd1b9740..8f177e0acb8c1dbb350728eb5dda97a1168c1feb 100644 (file)
@@ -43,7 +43,7 @@ static struct map_info ts5500_map = {
        .phys = WINDOW_ADDR
 };
 
-static struct mtd_partition ts5500_partitions[] = {
+static const struct mtd_partition ts5500_partitions[] = {
        {
                .name = "Drive A",
                .offset = 0,
index 00a8190797ec1d4a445fd4bd46bfe03903699a15..aef030ca8601c709cc735a180b6c997f8b951f7c 100644 (file)
@@ -49,7 +49,7 @@ static struct mtd_info *uclinux_ram_mtdinfo;
 
 /****************************************************************************/
 
-static struct mtd_partition uclinux_romfs[] = {
+static const struct mtd_partition uclinux_romfs[] = {
        { .name = "ROMfs" }
 };
 
index d573606b91c2a57a4ff07e040b79fd86a7762c5b..60bf53df5454101a533a17b8bf46eb11164a3824 100644 (file)
@@ -643,32 +643,6 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
        return err;
 }
 
-/*
- * try to support NOMMU mmaps on concatenated devices
- * - we don't support subdev spanning as we can't guarantee it'll work
- */
-static unsigned long concat_get_unmapped_area(struct mtd_info *mtd,
-                                             unsigned long len,
-                                             unsigned long offset,
-                                             unsigned long flags)
-{
-       struct mtd_concat *concat = CONCAT(mtd);
-       int i;
-
-       for (i = 0; i < concat->num_subdev; i++) {
-               struct mtd_info *subdev = concat->subdev[i];
-
-               if (offset >= subdev->size) {
-                       offset -= subdev->size;
-                       continue;
-               }
-
-               return mtd_get_unmapped_area(subdev, len, offset, flags);
-       }
-
-       return (unsigned long) -ENOSYS;
-}
-
 /*
  * This function constructs a virtual MTD device by concatenating
  * num_devs MTD devices. A pointer to the new device object is
@@ -790,7 +764,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        concat->mtd._unlock = concat_unlock;
        concat->mtd._suspend = concat_suspend;
        concat->mtd._resume = concat_resume;
-       concat->mtd._get_unmapped_area = concat_get_unmapped_area;
 
        /*
         * Combine the erase block size info of the subdevices:
index e7ea842ba3dbfc49f4e93d9c54b5f2b2cfc09f68..f80e911b8843819db8dcd1956c76ce2bf60b5ab8 100644 (file)
@@ -1022,11 +1022,18 @@ EXPORT_SYMBOL_GPL(mtd_unpoint);
 unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
                                    unsigned long offset, unsigned long flags)
 {
-       if (!mtd->_get_unmapped_area)
-               return -EOPNOTSUPP;
-       if (offset >= mtd->size || len > mtd->size - offset)
-               return -EINVAL;
-       return mtd->_get_unmapped_area(mtd, len, offset, flags);
+       size_t retlen;
+       void *virt;
+       int ret;
+
+       ret = mtd_point(mtd, offset, len, &retlen, &virt, NULL);
+       if (ret)
+               return ret;
+       if (retlen != len) {
+               mtd_unpoint(mtd, offset, retlen);
+               return -ENOSYS;
+       }
+       return (unsigned long)virt;
 }
 EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
 
@@ -1093,6 +1100,39 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
+static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs,
+                            struct mtd_oob_ops *ops)
+{
+       /*
+        * Some users are setting ->datbuf or ->oobbuf to NULL, but are leaving
+        * ->len or ->ooblen uninitialized. Force ->len and ->ooblen to 0 in
+        *  this case.
+        */
+       if (!ops->datbuf)
+               ops->len = 0;
+
+       if (!ops->oobbuf)
+               ops->ooblen = 0;
+
+       if (offs < 0 || offs + ops->len >= mtd->size)
+               return -EINVAL;
+
+       if (ops->ooblen) {
+               u64 maxooblen;
+
+               if (ops->ooboffs >= mtd_oobavail(mtd, ops))
+                       return -EINVAL;
+
+               maxooblen = ((mtd_div_by_ws(mtd->size, mtd) -
+                             mtd_div_by_ws(offs, mtd)) *
+                            mtd_oobavail(mtd, ops)) - ops->ooboffs;
+               if (ops->ooblen > maxooblen)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 {
        int ret_code;
@@ -1100,6 +1140,10 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
        if (!mtd->_read_oob)
                return -EOPNOTSUPP;
 
+       ret_code = mtd_check_oob_ops(mtd, from, ops);
+       if (ret_code)
+               return ret_code;
+
        ledtrig_mtd_activity();
        /*
         * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
@@ -1119,11 +1163,18 @@ EXPORT_SYMBOL_GPL(mtd_read_oob);
 int mtd_write_oob(struct mtd_info *mtd, loff_t to,
                                struct mtd_oob_ops *ops)
 {
+       int ret;
+
        ops->retlen = ops->oobretlen = 0;
        if (!mtd->_write_oob)
                return -EOPNOTSUPP;
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
+
+       ret = mtd_check_oob_ops(mtd, to, ops);
+       if (ret)
+               return ret;
+
        ledtrig_mtd_activity();
        return mtd->_write_oob(mtd, to, ops);
 }
index a308e707392d595902b77a03e2078ffe8da97d9e..be088bccd593142bd063955e29bdd84a4998d087 100644 (file)
@@ -101,18 +101,6 @@ static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
        return part->parent->_unpoint(part->parent, from + part->offset, len);
 }
 
-static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
-                                           unsigned long len,
-                                           unsigned long offset,
-                                           unsigned long flags)
-{
-       struct mtd_part *part = mtd_to_part(mtd);
-
-       offset += part->offset;
-       return part->parent->_get_unmapped_area(part->parent, len, offset,
-                                               flags);
-}
-
 static int part_read_oob(struct mtd_info *mtd, loff_t from,
                struct mtd_oob_ops *ops)
 {
@@ -458,8 +446,6 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
                slave->mtd._unpoint = part_unpoint;
        }
 
-       if (parent->_get_unmapped_area)
-               slave->mtd._get_unmapped_area = part_get_unmapped_area;
        if (parent->_read_oob)
                slave->mtd._read_oob = part_read_oob;
        if (parent->_write_oob)
index 7d9080e33865a92df1de69a69a9c0f4c1edb18fc..f07492c6f4b2bd76227a7e4251560ca3a424ec47 100644 (file)
@@ -50,7 +50,7 @@
  * Number of free eraseblocks below which GC can also collect low frag
  * blocks.
  */
-#define LOW_FRAG_GC_TRESHOLD   5
+#define LOW_FRAG_GC_THRESHOLD  5
 
 /*
  * Wear level cost amortization. We want to do wear leveling on the background
@@ -805,7 +805,7 @@ static int __mtdswap_choose_gc_tree(struct mtdswap_dev *d)
 {
        int idx, stopat;
 
-       if (TREE_COUNT(d, CLEAN) < LOW_FRAG_GC_TRESHOLD)
+       if (TREE_COUNT(d, CLEAN) < LOW_FRAG_GC_THRESHOLD)
                stopat = MTDSWAP_LOWFRAG;
        else
                stopat = MTDSWAP_HIFRAG;
index 3f2036f31da47ae7209365c31aab0bb363b6940f..bb48aafed9a2d2fcead8fd44ae5c571d7c3bb02f 100644 (file)
@@ -317,8 +317,11 @@ config MTD_NAND_PXA3xx
        tristate "NAND support on PXA3xx and Armada 370/XP"
        depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU
        help
+
          This enables the driver for the NAND flash device found on
-         PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
+         PXA3xx processors (NFCv1) and also on 32-bit Armada
+         platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada
+         platforms (7K, 8K) (NFCv2).
 
 config MTD_NAND_SLC_LPC32XX
        tristate "NXP LPC32xx SLC Controller"
index 6e2db700d923ddd14bdd6b0ae9cc5b554cf0ef1e..118a1349aad3a47a78242f8561d88c9ee2f2bb1d 100644 (file)
@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI)          += sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504)         += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)                += brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)            += qcom_nandc.o
-obj-$(CONFIG_MTD_NAND_MTK)             += mtk_nand.o mtk_ecc.o
+obj-$(CONFIG_MTD_NAND_MTK)             += mtk_ecc.o mtk_nand.o
 
 nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_amd.o
index dcec9cf4983f812833bc9082eee7dc383c913eff..d60ada45c549450758a1079d097b81f56271580d 100644 (file)
@@ -41,7 +41,7 @@ static struct mtd_info *ams_delta_mtd = NULL;
  * Define partitions for flash devices
  */
 
-static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
        { .name         = "Kernel",
          .offset       = 0,
          .size         = 3 * SZ_1M + SZ_512K },
index f25eca79f4e56d096ed749918752e8aca26ee68d..90a71a56bc230f9cc3324d2351f9d6bfc9667254 100644 (file)
@@ -718,8 +718,7 @@ static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column)
                nc->op.addrs[nc->op.naddrs++] = page;
                nc->op.addrs[nc->op.naddrs++] = page >> 8;
 
-               if ((mtd->writesize > 512 && chip->chipsize > SZ_128M) ||
-                   (mtd->writesize <= 512 && chip->chipsize > SZ_32M))
+               if (chip->options & NAND_ROW_ADDR_3)
                        nc->op.addrs[nc->op.naddrs++] = page >> 16;
        }
 }
@@ -2530,6 +2529,9 @@ static __maybe_unused int atmel_nand_controller_resume(struct device *dev)
        struct atmel_nand_controller *nc = dev_get_drvdata(dev);
        struct atmel_nand *nand;
 
+       if (nc->pmecc)
+               atmel_pmecc_reset(nc->pmecc);
+
        list_for_each_entry(nand, &nc->chips, node) {
                int i;
 
@@ -2547,6 +2549,7 @@ static struct platform_driver atmel_nand_controller_driver = {
        .driver = {
                .name = "atmel-nand-controller",
                .of_match_table = of_match_ptr(atmel_nand_controller_of_ids),
+               .pm = &atmel_nand_controller_pm_ops,
        },
        .probe = atmel_nand_controller_probe,
        .remove = atmel_nand_controller_remove,
index 8268636675efc8b3d81959f0f1911a145c42fcc1..fcbe4fd6e684bcc45721d52b4845e4018cb8edeb 100644 (file)
@@ -765,6 +765,13 @@ void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
 }
 EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes);
 
+void atmel_pmecc_reset(struct atmel_pmecc *pmecc)
+{
+       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_reset);
+
 int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
 {
        struct atmel_pmecc *pmecc = user->pmecc;
@@ -797,10 +804,7 @@ EXPORT_SYMBOL_GPL(atmel_pmecc_enable);
 
 void atmel_pmecc_disable(struct atmel_pmecc_user *user)
 {
-       struct atmel_pmecc *pmecc = user->pmecc;
-
-       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
-       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       atmel_pmecc_reset(user->pmecc);
        mutex_unlock(&user->pmecc->lock);
 }
 EXPORT_SYMBOL_GPL(atmel_pmecc_disable);
@@ -855,10 +859,7 @@ static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
 
        /* Disable all interrupts before registering the PMECC handler. */
        writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
-
-       /* Reset the ECC engine */
-       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
-       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       atmel_pmecc_reset(pmecc);
 
        return pmecc;
 }
index a8ddbfca2ea50f5e7fe3dd80e4ab18c65588647b..817e0dd9fd15771231d9472764c1a1ae160c88c8 100644 (file)
@@ -61,6 +61,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
                        struct atmel_pmecc_user_req *req);
 void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
 
+void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
 int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
 void atmel_pmecc_disable(struct atmel_pmecc_user *user);
 int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user);
index 9d4a28fa6b73b2aaf17591ba57d5cf74b67d1aa7..8ab827edf94e2fbc97885032da26105eaeb2bdea 100644 (file)
@@ -331,8 +331,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
 
                        ctx->write_byte(mtd, (u8)(page_addr >> 8));
 
-                       /* One more address cycle for devices > 32MiB */
-                       if (this->chipsize > (32 << 20))
+                       if (this->options & NAND_ROW_ADDR_3)
                                ctx->write_byte(mtd,
                                                ((page_addr >> 16) & 0x0f));
                }
index 1fc435f994e1eca9738b6d28c1b5adb8deb367d5..b01c9804590e5d484675a71bc684e99b51929c41 100644 (file)
@@ -42,7 +42,7 @@ static void __iomem *cmx270_nand_io;
 /*
  * Define static partitions for flash device
  */
-static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
        [0] = {
                .name   = "cmx270-0",
                .offset = 0,
index 3087b0ba7b7f3d708f92cf58ea838bb7685d3edb..5124f8ae8c04032e0e301931554aea3c80c0aee2 100644 (file)
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
  */
-#include <linux/interrupt.h>
-#include <linux/delay.h>
+
+#include <linux/bitfield.h>
+#include <linux/completion.h>
 #include <linux/dma-mapping.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/mtd/mtd.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 #include "denali.h"
 
@@ -31,9 +29,9 @@ MODULE_LICENSE("GPL");
 
 #define DENALI_NAND_NAME    "denali-nand"
 
-/* Host Data/Command Interface */
-#define DENALI_HOST_ADDR       0x00
-#define DENALI_HOST_DATA       0x10
+/* for Indexed Addressing */
+#define DENALI_INDEXED_CTRL    0x00
+#define DENALI_INDEXED_DATA    0x10
 
 #define DENALI_MAP00           (0 << 26)       /* direct access to buffer */
 #define DENALI_MAP01           (1 << 26)       /* read/write pages in PIO */
@@ -61,31 +59,55 @@ MODULE_LICENSE("GPL");
  */
 #define DENALI_CLK_X_MULT      6
 
-/*
- * this macro allows us to convert from an MTD structure to our own
- * device context (denali) structure.
- */
 static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
 {
        return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
 }
 
-static void denali_host_write(struct denali_nand_info *denali,
-                             uint32_t addr, uint32_t data)
+/*
+ * Direct Addressing - the slave address forms the control information (command
+ * type, bank, block, and page address).  The slave data is the actual data to
+ * be transferred.  This mode requires 28 bits of address region allocated.
+ */
+static u32 denali_direct_read(struct denali_nand_info *denali, u32 addr)
+{
+       return ioread32(denali->host + addr);
+}
+
+static void denali_direct_write(struct denali_nand_info *denali, u32 addr,
+                               u32 data)
 {
-       iowrite32(addr, denali->host + DENALI_HOST_ADDR);
-       iowrite32(data, denali->host + DENALI_HOST_DATA);
+       iowrite32(data, denali->host + addr);
+}
+
+/*
+ * Indexed Addressing - address translation module intervenes in passing the
+ * control information.  This mode reduces the required address range.  The
+ * control information and transferred data are latched by the registers in
+ * the translation module.
+ */
+static u32 denali_indexed_read(struct denali_nand_info *denali, u32 addr)
+{
+       iowrite32(addr, denali->host + DENALI_INDEXED_CTRL);
+       return ioread32(denali->host + DENALI_INDEXED_DATA);
+}
+
+static void denali_indexed_write(struct denali_nand_info *denali, u32 addr,
+                                u32 data)
+{
+       iowrite32(addr, denali->host + DENALI_INDEXED_CTRL);
+       iowrite32(data, denali->host + DENALI_INDEXED_DATA);
 }
 
 /*
  * Use the configuration feature register to determine the maximum number of
  * banks that the hardware supports.
  */
-static void detect_max_banks(struct denali_nand_info *denali)
+static void denali_detect_max_banks(struct denali_nand_info *denali)
 {
        uint32_t features = ioread32(denali->reg + FEATURES);
 
-       denali->max_banks = 1 << (features & FEATURES__N_BANKS);
+       denali->max_banks = 1 << FIELD_GET(FEATURES__N_BANKS, features);
 
        /* the encoding changed from rev 5.0 to 5.1 */
        if (denali->revision < 0x0501)
@@ -189,7 +211,7 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali,
                                                msecs_to_jiffies(1000));
        if (!time_left) {
                dev_err(denali->dev, "timeout while waiting for irq 0x%x\n",
-                       denali->irq_mask);
+                       irq_mask);
                return 0;
        }
 
@@ -208,73 +230,47 @@ static uint32_t denali_check_irq(struct denali_nand_info *denali)
        return irq_status;
 }
 
-/*
- * This helper function setups the registers for ECC and whether or not
- * the spare area will be transferred.
- */
-static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en,
-                               bool transfer_spare)
-{
-       int ecc_en_flag, transfer_spare_flag;
-
-       /* set ECC, transfer spare bits if needed */
-       ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0;
-       transfer_spare_flag = transfer_spare ? TRANSFER_SPARE_REG__FLAG : 0;
-
-       /* Enable spare area/ECC per user's request. */
-       iowrite32(ecc_en_flag, denali->reg + ECC_ENABLE);
-       iowrite32(transfer_spare_flag, denali->reg + TRANSFER_SPARE_REG);
-}
-
 static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
+       u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
        int i;
 
-       iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali),
-                 denali->host + DENALI_HOST_ADDR);
-
        for (i = 0; i < len; i++)
-               buf[i] = ioread32(denali->host + DENALI_HOST_DATA);
+               buf[i] = denali->host_read(denali, addr);
 }
 
 static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
+       u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
        int i;
 
-       iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali),
-                 denali->host + DENALI_HOST_ADDR);
-
        for (i = 0; i < len; i++)
-               iowrite32(buf[i], denali->host + DENALI_HOST_DATA);
+               denali->host_write(denali, addr, buf[i]);
 }
 
 static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
+       u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
        uint16_t *buf16 = (uint16_t *)buf;
        int i;
 
-       iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali),
-                 denali->host + DENALI_HOST_ADDR);
-
        for (i = 0; i < len / 2; i++)
-               buf16[i] = ioread32(denali->host + DENALI_HOST_DATA);
+               buf16[i] = denali->host_read(denali, addr);
 }
 
 static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf,
                               int len)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
+       u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali);
        const uint16_t *buf16 = (const uint16_t *)buf;
        int i;
 
-       iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali),
-                 denali->host + DENALI_HOST_ADDR);
-
        for (i = 0; i < len / 2; i++)
-               iowrite32(buf16[i], denali->host + DENALI_HOST_DATA);
+               denali->host_write(denali, addr, buf16[i]);
 }
 
 static uint8_t denali_read_byte(struct mtd_info *mtd)
@@ -319,7 +315,7 @@ static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
        if (ctrl & NAND_CTRL_CHANGE)
                denali_reset_irq(denali);
 
-       denali_host_write(denali, DENALI_BANK(denali) | type, dat);
+       denali->host_write(denali, DENALI_BANK(denali) | type, dat);
 }
 
 static int denali_dev_ready(struct mtd_info *mtd)
@@ -389,7 +385,7 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd,
                return 0;
        }
 
-       max_bitflips = ecc_cor & ECC_COR_INFO__MAX_ERRORS;
+       max_bitflips = FIELD_GET(ECC_COR_INFO__MAX_ERRORS, ecc_cor);
 
        /*
         * The register holds the maximum of per-sector corrected bitflips.
@@ -402,13 +398,6 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd,
        return max_bitflips;
 }
 
-#define ECC_SECTOR(x)  (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12)
-#define ECC_BYTE(x)    (((x) & ECC_ERROR_ADDRESS__OFFSET))
-#define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK)
-#define ECC_ERROR_UNCORRECTABLE(x) ((x) & ERR_CORRECTION_INFO__ERROR_TYPE)
-#define ECC_ERR_DEVICE(x)      (((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8)
-#define ECC_LAST_ERR(x)                ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)
-
 static int denali_sw_ecc_fixup(struct mtd_info *mtd,
                               struct denali_nand_info *denali,
                               unsigned long *uncor_ecc_flags, uint8_t *buf)
@@ -426,18 +415,20 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd,
 
        do {
                err_addr = ioread32(denali->reg + ECC_ERROR_ADDRESS);
-               err_sector = ECC_SECTOR(err_addr);
-               err_byte = ECC_BYTE(err_addr);
+               err_sector = FIELD_GET(ECC_ERROR_ADDRESS__SECTOR, err_addr);
+               err_byte = FIELD_GET(ECC_ERROR_ADDRESS__OFFSET, err_addr);
 
                err_cor_info = ioread32(denali->reg + ERR_CORRECTION_INFO);
-               err_cor_value = ECC_CORRECTION_VALUE(err_cor_info);
-               err_device = ECC_ERR_DEVICE(err_cor_info);
+               err_cor_value = FIELD_GET(ERR_CORRECTION_INFO__BYTE,
+                                         err_cor_info);
+               err_device = FIELD_GET(ERR_CORRECTION_INFO__DEVICE,
+                                      err_cor_info);
 
                /* reset the bitflip counter when crossing ECC sector */
                if (err_sector != prev_sector)
                        bitflips = 0;
 
-               if (ECC_ERROR_UNCORRECTABLE(err_cor_info)) {
+               if (err_cor_info & ERR_CORRECTION_INFO__UNCOR) {
                        /*
                         * Check later if this is a real ECC error, or
                         * an erased sector.
@@ -467,12 +458,11 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd,
                }
 
                prev_sector = err_sector;
-       } while (!ECC_LAST_ERR(err_cor_info));
+       } while (!(err_cor_info & ERR_CORRECTION_INFO__LAST_ERR));
 
        /*
-        * Once handle all ecc errors, controller will trigger a
-        * ECC_TRANSACTION_DONE interrupt, so here just wait for
-        * a while for this interrupt
+        * Once handle all ECC errors, controller will trigger an
+        * ECC_TRANSACTION_DONE interrupt.
         */
        irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE);
        if (!(irq_status & INTR__ECC_TRANSACTION_DONE))
@@ -481,13 +471,6 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd,
        return max_bitflips;
 }
 
-/* programs the controller to either enable/disable DMA transfers */
-static void denali_enable_dma(struct denali_nand_info *denali, bool en)
-{
-       iowrite32(en ? DMA_ENABLE__FLAG : 0, denali->reg + DMA_ENABLE);
-       ioread32(denali->reg + DMA_ENABLE);
-}
-
 static void denali_setup_dma64(struct denali_nand_info *denali,
                               dma_addr_t dma_addr, int page, int write)
 {
@@ -502,14 +485,14 @@ static void denali_setup_dma64(struct denali_nand_info *denali,
         * 1. setup transfer type, interrupt when complete,
         *    burst len = 64 bytes, the number of pages
         */
-       denali_host_write(denali, mode,
-                         0x01002000 | (64 << 16) | (write << 8) | page_count);
+       denali->host_write(denali, mode,
+                          0x01002000 | (64 << 16) | (write << 8) | page_count);
 
        /* 2. set memory low address */
-       denali_host_write(denali, mode, dma_addr);
+       denali->host_write(denali, mode, lower_32_bits(dma_addr));
 
        /* 3. set memory high address */
-       denali_host_write(denali, mode, (uint64_t)dma_addr >> 32);
+       denali->host_write(denali, mode, upper_32_bits(dma_addr));
 }
 
 static void denali_setup_dma32(struct denali_nand_info *denali,
@@ -523,32 +506,23 @@ static void denali_setup_dma32(struct denali_nand_info *denali,
        /* DMA is a four step process */
 
        /* 1. setup transfer type and # of pages */
-       denali_host_write(denali, mode | page,
-                         0x2000 | (write << 8) | page_count);
+       denali->host_write(denali, mode | page,
+                          0x2000 | (write << 8) | page_count);
 
        /* 2. set memory high address bits 23:8 */
-       denali_host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200);
+       denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200);
 
        /* 3. set memory low address bits 23:8 */
-       denali_host_write(denali, mode | ((dma_addr & 0xffff) << 8), 0x2300);
+       denali->host_write(denali, mode | ((dma_addr & 0xffff) << 8), 0x2300);
 
        /* 4. interrupt when complete, burst len = 64 bytes */
-       denali_host_write(denali, mode | 0x14000, 0x2400);
-}
-
-static void denali_setup_dma(struct denali_nand_info *denali,
-                            dma_addr_t dma_addr, int page, int write)
-{
-       if (denali->caps & DENALI_CAP_DMA_64BIT)
-               denali_setup_dma64(denali, dma_addr, page, write);
-       else
-               denali_setup_dma32(denali, dma_addr, page, write);
+       denali->host_write(denali, mode | 0x14000, 0x2400);
 }
 
 static int denali_pio_read(struct denali_nand_info *denali, void *buf,
                           size_t size, int page, int raw)
 {
-       uint32_t addr = DENALI_BANK(denali) | page;
+       u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page;
        uint32_t *buf32 = (uint32_t *)buf;
        uint32_t irq_status, ecc_err_mask;
        int i;
@@ -560,9 +534,8 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf,
 
        denali_reset_irq(denali);
 
-       iowrite32(DENALI_MAP01 | addr, denali->host + DENALI_HOST_ADDR);
        for (i = 0; i < size / 4; i++)
-               *buf32++ = ioread32(denali->host + DENALI_HOST_DATA);
+               *buf32++ = denali->host_read(denali, addr);
 
        irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC);
        if (!(irq_status & INTR__PAGE_XFER_INC))
@@ -577,16 +550,15 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf,
 static int denali_pio_write(struct denali_nand_info *denali,
                            const void *buf, size_t size, int page, int raw)
 {
-       uint32_t addr = DENALI_BANK(denali) | page;
+       u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page;
        const uint32_t *buf32 = (uint32_t *)buf;
        uint32_t irq_status;
        int i;
 
        denali_reset_irq(denali);
 
-       iowrite32(DENALI_MAP01 | addr, denali->host + DENALI_HOST_ADDR);
        for (i = 0; i < size / 4; i++)
-               iowrite32(*buf32++, denali->host + DENALI_HOST_DATA);
+               denali->host_write(denali, addr, *buf32++);
 
        irq_status = denali_wait_for_irq(denali,
                                INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL);
@@ -635,19 +607,19 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf,
                ecc_err_mask = INTR__ECC_ERR;
        }
 
-       denali_enable_dma(denali, true);
+       iowrite32(DMA_ENABLE__FLAG, denali->reg + DMA_ENABLE);
 
        denali_reset_irq(denali);
-       denali_setup_dma(denali, dma_addr, page, write);
+       denali->setup_dma(denali, dma_addr, page, write);
 
-       /* wait for operation to complete */
        irq_status = denali_wait_for_irq(denali, irq_mask);
        if (!(irq_status & INTR__DMA_CMD_COMP))
                ret = -EIO;
        else if (irq_status & ecc_err_mask)
                ret = -EBADMSG;
 
-       denali_enable_dma(denali, false);
+       iowrite32(0, denali->reg + DMA_ENABLE);
+
        dma_unmap_single(denali->dev, dma_addr, size, dir);
 
        if (irq_status & INTR__ERASED_PAGE)
@@ -659,7 +631,9 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf,
 static int denali_data_xfer(struct denali_nand_info *denali, void *buf,
                            size_t size, int page, int raw, int write)
 {
-       setup_ecc_for_xfer(denali, !raw, raw);
+       iowrite32(raw ? 0 : ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE);
+       iowrite32(raw ? TRANSFER_SPARE_REG__FLAG : 0,
+                 denali->reg + TRANSFER_SPARE_REG);
 
        if (denali->dma_avail)
                return denali_dma_xfer(denali, buf, size, page, raw, write);
@@ -970,8 +944,8 @@ static int denali_erase(struct mtd_info *mtd, int page)
 
        denali_reset_irq(denali);
 
-       denali_host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page,
-                         DENALI_ERASE);
+       denali->host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page,
+                          DENALI_ERASE);
 
        /* wait for erase to complete or failure to occur */
        irq_status = denali_wait_for_irq(denali,
@@ -1009,7 +983,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + ACC_CLKS);
        tmp &= ~ACC_CLKS__VALUE;
-       tmp |= acc_clks;
+       tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks);
        iowrite32(tmp, denali->reg + ACC_CLKS);
 
        /* tRWH -> RE_2_WE */
@@ -1018,7 +992,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + RE_2_WE);
        tmp &= ~RE_2_WE__VALUE;
-       tmp |= re_2_we;
+       tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we);
        iowrite32(tmp, denali->reg + RE_2_WE);
 
        /* tRHZ -> RE_2_RE */
@@ -1027,16 +1001,22 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + RE_2_RE);
        tmp &= ~RE_2_RE__VALUE;
-       tmp |= re_2_re;
+       tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re);
        iowrite32(tmp, denali->reg + RE_2_RE);
 
-       /* tWHR -> WE_2_RE */
-       we_2_re = DIV_ROUND_UP(timings->tWHR_min, t_clk);
+       /*
+        * tCCS, tWHR -> WE_2_RE
+        *
+        * With WE_2_RE properly set, the Denali controller automatically takes
+        * care of the delay; the driver need not set NAND_WAIT_TCCS.
+        */
+       we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min),
+                              t_clk);
        we_2_re = min_t(int, we_2_re, TWHR2_AND_WE_2_RE__WE_2_RE);
 
        tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE);
        tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE;
-       tmp |= we_2_re;
+       tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re);
        iowrite32(tmp, denali->reg + TWHR2_AND_WE_2_RE);
 
        /* tADL -> ADDR_2_DATA */
@@ -1050,8 +1030,8 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
        addr_2_data = min_t(int, addr_2_data, addr_2_data_mask);
 
        tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA);
-       tmp &= ~addr_2_data_mask;
-       tmp |= addr_2_data;
+       tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA;
+       tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data);
        iowrite32(tmp, denali->reg + TCWAW_AND_ADDR_2_DATA);
 
        /* tREH, tWH -> RDWR_EN_HI_CNT */
@@ -1061,7 +1041,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + RDWR_EN_HI_CNT);
        tmp &= ~RDWR_EN_HI_CNT__VALUE;
-       tmp |= rdwr_en_hi;
+       tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi);
        iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT);
 
        /* tRP, tWP -> RDWR_EN_LO_CNT */
@@ -1075,7 +1055,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + RDWR_EN_LO_CNT);
        tmp &= ~RDWR_EN_LO_CNT__VALUE;
-       tmp |= rdwr_en_lo;
+       tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo);
        iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT);
 
        /* tCS, tCEA -> CS_SETUP_CNT */
@@ -1086,7 +1066,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
 
        tmp = ioread32(denali->reg + CS_SETUP_CNT);
        tmp &= ~CS_SETUP_CNT__VALUE;
-       tmp |= cs_setup;
+       tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup);
        iowrite32(tmp, denali->reg + CS_SETUP_CNT);
 
        return 0;
@@ -1131,15 +1111,11 @@ static void denali_hw_init(struct denali_nand_info *denali)
         * if this value is 0, just let it be.
         */
        denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES);
-       detect_max_banks(denali);
+       denali_detect_max_banks(denali);
        iowrite32(0x0F, denali->reg + RB_PIN_ENABLED);
        iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE);
 
        iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER);
-
-       /* Should set value for these registers when init */
-       iowrite32(0, denali->reg + TWO_ROW_ADDR_CYCLES);
-       iowrite32(1, denali->reg + ECC_ENABLE);
 }
 
 int denali_calc_ecc_bytes(int step_size, int strength)
@@ -1211,22 +1187,6 @@ static const struct mtd_ooblayout_ops denali_ooblayout_ops = {
        .free = denali_ooblayout_free,
 };
 
-/* initialize driver data structures */
-static void denali_drv_init(struct denali_nand_info *denali)
-{
-       /*
-        * the completion object will be used to notify
-        * the callee that the interrupt is done
-        */
-       init_completion(&denali->complete);
-
-       /*
-        * the spinlock will be used to synchronize the ISR with any
-        * element that might be access shared data (interrupt status)
-        */
-       spin_lock_init(&denali->irq_lock);
-}
-
 static int denali_multidev_fixup(struct denali_nand_info *denali)
 {
        struct nand_chip *chip = &denali->nand;
@@ -1282,15 +1242,17 @@ int denali_init(struct denali_nand_info *denali)
 {
        struct nand_chip *chip = &denali->nand;
        struct mtd_info *mtd = nand_to_mtd(chip);
+       u32 features = ioread32(denali->reg + FEATURES);
        int ret;
 
        mtd->dev.parent = denali->dev;
        denali_hw_init(denali);
-       denali_drv_init(denali);
+
+       init_completion(&denali->complete);
+       spin_lock_init(&denali->irq_lock);
 
        denali_clear_irq_all(denali);
 
-       /* Request IRQ after all the hardware initialization is finished */
        ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
                               IRQF_SHARED, DENALI_NAND_NAME, denali);
        if (ret) {
@@ -1308,7 +1270,6 @@ int denali_init(struct denali_nand_info *denali)
        if (!mtd->name)
                mtd->name = "denali-nand";
 
-       /* register the driver with the NAND core subsystem */
        chip->select_chip = denali_select_chip;
        chip->read_byte = denali_read_byte;
        chip->write_byte = denali_write_byte;
@@ -1317,15 +1278,18 @@ int denali_init(struct denali_nand_info *denali)
        chip->dev_ready = denali_dev_ready;
        chip->waitfunc = denali_waitfunc;
 
+       if (features & FEATURES__INDEX_ADDR) {
+               denali->host_read = denali_indexed_read;
+               denali->host_write = denali_indexed_write;
+       } else {
+               denali->host_read = denali_direct_read;
+               denali->host_write = denali_direct_write;
+       }
+
        /* clk rate info is needed for setup_data_interface */
        if (denali->clk_x_rate)
                chip->setup_data_interface = denali_setup_data_interface;
 
-       /*
-        * scan for NAND devices attached to the controller
-        * this is the first stage in a two step process to register
-        * with the nand subsystem
-        */
        ret = nand_scan_ident(mtd, denali->max_banks, NULL);
        if (ret)
                goto disable_irq;
@@ -1347,20 +1311,15 @@ int denali_init(struct denali_nand_info *denali)
        if (denali->dma_avail) {
                chip->options |= NAND_USE_BOUNCE_BUFFER;
                chip->buf_align = 16;
+               if (denali->caps & DENALI_CAP_DMA_64BIT)
+                       denali->setup_dma = denali_setup_dma64;
+               else
+                       denali->setup_dma = denali_setup_dma32;
        }
 
-       /*
-        * second stage of the NAND scan
-        * this stage requires information regarding ECC and
-        * bad block management.
-        */
-
        chip->bbt_options |= NAND_BBT_USE_FLASH;
        chip->bbt_options |= NAND_BBT_NO_OOB;
-
        chip->ecc.mode = NAND_ECC_HW_SYNDROME;
-
-       /* no subpage writes on denali */
        chip->options |= NAND_NO_SUBPAGE_WRITE;
 
        ret = denali_ecc_setup(mtd, chip, denali);
@@ -1373,12 +1332,15 @@ int denali_init(struct denali_nand_info *denali)
                "chosen ECC settings: step=%d, strength=%d, bytes=%d\n",
                chip->ecc.size, chip->ecc.strength, chip->ecc.bytes);
 
-       iowrite32(MAKE_ECC_CORRECTION(chip->ecc.strength, 1),
+       iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) |
+                 FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength),
                  denali->reg + ECC_CORRECTION);
        iowrite32(mtd->erasesize / mtd->writesize,
                  denali->reg + PAGES_PER_BLOCK);
        iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0,
                  denali->reg + DEVICE_WIDTH);
+       iowrite32(chip->options & NAND_ROW_ADDR_3 ? 0 : TWO_ROW_ADDR_CYCLES__FLAG,
+                 denali->reg + TWO_ROW_ADDR_CYCLES);
        iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE);
        iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE);
 
@@ -1441,7 +1403,6 @@ disable_irq:
 }
 EXPORT_SYMBOL(denali_init);
 
-/* driver exit point */
 void denali_remove(struct denali_nand_info *denali)
 {
        struct mtd_info *mtd = nand_to_mtd(&denali->nand);
index 9239e6793e6eade20a38287cfb26c399f09ac2ac..2911066dacace199615c9e673d3dfcab830bfe1a 100644 (file)
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
  */
 
 #ifndef __DENALI_H__
 #define __DENALI_H__
 
 #include <linux/bitops.h>
+#include <linux/completion.h>
 #include <linux/mtd/rawnand.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
 
 #define DEVICE_RESET                           0x0
 #define     DEVICE_RESET__BANK(bank)                   BIT(bank)
 #define ECC_CORRECTION                         0x1b0
 #define     ECC_CORRECTION__VALUE                      GENMASK(4, 0)
 #define     ECC_CORRECTION__ERASE_THRESHOLD            GENMASK(31, 16)
-#define     MAKE_ECC_CORRECTION(val, thresh)           \
-                       (((val) & (ECC_CORRECTION__VALUE)) | \
-                       (((thresh) << 16) & (ECC_CORRECTION__ERASE_THRESHOLD)))
 
 #define READ_MODE                              0x1c0
 #define     READ_MODE__VALUE                           GENMASK(3, 0)
 
 #define ECC_ERROR_ADDRESS                      0x630
 #define     ECC_ERROR_ADDRESS__OFFSET                  GENMASK(11, 0)
-#define     ECC_ERROR_ADDRESS__SECTOR_NR               GENMASK(15, 12)
+#define     ECC_ERROR_ADDRESS__SECTOR                  GENMASK(15, 12)
 
 #define ERR_CORRECTION_INFO                    0x640
-#define     ERR_CORRECTION_INFO__BYTEMASK              GENMASK(7, 0)
-#define     ERR_CORRECTION_INFO__DEVICE_NR             GENMASK(11, 8)
-#define     ERR_CORRECTION_INFO__ERROR_TYPE            BIT(14)
-#define     ERR_CORRECTION_INFO__LAST_ERR_INFO         BIT(15)
+#define     ERR_CORRECTION_INFO__BYTE                  GENMASK(7, 0)
+#define     ERR_CORRECTION_INFO__DEVICE                        GENMASK(11, 8)
+#define     ERR_CORRECTION_INFO__UNCOR                 BIT(14)
+#define     ERR_CORRECTION_INFO__LAST_ERR              BIT(15)
 
 #define ECC_COR_INFO(bank)                     (0x650 + (bank) / 2 * 0x10)
 #define     ECC_COR_INFO__SHIFT(bank)                  ((bank) % 2 * 8)
@@ -310,23 +305,24 @@ struct denali_nand_info {
        struct device *dev;
        void __iomem *reg;              /* Register Interface */
        void __iomem *host;             /* Host Data/Command Interface */
-
-       /* elements used by ISR */
        struct completion complete;
-       spinlock_t irq_lock;
-       uint32_t irq_mask;
-       uint32_t irq_status;
+       spinlock_t irq_lock;            /* protect irq_mask and irq_status */
+       u32 irq_mask;                   /* interrupts we are waiting for */
+       u32 irq_status;                 /* interrupts that have happened */
        int irq;
-
-       void *buf;
+       void *buf;                      /* for syndrome layout conversion */
        dma_addr_t dma_addr;
-       int dma_avail;
+       int dma_avail;                  /* can support DMA? */
        int devs_per_cs;                /* devices connected in parallel */
-       int oob_skip_bytes;
+       int oob_skip_bytes;             /* number of bytes reserved for BBM */
        int max_banks;
-       unsigned int revision;
-       unsigned int caps;
+       unsigned int revision;          /* IP revision */
+       unsigned int caps;              /* IP capability (or quirk) */
        const struct nand_ecc_caps *ecc_caps;
+       u32 (*host_read)(struct denali_nand_info *denali, u32 addr);
+       void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data);
+       void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr,
+                         int page, int write);
 };
 
 #define DENALI_CAP_HW_ECC_FIXUP                        BIT(0)
index 56e2e177644d6c3d9b0301b50ed780c51509a9bb..cfd33e6ca77f903a6afc636e73f31ffb40d0d0bd 100644 (file)
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  */
+
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/platform_device.h>
 
 #include "denali.h"
 
@@ -155,7 +156,6 @@ static struct platform_driver denali_dt_driver = {
                .of_match_table = denali_nand_dt_ids,
        },
 };
-
 module_platform_driver(denali_dt_driver);
 
 MODULE_LICENSE("GPL");
index 81370c79aa48aa4fe6ef3d4d65bb7dd3c2a91db7..57fb7ae314126ca567fe4ddea476c885c17e5105 100644 (file)
@@ -11,6 +11,9 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  */
+
+#include <linux/errno.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -106,7 +109,6 @@ failed_remap_reg:
        return ret;
 }
 
-/* driver exit point */
 static void denali_pci_remove(struct pci_dev *dev)
 {
        struct denali_nand_info *denali = pci_get_drvdata(dev);
@@ -122,5 +124,4 @@ static struct pci_driver denali_pci_driver = {
        .probe = denali_pci_probe,
        .remove = denali_pci_remove,
 };
-
 module_pci_driver(denali_pci_driver);
index c3aa53caab5cfe539def22e4dc3302afd6a0b67f..72671dc52e2e705ed8d7ee002ce3dba91124995f 100644 (file)
@@ -705,8 +705,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
                if (page_addr != -1) {
                        WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress);
                        WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
-                       /* One more address cycle for higher density devices */
-                       if (this->chipsize & 0x0c000000) {
+                       if (this->options & NAND_ROW_ADDR_3) {
                                WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
                                printk("high density\n");
                        }
index fd3648952b5a70281ce9e7ac596facdfe4ddfd04..484f7fbc3f7d2d11cd66fc3416e64ab38d47f852 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand-gpio.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_gpio.h>
 
 struct gpiomtd {
        void __iomem            *io_sync;
        struct nand_chip        nand_chip;
        struct gpio_nand_platdata plat;
+       struct gpio_desc *nce; /* Optional chip enable */
+       struct gpio_desc *cle;
+       struct gpio_desc *ale;
+       struct gpio_desc *rdy;
+       struct gpio_desc *nwp; /* Optional write protection */
 };
 
 static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
@@ -78,11 +82,10 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
        gpio_nand_dosync(gpiomtd);
 
        if (ctrl & NAND_CTRL_CHANGE) {
-               if (gpio_is_valid(gpiomtd->plat.gpio_nce))
-                       gpio_set_value(gpiomtd->plat.gpio_nce,
-                                      !(ctrl & NAND_NCE));
-               gpio_set_value(gpiomtd->plat.gpio_cle, !!(ctrl & NAND_CLE));
-               gpio_set_value(gpiomtd->plat.gpio_ale, !!(ctrl & NAND_ALE));
+               if (gpiomtd->nce)
+                       gpiod_set_value(gpiomtd->nce, !(ctrl & NAND_NCE));
+               gpiod_set_value(gpiomtd->cle, !!(ctrl & NAND_CLE));
+               gpiod_set_value(gpiomtd->ale, !!(ctrl & NAND_ALE));
                gpio_nand_dosync(gpiomtd);
        }
        if (cmd == NAND_CMD_NONE)
@@ -96,7 +99,7 @@ static int gpio_nand_devready(struct mtd_info *mtd)
 {
        struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
 
-       return gpio_get_value(gpiomtd->plat.gpio_rdy);
+       return gpiod_get_value(gpiomtd->rdy);
 }
 
 #ifdef CONFIG_OF
@@ -123,12 +126,6 @@ static int gpio_nand_get_config_of(const struct device *dev,
                }
        }
 
-       plat->gpio_rdy = of_get_gpio(dev->of_node, 0);
-       plat->gpio_nce = of_get_gpio(dev->of_node, 1);
-       plat->gpio_ale = of_get_gpio(dev->of_node, 2);
-       plat->gpio_cle = of_get_gpio(dev->of_node, 3);
-       plat->gpio_nwp = of_get_gpio(dev->of_node, 4);
-
        if (!of_property_read_u32(dev->of_node, "chip-delay", &val))
                plat->chip_delay = val;
 
@@ -201,10 +198,11 @@ static int gpio_nand_remove(struct platform_device *pdev)
 
        nand_release(nand_to_mtd(&gpiomtd->nand_chip));
 
-       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
-               gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
-       if (gpio_is_valid(gpiomtd->plat.gpio_nce))
-               gpio_set_value(gpiomtd->plat.gpio_nce, 1);
+       /* Enable write protection and disable the chip */
+       if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
+               gpiod_set_value(gpiomtd->nwp, 0);
+       if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
+               gpiod_set_value(gpiomtd->nce, 0);
 
        return 0;
 }
@@ -215,66 +213,66 @@ static int gpio_nand_probe(struct platform_device *pdev)
        struct nand_chip *chip;
        struct mtd_info *mtd;
        struct resource *res;
+       struct device *dev = &pdev->dev;
        int ret = 0;
 
-       if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev))
+       if (!dev->of_node && !dev_get_platdata(dev))
                return -EINVAL;
 
-       gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL);
+       gpiomtd = devm_kzalloc(dev, sizeof(*gpiomtd), GFP_KERNEL);
        if (!gpiomtd)
                return -ENOMEM;
 
        chip = &gpiomtd->nand_chip;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
+       chip->IO_ADDR_R = devm_ioremap_resource(dev, res);
        if (IS_ERR(chip->IO_ADDR_R))
                return PTR_ERR(chip->IO_ADDR_R);
 
        res = gpio_nand_get_io_sync(pdev);
        if (res) {
-               gpiomtd->io_sync = devm_ioremap_resource(&pdev->dev, res);
+               gpiomtd->io_sync = devm_ioremap_resource(dev, res);
                if (IS_ERR(gpiomtd->io_sync))
                        return PTR_ERR(gpiomtd->io_sync);
        }
 
-       ret = gpio_nand_get_config(&pdev->dev, &gpiomtd->plat);
+       ret = gpio_nand_get_config(dev, &gpiomtd->plat);
        if (ret)
                return ret;
 
-       if (gpio_is_valid(gpiomtd->plat.gpio_nce)) {
-               ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce,
-                                       "NAND NCE");
-               if (ret)
-                       return ret;
-               gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+       /* Just enable the chip */
+       gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH);
+       if (IS_ERR(gpiomtd->nce))
+               return PTR_ERR(gpiomtd->nce);
+
+       /* We disable write protection once we know probe() will succeed */
+       gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiomtd->nwp)) {
+               ret = PTR_ERR(gpiomtd->nwp);
+               goto out_ce;
        }
 
-       if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
-               ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp,
-                                       "NAND NWP");
-               if (ret)
-                       return ret;
+       gpiomtd->nwp = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiomtd->nwp)) {
+               ret = PTR_ERR(gpiomtd->nwp);
+               goto out_ce;
        }
 
-       ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_ale, "NAND ALE");
-       if (ret)
-               return ret;
-       gpio_direction_output(gpiomtd->plat.gpio_ale, 0);
+       gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiomtd->cle)) {
+               ret = PTR_ERR(gpiomtd->cle);
+               goto out_ce;
+       }
 
-       ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_cle, "NAND CLE");
-       if (ret)
-               return ret;
-       gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
-
-       if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) {
-               ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_rdy,
-                                       "NAND RDY");
-               if (ret)
-                       return ret;
-               gpio_direction_input(gpiomtd->plat.gpio_rdy);
-               chip->dev_ready = gpio_nand_devready;
+       gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN);
+       if (IS_ERR(gpiomtd->rdy)) {
+               ret = PTR_ERR(gpiomtd->rdy);
+               goto out_ce;
        }
+       /* Using RDY pin */
+       if (gpiomtd->rdy)
+               chip->dev_ready = gpio_nand_devready;
 
        nand_set_flash_node(chip, pdev->dev.of_node);
        chip->IO_ADDR_W         = chip->IO_ADDR_R;
@@ -285,12 +283,13 @@ static int gpio_nand_probe(struct platform_device *pdev)
        chip->cmd_ctrl          = gpio_nand_cmd_ctrl;
 
        mtd                     = nand_to_mtd(chip);
-       mtd->dev.parent         = &pdev->dev;
+       mtd->dev.parent         = dev;
 
        platform_set_drvdata(pdev, gpiomtd);
 
-       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
-               gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
+       /* Disable write protection, if wired up */
+       if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
+               gpiod_direction_output(gpiomtd->nwp, 1);
 
        ret = nand_scan(mtd, 1);
        if (ret)
@@ -305,8 +304,11 @@ static int gpio_nand_probe(struct platform_device *pdev)
                return 0;
 
 err_wp:
-       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
-               gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
+       if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
+               gpiod_set_value(gpiomtd->nwp, 0);
+out_ce:
+       if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
+               gpiod_set_value(gpiomtd->nce, 0);
 
        return ret;
 }
index d9ee1a7e695636b21f13236002903ae7dfe0249a..0897261c3e1702fe69239eb3ef3cf7bc1bc9e1e6 100644 (file)
@@ -432,8 +432,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
                host->addr_value[0] |= (page_addr & 0xffff)
                        << (host->addr_cycle * 8);
                host->addr_cycle    += 2;
-               /* One more address cycle for devices > 128MiB */
-               if (chip->chipsize > (128 << 20)) {
+               if (chip->options & NAND_ROW_ADDR_3) {
                        host->addr_cycle += 1;
                        if (host->command == NAND_CMD_ERASE1)
                                host->addr_value[0] |= ((page_addr >> 16) & 0xff) << 16;
index 7f3b065b6b8fe7bfcc5e5c20a55262cb8d4a95c9..c51d214d169ea436273435f99965031e3ad70348 100644 (file)
@@ -115,6 +115,11 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id)
                op = ECC_DECODE;
                dec = readw(ecc->regs + ECC_DECDONE);
                if (dec & ecc->sectors) {
+                       /*
+                        * Clear decode IRQ status once again to ensure that
+                        * there will be no extra IRQ.
+                        */
+                       readw(ecc->regs + ECC_DECIRQ_STA);
                        ecc->sectors = 0;
                        complete(&ecc->done);
                } else {
@@ -130,8 +135,6 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id)
                }
        }
 
-       writel(0, ecc->regs + ECC_IRQ_REG(op));
-
        return IRQ_HANDLED;
 }
 
@@ -307,6 +310,12 @@ void mtk_ecc_disable(struct mtk_ecc *ecc)
 
        /* disable it */
        mtk_ecc_wait_idle(ecc, op);
+       if (op == ECC_DECODE)
+               /*
+                * Clear decode IRQ status in case there is a timeout to wait
+                * decode IRQ.
+                */
+               readw(ecc->regs + ECC_DECIRQ_STA);
        writew(0, ecc->regs + ECC_IRQ_REG(op));
        writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op));
 
index 53e5e0337c3e206dc6f791170360b44333504ac5..f3be0b2a88692b96589023b825fe6a1a1b9b566e 100644 (file)
@@ -415,7 +415,7 @@ static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
  * waits for completion. */
 static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
-       pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+       dev_dbg(host->dev, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
        writew(cmd, NFC_V1_V2_FLASH_CMD);
        writew(NFC_CMD, NFC_V1_V2_CONFIG2);
@@ -431,7 +431,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
                        udelay(1);
                }
                if (max_retries < 0)
-                       pr_debug("%s: RESET failed\n", __func__);
+                       dev_dbg(host->dev, "%s: RESET failed\n", __func__);
        } else {
                /* Wait for operation to complete */
                wait_op_done(host, useirq);
@@ -454,7 +454,7 @@ static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
  * a NAND command. */
 static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
 {
-       pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
+       dev_dbg(host->dev, "send_addr(host, 0x%x %d)\n", addr, islast);
 
        writew(addr, NFC_V1_V2_FLASH_ADDR);
        writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
@@ -607,7 +607,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
        uint16_t ecc_status = get_ecc_status_v1(host);
 
        if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
-               pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+               dev_dbg(host->dev, "HWECC uncorrectable 2-bit ECC error\n");
                return -EBADMSG;
        }
 
@@ -634,7 +634,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
        do {
                err = ecc_stat & ecc_bit_mask;
                if (err > err_limit) {
-                       printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+                       dev_dbg(host->dev, "UnCorrectable RS-ECC Error\n");
                        return -EBADMSG;
                } else {
                        ret += err;
@@ -642,7 +642,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
                ecc_stat >>= 4;
        } while (--no_subpages);
 
-       pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
+       dev_dbg(host->dev, "%d Symbol Correctable RS-ECC Error\n", ret);
 
        return ret;
 }
@@ -673,7 +673,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
                host->buf_start++;
        }
 
-       pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
+       dev_dbg(host->dev, "%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
        return ret;
 }
 
@@ -859,8 +859,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
                                host->devtype_data->send_addr(host,
                                                (page_addr >> 8) & 0xff, true);
                } else {
-                       /* One more address cycle for higher density devices */
-                       if (mtd->size >= 0x4000000) {
+                       if (nand_chip->options & NAND_ROW_ADDR_3) {
                                /* paddr_8 - paddr_15 */
                                host->devtype_data->send_addr(host,
                                                (page_addr >> 8) & 0xff,
@@ -1212,7 +1211,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
        struct nand_chip *nand_chip = mtd_to_nand(mtd);
        struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
-       pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+       dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
              command, column, page_addr);
 
        /* Reset command state information */
index 12edaae17d81f2228eefcc50b9d5de7433119987..6135d007a0686193d557ce831553ed53c9dd58c6 100644 (file)
@@ -115,7 +115,7 @@ static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
        struct nand_chip *chip = mtd_to_nand(mtd);
        struct nand_ecc_ctrl *ecc = &chip->ecc;
 
-       if (section)
+       if (section || !ecc->total)
                return -ERANGE;
 
        oobregion->length = ecc->total;
@@ -727,8 +727,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
                chip->cmd_ctrl(mtd, page_addr, ctrl);
                ctrl &= ~NAND_CTRL_CHANGE;
                chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
-               /* One more address cycle for devices > 32MiB */
-               if (chip->chipsize > (32 << 20))
+               if (chip->options & NAND_ROW_ADDR_3)
                        chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
        }
        chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
@@ -854,8 +853,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
                        chip->cmd_ctrl(mtd, page_addr, ctrl);
                        chip->cmd_ctrl(mtd, page_addr >> 8,
                                       NAND_NCE | NAND_ALE);
-                       /* One more address cycle for devices > 128MiB */
-                       if (chip->chipsize > (128 << 20))
+                       if (chip->options & NAND_ROW_ADDR_3)
                                chip->cmd_ctrl(mtd, page_addr >> 16,
                                               NAND_NCE | NAND_ALE);
                }
@@ -1246,6 +1244,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nand_reset);
 
 /**
  * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
@@ -2799,15 +2798,18 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
                            size_t *retlen, const uint8_t *buf)
 {
        struct nand_chip *chip = mtd_to_nand(mtd);
+       int chipnr = (int)(to >> chip->chip_shift);
        struct mtd_oob_ops ops;
        int ret;
 
-       /* Wait for the device to get ready */
-       panic_nand_wait(mtd, chip, 400);
-
        /* Grab the device */
        panic_nand_get_device(chip, mtd, FL_WRITING);
 
+       chip->select_chip(mtd, chipnr);
+
+       /* Wait for the device to get ready */
+       panic_nand_wait(mtd, chip, 400);
+
        memset(&ops, 0, sizeof(ops));
        ops.len = len;
        ops.datbuf = (uint8_t *)buf;
@@ -3999,6 +4001,9 @@ ident_done:
                chip->chip_shift += 32 - 1;
        }
 
+       if (chip->chip_shift - chip->page_shift > 16)
+               chip->options |= NAND_ROW_ADDR_3;
+
        chip->badblockbits = 8;
        chip->erase = single_erase;
 
@@ -4700,6 +4705,19 @@ int nand_scan_tail(struct mtd_info *mtd)
                        mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
                        break;
                default:
+                       /*
+                        * Expose the whole OOB area to users if ECC_NONE
+                        * is passed. We could do that for all kind of
+                        * ->oobsize, but we must keep the old large/small
+                        * page with ECC layout when ->oobsize <= 128 for
+                        * compatibility reasons.
+                        */
+                       if (ecc->mode == NAND_ECC_NONE) {
+                               mtd_set_ooblayout(mtd,
+                                               &nand_ooblayout_lp_ops);
+                               break;
+                       }
+
                        WARN(1, "No oob scheme defined for oobsize %d\n",
                                mtd->oobsize);
                        ret = -EINVAL;
index 246b4393118e4df5c645b3e4eb338a70958ba4b9..44322a363ba549dd7120138fb2b0f977a09260f5 100644 (file)
@@ -520,11 +520,16 @@ static int nandsim_debugfs_create(struct nandsim *dev)
        struct dentry *root = nsmtd->dbg.dfs_dir;
        struct dentry *dent;
 
-       if (!IS_ENABLED(CONFIG_DEBUG_FS))
+       /*
+        * Just skip debugfs initialization when the debugfs directory is
+        * missing.
+        */
+       if (IS_ERR_OR_NULL(root)) {
+               if (IS_ENABLED(CONFIG_DEBUG_FS) &&
+                   !IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
+                       NS_WARN("CONFIG_MTD_PARTITIONED_MASTER must be enabled to expose debugfs stuff\n");
                return 0;
-
-       if (IS_ERR_OR_NULL(root))
-               return -1;
+       }
 
        dent = debugfs_create_file("nandsim_wear_report", S_IRUSR,
                                   root, dev, &dfs_fops);
index 7bb4d2ea93421a4d880b77bdce8fad99052fc53f..af5b32c9a791dc18934b916cec03573995bf307a 100644 (file)
@@ -154,7 +154,7 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
                if (page_addr != -1) {
                        write_addr_reg(nand, page_addr);
 
-                       if (chip->chipsize > (128 << 20)) {
+                       if (chip->options & NAND_ROW_ADDR_3) {
                                write_addr_reg(nand, page_addr >> 8);
                                write_addr_reg(nand, page_addr >> 16 | ENDADDR);
                        } else {
index 54540c8fa1a28edab3fbaaf648ab5032942bbcae..dad438c4906af205a73f44eade6743cd4460faf9 100644 (file)
@@ -1133,129 +1133,172 @@ static u8  bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
                                0x97, 0x79, 0xe5, 0x24, 0xb5};
 
 /**
- * omap_calculate_ecc_bch - Generate bytes of ECC bytes
+ * _omap_calculate_ecc_bch - Generate ECC bytes for one sector
  * @mtd:       MTD device structure
  * @dat:       The pointer to data on which ecc is computed
  * @ecc_code:  The ecc_code buffer
+ * @i:         The sector number (for a multi sector page)
  *
- * Support calculating of BCH4/8 ecc vectors for the page
+ * Support calculating of BCH4/8/16 ECC vectors for one sector
+ * within a page. Sector number is in @i.
  */
-static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
-                                       const u_char *dat, u_char *ecc_calc)
+static int _omap_calculate_ecc_bch(struct mtd_info *mtd,
+                                  const u_char *dat, u_char *ecc_calc, int i)
 {
        struct omap_nand_info *info = mtd_to_omap(mtd);
        int eccbytes    = info->nand.ecc.bytes;
        struct gpmc_nand_regs   *gpmc_regs = &info->reg;
        u8 *ecc_code;
-       unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4;
+       unsigned long bch_val1, bch_val2, bch_val3, bch_val4;
        u32 val;
-       int i, j;
+       int j;
+
+       ecc_code = ecc_calc;
+       switch (info->ecc_opt) {
+       case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+       case OMAP_ECC_BCH8_CODE_HW:
+               bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]);
+               bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]);
+               bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]);
+               bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]);
+               *ecc_code++ = (bch_val4 & 0xFF);
+               *ecc_code++ = ((bch_val3 >> 24) & 0xFF);
+               *ecc_code++ = ((bch_val3 >> 16) & 0xFF);
+               *ecc_code++ = ((bch_val3 >> 8) & 0xFF);
+               *ecc_code++ = (bch_val3 & 0xFF);
+               *ecc_code++ = ((bch_val2 >> 24) & 0xFF);
+               *ecc_code++ = ((bch_val2 >> 16) & 0xFF);
+               *ecc_code++ = ((bch_val2 >> 8) & 0xFF);
+               *ecc_code++ = (bch_val2 & 0xFF);
+               *ecc_code++ = ((bch_val1 >> 24) & 0xFF);
+               *ecc_code++ = ((bch_val1 >> 16) & 0xFF);
+               *ecc_code++ = ((bch_val1 >> 8) & 0xFF);
+               *ecc_code++ = (bch_val1 & 0xFF);
+               break;
+       case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+       case OMAP_ECC_BCH4_CODE_HW:
+               bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]);
+               bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]);
+               *ecc_code++ = ((bch_val2 >> 12) & 0xFF);
+               *ecc_code++ = ((bch_val2 >> 4) & 0xFF);
+               *ecc_code++ = ((bch_val2 & 0xF) << 4) |
+                       ((bch_val1 >> 28) & 0xF);
+               *ecc_code++ = ((bch_val1 >> 20) & 0xFF);
+               *ecc_code++ = ((bch_val1 >> 12) & 0xFF);
+               *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
+               *ecc_code++ = ((bch_val1 & 0xF) << 4);
+               break;
+       case OMAP_ECC_BCH16_CODE_HW:
+               val = readl(gpmc_regs->gpmc_bch_result6[i]);
+               ecc_code[0]  = ((val >>  8) & 0xFF);
+               ecc_code[1]  = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result5[i]);
+               ecc_code[2]  = ((val >> 24) & 0xFF);
+               ecc_code[3]  = ((val >> 16) & 0xFF);
+               ecc_code[4]  = ((val >>  8) & 0xFF);
+               ecc_code[5]  = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result4[i]);
+               ecc_code[6]  = ((val >> 24) & 0xFF);
+               ecc_code[7]  = ((val >> 16) & 0xFF);
+               ecc_code[8]  = ((val >>  8) & 0xFF);
+               ecc_code[9]  = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result3[i]);
+               ecc_code[10] = ((val >> 24) & 0xFF);
+               ecc_code[11] = ((val >> 16) & 0xFF);
+               ecc_code[12] = ((val >>  8) & 0xFF);
+               ecc_code[13] = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result2[i]);
+               ecc_code[14] = ((val >> 24) & 0xFF);
+               ecc_code[15] = ((val >> 16) & 0xFF);
+               ecc_code[16] = ((val >>  8) & 0xFF);
+               ecc_code[17] = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result1[i]);
+               ecc_code[18] = ((val >> 24) & 0xFF);
+               ecc_code[19] = ((val >> 16) & 0xFF);
+               ecc_code[20] = ((val >>  8) & 0xFF);
+               ecc_code[21] = ((val >>  0) & 0xFF);
+               val = readl(gpmc_regs->gpmc_bch_result0[i]);
+               ecc_code[22] = ((val >> 24) & 0xFF);
+               ecc_code[23] = ((val >> 16) & 0xFF);
+               ecc_code[24] = ((val >>  8) & 0xFF);
+               ecc_code[25] = ((val >>  0) & 0xFF);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* ECC scheme specific syndrome customizations */
+       switch (info->ecc_opt) {
+       case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+               /* Add constant polynomial to remainder, so that
+                * ECC of blank pages results in 0x0 on reading back
+                */
+               for (j = 0; j < eccbytes; j++)
+                       ecc_calc[j] ^= bch4_polynomial[j];
+               break;
+       case OMAP_ECC_BCH4_CODE_HW:
+               /* Set  8th ECC byte as 0x0 for ROM compatibility */
+               ecc_calc[eccbytes - 1] = 0x0;
+               break;
+       case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+               /* Add constant polynomial to remainder, so that
+                * ECC of blank pages results in 0x0 on reading back
+                */
+               for (j = 0; j < eccbytes; j++)
+                       ecc_calc[j] ^= bch8_polynomial[j];
+               break;
+       case OMAP_ECC_BCH8_CODE_HW:
+               /* Set 14th ECC byte as 0x0 for ROM compatibility */
+               ecc_calc[eccbytes - 1] = 0x0;
+               break;
+       case OMAP_ECC_BCH16_CODE_HW:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction
+ * @mtd:       MTD device structure
+ * @dat:       The pointer to data on which ecc is computed
+ * @ecc_code:  The ecc_code buffer
+ *
+ * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
+ * when SW based correction is required as ECC is required for one sector
+ * at a time.
+ */
+static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd,
+                                    const u_char *dat, u_char *ecc_calc)
+{
+       return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0);
+}
+
+/**
+ * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
+ * @mtd:       MTD device structure
+ * @dat:       The pointer to data on which ecc is computed
+ * @ecc_code:  The ecc_code buffer
+ *
+ * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
+ */
+static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd,
+                                       const u_char *dat, u_char *ecc_calc)
+{
+       struct omap_nand_info *info = mtd_to_omap(mtd);
+       int eccbytes = info->nand.ecc.bytes;
+       unsigned long nsectors;
+       int i, ret;
 
        nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
        for (i = 0; i < nsectors; i++) {
-               ecc_code = ecc_calc;
-               switch (info->ecc_opt) {
-               case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-               case OMAP_ECC_BCH8_CODE_HW:
-                       bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]);
-                       bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]);
-                       bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]);
-                       bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]);
-                       *ecc_code++ = (bch_val4 & 0xFF);
-                       *ecc_code++ = ((bch_val3 >> 24) & 0xFF);
-                       *ecc_code++ = ((bch_val3 >> 16) & 0xFF);
-                       *ecc_code++ = ((bch_val3 >> 8) & 0xFF);
-                       *ecc_code++ = (bch_val3 & 0xFF);
-                       *ecc_code++ = ((bch_val2 >> 24) & 0xFF);
-                       *ecc_code++ = ((bch_val2 >> 16) & 0xFF);
-                       *ecc_code++ = ((bch_val2 >> 8) & 0xFF);
-                       *ecc_code++ = (bch_val2 & 0xFF);
-                       *ecc_code++ = ((bch_val1 >> 24) & 0xFF);
-                       *ecc_code++ = ((bch_val1 >> 16) & 0xFF);
-                       *ecc_code++ = ((bch_val1 >> 8) & 0xFF);
-                       *ecc_code++ = (bch_val1 & 0xFF);
-                       break;
-               case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
-               case OMAP_ECC_BCH4_CODE_HW:
-                       bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]);
-                       bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]);
-                       *ecc_code++ = ((bch_val2 >> 12) & 0xFF);
-                       *ecc_code++ = ((bch_val2 >> 4) & 0xFF);
-                       *ecc_code++ = ((bch_val2 & 0xF) << 4) |
-                               ((bch_val1 >> 28) & 0xF);
-                       *ecc_code++ = ((bch_val1 >> 20) & 0xFF);
-                       *ecc_code++ = ((bch_val1 >> 12) & 0xFF);
-                       *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
-                       *ecc_code++ = ((bch_val1 & 0xF) << 4);
-                       break;
-               case OMAP_ECC_BCH16_CODE_HW:
-                       val = readl(gpmc_regs->gpmc_bch_result6[i]);
-                       ecc_code[0]  = ((val >>  8) & 0xFF);
-                       ecc_code[1]  = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result5[i]);
-                       ecc_code[2]  = ((val >> 24) & 0xFF);
-                       ecc_code[3]  = ((val >> 16) & 0xFF);
-                       ecc_code[4]  = ((val >>  8) & 0xFF);
-                       ecc_code[5]  = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result4[i]);
-                       ecc_code[6]  = ((val >> 24) & 0xFF);
-                       ecc_code[7]  = ((val >> 16) & 0xFF);
-                       ecc_code[8]  = ((val >>  8) & 0xFF);
-                       ecc_code[9]  = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result3[i]);
-                       ecc_code[10] = ((val >> 24) & 0xFF);
-                       ecc_code[11] = ((val >> 16) & 0xFF);
-                       ecc_code[12] = ((val >>  8) & 0xFF);
-                       ecc_code[13] = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result2[i]);
-                       ecc_code[14] = ((val >> 24) & 0xFF);
-                       ecc_code[15] = ((val >> 16) & 0xFF);
-                       ecc_code[16] = ((val >>  8) & 0xFF);
-                       ecc_code[17] = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result1[i]);
-                       ecc_code[18] = ((val >> 24) & 0xFF);
-                       ecc_code[19] = ((val >> 16) & 0xFF);
-                       ecc_code[20] = ((val >>  8) & 0xFF);
-                       ecc_code[21] = ((val >>  0) & 0xFF);
-                       val = readl(gpmc_regs->gpmc_bch_result0[i]);
-                       ecc_code[22] = ((val >> 24) & 0xFF);
-                       ecc_code[23] = ((val >> 16) & 0xFF);
-                       ecc_code[24] = ((val >>  8) & 0xFF);
-                       ecc_code[25] = ((val >>  0) & 0xFF);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               /* ECC scheme specific syndrome customizations */
-               switch (info->ecc_opt) {
-               case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
-                       /* Add constant polynomial to remainder, so that
-                        * ECC of blank pages results in 0x0 on reading back */
-                       for (j = 0; j < eccbytes; j++)
-                               ecc_calc[j] ^= bch4_polynomial[j];
-                       break;
-               case OMAP_ECC_BCH4_CODE_HW:
-                       /* Set  8th ECC byte as 0x0 for ROM compatibility */
-                       ecc_calc[eccbytes - 1] = 0x0;
-                       break;
-               case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-                       /* Add constant polynomial to remainder, so that
-                        * ECC of blank pages results in 0x0 on reading back */
-                       for (j = 0; j < eccbytes; j++)
-                               ecc_calc[j] ^= bch8_polynomial[j];
-                       break;
-               case OMAP_ECC_BCH8_CODE_HW:
-                       /* Set 14th ECC byte as 0x0 for ROM compatibility */
-                       ecc_calc[eccbytes - 1] = 0x0;
-                       break;
-               case OMAP_ECC_BCH16_CODE_HW:
-                       break;
-               default:
-                       return -EINVAL;
-               }
+               ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i);
+               if (ret)
+                       return ret;
 
-       ecc_calc += eccbytes;
+               ecc_calc += eccbytes;
        }
 
        return 0;
@@ -1496,7 +1539,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
        chip->write_buf(mtd, buf, mtd->writesize);
 
        /* Update ecc vector from GPMC result registers */
-       chip->ecc.calculate(mtd, buf, &ecc_calc[0]);
+       omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]);
 
        ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
                                         chip->ecc.total);
@@ -1508,6 +1551,72 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
        return 0;
 }
 
+/**
+ * omap_write_subpage_bch - BCH hardware ECC based subpage write
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @offset:    column address of subpage within the page
+ * @data_len:  data length
+ * @buf:       data buffer
+ * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
+ *
+ * OMAP optimized subpage write method.
+ */
+static int omap_write_subpage_bch(struct mtd_info *mtd,
+                                 struct nand_chip *chip, u32 offset,
+                                 u32 data_len, const u8 *buf,
+                                 int oob_required, int page)
+{
+       u8 *ecc_calc = chip->buffers->ecccalc;
+       int ecc_size      = chip->ecc.size;
+       int ecc_bytes     = chip->ecc.bytes;
+       int ecc_steps     = chip->ecc.steps;
+       u32 start_step = offset / ecc_size;
+       u32 end_step   = (offset + data_len - 1) / ecc_size;
+       int step, ret = 0;
+
+       /*
+        * Write entire page at one go as it would be optimal
+        * as ECC is calculated by hardware.
+        * ECC is calculated for all subpages but we choose
+        * only what we want.
+        */
+
+       /* Enable GPMC ECC engine */
+       chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+
+       /* Write data */
+       chip->write_buf(mtd, buf, mtd->writesize);
+
+       for (step = 0; step < ecc_steps; step++) {
+               /* mask ECC of un-touched subpages by padding 0xFF */
+               if (step < start_step || step > end_step)
+                       memset(ecc_calc, 0xff, ecc_bytes);
+               else
+                       ret = _omap_calculate_ecc_bch(mtd, buf, ecc_calc, step);
+
+               if (ret)
+                       return ret;
+
+               buf += ecc_size;
+               ecc_calc += ecc_bytes;
+       }
+
+       /* copy calculated ECC for whole page to chip->buffer->oob */
+       /* this include masked-value(0xFF) for unwritten subpages */
+       ecc_calc = chip->buffers->ecccalc;
+       ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0,
+                                        chip->ecc.total);
+       if (ret)
+               return ret;
+
+       /* write OOB buffer to NAND device */
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
+}
+
 /**
  * omap_read_page_bch - BCH ecc based page read function for entire page
  * @mtd:               mtd info structure
@@ -1544,7 +1653,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
                       chip->ecc.total);
 
        /* Calculate ecc bytes */
-       chip->ecc.calculate(mtd, buf, ecc_calc);
+       omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
 
        ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
                                         chip->ecc.total);
@@ -1588,8 +1697,7 @@ static bool is_elm_present(struct omap_nand_info *info,
        return true;
 }
 
-static bool omap2_nand_ecc_check(struct omap_nand_info *info,
-                                struct omap_nand_platform_data *pdata)
+static bool omap2_nand_ecc_check(struct omap_nand_info *info)
 {
        bool ecc_needs_bch, ecc_needs_omap_bch, ecc_needs_elm;
 
@@ -1804,7 +1912,6 @@ static const struct mtd_ooblayout_ops omap_sw_ooblayout_ops = {
 static int omap_nand_probe(struct platform_device *pdev)
 {
        struct omap_nand_info           *info;
-       struct omap_nand_platform_data  *pdata = NULL;
        struct mtd_info                 *mtd;
        struct nand_chip                *nand_chip;
        int                             err;
@@ -1821,29 +1928,10 @@ static int omap_nand_probe(struct platform_device *pdev)
 
        info->pdev = pdev;
 
-       if (dev->of_node) {
-               if (omap_get_dt_info(dev, info))
-                       return -EINVAL;
-       } else {
-               pdata = dev_get_platdata(&pdev->dev);
-               if (!pdata) {
-                       dev_err(&pdev->dev, "platform data missing\n");
-                       return -EINVAL;
-               }
-
-               info->gpmc_cs = pdata->cs;
-               info->reg = pdata->reg;
-               info->ecc_opt = pdata->ecc_opt;
-               if (pdata->dev_ready)
-                       dev_info(&pdev->dev, "pdata->dev_ready is deprecated\n");
-
-               info->xfer_type = pdata->xfer_type;
-               info->devsize = pdata->devsize;
-               info->elm_of_node = pdata->elm_of_node;
-               info->flash_bbt = pdata->flash_bbt;
-       }
+       err = omap_get_dt_info(dev, info);
+       if (err)
+               return err;
 
-       platform_set_drvdata(pdev, info);
        info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs);
        if (!info->ops) {
                dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n");
@@ -2002,7 +2090,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                goto return_error;
        }
 
-       if (!omap2_nand_ecc_check(info, pdata)) {
+       if (!omap2_nand_ecc_check(info)) {
                err = -EINVAL;
                goto return_error;
        }
@@ -2044,7 +2132,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.strength         = 4;
                nand_chip->ecc.hwctl            = omap_enable_hwecc_bch;
                nand_chip->ecc.correct          = nand_bch_correct_data;
-               nand_chip->ecc.calculate        = omap_calculate_ecc_bch;
+               nand_chip->ecc.calculate        = omap_calculate_ecc_bch_sw;
                mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
                /* Reserve one byte for the OMAP marker */
                oobbytes_per_step               = nand_chip->ecc.bytes + 1;
@@ -2066,9 +2154,9 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.strength         = 4;
                nand_chip->ecc.hwctl            = omap_enable_hwecc_bch;
                nand_chip->ecc.correct          = omap_elm_correct_data;
-               nand_chip->ecc.calculate        = omap_calculate_ecc_bch;
                nand_chip->ecc.read_page        = omap_read_page_bch;
                nand_chip->ecc.write_page       = omap_write_page_bch;
+               nand_chip->ecc.write_subpage    = omap_write_subpage_bch;
                mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
                oobbytes_per_step               = nand_chip->ecc.bytes;
 
@@ -2087,7 +2175,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.strength         = 8;
                nand_chip->ecc.hwctl            = omap_enable_hwecc_bch;
                nand_chip->ecc.correct          = nand_bch_correct_data;
-               nand_chip->ecc.calculate        = omap_calculate_ecc_bch;
+               nand_chip->ecc.calculate        = omap_calculate_ecc_bch_sw;
                mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
                /* Reserve one byte for the OMAP marker */
                oobbytes_per_step               = nand_chip->ecc.bytes + 1;
@@ -2109,9 +2197,9 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.strength         = 8;
                nand_chip->ecc.hwctl            = omap_enable_hwecc_bch;
                nand_chip->ecc.correct          = omap_elm_correct_data;
-               nand_chip->ecc.calculate        = omap_calculate_ecc_bch;
                nand_chip->ecc.read_page        = omap_read_page_bch;
                nand_chip->ecc.write_page       = omap_write_page_bch;
+               nand_chip->ecc.write_subpage    = omap_write_subpage_bch;
                mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
                oobbytes_per_step               = nand_chip->ecc.bytes;
 
@@ -2131,9 +2219,9 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.strength         = 16;
                nand_chip->ecc.hwctl            = omap_enable_hwecc_bch;
                nand_chip->ecc.correct          = omap_elm_correct_data;
-               nand_chip->ecc.calculate        = omap_calculate_ecc_bch;
                nand_chip->ecc.read_page        = omap_read_page_bch;
                nand_chip->ecc.write_page       = omap_write_page_bch;
+               nand_chip->ecc.write_subpage    = omap_write_subpage_bch;
                mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
                oobbytes_per_step               = nand_chip->ecc.bytes;
 
@@ -2167,10 +2255,9 @@ scan_tail:
        if (err)
                goto return_error;
 
-       if (dev->of_node)
-               mtd_device_register(mtd, NULL, 0);
-       else
-               mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
+       err = mtd_device_register(mtd, NULL, 0);
+       if (err)
+               goto return_error;
 
        platform_set_drvdata(pdev, mtd);
 
index 85cff68643e0bd3b5ab1e504277edf4b67fbd4e9..90b9a9ccbe60e3fad44855705bf2dc4623cd5347 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #define        CHIP_DELAY_TIMEOUT      msecs_to_jiffies(200)
 #define NAND_STOP_DELAY                msecs_to_jiffies(40)
  */
 #define INIT_BUFFER_SIZE       2048
 
+/* System control register and bit to enable NAND on some SoCs */
+#define GENCONF_SOC_DEVICE_MUX 0x208
+#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0)
+
 /* registers and bit definitions */
 #define NDCR           (0x00) /* Control register */
 #define NDTR0CS0       (0x04) /* Timing Parameter 0 for CS0 */
@@ -174,6 +180,7 @@ enum {
 enum pxa3xx_nand_variant {
        PXA3XX_NAND_VARIANT_PXA,
        PXA3XX_NAND_VARIANT_ARMADA370,
+       PXA3XX_NAND_VARIANT_ARMADA_8K,
 };
 
 struct pxa3xx_nand_host {
@@ -425,6 +432,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = {
                .compatible = "marvell,armada370-nand",
                .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
        },
+       {
+               .compatible = "marvell,armada-8k-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA_8K,
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
@@ -825,7 +836,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                info->retcode = ERR_UNCORERR;
        if (status & NDSR_CORERR) {
                info->retcode = ERR_CORERR;
-               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
+               if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+                    info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) &&
                    info->ecc_bch)
                        info->ecc_err_cnt = NDSR_ERR_CNT(status);
                else
@@ -888,7 +900,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                nand_writel(info, NDCB0, info->ndcb2);
 
                /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
-               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+                   info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
                        nand_writel(info, NDCB0, info->ndcb3);
        }
 
@@ -1671,7 +1684,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
                chip->options |= NAND_BUSWIDTH_16;
 
        /* Device detection must be done with ECC disabled */
-       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+           info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
                nand_writel(info, NDECCCTRL, 0x0);
 
        if (pdata->flash_bbt)
@@ -1709,7 +1723,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
         * (aka splitted) command handling,
         */
        if (mtd->writesize > PAGE_CHUNK_SIZE) {
-               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+                   info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) {
                        chip->cmdfunc = nand_cmdfunc_extended;
                } else {
                        dev_err(&info->pdev->dev,
@@ -1928,6 +1943,24 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
        if (!of_id)
                return 0;
 
+       /*
+        * Some SoCs like A7k/A8k need to enable manually the NAND
+        * controller to avoid being bootloader dependent. This is done
+        * through the use of a single bit in the System Functions registers.
+        */
+       if (pxa3xx_nand_get_variant(pdev) == PXA3XX_NAND_VARIANT_ARMADA_8K) {
+               struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle(
+                       pdev->dev.of_node, "marvell,system-controller");
+               u32 reg;
+
+               if (IS_ERR(sysctrl_base))
+                       return PTR_ERR(sysctrl_base);
+
+               regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, &reg);
+               reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN;
+               regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg);
+       }
+
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return -ENOMEM;
index 3baddfc997d139358ec63ff50f6d66c474e48ad9..2656c1ac5646e0e4bd43eeabb95bd507f926bf40 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/delay.h>
+#include <linux/dma/qcom_bam_dma.h>
 
 /* NANDc reg offsets */
 #define        NAND_FLASH_CMD                  0x00
@@ -199,6 +200,15 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg,                     \
  */
 #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg))
 
+/* Returns the NAND register physical address */
+#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
+
+/* Returns the dma address for reg read buffer */
+#define reg_buf_dma_addr(chip, vaddr) \
+       ((chip)->reg_read_dma + \
+       ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
+
+#define QPIC_PER_CW_CMD_ELEMENTS       32
 #define QPIC_PER_CW_CMD_SGL            32
 #define QPIC_PER_CW_DATA_SGL           8
 
@@ -221,8 +231,13 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg,                     \
 /*
  * This data type corresponds to the BAM transaction which will be used for all
  * NAND transfers.
+ * @bam_ce - the array of BAM command elements
  * @cmd_sgl - sgl for NAND BAM command pipe
  * @data_sgl - sgl for NAND BAM consumer/producer pipe
+ * @bam_ce_pos - the index in bam_ce which is available for next sgl
+ * @bam_ce_start - the index in bam_ce which marks the start position ce
+ *                for current sgl. It will be used for size calculation
+ *                for current sgl
  * @cmd_sgl_pos - current index in command sgl.
  * @cmd_sgl_start - start index in command sgl.
  * @tx_sgl_pos - current index in data sgl for tx.
@@ -231,8 +246,11 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg,                     \
  * @rx_sgl_start - start index in data sgl for rx.
  */
 struct bam_transaction {
+       struct bam_cmd_element *bam_ce;
        struct scatterlist *cmd_sgl;
        struct scatterlist *data_sgl;
+       u32 bam_ce_pos;
+       u32 bam_ce_start;
        u32 cmd_sgl_pos;
        u32 cmd_sgl_start;
        u32 tx_sgl_pos;
@@ -307,7 +325,8 @@ struct nandc_regs {
  *                             controller
  * @dev:                       parent device
  * @base:                      MMIO base
- * @base_dma:                  physical base address of controller registers
+ * @base_phys:                 physical base address of controller registers
+ * @base_dma:                  dma base address of controller registers
  * @core_clk:                  controller clock
  * @aon_clk:                   another controller clock
  *
@@ -340,6 +359,7 @@ struct qcom_nand_controller {
        struct device *dev;
 
        void __iomem *base;
+       phys_addr_t base_phys;
        dma_addr_t base_dma;
 
        struct clk *core_clk;
@@ -462,7 +482,8 @@ alloc_bam_transaction(struct qcom_nand_controller *nandc)
 
        bam_txn_size =
                sizeof(*bam_txn) + num_cw *
-               ((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
+               ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) +
+               (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
                (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL));
 
        bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL);
@@ -472,6 +493,10 @@ alloc_bam_transaction(struct qcom_nand_controller *nandc)
        bam_txn = bam_txn_buf;
        bam_txn_buf += sizeof(*bam_txn);
 
+       bam_txn->bam_ce = bam_txn_buf;
+       bam_txn_buf +=
+               sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw;
+
        bam_txn->cmd_sgl = bam_txn_buf;
        bam_txn_buf +=
                sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
@@ -489,6 +514,8 @@ static void clear_bam_transaction(struct qcom_nand_controller *nandc)
        if (!nandc->props->is_bam)
                return;
 
+       bam_txn->bam_ce_pos = 0;
+       bam_txn->bam_ce_start = 0;
        bam_txn->cmd_sgl_pos = 0;
        bam_txn->cmd_sgl_start = 0;
        bam_txn->tx_sgl_pos = 0;
@@ -733,6 +760,66 @@ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc,
        return 0;
 }
 
+/*
+ * Prepares the command descriptor for BAM DMA which will be used for NAND
+ * register reads and writes. The command descriptor requires the command
+ * to be formed in command element type so this function uses the command
+ * element from bam transaction ce array and fills the same with required
+ * data. A single SGL can contain multiple command elements so
+ * NAND_BAM_NEXT_SGL will be used for starting the separate SGL
+ * after the current command element.
+ */
+static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
+                                int reg_off, const void *vaddr,
+                                int size, unsigned int flags)
+{
+       int bam_ce_size;
+       int i, ret;
+       struct bam_cmd_element *bam_ce_buffer;
+       struct bam_transaction *bam_txn = nandc->bam_txn;
+
+       bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
+
+       /* fill the command desc */
+       for (i = 0; i < size; i++) {
+               if (read)
+                       bam_prep_ce(&bam_ce_buffer[i],
+                                   nandc_reg_phys(nandc, reg_off + 4 * i),
+                                   BAM_READ_COMMAND,
+                                   reg_buf_dma_addr(nandc,
+                                                    (__le32 *)vaddr + i));
+               else
+                       bam_prep_ce_le32(&bam_ce_buffer[i],
+                                        nandc_reg_phys(nandc, reg_off + 4 * i),
+                                        BAM_WRITE_COMMAND,
+                                        *((__le32 *)vaddr + i));
+       }
+
+       bam_txn->bam_ce_pos += size;
+
+       /* use the separate sgl after this command */
+       if (flags & NAND_BAM_NEXT_SGL) {
+               bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
+               bam_ce_size = (bam_txn->bam_ce_pos -
+                               bam_txn->bam_ce_start) *
+                               sizeof(struct bam_cmd_element);
+               sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
+                          bam_ce_buffer, bam_ce_size);
+               bam_txn->cmd_sgl_pos++;
+               bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
+
+               if (flags & NAND_BAM_NWD) {
+                       ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+                                                    DMA_PREP_FENCE |
+                                                    DMA_PREP_CMD);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Prepares the data descriptor for BAM DMA which will be used for NAND
  * data reads and writes.
@@ -851,19 +938,22 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
 {
        bool flow_control = false;
        void *vaddr;
-       int size;
 
-       if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
-               flow_control = true;
+       vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
+       nandc->reg_read_pos += num_regs;
 
        if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
                first = dev_cmd_reg_addr(nandc, first);
 
-       size = num_regs * sizeof(u32);
-       vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
-       nandc->reg_read_pos += num_regs;
+       if (nandc->props->is_bam)
+               return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
+                                            num_regs, flags);
+
+       if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
+               flow_control = true;
 
-       return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control);
+       return prep_adm_dma_desc(nandc, true, first, vaddr,
+                                num_regs * sizeof(u32), flow_control);
 }
 
 /*
@@ -880,13 +970,9 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
        bool flow_control = false;
        struct nandc_regs *regs = nandc->regs;
        void *vaddr;
-       int size;
 
        vaddr = offset_to_nandc_reg(regs, first);
 
-       if (first == NAND_FLASH_CMD)
-               flow_control = true;
-
        if (first == NAND_ERASED_CW_DETECT_CFG) {
                if (flags & NAND_ERASED_CW_SET)
                        vaddr = &regs->erased_cw_detect_cfg_set;
@@ -903,10 +989,15 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
        if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
                first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD);
 
-       size = num_regs * sizeof(u32);
+       if (nandc->props->is_bam)
+               return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
+                                            num_regs, flags);
+
+       if (first == NAND_FLASH_CMD)
+               flow_control = true;
 
-       return prep_adm_dma_desc(nandc, false, first, vaddr, size,
-                                flow_control);
+       return prep_adm_dma_desc(nandc, false, first, vaddr,
+                                num_regs * sizeof(u32), flow_control);
 }
 
 /*
@@ -1170,7 +1261,8 @@ static int submit_descs(struct qcom_nand_controller *nandc)
                }
 
                if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
-                       r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0);
+                       r = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+                                                  DMA_PREP_CMD);
                        if (r)
                                return r;
                }
@@ -2705,6 +2797,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
        if (IS_ERR(nandc->base))
                return PTR_ERR(nandc->base);
 
+       nandc->base_phys = res->start;
        nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start);
 
        nandc->core_clk = devm_clk_get(dev, "core");
index e7f3c98487e620bc902a56057a537d6f0a4d1819..3c5008a4f5f33accc4fa09d6cc95a2339daf868a 100644 (file)
@@ -1094,14 +1094,11 @@ MODULE_DEVICE_TABLE(of, of_flctl_match);
 
 static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 {
-       const struct of_device_id *match;
-       struct flctl_soc_config *config;
+       const struct flctl_soc_config *config;
        struct sh_flctl_platform_data *pdata;
 
-       match = of_match_device(of_flctl_match, dev);
-       if (match)
-               config = (struct flctl_soc_config *)match->data;
-       else {
+       config = of_device_get_match_data(dev);
+ &n