pistachio: remove kernel 4.9 support
Signed-off-by: Matti Laakso <matti.laakso@outlook.com>
This commit is contained in:
parent
0394edbba0
commit
76f267ef6c
21 changed files with 0 additions and 3690 deletions
|
@ -1,340 +0,0 @@
|
||||||
CONFIG_ARCH_BINFMT_ELF_STATE=y
|
|
||||||
CONFIG_ARCH_CLOCKSOURCE_DATA=y
|
|
||||||
CONFIG_ARCH_DISCARD_MEMBLOCK=y
|
|
||||||
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
|
|
||||||
# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
|
|
||||||
# CONFIG_ARCH_HAS_SG_CHAIN is not set
|
|
||||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
|
||||||
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
|
||||||
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
|
|
||||||
CONFIG_ARCH_SUPPORTS_UPROBES=y
|
|
||||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
|
||||||
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
|
|
||||||
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
|
|
||||||
CONFIG_BLK_DEV_LOOP=y
|
|
||||||
CONFIG_BLK_DEV_SD=y
|
|
||||||
CONFIG_BOARD_SCACHE=y
|
|
||||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
|
||||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
|
|
||||||
CONFIG_BOOT_ELF32=y
|
|
||||||
CONFIG_CEVT_R4K=y
|
|
||||||
CONFIG_CLKDEV_LOOKUP=y
|
|
||||||
CONFIG_CLKSRC_MIPS_GIC=y
|
|
||||||
CONFIG_CLKSRC_OF=y
|
|
||||||
CONFIG_CLKSRC_PISTACHIO=y
|
|
||||||
CONFIG_CLKSRC_PROBE=y
|
|
||||||
CONFIG_CLONE_BACKWARDS=y
|
|
||||||
CONFIG_COMMON_CLK=y
|
|
||||||
CONFIG_CONNECTOR=y
|
|
||||||
CONFIG_CPU_GENERIC_DUMP_TLB=y
|
|
||||||
CONFIG_CPU_HAS_PREFETCH=y
|
|
||||||
CONFIG_CPU_HAS_RIXI=y
|
|
||||||
CONFIG_CPU_HAS_SYNC=y
|
|
||||||
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
|
|
||||||
CONFIG_CPU_IDLE=y
|
|
||||||
CONFIG_CPU_IDLE_GOV_LADDER=y
|
|
||||||
CONFIG_CPU_IDLE_GOV_MENU=y
|
|
||||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
|
||||||
CONFIG_CPU_MIPS32=y
|
|
||||||
CONFIG_CPU_MIPS32_R2=y
|
|
||||||
CONFIG_CPU_MIPSR2=y
|
|
||||||
CONFIG_CPU_MIPSR2_IRQ_EI=y
|
|
||||||
CONFIG_CPU_MIPSR2_IRQ_VI=y
|
|
||||||
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
|
|
||||||
CONFIG_CPU_PM=y
|
|
||||||
CONFIG_CPU_R4K_CACHE_TLB=y
|
|
||||||
CONFIG_CPU_R4K_FPU=y
|
|
||||||
CONFIG_CPU_RMAP=y
|
|
||||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
|
||||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
|
||||||
CONFIG_CPU_SUPPORTS_MSA=y
|
|
||||||
CONFIG_CRC16=y
|
|
||||||
CONFIG_CRC_CCITT=y
|
|
||||||
CONFIG_CRYPTO_AEAD=y
|
|
||||||
CONFIG_CRYPTO_AEAD2=y
|
|
||||||
CONFIG_CRYPTO_CBC=y
|
|
||||||
CONFIG_CRYPTO_CRC32C=y
|
|
||||||
CONFIG_CRYPTO_DEFLATE=y
|
|
||||||
CONFIG_CRYPTO_HASH=y
|
|
||||||
CONFIG_CRYPTO_HASH2=y
|
|
||||||
CONFIG_CRYPTO_LZO=y
|
|
||||||
CONFIG_CRYPTO_MANAGER=y
|
|
||||||
CONFIG_CRYPTO_MANAGER2=y
|
|
||||||
CONFIG_CRYPTO_MD5=y
|
|
||||||
CONFIG_CRYPTO_NULL=y
|
|
||||||
CONFIG_CRYPTO_NULL2=y
|
|
||||||
CONFIG_CRYPTO_RNG=y
|
|
||||||
CONFIG_CRYPTO_RNG2=y
|
|
||||||
CONFIG_CRYPTO_SHA1=y
|
|
||||||
CONFIG_CRYPTO_SHA256=y
|
|
||||||
CONFIG_CRYPTO_WORKQUEUE=y
|
|
||||||
CONFIG_CSRC_R4K=y
|
|
||||||
CONFIG_DMADEVICES=y
|
|
||||||
CONFIG_DMA_ENGINE=y
|
|
||||||
CONFIG_DMA_NONCOHERENT=y
|
|
||||||
CONFIG_DMA_OF=y
|
|
||||||
CONFIG_DMA_VIRTUAL_CHANNELS=y
|
|
||||||
CONFIG_DTC=y
|
|
||||||
CONFIG_DWMAC_GENERIC=y
|
|
||||||
CONFIG_EARLY_PRINTK=y
|
|
||||||
CONFIG_EARLY_PRINTK_8250=y
|
|
||||||
CONFIG_EXT4_FS=y
|
|
||||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
|
||||||
CONFIG_EXT4_FS_SECURITY=y
|
|
||||||
CONFIG_FIXED_PHY=y
|
|
||||||
CONFIG_FS_MBCACHE=y
|
|
||||||
CONFIG_FS_POSIX_ACL=y
|
|
||||||
CONFIG_GENERIC_ALLOCATOR=y
|
|
||||||
CONFIG_GENERIC_ATOMIC64=y
|
|
||||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
|
||||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
|
||||||
CONFIG_GENERIC_IO=y
|
|
||||||
CONFIG_GENERIC_IRQ_CHIP=y
|
|
||||||
CONFIG_GENERIC_IRQ_IPI=y
|
|
||||||
CONFIG_GENERIC_IRQ_SHOW=y
|
|
||||||
CONFIG_GENERIC_PCI_IOMAP=y
|
|
||||||
CONFIG_GENERIC_PHY=y
|
|
||||||
CONFIG_GENERIC_PINCONF=y
|
|
||||||
CONFIG_GENERIC_SCHED_CLOCK=y
|
|
||||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
|
||||||
CONFIG_GENERIC_TIME_VSYSCALL=y
|
|
||||||
CONFIG_GPIOLIB=y
|
|
||||||
CONFIG_GPIOLIB_IRQCHIP=y
|
|
||||||
CONFIG_GPIO_SYSFS=y
|
|
||||||
CONFIG_HANDLE_DOMAIN_IRQ=y
|
|
||||||
CONFIG_HARDWARE_WATCHPOINTS=y
|
|
||||||
CONFIG_HAS_DMA=y
|
|
||||||
CONFIG_HAS_IOMEM=y
|
|
||||||
CONFIG_HAS_IOPORT_MAP=y
|
|
||||||
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
|
|
||||||
# CONFIG_HAVE_ARCH_BITREVERSE is not set
|
|
||||||
CONFIG_HAVE_ARCH_JUMP_LABEL=y
|
|
||||||
CONFIG_HAVE_ARCH_KGDB=y
|
|
||||||
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
|
|
||||||
CONFIG_HAVE_ARCH_TRACEHOOK=y
|
|
||||||
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
|
|
||||||
CONFIG_HAVE_CBPF_JIT=y
|
|
||||||
CONFIG_HAVE_CC_STACKPROTECTOR=y
|
|
||||||
CONFIG_HAVE_CLK=y
|
|
||||||
CONFIG_HAVE_CLK_PREPARE=y
|
|
||||||
CONFIG_HAVE_CONTEXT_TRACKING=y
|
|
||||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
|
||||||
CONFIG_HAVE_DEBUG_KMEMLEAK=y
|
|
||||||
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
|
|
||||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
|
||||||
CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|
||||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
|
||||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
|
||||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
|
||||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
|
||||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
|
||||||
CONFIG_HAVE_IDE=y
|
|
||||||
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
|
|
||||||
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
|
|
||||||
CONFIG_HAVE_KVM=y
|
|
||||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
|
||||||
CONFIG_HAVE_MEMBLOCK=y
|
|
||||||
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
|
|
||||||
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
|
|
||||||
CONFIG_HAVE_NET_DSA=y
|
|
||||||
CONFIG_HAVE_OPROFILE=y
|
|
||||||
CONFIG_HAVE_PERF_EVENTS=y
|
|
||||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
|
||||||
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
|
|
||||||
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
|
|
||||||
CONFIG_HOTPLUG_CPU=y
|
|
||||||
CONFIG_I2C=y
|
|
||||||
CONFIG_I2C_BOARDINFO=y
|
|
||||||
CONFIG_I2C_IMG=y
|
|
||||||
CONFIG_IMGPDC_WDT=y
|
|
||||||
CONFIG_IMG_MDC_DMA=y
|
|
||||||
CONFIG_INITRAMFS_SOURCE=""
|
|
||||||
CONFIG_IRQCHIP=y
|
|
||||||
CONFIG_IRQ_DOMAIN=y
|
|
||||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
|
||||||
CONFIG_IRQ_FORCED_THREADING=y
|
|
||||||
CONFIG_IRQ_MIPS_CPU=y
|
|
||||||
CONFIG_IRQ_WORK=y
|
|
||||||
CONFIG_JBD2=y
|
|
||||||
CONFIG_LEDS_PWM=y
|
|
||||||
CONFIG_LIBFDT=y
|
|
||||||
CONFIG_LKDTM=y
|
|
||||||
CONFIG_LOCKUP_DETECTOR=y
|
|
||||||
CONFIG_LOG_BUF_SHIFT=18
|
|
||||||
CONFIG_LZO_COMPRESS=y
|
|
||||||
CONFIG_LZO_DECOMPRESS=y
|
|
||||||
CONFIG_MACH_PISTACHIO=y
|
|
||||||
CONFIG_MAGIC_SYSRQ=y
|
|
||||||
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0
|
|
||||||
CONFIG_MDIO_BOARDINFO=y
|
|
||||||
# CONFIG_MFD_MAX77620 is not set
|
|
||||||
CONFIG_MFD_SYSCON=y
|
|
||||||
CONFIG_MICREL_PHY=y
|
|
||||||
CONFIG_MIPS=y
|
|
||||||
CONFIG_MIPS_ASID_BITS=8
|
|
||||||
CONFIG_MIPS_ASID_SHIFT=0
|
|
||||||
CONFIG_MIPS_CLOCK_VSYSCALL=y
|
|
||||||
CONFIG_MIPS_CM=y
|
|
||||||
# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
|
|
||||||
CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y
|
|
||||||
# CONFIG_MIPS_CMDLINE_FROM_DTB is not set
|
|
||||||
CONFIG_MIPS_CPC=y
|
|
||||||
CONFIG_MIPS_CPS=y
|
|
||||||
# CONFIG_MIPS_CPS_CPUIDLE is not set
|
|
||||||
# CONFIG_MIPS_CPS_NS16550 is not set
|
|
||||||
CONFIG_MIPS_CPS_PM=y
|
|
||||||
CONFIG_MIPS_CPU_SCACHE=y
|
|
||||||
# CONFIG_MIPS_ELF_APPENDED_DTB is not set
|
|
||||||
CONFIG_MIPS_EXTERNAL_TIMER=y
|
|
||||||
CONFIG_MIPS_GIC=y
|
|
||||||
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
|
|
||||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
|
||||||
# CONFIG_MIPS_MACHINE is not set
|
|
||||||
CONFIG_MIPS_MT=y
|
|
||||||
CONFIG_MIPS_MT_FPAFF=y
|
|
||||||
CONFIG_MIPS_MT_SMP=y
|
|
||||||
CONFIG_MIPS_NO_APPENDED_DTB=y
|
|
||||||
CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
|
|
||||||
# CONFIG_MIPS_RAW_APPENDED_DTB is not set
|
|
||||||
CONFIG_MIPS_SPRAM=y
|
|
||||||
# CONFIG_MIPS_VPE_LOADER is not set
|
|
||||||
CONFIG_MMC=y
|
|
||||||
CONFIG_MMC_BLOCK=y
|
|
||||||
CONFIG_MMC_DW=y
|
|
||||||
# CONFIG_MMC_DW_EXYNOS is not set
|
|
||||||
# CONFIG_MMC_DW_K3 is not set
|
|
||||||
CONFIG_MMC_DW_PLTFM=y
|
|
||||||
CONFIG_MODULES_USE_ELF_REL=y
|
|
||||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
|
||||||
CONFIG_MTD_CMDLINE_PARTS=y
|
|
||||||
CONFIG_MTD_M25P80=y
|
|
||||||
CONFIG_MTD_NAND=y
|
|
||||||
CONFIG_MTD_NAND_ECC=y
|
|
||||||
# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set
|
|
||||||
CONFIG_MTD_SPI_NAND=y
|
|
||||||
CONFIG_MTD_SPI_NAND_DEVICES=y
|
|
||||||
CONFIG_MTD_SPI_NOR=y
|
|
||||||
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
|
|
||||||
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=16384
|
|
||||||
CONFIG_MTD_UBI=y
|
|
||||||
CONFIG_MTD_UBI_BEB_LIMIT=20
|
|
||||||
CONFIG_MTD_UBI_BLOCK=y
|
|
||||||
CONFIG_MTD_UBI_FASTMAP=y
|
|
||||||
# CONFIG_MTD_UBI_GLUEBI is not set
|
|
||||||
CONFIG_MTD_UBI_WL_THRESHOLD=4096
|
|
||||||
CONFIG_NAMESPACES=y
|
|
||||||
CONFIG_NEED_DMA_MAP_STATE=y
|
|
||||||
CONFIG_NET_FLOW_LIMIT=y
|
|
||||||
CONFIG_NET_NS=y
|
|
||||||
CONFIG_NET_PTP_CLASSIFY=y
|
|
||||||
CONFIG_NLS=y
|
|
||||||
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
|
|
||||||
CONFIG_NO_HZ=y
|
|
||||||
CONFIG_NO_HZ_COMMON=y
|
|
||||||
CONFIG_NO_HZ_IDLE=y
|
|
||||||
# CONFIG_NO_IOPORT_MAP is not set
|
|
||||||
CONFIG_NR_CPUS=4
|
|
||||||
CONFIG_OF=y
|
|
||||||
CONFIG_OF_ADDRESS=y
|
|
||||||
CONFIG_OF_EARLY_FLATTREE=y
|
|
||||||
CONFIG_OF_FLATTREE=y
|
|
||||||
CONFIG_OF_GPIO=y
|
|
||||||
CONFIG_OF_IRQ=y
|
|
||||||
CONFIG_OF_MDIO=y
|
|
||||||
CONFIG_OF_NET=y
|
|
||||||
CONFIG_PADATA=y
|
|
||||||
CONFIG_PCI_DRIVERS_LEGACY=y
|
|
||||||
CONFIG_PERF_USE_VMALLOC=y
|
|
||||||
CONFIG_PGTABLE_LEVELS=2
|
|
||||||
# CONFIG_PGTABLE_MAPPING is not set
|
|
||||||
CONFIG_PHYLIB=y
|
|
||||||
CONFIG_PHY_PISTACHIO_USB=y
|
|
||||||
CONFIG_PINCTRL=y
|
|
||||||
CONFIG_PINCTRL_PISTACHIO=y
|
|
||||||
CONFIG_PISTACHIO_GPTIMER_CLKSRC=y
|
|
||||||
CONFIG_POWER_SUPPLY=y
|
|
||||||
CONFIG_PPS=y
|
|
||||||
# CONFIG_PREEMPT_NONE is not set
|
|
||||||
CONFIG_PREEMPT_VOLUNTARY=y
|
|
||||||
CONFIG_PRINTK_TIME=y
|
|
||||||
CONFIG_PROC_EVENTS=y
|
|
||||||
CONFIG_PROFILING=y
|
|
||||||
CONFIG_PTP_1588_CLOCK=y
|
|
||||||
CONFIG_PWM=y
|
|
||||||
CONFIG_PWM_IMG=y
|
|
||||||
CONFIG_PWM_SYSFS=y
|
|
||||||
CONFIG_RATIONAL=y
|
|
||||||
CONFIG_RCU_STALL_COMMON=y
|
|
||||||
CONFIG_REGMAP=y
|
|
||||||
CONFIG_REGMAP_I2C=y
|
|
||||||
CONFIG_REGMAP_MMIO=y
|
|
||||||
CONFIG_REGMAP_SPI=y
|
|
||||||
CONFIG_REGULATOR=y
|
|
||||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
|
||||||
CONFIG_REGULATOR_GPIO=y
|
|
||||||
CONFIG_RESET_CONTROLLER=y
|
|
||||||
CONFIG_RESET_PISTACHIO=y
|
|
||||||
CONFIG_RFS_ACCEL=y
|
|
||||||
CONFIG_RPS=y
|
|
||||||
CONFIG_SCHEDSTATS=y
|
|
||||||
CONFIG_SCHED_INFO=y
|
|
||||||
CONFIG_SCSI=y
|
|
||||||
CONFIG_SCSI_SPI_ATTRS=y
|
|
||||||
CONFIG_SERIAL_8250_DW=y
|
|
||||||
# CONFIG_SERIAL_8250_FSL is not set
|
|
||||||
CONFIG_SERIAL_OF_PLATFORM=y
|
|
||||||
CONFIG_SG_POOL=y
|
|
||||||
CONFIG_SMP=y
|
|
||||||
CONFIG_SMP_UP=y
|
|
||||||
CONFIG_SPI=y
|
|
||||||
CONFIG_SPI_IMG_SPFI=y
|
|
||||||
CONFIG_SPI_MASTER=y
|
|
||||||
CONFIG_SRAM=y
|
|
||||||
CONFIG_SRCU=y
|
|
||||||
CONFIG_STMMAC_ETH=y
|
|
||||||
CONFIG_STMMAC_PLATFORM=y
|
|
||||||
CONFIG_SWPHY=y
|
|
||||||
CONFIG_SYNC_R4K=y
|
|
||||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
|
||||||
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
|
|
||||||
CONFIG_SYS_HAS_EARLY_PRINTK=y
|
|
||||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
|
||||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
|
||||||
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
|
|
||||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
|
|
||||||
CONFIG_SYS_SUPPORTS_MIPS_CPS=y
|
|
||||||
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
|
|
||||||
CONFIG_SYS_SUPPORTS_RELOCATABLE=y
|
|
||||||
CONFIG_SYS_SUPPORTS_SCHED_SMT=y
|
|
||||||
CONFIG_SYS_SUPPORTS_SMP=y
|
|
||||||
CONFIG_SYS_SUPPORTS_ZBOOT=y
|
|
||||||
CONFIG_TICK_CPU_ACCOUNTING=y
|
|
||||||
CONFIG_TIMER_STATS=y
|
|
||||||
CONFIG_TMPFS_POSIX_ACL=y
|
|
||||||
CONFIG_TREE_RCU=y
|
|
||||||
CONFIG_UBIFS_FS=y
|
|
||||||
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
|
|
||||||
CONFIG_UBIFS_FS_LZO=y
|
|
||||||
CONFIG_UBIFS_FS_ZLIB=y
|
|
||||||
CONFIG_USB=y
|
|
||||||
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
|
|
||||||
CONFIG_USB_COMMON=y
|
|
||||||
CONFIG_USB_DWC2=y
|
|
||||||
CONFIG_USB_DWC2_DUAL_ROLE=y
|
|
||||||
# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
|
|
||||||
CONFIG_USB_EHCI_HCD=y
|
|
||||||
# CONFIG_USB_EHCI_HCD_PLATFORM is not set
|
|
||||||
# CONFIG_USB_ETH is not set
|
|
||||||
CONFIG_USB_GADGET=y
|
|
||||||
CONFIG_USB_STORAGE=y
|
|
||||||
CONFIG_USB_SUPPORT=y
|
|
||||||
CONFIG_USER_NS=y
|
|
||||||
CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y
|
|
||||||
CONFIG_USE_OF=y
|
|
||||||
CONFIG_WATCHDOG_CORE=y
|
|
||||||
CONFIG_WEAK_ORDERING=y
|
|
||||||
CONFIG_XPS=y
|
|
||||||
CONFIG_ZLIB_DEFLATE=y
|
|
||||||
CONFIG_ZLIB_INFLATE=y
|
|
||||||
CONFIG_ZSMALLOC=y
|
|
||||||
# CONFIG_ZSMALLOC_STAT is not set
|
|
|
@ -1,983 +0,0 @@
|
||||||
From 8efda11baddf344cbfab01dc016a8fef9bb64641 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rahul Bedarkar <rahul.bedarkar@imgtec.com>
|
|
||||||
Date: Fri, 14 Oct 2016 11:25:54 +0530
|
|
||||||
Subject: MIPS: DTS: Add base device tree for Pistachio SoC
|
|
||||||
|
|
||||||
Add support for the base Device Tree for Imagination Technologies'
|
|
||||||
Pistachio SoC.
|
|
||||||
|
|
||||||
This commit supports the following peripherals:
|
|
||||||
|
|
||||||
* Clocks
|
|
||||||
* Pinctrl and GPIO
|
|
||||||
* UART
|
|
||||||
* SPI
|
|
||||||
* I2C
|
|
||||||
* PWM
|
|
||||||
* ADC
|
|
||||||
* Watchdog
|
|
||||||
* Ethernet
|
|
||||||
* MMC
|
|
||||||
* DMA engine
|
|
||||||
* Crypto
|
|
||||||
* I2S
|
|
||||||
* SPDIF
|
|
||||||
* Internal DAC
|
|
||||||
* Timer
|
|
||||||
* USB
|
|
||||||
* IR
|
|
||||||
* Interrupt Controller
|
|
||||||
|
|
||||||
Signed-off-by: Rahul Bedarkar <rahul.bedarkar@imgtec.com>
|
|
||||||
Acked-by: James Hartley <james.hartley@imgtec.com>
|
|
||||||
Cc: Rob Herring <robh+dt@kernel.org>
|
|
||||||
Cc: Mark Rutland <mark.rutland@arm.com>
|
|
||||||
Cc: linux-mips@linux-mips.org
|
|
||||||
Cc: devicetree@vger.kernel.org
|
|
||||||
Cc: linux-kernel@vger.kernel.org
|
|
||||||
Patchwork: https://patchwork.linux-mips.org/patch/14393/
|
|
||||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
|
||||||
---
|
|
||||||
MAINTAINERS | 2 +-
|
|
||||||
arch/mips/boot/dts/img/pistachio.dtsi | 924 ++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 925 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 arch/mips/boot/dts/img/pistachio.dtsi
|
|
||||||
|
|
||||||
--- a/MAINTAINERS
|
|
||||||
+++ b/MAINTAINERS
|
|
||||||
@@ -9569,7 +9569,7 @@ L: linux-mips@linux-mips.org
|
|
||||||
S: Maintained
|
|
||||||
F: arch/mips/pistachio/
|
|
||||||
F: arch/mips/include/asm/mach-pistachio/
|
|
||||||
-F: arch/mips/boot/dts/pistachio/
|
|
||||||
+F: arch/mips/boot/dts/img/pistachio*
|
|
||||||
F: arch/mips/configs/pistachio*_defconfig
|
|
||||||
|
|
||||||
PKTCDVD DRIVER
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/mips/boot/dts/img/pistachio.dtsi
|
|
||||||
@@ -0,0 +1,924 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2015, 2016 Imagination Technologies Ltd.
|
|
||||||
+ * Copyright (C) 2015 Google, Inc.
|
|
||||||
+ *
|
|
||||||
+ * 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.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <dt-bindings/clock/pistachio-clk.h>
|
|
||||||
+#include <dt-bindings/gpio/gpio.h>
|
|
||||||
+#include <dt-bindings/interrupt-controller/irq.h>
|
|
||||||
+#include <dt-bindings/interrupt-controller/mips-gic.h>
|
|
||||||
+#include <dt-bindings/reset/pistachio-resets.h>
|
|
||||||
+
|
|
||||||
+/ {
|
|
||||||
+ compatible = "img,pistachio";
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <1>;
|
|
||||||
+
|
|
||||||
+ interrupt-parent = <&gic>;
|
|
||||||
+
|
|
||||||
+ cpus {
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+
|
|
||||||
+ cpu0: cpu@0 {
|
|
||||||
+ device_type = "cpu";
|
|
||||||
+ compatible = "mti,interaptiv";
|
|
||||||
+ reg = <0>;
|
|
||||||
+ clocks = <&clk_core CLK_MIPS_PLL>;
|
|
||||||
+ clock-names = "cpu";
|
|
||||||
+ clock-latency = <1000>;
|
|
||||||
+ operating-points = <
|
|
||||||
+ /* kHz uV(dummy) */
|
|
||||||
+ 546000 1150000
|
|
||||||
+ 520000 1100000
|
|
||||||
+ 494000 1000000
|
|
||||||
+ 468000 950000
|
|
||||||
+ 442000 900000
|
|
||||||
+ 416000 800000
|
|
||||||
+ >;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c0: i2c@18100000 {
|
|
||||||
+ compatible = "img,scb-i2c";
|
|
||||||
+ reg = <0x18100000 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 2 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_I2C0>,
|
|
||||||
+ <&cr_periph SYS_CLK_I2C0>;
|
|
||||||
+ clock-names = "scb", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_I2C0_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_I2C0_DIV>;
|
|
||||||
+ assigned-clock-rates = <100000000>, <33333334>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2c0_pins>;
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c1: i2c@18100200 {
|
|
||||||
+ compatible = "img,scb-i2c";
|
|
||||||
+ reg = <0x18100200 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_I2C1>,
|
|
||||||
+ <&cr_periph SYS_CLK_I2C1>;
|
|
||||||
+ clock-names = "scb", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_I2C1_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_I2C1_DIV>;
|
|
||||||
+ assigned-clock-rates = <100000000>, <33333334>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2c1_pins>;
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c2: i2c@18100400 {
|
|
||||||
+ compatible = "img,scb-i2c";
|
|
||||||
+ reg = <0x18100400 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_I2C2>,
|
|
||||||
+ <&cr_periph SYS_CLK_I2C2>;
|
|
||||||
+ clock-names = "scb", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_I2C2_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_I2C2_DIV>;
|
|
||||||
+ assigned-clock-rates = <100000000>, <33333334>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2c2_pins>;
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c3: i2c@18100600 {
|
|
||||||
+ compatible = "img,scb-i2c";
|
|
||||||
+ reg = <0x18100600 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 5 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_I2C3>,
|
|
||||||
+ <&cr_periph SYS_CLK_I2C3>;
|
|
||||||
+ clock-names = "scb", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_I2C3_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_I2C3_DIV>;
|
|
||||||
+ assigned-clock-rates = <100000000>, <33333334>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2c3_pins>;
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2s_in: i2s-in@18100800 {
|
|
||||||
+ compatible = "img,i2s-in";
|
|
||||||
+ reg = <0x18100800 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 7 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 30 0xffffffff 0>;
|
|
||||||
+ dma-names = "rx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_I2S_IN>;
|
|
||||||
+ clock-names = "sys";
|
|
||||||
+ img,i2s-channels = <6>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2s_in_pins>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2s_out: i2s-out@18100a00 {
|
|
||||||
+ compatible = "img,i2s-out";
|
|
||||||
+ reg = <0x18100a00 0x200>;
|
|
||||||
+ interrupts = <GIC_SHARED 13 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 23 0xffffffff 0>;
|
|
||||||
+ dma-names = "tx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_I2S_OUT>,
|
|
||||||
+ <&clk_core CLK_I2S>;
|
|
||||||
+ clock-names = "sys", "ref";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_I2S_DIV>;
|
|
||||||
+ assigned-clock-rates = <12288000>;
|
|
||||||
+ img,i2s-channels = <6>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&i2s_out_pins>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ resets = <&pistachio_reset PISTACHIO_RESET_I2S_OUT>;
|
|
||||||
+ reset-names = "rst";
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ parallel_out: parallel-audio-out@18100c00 {
|
|
||||||
+ compatible = "img,parallel-out";
|
|
||||||
+ reg = <0x18100c00 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 19 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 16 0xffffffff 0>;
|
|
||||||
+ dma-names = "tx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_PAUD_OUT>,
|
|
||||||
+ <&clk_core CLK_AUDIO_DAC>;
|
|
||||||
+ clock-names = "sys", "ref";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_AUDIO_DAC_DIV>;
|
|
||||||
+ assigned-clock-rates = <12288000>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ resets = <&pistachio_reset PISTACHIO_RESET_PRL_OUT>;
|
|
||||||
+ reset-names = "rst";
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spdif_out: spdif-out@18100d00 {
|
|
||||||
+ compatible = "img,spdif-out";
|
|
||||||
+ reg = <0x18100d00 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 21 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 14 0xffffffff 0>;
|
|
||||||
+ dma-names = "tx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_SPDIF_OUT>,
|
|
||||||
+ <&clk_core CLK_SPDIF>;
|
|
||||||
+ clock-names = "sys", "ref";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_SPDIF_DIV>;
|
|
||||||
+ assigned-clock-rates = <12288000>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&spdif_out_pin>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ resets = <&pistachio_reset PISTACHIO_RESET_SPDIF_OUT>;
|
|
||||||
+ reset-names = "rst";
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spdif_in: spdif-in@18100e00 {
|
|
||||||
+ compatible = "img,spdif-in";
|
|
||||||
+ reg = <0x18100e00 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 20 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 15 0xffffffff 0>;
|
|
||||||
+ dma-names = "rx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_SPDIF_IN>;
|
|
||||||
+ clock-names = "sys";
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ pinctrl-0 = <&spdif_in_pin>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ internal_dac: internal-dac {
|
|
||||||
+ compatible = "img,pistachio-internal-dac";
|
|
||||||
+ img,cr-top = <&cr_top>;
|
|
||||||
+ img,voltage-select = <1>;
|
|
||||||
+
|
|
||||||
+ #sound-dai-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spfi0: spi@18100f00 {
|
|
||||||
+ compatible = "img,spfi";
|
|
||||||
+ reg = <0x18100f00 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 22 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_core CLK_SPI0>, <&cr_periph SYS_CLK_SPI0_MASTER>;
|
|
||||||
+ clock-names = "sys", "spfi";
|
|
||||||
+ dmas = <&mdc 9 0xffffffff 0>, <&mdc 10 0xffffffff 0>;
|
|
||||||
+ dma-names = "rx", "tx";
|
|
||||||
+ spfi-max-frequency = <50000000>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spfi1: spi@18101000 {
|
|
||||||
+ compatible = "img,spfi";
|
|
||||||
+ reg = <0x18101000 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 26 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_core CLK_SPI1>, <&cr_periph SYS_CLK_SPI1>;
|
|
||||||
+ clock-names = "sys", "spfi";
|
|
||||||
+ dmas = <&mdc 1 0xffffffff 0>, <&mdc 2 0xffffffff 0>;
|
|
||||||
+ dma-names = "rx", "tx";
|
|
||||||
+ img,supports-quad-mode;
|
|
||||||
+ spfi-max-frequency = <50000000>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pwm: pwm@18101300 {
|
|
||||||
+ compatible = "img,pistachio-pwm";
|
|
||||||
+ reg = <0x18101300 0x100>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_PWM>,
|
|
||||||
+ <&cr_periph SYS_CLK_PWM>;
|
|
||||||
+ clock-names = "pwm", "sys";
|
|
||||||
+ img,cr-periph = <&cr_periph>;
|
|
||||||
+ #pwm-cells = <2>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart0: uart@18101400 {
|
|
||||||
+ compatible = "snps,dw-apb-uart";
|
|
||||||
+ reg = <0x18101400 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_core CLK_UART0>, <&cr_periph SYS_CLK_UART0>;
|
|
||||||
+ clock-names = "baudclk", "apb_pclk";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_UART0_INTERNAL_DIV>,
|
|
||||||
+ <&clk_core CLK_UART0_DIV>;
|
|
||||||
+ reg-shift = <2>;
|
|
||||||
+ reg-io-width = <4>;
|
|
||||||
+ pinctrl-0 = <&uart0_pins>, <&uart0_rts_cts_pins>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart1: uart@18101500 {
|
|
||||||
+ compatible = "snps,dw-apb-uart";
|
|
||||||
+ reg = <0x18101500 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_core CLK_UART1>, <&cr_periph SYS_CLK_UART1>;
|
|
||||||
+ clock-names = "baudclk", "apb_pclk";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_UART1_INTERNAL_DIV>,
|
|
||||||
+ <&clk_core CLK_UART1_DIV>;
|
|
||||||
+ assigned-clock-rates = <114278400>, <1843200>;
|
|
||||||
+ reg-shift = <2>;
|
|
||||||
+ reg-io-width = <4>;
|
|
||||||
+ pinctrl-0 = <&uart1_pins>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ adc: adc@18101600 {
|
|
||||||
+ compatible = "cosmic,10001-adc";
|
|
||||||
+ reg = <0x18101600 0x24>;
|
|
||||||
+ adc-reserved-channels = <0x30>;
|
|
||||||
+ clocks = <&clk_core CLK_AUX_ADC>;
|
|
||||||
+ clock-names = "adc";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_AUX_ADC_INTERNAL_DIV>,
|
|
||||||
+ <&clk_core CLK_AUX_ADC_DIV>;
|
|
||||||
+ assigned-clock-rates = <100000000>, <1000000>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+
|
|
||||||
+ #io-channel-cells = <1>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pinctrl: pinctrl@18101c00 {
|
|
||||||
+ compatible = "img,pistachio-system-pinctrl";
|
|
||||||
+ reg = <0x18101c00 0x400>;
|
|
||||||
+
|
|
||||||
+ gpio0: gpio0 {
|
|
||||||
+ interrupts = <GIC_SHARED 71 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 0 16>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gpio1: gpio1 {
|
|
||||||
+ interrupts = <GIC_SHARED 72 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 16 16>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gpio2: gpio2 {
|
|
||||||
+ interrupts = <GIC_SHARED 73 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 32 16>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gpio3: gpio3 {
|
|
||||||
+ interrupts = <GIC_SHARED 74 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 48 16>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gpio4: gpio4 {
|
|
||||||
+ interrupts = <GIC_SHARED 75 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 64 16>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gpio5: gpio5 {
|
|
||||||
+ interrupts = <GIC_SHARED 76 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+
|
|
||||||
+ gpio-controller;
|
|
||||||
+ #gpio-cells = <2>;
|
|
||||||
+ gpio-ranges = <&pinctrl 0 80 10>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <2>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c0_pins: i2c0-pins {
|
|
||||||
+ pin_i2c0: i2c0 {
|
|
||||||
+ pins = "mfio28", "mfio29";
|
|
||||||
+ function = "i2c0";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c1_pins: i2c1-pins {
|
|
||||||
+ pin_i2c1: i2c1 {
|
|
||||||
+ pins = "mfio30", "mfio31";
|
|
||||||
+ function = "i2c1";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c2_pins: i2c2-pins {
|
|
||||||
+ pin_i2c2: i2c2 {
|
|
||||||
+ pins = "mfio32", "mfio33";
|
|
||||||
+ function = "i2c2";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2c3_pins: i2c3-pins {
|
|
||||||
+ pin_i2c3: i2c3 {
|
|
||||||
+ pins = "mfio34", "mfio35";
|
|
||||||
+ function = "i2c3";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_pins: spim0-pins {
|
|
||||||
+ pin_spim0: spim0 {
|
|
||||||
+ pins = "mfio9", "mfio10";
|
|
||||||
+ function = "spim0";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ spim0_clk: spim0-clk {
|
|
||||||
+ pins = "mfio8";
|
|
||||||
+ function = "spim0";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs0_alt_pin: spim0-cs0-alt-pin {
|
|
||||||
+ spim0-cs0 {
|
|
||||||
+ pins = "mfio2";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs1_pin: spim0-cs1-pin {
|
|
||||||
+ spim0-cs1 {
|
|
||||||
+ pins = "mfio1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs2_pin: spim0-cs2-pin {
|
|
||||||
+ spim0-cs2 {
|
|
||||||
+ pins = "mfio55";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs2_alt_pin: spim0-cs2-alt-pin {
|
|
||||||
+ spim0-cs2 {
|
|
||||||
+ pins = "mfio28";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs3_pin: spim0-cs3-pin {
|
|
||||||
+ spim0-cs3 {
|
|
||||||
+ pins = "mfio56";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs3_alt_pin: spim0-cs3-alt-pin {
|
|
||||||
+ spim0-cs3 {
|
|
||||||
+ pins = "mfio29";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs4_pin: spim0-cs4-pin {
|
|
||||||
+ spim0-cs4 {
|
|
||||||
+ pins = "mfio57";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim0_cs4_alt_pin: spim0-cs4-alt-pin {
|
|
||||||
+ spim0-cs4 {
|
|
||||||
+ pins = "mfio30";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_pins: spim1-pins {
|
|
||||||
+ spim1 {
|
|
||||||
+ pins = "mfio3", "mfio4", "mfio5";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_quad_pins: spim1-quad-pins {
|
|
||||||
+ spim1-quad {
|
|
||||||
+ pins = "mfio6", "mfio7";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs0_pin: spim1-cs0-pins {
|
|
||||||
+ spim1-cs0 {
|
|
||||||
+ pins = "mfio0";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs1_pin: spim1-cs1-pin {
|
|
||||||
+ spim1-cs1 {
|
|
||||||
+ pins = "mfio1";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs1_alt_pin: spim1-cs1-alt-pin {
|
|
||||||
+ spim1-cs1 {
|
|
||||||
+ pins = "mfio58";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs2_pin: spim1-cs2-pin {
|
|
||||||
+ spim1-cs2 {
|
|
||||||
+ pins = "mfio2";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs2_alt0_pin: spim1-cs2-alt0-pin {
|
|
||||||
+ spim1-cs2 {
|
|
||||||
+ pins = "mfio31";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs2_alt1_pin: spim1-cs2-alt1-pin {
|
|
||||||
+ spim1-cs2 {
|
|
||||||
+ pins = "mfio55";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs3_pin: spim1-cs3-pin {
|
|
||||||
+ spim1-cs3 {
|
|
||||||
+ pins = "mfio56";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spim1_cs4_pin: spim1-cs4-pin {
|
|
||||||
+ spim1-cs4 {
|
|
||||||
+ pins = "mfio57";
|
|
||||||
+ function = "spim1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart0_pins: uart0-pins {
|
|
||||||
+ uart0 {
|
|
||||||
+ pins = "mfio55", "mfio56";
|
|
||||||
+ function = "uart0";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart0_rts_cts_pins: uart0-rts-cts-pins {
|
|
||||||
+ uart0-rts-cts {
|
|
||||||
+ pins = "mfio57", "mfio58";
|
|
||||||
+ function = "uart0";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart1_pins: uart1-pins {
|
|
||||||
+ uart1 {
|
|
||||||
+ pins = "mfio59", "mfio60";
|
|
||||||
+ function = "uart1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ uart1_rts_cts_pins: uart1-rts-cts-pins {
|
|
||||||
+ uart1-rts-cts {
|
|
||||||
+ pins = "mfio1", "mfio2";
|
|
||||||
+ function = "uart1";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ enet_pins: enet-pins {
|
|
||||||
+ pin_enet: enet {
|
|
||||||
+ pins = "mfio63", "mfio64", "mfio65", "mfio66",
|
|
||||||
+ "mfio67", "mfio68", "mfio69", "mfio70";
|
|
||||||
+ function = "eth";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ pin_enet_phy_clk: enet-phy-clk {
|
|
||||||
+ pins = "mfio71";
|
|
||||||
+ function = "eth";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <8>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ sdhost_pins: sdhost-pins {
|
|
||||||
+ pin_sdhost_clk: sdhost-clk {
|
|
||||||
+ pins = "mfio15";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ pin_sdhost_cmd: sdhost-cmd {
|
|
||||||
+ pins = "mfio16";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ pin_sdhost_data: sdhost-data {
|
|
||||||
+ pins = "mfio17", "mfio18", "mfio19", "mfio20",
|
|
||||||
+ "mfio21", "mfio22", "mfio23", "mfio24";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ pin_sdhost_power_select: sdhost-power-select {
|
|
||||||
+ pins = "mfio25";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ pin_sdhost_card_detect: sdhost-card-detect {
|
|
||||||
+ pins = "mfio26";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ pin_sdhost_write_protect: sdhost-write-protect {
|
|
||||||
+ pins = "mfio27";
|
|
||||||
+ function = "sdhost";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ir_pin: ir-pin {
|
|
||||||
+ ir-data {
|
|
||||||
+ pins = "mfio72";
|
|
||||||
+ function = "ir";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pwmpdm0_pin: pwmpdm0-pin {
|
|
||||||
+ pwmpdm0 {
|
|
||||||
+ pins = "mfio73";
|
|
||||||
+ function = "pwmpdm";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pwmpdm1_pin: pwmpdm1-pin {
|
|
||||||
+ pwmpdm1 {
|
|
||||||
+ pins = "mfio74";
|
|
||||||
+ function = "pwmpdm";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pwmpdm2_pin: pwmpdm2-pin {
|
|
||||||
+ pwmpdm2 {
|
|
||||||
+ pins = "mfio75";
|
|
||||||
+ function = "pwmpdm";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ pwmpdm3_pin: pwmpdm3-pin {
|
|
||||||
+ pwmpdm3 {
|
|
||||||
+ pins = "mfio76";
|
|
||||||
+ function = "pwmpdm";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ dac_clk_pin: dac-clk-pin {
|
|
||||||
+ pin_dac_clk: dac-clk {
|
|
||||||
+ pins = "mfio45";
|
|
||||||
+ function = "i2s_dac_clk";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2s_mclk_pin: i2s-mclk-pin {
|
|
||||||
+ pin_i2s_mclk: i2s-mclk {
|
|
||||||
+ pins = "mfio36";
|
|
||||||
+ function = "i2s_out";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spdif_out_pin: spdif-out-pin {
|
|
||||||
+ spdif-out {
|
|
||||||
+ pins = "mfio61";
|
|
||||||
+ function = "spdif_out";
|
|
||||||
+ slew-rate = <1>;
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ spdif_in_pin: spdif-in-pin {
|
|
||||||
+ spdif-in {
|
|
||||||
+ pins = "mfio62";
|
|
||||||
+ function = "spdif_in";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2s_out_pins: i2s-out-pins {
|
|
||||||
+ pins_i2s_out_clk: i2s-out-clk {
|
|
||||||
+ pins = "mfio37", "mfio38";
|
|
||||||
+ function = "i2s_out";
|
|
||||||
+ drive-strength = <4>;
|
|
||||||
+ };
|
|
||||||
+ pins_i2s_out: i2s-out {
|
|
||||||
+ pins = "mfio39", "mfio40",
|
|
||||||
+ "mfio41", "mfio42",
|
|
||||||
+ "mfio43", "mfio44";
|
|
||||||
+ function = "i2s_out";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ i2s_in_pins: i2s-in-pins {
|
|
||||||
+ i2s-in {
|
|
||||||
+ pins = "mfio47", "mfio48", "mfio49",
|
|
||||||
+ "mfio50", "mfio51", "mfio52",
|
|
||||||
+ "mfio53", "mfio54";
|
|
||||||
+ function = "i2s_in";
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ timer: timer@18102000 {
|
|
||||||
+ compatible = "img,pistachio-gptimer";
|
|
||||||
+ reg = <0x18102000 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 60 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_COUNTER_FAST>,
|
|
||||||
+ <&cr_periph SYS_CLK_TIMER>;
|
|
||||||
+ clock-names = "fast", "sys";
|
|
||||||
+ img,cr-periph = <&cr_periph>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ wdt: watchdog@18102100 {
|
|
||||||
+ compatible = "img,pdc-wdt";
|
|
||||||
+ reg = <0x18102100 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 52 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_WD>, <&cr_periph SYS_CLK_WD>;
|
|
||||||
+ clock-names = "wdt", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_WD_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_WD_DIV>;
|
|
||||||
+ assigned-clock-rates = <4000000>, <32768>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ir: ir@18102200 {
|
|
||||||
+ compatible = "img,ir-rev1";
|
|
||||||
+ reg = <0x18102200 0x100>;
|
|
||||||
+ interrupts = <GIC_SHARED 51 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_IR>, <&cr_periph SYS_CLK_IR>;
|
|
||||||
+ clock-names = "core", "sys";
|
|
||||||
+ assigned-clocks = <&clk_periph PERIPH_CLK_IR_PRE_DIV>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_IR_DIV>;
|
|
||||||
+ assigned-clock-rates = <4000000>, <32768>;
|
|
||||||
+ pinctrl-0 = <&ir_pin>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ usb: usb@18120000 {
|
|
||||||
+ compatible = "snps,dwc2";
|
|
||||||
+ reg = <0x18120000 0x1c000>;
|
|
||||||
+ interrupts = <GIC_SHARED 49 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ phys = <&usb_phy>;
|
|
||||||
+ phy-names = "usb2-phy";
|
|
||||||
+ g-tx-fifo-size = <256 256 256 256>;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ enet: ethernet@18140000 {
|
|
||||||
+ compatible = "snps,dwmac";
|
|
||||||
+ reg = <0x18140000 0x2000>;
|
|
||||||
+ interrupts = <GIC_SHARED 50 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ interrupt-names = "macirq";
|
|
||||||
+ clocks = <&clk_core CLK_ENET>, <&cr_periph SYS_CLK_ENET>;
|
|
||||||
+ clock-names = "stmmaceth", "pclk";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_ENET_MUX>,
|
|
||||||
+ <&clk_core CLK_ENET_DIV>;
|
|
||||||
+ assigned-clock-parents = <&clk_core CLK_SYS_INTERNAL_DIV>;
|
|
||||||
+ assigned-clock-rates = <0>, <50000000>;
|
|
||||||
+ pinctrl-0 = <&enet_pins>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ phy-mode = "rmii";
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ sdhost: mmc@18142000 {
|
|
||||||
+ compatible = "img,pistachio-dw-mshc";
|
|
||||||
+ reg = <0x18142000 0x400>;
|
|
||||||
+ interrupts = <GIC_SHARED 39 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&clk_core CLK_SD_HOST>, <&cr_periph SYS_CLK_SD_HOST>;
|
|
||||||
+ clock-names = "ciu", "biu";
|
|
||||||
+ pinctrl-0 = <&sdhost_pins>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ fifo-depth = <0x20>;
|
|
||||||
+ num-slots = <1>;
|
|
||||||
+ clock-frequency = <50000000>;
|
|
||||||
+ bus-width = <8>;
|
|
||||||
+ cap-mmc-highspeed;
|
|
||||||
+ cap-sd-highspeed;
|
|
||||||
+ status = "disabled";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ sram: sram@1b000000 {
|
|
||||||
+ compatible = "mmio-sram";
|
|
||||||
+ reg = <0x1b000000 0x10000>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ mdc: dma-controller@18143000 {
|
|
||||||
+ compatible = "img,pistachio-mdc-dma";
|
|
||||||
+ reg = <0x18143000 0x1000>;
|
|
||||||
+ interrupts = <GIC_SHARED 27 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 28 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 29 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 30 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 31 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 32 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 33 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 34 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 35 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 36 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 37 IRQ_TYPE_LEVEL_HIGH>,
|
|
||||||
+ <GIC_SHARED 38 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_MDC>;
|
|
||||||
+ clock-names = "sys";
|
|
||||||
+
|
|
||||||
+ img,max-burst-multiplier = <16>;
|
|
||||||
+ img,cr-periph = <&cr_periph>;
|
|
||||||
+
|
|
||||||
+ #dma-cells = <3>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ clk_core: clk@18144000 {
|
|
||||||
+ compatible = "img,pistachio-clk", "syscon";
|
|
||||||
+ clocks = <&xtal>, <&cr_top EXT_CLK_AUDIO_IN>,
|
|
||||||
+ <&cr_top EXT_CLK_ENET_IN>;
|
|
||||||
+ clock-names = "xtal", "audio_refclk_ext_gate",
|
|
||||||
+ "ext_enet_in_gate";
|
|
||||||
+ reg = <0x18144000 0x800>;
|
|
||||||
+ #clock-cells = <1>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ clk_periph: clk@18144800 {
|
|
||||||
+ compatible = "img,pistachio-clk-periph";
|
|
||||||
+ reg = <0x18144800 0x1000>;
|
|
||||||
+ clocks = <&clk_core CLK_PERIPH_SYS>;
|
|
||||||
+ clock-names = "periph_sys_core";
|
|
||||||
+ #clock-cells = <1>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ cr_periph: clk@18148000 {
|
|
||||||
+ compatible = "img,pistachio-cr-periph", "syscon", "simple-bus";
|
|
||||||
+ reg = <0x18148000 0x1000>;
|
|
||||||
+ clocks = <&clk_periph PERIPH_CLK_SYS>;
|
|
||||||
+ clock-names = "sys";
|
|
||||||
+ #clock-cells = <1>;
|
|
||||||
+
|
|
||||||
+ pistachio_reset: reset-controller {
|
|
||||||
+ compatible = "img,pistachio-reset";
|
|
||||||
+ #reset-cells = <1>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ cr_top: clk@18149000 {
|
|
||||||
+ compatible = "img,pistachio-cr-top", "syscon";
|
|
||||||
+ reg = <0x18149000 0x200>;
|
|
||||||
+ #clock-cells = <1>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ hash: hash@18149600 {
|
|
||||||
+ compatible = "img,hash-accelerator";
|
|
||||||
+ reg = <0x18149600 0x100>, <0x18101100 0x4>;
|
|
||||||
+ interrupts = <GIC_SHARED 59 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
+ dmas = <&mdc 8 0xffffffff 0>;
|
|
||||||
+ dma-names = "tx";
|
|
||||||
+ clocks = <&cr_periph SYS_CLK_HASH>,
|
|
||||||
+ <&clk_periph PERIPH_CLK_ROM>;
|
|
||||||
+ clock-names = "sys", "hash";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ gic: interrupt-controller@1bdc0000 {
|
|
||||||
+ compatible = "mti,gic";
|
|
||||||
+ reg = <0x1bdc0000 0x20000>;
|
|
||||||
+
|
|
||||||
+ interrupt-controller;
|
|
||||||
+ #interrupt-cells = <3>;
|
|
||||||
+
|
|
||||||
+ timer {
|
|
||||||
+ compatible = "mti,gic-timer";
|
|
||||||
+ interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
|
|
||||||
+ clocks = <&clk_core CLK_MIPS>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ usb_phy: usb-phy {
|
|
||||||
+ compatible = "img,pistachio-usb-phy";
|
|
||||||
+ clocks = <&clk_core CLK_USB_PHY>;
|
|
||||||
+ clock-names = "usb_phy";
|
|
||||||
+ assigned-clocks = <&clk_core CLK_USB_PHY_DIV>;
|
|
||||||
+ assigned-clock-rates = <50000000>;
|
|
||||||
+ img,refclk = <0x2>;
|
|
||||||
+ img,cr-top = <&cr_top>;
|
|
||||||
+ #phy-cells = <0>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ xtal: xtal {
|
|
||||||
+ compatible = "fixed-clock";
|
|
||||||
+ #clock-cells = <0>;
|
|
||||||
+ clock-frequency = <52000000>;
|
|
||||||
+ clock-output-names = "xtal";
|
|
||||||
+ };
|
|
||||||
+};
|
|
|
@ -1,230 +0,0 @@
|
||||||
From a189771546b304250cf18b26748edfefb857adbf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rahul Bedarkar <rahul.bedarkar@imgtec.com>
|
|
||||||
Date: Fri, 14 Oct 2016 11:25:55 +0530
|
|
||||||
Subject: MIPS: DTS: img: add device tree for Marduk board
|
|
||||||
|
|
||||||
Add support for Imagination Technologies' Marduk board which is based
|
|
||||||
on Pistachio SoC. It is also known as Creator Ci40. Marduk is legacy
|
|
||||||
name and will be there for decades.
|
|
||||||
|
|
||||||
Documentation for this board can be found on
|
|
||||||
https://docs.creatordev.io/ci40/
|
|
||||||
|
|
||||||
This patch adds initial support for board with following peripherals:
|
|
||||||
|
|
||||||
* PWM based heartbeat LED
|
|
||||||
* GPIO based buttons
|
|
||||||
* SPI NOR flash on SPI1
|
|
||||||
* UART0 and UART1
|
|
||||||
* SD card
|
|
||||||
* Ethernet
|
|
||||||
* USB
|
|
||||||
* PWM
|
|
||||||
* ADC
|
|
||||||
* I2C
|
|
||||||
|
|
||||||
(apply from https://patchwork.linux-mips.org/project/linux-mips/list/?submitter=7165)
|
|
||||||
|
|
||||||
Signed-off-by: Rahul Bedarkar <rahul.bedarkar@imgtec.com>
|
|
||||||
Acked-by: Rob Herring <robh@kernel.org>
|
|
||||||
Acked-by: James Hartley <james.hartley@imgtec.com>
|
|
||||||
---
|
|
||||||
.../bindings/mips/img/pistachio-marduk.txt | 10 ++
|
|
||||||
arch/mips/boot/dts/img/Makefile | 9 ++
|
|
||||||
arch/mips/boot/dts/img/pistachio_marduk.dts | 163 +++++++++++++++++++++
|
|
||||||
3 files changed, 182 insertions(+)
|
|
||||||
create mode 100644 Documentation/devicetree/bindings/mips/img/pistachio-marduk.txt
|
|
||||||
create mode 100644 arch/mips/boot/dts/img/Makefile
|
|
||||||
create mode 100644 arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Documentation/devicetree/bindings/mips/img/pistachio-marduk.txt
|
|
||||||
@@ -0,0 +1,10 @@
|
|
||||||
+Imagination Technologies' Pistachio SoC based Marduk Board
|
|
||||||
+==========================================================
|
|
||||||
+
|
|
||||||
+Compatible string must be "img,pistachio-marduk", "img,pistachio"
|
|
||||||
+
|
|
||||||
+Hardware and other related documentation is available at
|
|
||||||
+https://docs.creatordev.io/ci40/
|
|
||||||
+
|
|
||||||
+It is also known as Creator Ci40. Marduk is legacy name and will
|
|
||||||
+be there for decades.
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/mips/boot/dts/img/Makefile
|
|
||||||
@@ -0,0 +1,9 @@
|
|
||||||
+dtb-$(CONFIG_MACH_PISTACHIO) += pistachio_marduk.dtb
|
|
||||||
+
|
|
||||||
+obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
|
|
||||||
+
|
|
||||||
+# Force kbuild to make empty built-in.o if necessary
|
|
||||||
+obj- += dummy.o
|
|
||||||
+
|
|
||||||
+always := $(dtb-y)
|
|
||||||
+clean-files := *.dtb *.dtb.S
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
@@ -0,0 +1,163 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2015, 2016 Imagination Technologies Ltd.
|
|
||||||
+ *
|
|
||||||
+ * 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.
|
|
||||||
+ *
|
|
||||||
+ * IMG Marduk board is also known as Creator Ci40.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+/dts-v1/;
|
|
||||||
+
|
|
||||||
+#include "pistachio.dtsi"
|
|
||||||
+
|
|
||||||
+/ {
|
|
||||||
+ model = "IMG Marduk (Creator Ci40)";
|
|
||||||
+ compatible = "img,pistachio-marduk", "img,pistachio";
|
|
||||||
+
|
|
||||||
+ aliases {
|
|
||||||
+ serial0 = &uart0;
|
|
||||||
+ serial1 = &uart1;
|
|
||||||
+ ethernet0 = &enet;
|
|
||||||
+ spi0 = &spfi0;
|
|
||||||
+ spi1 = &spfi1;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ chosen {
|
|
||||||
+ bootargs = "root=/dev/sda1 rootwait ro lpj=723968";
|
|
||||||
+ stdout-path = "serial1:115200";
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ memory {
|
|
||||||
+ device_type = "memory";
|
|
||||||
+ reg = <0x00000000 0x10000000>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ reg_1v8: fixed-regulator {
|
|
||||||
+ compatible = "regulator-fixed";
|
|
||||||
+ regulator-name = "aux_adc_vref";
|
|
||||||
+ regulator-min-microvolt = <1800000>;
|
|
||||||
+ regulator-max-microvolt = <1800000>;
|
|
||||||
+ regulator-boot-on;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ internal_dac_supply: internal-dac-supply {
|
|
||||||
+ compatible = "regulator-fixed";
|
|
||||||
+ regulator-name = "internal_dac_supply";
|
|
||||||
+ regulator-min-microvolt = <1800000>;
|
|
||||||
+ regulator-max-microvolt = <1800000>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ leds {
|
|
||||||
+ compatible = "pwm-leds";
|
|
||||||
+ heartbeat {
|
|
||||||
+ label = "marduk:red:heartbeat";
|
|
||||||
+ pwms = <&pwm 3 300000>;
|
|
||||||
+ max-brightness = <255>;
|
|
||||||
+ linux,default-trigger = "heartbeat";
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ keys {
|
|
||||||
+ compatible = "gpio-keys";
|
|
||||||
+ button@1 {
|
|
||||||
+ label = "Button 1";
|
|
||||||
+ linux,code = <0x101>; /* BTN_1 */
|
|
||||||
+ gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
|
|
||||||
+ };
|
|
||||||
+ button@2 {
|
|
||||||
+ label = "Button 2";
|
|
||||||
+ linux,code = <0x102>; /* BTN_2 */
|
|
||||||
+ gpios = <&gpio2 14 GPIO_ACTIVE_LOW>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&internal_dac {
|
|
||||||
+ VDD-supply = <&internal_dac_supply>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&spfi1 {
|
|
||||||
+ status = "okay";
|
|
||||||
+
|
|
||||||
+ pinctrl-0 = <&spim1_pins>, <&spim1_quad_pins>, <&spim1_cs0_pin>,
|
|
||||||
+ <&spim1_cs1_pin>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+ cs-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>, <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
|
||||||
+
|
|
||||||
+ flash@0 {
|
|
||||||
+ compatible = "spansion,s25fl016k", "jedec,spi-nor";
|
|
||||||
+ reg = <0>;
|
|
||||||
+ spi-max-frequency = <50000000>;
|
|
||||||
+ };
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&uart0 {
|
|
||||||
+ status = "okay";
|
|
||||||
+ assigned-clock-rates = <114278400>, <1843200>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&uart1 {
|
|
||||||
+ status = "okay";
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&usb {
|
|
||||||
+ status = "okay";
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&enet {
|
|
||||||
+ status = "okay";
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&pin_enet {
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&pin_enet_phy_clk {
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&sdhost {
|
|
||||||
+ status = "okay";
|
|
||||||
+ bus-width = <4>;
|
|
||||||
+ disable-wp;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&pin_sdhost_cmd {
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&pin_sdhost_data {
|
|
||||||
+ drive-strength = <2>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&pwm {
|
|
||||||
+ status = "okay";
|
|
||||||
+
|
|
||||||
+ pinctrl-0 = <&pwmpdm0_pin>, <&pwmpdm1_pin>, <&pwmpdm2_pin>,
|
|
||||||
+ <&pwmpdm3_pin>;
|
|
||||||
+ pinctrl-names = "default";
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&adc {
|
|
||||||
+ status = "okay";
|
|
||||||
+ vref-supply = <®_1v8>;
|
|
||||||
+ adc-reserved-channels = <0x10>;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&i2c2 {
|
|
||||||
+ status = "okay";
|
|
||||||
+ clock-frequency = <400000>;
|
|
||||||
+
|
|
||||||
+ tpm@20 {
|
|
||||||
+ compatible = "infineon,slb9645tt";
|
|
||||||
+ reg = <0x20>;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+&i2c3 {
|
|
||||||
+ status = "okay";
|
|
||||||
+ clock-frequency = <400000>;
|
|
||||||
+};
|
|
|
@ -1,22 +0,0 @@
|
||||||
From a907fdeb3f057e4c4b3960ca864b460dc1fa687a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
Date: Thu, 16 Feb 2017 10:42:22 +0000
|
|
||||||
Subject: MIPS: DTS: add img directory to Makefile
|
|
||||||
|
|
||||||
An img directory exists for the Pistchio Soc but the directory
|
|
||||||
itself isn't in the dts Makefile meaning the dtbs never get built.
|
|
||||||
|
|
||||||
Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
---
|
|
||||||
arch/mips/boot/dts/Makefile | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
--- a/arch/mips/boot/dts/Makefile
|
|
||||||
+++ b/arch/mips/boot/dts/Makefile
|
|
||||||
@@ -1,5 +1,6 @@
|
|
||||||
dts-dirs += brcm
|
|
||||||
dts-dirs += cavium-octeon
|
|
||||||
+dts-dirs += img
|
|
||||||
dts-dirs += ingenic
|
|
||||||
dts-dirs += lantiq
|
|
||||||
dts-dirs += mti
|
|
|
@ -1,68 +0,0 @@
|
||||||
From a2dd154377c9aa6ddda00d39b8c7c334e4fa16ff Mon Sep 17 00:00:00 2001
|
|
||||||
From: Damien Horsley <damien.horsley@imgtec.com>
|
|
||||||
Date: Tue, 22 Mar 2016 12:46:09 +0000
|
|
||||||
Subject: dmaengine: img-mdc: Handle early status read
|
|
||||||
|
|
||||||
It is possible that mdc_tx_status may be called before the first
|
|
||||||
node has been read from memory.
|
|
||||||
|
|
||||||
In this case, the residue value stored in the register is undefined.
|
|
||||||
Return the transfer size instead.
|
|
||||||
|
|
||||||
Signed-off-by: Damien Horsley <damien.horsley@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/dma/img-mdc-dma.c | 40 ++++++++++++++++++++++++----------------
|
|
||||||
1 file changed, 24 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/dma/img-mdc-dma.c
|
|
||||||
+++ b/drivers/dma/img-mdc-dma.c
|
|
||||||
@@ -623,25 +623,33 @@ static enum dma_status mdc_tx_status(str
|
|
||||||
(MDC_CMDS_PROCESSED_CMDS_DONE_MASK + 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * If the command loaded event hasn't been processed yet, then
|
|
||||||
- * the difference above includes an extra command.
|
|
||||||
+ * If the first node has not yet been read from memory,
|
|
||||||
+ * the residue register value is undefined
|
|
||||||
*/
|
|
||||||
- if (!mdesc->cmd_loaded)
|
|
||||||
- cmds--;
|
|
||||||
- else
|
|
||||||
- cmds += mdesc->list_cmds_done;
|
|
||||||
-
|
|
||||||
- bytes = mdesc->list_xfer_size;
|
|
||||||
- ldesc = mdesc->list;
|
|
||||||
- for (i = 0; i < cmds; i++) {
|
|
||||||
- bytes -= ldesc->xfer_size + 1;
|
|
||||||
- ldesc = ldesc->next_desc;
|
|
||||||
- }
|
|
||||||
- if (ldesc) {
|
|
||||||
- if (residue != MDC_TRANSFER_SIZE_MASK)
|
|
||||||
- bytes -= ldesc->xfer_size - residue;
|
|
||||||
+ if (!mdesc->cmd_loaded && !cmds) {
|
|
||||||
+ bytes = mdesc->list_xfer_size;
|
|
||||||
+ } else {
|
|
||||||
+ /*
|
|
||||||
+ * If the command loaded event hasn't been processed yet, then
|
|
||||||
+ * the difference above includes an extra command.
|
|
||||||
+ */
|
|
||||||
+ if (!mdesc->cmd_loaded)
|
|
||||||
+ cmds--;
|
|
||||||
else
|
|
||||||
+ cmds += mdesc->list_cmds_done;
|
|
||||||
+
|
|
||||||
+ bytes = mdesc->list_xfer_size;
|
|
||||||
+ ldesc = mdesc->list;
|
|
||||||
+ for (i = 0; i < cmds; i++) {
|
|
||||||
bytes -= ldesc->xfer_size + 1;
|
|
||||||
+ ldesc = ldesc->next_desc;
|
|
||||||
+ }
|
|
||||||
+ if (ldesc) {
|
|
||||||
+ if (residue != MDC_TRANSFER_SIZE_MASK)
|
|
||||||
+ bytes -= ldesc->xfer_size - residue;
|
|
||||||
+ else
|
|
||||||
+ bytes -= ldesc->xfer_size + 1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&mchan->vc.lock, flags);
|
|
|
@ -1,198 +0,0 @@
|
||||||
From cd2a6af51553d38072cd31699b58d16ca6176ef5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Date: Thu, 2 Feb 2017 16:46:14 +0000
|
|
||||||
Subject: spi: img-spfi: Implement dual and quad mode
|
|
||||||
|
|
||||||
For dual and quad modes to work the SPFI controller needs
|
|
||||||
to have information about command/address/dummy bytes in the
|
|
||||||
transaction register. This information is not relevant for
|
|
||||||
single mode, and therefore it can have any value in the
|
|
||||||
allowed range. Therefore, for any read or write transfers of less
|
|
||||||
than 8 bytes (cmd = 1 byte, addr up to 7 bytes), SPFI will be
|
|
||||||
configured, but not enabled (unless it is the last transfer in
|
|
||||||
the queue). The transfer will be enabled by the subsequent tranfer.
|
|
||||||
A pending transfer is determined by the content of the transaction
|
|
||||||
register: if command part is set and tsize is not.
|
|
||||||
|
|
||||||
This way we ensure that for dual and quad transactions
|
|
||||||
the command request size will apear in the command/address part
|
|
||||||
of the transaction register, while the data size will be in
|
|
||||||
tsize, all data being sent/received in the same transaction (as
|
|
||||||
set up in the transaction register).
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-img-spfi.c | 96 ++++++++++++++++++++++++++++++++++++++++------
|
|
||||||
1 file changed, 85 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-img-spfi.c
|
|
||||||
+++ b/drivers/spi/spi-img-spfi.c
|
|
||||||
@@ -40,7 +40,8 @@
|
|
||||||
#define SPFI_CONTROL_SOFT_RESET BIT(11)
|
|
||||||
#define SPFI_CONTROL_SEND_DMA BIT(10)
|
|
||||||
#define SPFI_CONTROL_GET_DMA BIT(9)
|
|
||||||
-#define SPFI_CONTROL_SE BIT(8)
|
|
||||||
+#define SPFI_CONTROL_SE BIT(8)
|
|
||||||
+#define SPFI_CONTROL_TX_RX BIT(1)
|
|
||||||
#define SPFI_CONTROL_TMODE_SHIFT 5
|
|
||||||
#define SPFI_CONTROL_TMODE_MASK 0x7
|
|
||||||
#define SPFI_CONTROL_TMODE_SINGLE 0
|
|
||||||
@@ -51,6 +52,10 @@
|
|
||||||
#define SPFI_TRANSACTION 0x18
|
|
||||||
#define SPFI_TRANSACTION_TSIZE_SHIFT 16
|
|
||||||
#define SPFI_TRANSACTION_TSIZE_MASK 0xffff
|
|
||||||
+#define SPFI_TRANSACTION_CMD_SHIFT 13
|
|
||||||
+#define SPFI_TRANSACTION_CMD_MASK 0x7
|
|
||||||
+#define SPFI_TRANSACTION_ADDR_SHIFT 10
|
|
||||||
+#define SPFI_TRANSACTION_ADDR_MASK 0x7
|
|
||||||
|
|
||||||
#define SPFI_PORT_STATE 0x1c
|
|
||||||
#define SPFI_PORT_STATE_DEV_SEL_SHIFT 20
|
|
||||||
@@ -87,6 +92,7 @@
|
|
||||||
*/
|
|
||||||
#define SPFI_32BIT_FIFO_SIZE 64
|
|
||||||
#define SPFI_8BIT_FIFO_SIZE 16
|
|
||||||
+#define SPFI_DATA_REQUEST_MAX_SIZE 8
|
|
||||||
|
|
||||||
struct img_spfi {
|
|
||||||
struct device *dev;
|
|
||||||
@@ -103,6 +109,8 @@ struct img_spfi {
|
|
||||||
struct dma_chan *tx_ch;
|
|
||||||
bool tx_dma_busy;
|
|
||||||
bool rx_dma_busy;
|
|
||||||
+
|
|
||||||
+ bool complete;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct img_spfi_device_data {
|
|
||||||
@@ -123,9 +131,11 @@ static inline void spfi_start(struct img
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
- val = spfi_readl(spfi, SPFI_CONTROL);
|
|
||||||
- val |= SPFI_CONTROL_SPFI_EN;
|
|
||||||
- spfi_writel(spfi, val, SPFI_CONTROL);
|
|
||||||
+ if (spfi->complete) {
|
|
||||||
+ val = spfi_readl(spfi, SPFI_CONTROL);
|
|
||||||
+ val |= SPFI_CONTROL_SPFI_EN;
|
|
||||||
+ spfi_writel(spfi, val, SPFI_CONTROL);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void spfi_reset(struct img_spfi *spfi)
|
|
||||||
@@ -138,12 +148,21 @@ static int spfi_wait_all_done(struct img
|
|
||||||
{
|
|
||||||
unsigned long timeout = jiffies + msecs_to_jiffies(50);
|
|
||||||
|
|
||||||
+ if (!(spfi->complete))
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
u32 status = spfi_readl(spfi, SPFI_INTERRUPT_STATUS);
|
|
||||||
|
|
||||||
if (status & SPFI_INTERRUPT_ALLDONETRIG) {
|
|
||||||
spfi_writel(spfi, SPFI_INTERRUPT_ALLDONETRIG,
|
|
||||||
SPFI_INTERRUPT_CLEAR);
|
|
||||||
+ /*
|
|
||||||
+ * Disable SPFI for it not to interfere with
|
|
||||||
+ * pending transactions
|
|
||||||
+ */
|
|
||||||
+ spfi_writel(spfi, spfi_readl(spfi, SPFI_CONTROL)
|
|
||||||
+ & ~SPFI_CONTROL_SPFI_EN, SPFI_CONTROL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cpu_relax();
|
|
||||||
@@ -494,9 +513,32 @@ static void img_spfi_config(struct spi_m
|
|
||||||
struct spi_transfer *xfer)
|
|
||||||
{
|
|
||||||
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
|
|
||||||
- u32 val, div;
|
|
||||||
+ u32 val, div, transact;
|
|
||||||
+ bool is_pending;
|
|
||||||
|
|
||||||
/*
|
|
||||||
+ * For read or write transfers of less than 8 bytes (cmd = 1 byte,
|
|
||||||
+ * addr up to 7 bytes), SPFI will be configured, but not enabled
|
|
||||||
+ * (unless it is the last transfer in the queue).The transfer will
|
|
||||||
+ * be enabled by the subsequent transfer.
|
|
||||||
+ * A pending transfer is determined by the content of the
|
|
||||||
+ * transaction register: if command part is set and tsize
|
|
||||||
+ * is not
|
|
||||||
+ */
|
|
||||||
+ transact = spfi_readl(spfi, SPFI_TRANSACTION);
|
|
||||||
+ is_pending = ((transact >> SPFI_TRANSACTION_CMD_SHIFT) &
|
|
||||||
+ SPFI_TRANSACTION_CMD_MASK) &&
|
|
||||||
+ (!((transact >> SPFI_TRANSACTION_TSIZE_SHIFT) &
|
|
||||||
+ SPFI_TRANSACTION_TSIZE_MASK));
|
|
||||||
+
|
|
||||||
+ /* If there are no pending transactions it's OK to soft reset */
|
|
||||||
+ if (!is_pending) {
|
|
||||||
+ /* Start the transaction from a known (reset) state */
|
|
||||||
+ spfi_reset(spfi);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Before anything else, set up parameters.
|
|
||||||
* output = spfi_clk * (BITCLK / 512), where BITCLK must be a
|
|
||||||
* power of 2 up to 128
|
|
||||||
*/
|
|
||||||
@@ -509,20 +551,52 @@ static void img_spfi_config(struct spi_m
|
|
||||||
val |= div << SPFI_DEVICE_PARAMETER_BITCLK_SHIFT;
|
|
||||||
spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(spi->chip_select));
|
|
||||||
|
|
||||||
- spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
|
|
||||||
- SPFI_TRANSACTION);
|
|
||||||
+ if (!list_is_last(&xfer->transfer_list, &master->cur_msg->transfers) &&
|
|
||||||
+ /*
|
|
||||||
+ * For duplex mode (both the tx and rx buffers are !NULL) the
|
|
||||||
+ * CMD, ADDR, and DUMMY byte parts of the transaction register
|
|
||||||
+ * should always be 0 and therefore the pending transfer
|
|
||||||
+ * technique cannot be used.
|
|
||||||
+ */
|
|
||||||
+ (xfer->tx_buf) && (!xfer->rx_buf) &&
|
|
||||||
+ (xfer->len <= SPFI_DATA_REQUEST_MAX_SIZE) && !is_pending) {
|
|
||||||
+ transact = (1 & SPFI_TRANSACTION_CMD_MASK) <<
|
|
||||||
+ SPFI_TRANSACTION_CMD_SHIFT;
|
|
||||||
+ transact |= ((xfer->len - 1) & SPFI_TRANSACTION_ADDR_MASK) <<
|
|
||||||
+ SPFI_TRANSACTION_ADDR_SHIFT;
|
|
||||||
+ spfi->complete = false;
|
|
||||||
+ } else {
|
|
||||||
+ spfi->complete = true;
|
|
||||||
+ if (is_pending) {
|
|
||||||
+ /* Keep setup from pending transfer */
|
|
||||||
+ transact |= ((xfer->len & SPFI_TRANSACTION_TSIZE_MASK) <<
|
|
||||||
+ SPFI_TRANSACTION_TSIZE_SHIFT);
|
|
||||||
+ } else {
|
|
||||||
+ transact = ((xfer->len & SPFI_TRANSACTION_TSIZE_MASK) <<
|
|
||||||
+ SPFI_TRANSACTION_TSIZE_SHIFT);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ spfi_writel(spfi, transact, SPFI_TRANSACTION);
|
|
||||||
|
|
||||||
val = spfi_readl(spfi, SPFI_CONTROL);
|
|
||||||
val &= ~(SPFI_CONTROL_SEND_DMA | SPFI_CONTROL_GET_DMA);
|
|
||||||
- if (xfer->tx_buf)
|
|
||||||
+ /*
|
|
||||||
+ * We set up send DMA for pending transfers also, as
|
|
||||||
+ * those are always send transfers
|
|
||||||
+ */
|
|
||||||
+ if ((xfer->tx_buf) || is_pending)
|
|
||||||
val |= SPFI_CONTROL_SEND_DMA;
|
|
||||||
- if (xfer->rx_buf)
|
|
||||||
+ if (xfer->tx_buf)
|
|
||||||
+ val |= SPFI_CONTROL_TX_RX;
|
|
||||||
+ if (xfer->rx_buf) {
|
|
||||||
val |= SPFI_CONTROL_GET_DMA;
|
|
||||||
+ val &= ~SPFI_CONTROL_TX_RX;
|
|
||||||
+ }
|
|
||||||
val &= ~(SPFI_CONTROL_TMODE_MASK << SPFI_CONTROL_TMODE_SHIFT);
|
|
||||||
- if (xfer->tx_nbits == SPI_NBITS_DUAL &&
|
|
||||||
+ if (xfer->tx_nbits == SPI_NBITS_DUAL ||
|
|
||||||
xfer->rx_nbits == SPI_NBITS_DUAL)
|
|
||||||
val |= SPFI_CONTROL_TMODE_DUAL << SPFI_CONTROL_TMODE_SHIFT;
|
|
||||||
- else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
|
|
||||||
+ else if (xfer->tx_nbits == SPI_NBITS_QUAD ||
|
|
||||||
xfer->rx_nbits == SPI_NBITS_QUAD)
|
|
||||||
val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
|
|
||||||
val |= SPFI_CONTROL_SE;
|
|
|
@ -1,27 +0,0 @@
|
||||||
From 145f5369510b86cd55c659388a26a0cc267f8874 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Date: Mon, 1 Feb 2016 10:58:08 +0000
|
|
||||||
Subject: spi: img-spfi: set device select bits for SPFI port state
|
|
||||||
|
|
||||||
Even if the chip select line is not controlled by the SPFI
|
|
||||||
hardware, the device select bits need to be set to specify
|
|
||||||
the chip select line in use for the hardware to know what
|
|
||||||
parameters to use for the current transfer.
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-img-spfi.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-img-spfi.c
|
|
||||||
+++ b/drivers/spi/spi-img-spfi.c
|
|
||||||
@@ -438,6 +438,9 @@ static int img_spfi_prepare(struct spi_m
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
val = spfi_readl(spfi, SPFI_PORT_STATE);
|
|
||||||
+ val &= ~(SPFI_PORT_STATE_DEV_SEL_MASK <<
|
|
||||||
+ SPFI_PORT_STATE_DEV_SEL_SHIFT);
|
|
||||||
+ val |= msg->spi->chip_select << SPFI_PORT_STATE_DEV_SEL_SHIFT;
|
|
||||||
if (msg->spi->mode & SPI_CPHA)
|
|
||||||
val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
|
|
||||||
else
|
|
|
@ -1,64 +0,0 @@
|
||||||
From 905ee06a9966113fe51d6bad1819759cb30fd0bd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Date: Tue, 9 Feb 2016 10:18:31 +0000
|
|
||||||
Subject: spi: img-spfi: use device 0 configuration for all devices
|
|
||||||
|
|
||||||
Given that we control the chip select line externally
|
|
||||||
we can use only one parameter register (device 0 parameter
|
|
||||||
register) and one set of configuration bits (port configuration
|
|
||||||
bits for device 0) for all devices (all chip select lines).
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-img-spfi.c | 23 ++++++++++++++++-------
|
|
||||||
1 file changed, 16 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-img-spfi.c
|
|
||||||
+++ b/drivers/spi/spi-img-spfi.c
|
|
||||||
@@ -437,18 +437,23 @@ static int img_spfi_prepare(struct spi_m
|
|
||||||
struct img_spfi *spfi = spi_master_get_devdata(master);
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * The chip select line is controlled externally so
|
|
||||||
+ * we can use the CS0 configuration for all devices
|
|
||||||
+ */
|
|
||||||
val = spfi_readl(spfi, SPFI_PORT_STATE);
|
|
||||||
+
|
|
||||||
+ /* 0 for device selection */
|
|
||||||
val &= ~(SPFI_PORT_STATE_DEV_SEL_MASK <<
|
|
||||||
SPFI_PORT_STATE_DEV_SEL_SHIFT);
|
|
||||||
- val |= msg->spi->chip_select << SPFI_PORT_STATE_DEV_SEL_SHIFT;
|
|
||||||
if (msg->spi->mode & SPI_CPHA)
|
|
||||||
- val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
|
|
||||||
+ val |= SPFI_PORT_STATE_CK_PHASE(0);
|
|
||||||
else
|
|
||||||
- val &= ~SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
|
|
||||||
+ val &= ~SPFI_PORT_STATE_CK_PHASE(0);
|
|
||||||
if (msg->spi->mode & SPI_CPOL)
|
|
||||||
- val |= SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
|
|
||||||
+ val |= SPFI_PORT_STATE_CK_POL(0);
|
|
||||||
else
|
|
||||||
- val &= ~SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
|
|
||||||
+ val &= ~SPFI_PORT_STATE_CK_POL(0);
|
|
||||||
spfi_writel(spfi, val, SPFI_PORT_STATE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -548,11 +553,15 @@ static void img_spfi_config(struct spi_m
|
|
||||||
div = DIV_ROUND_UP(clk_get_rate(spfi->spfi_clk), xfer->speed_hz);
|
|
||||||
div = clamp(512 / (1 << get_count_order(div)), 1, 128);
|
|
||||||
|
|
||||||
- val = spfi_readl(spfi, SPFI_DEVICE_PARAMETER(spi->chip_select));
|
|
||||||
+ /*
|
|
||||||
+ * The chip select line is controlled externally so
|
|
||||||
+ * we can use the CS0 parameters for all devices
|
|
||||||
+ */
|
|
||||||
+ val = spfi_readl(spfi, SPFI_DEVICE_PARAMETER(0));
|
|
||||||
val &= ~(SPFI_DEVICE_PARAMETER_BITCLK_MASK <<
|
|
||||||
SPFI_DEVICE_PARAMETER_BITCLK_SHIFT);
|
|
||||||
val |= div << SPFI_DEVICE_PARAMETER_BITCLK_SHIFT;
|
|
||||||
- spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(spi->chip_select));
|
|
||||||
+ spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(0));
|
|
||||||
|
|
||||||
if (!list_is_last(&xfer->transfer_list, &master->cur_msg->transfers) &&
|
|
||||||
/*
|
|
|
@ -1,59 +0,0 @@
|
||||||
From 56466f505f58f44b69feb7eaed3b506842800456 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Date: Tue, 1 Mar 2016 17:49:45 +0000
|
|
||||||
Subject: spi: img-spfi: RX maximum burst size for DMA is 8
|
|
||||||
|
|
||||||
The depth of the FIFOs is 16 bytes. The DMA request line is tied
|
|
||||||
to the half full/empty (depending on the use of the TX or RX FIFO)
|
|
||||||
threshold. For the TX FIFO, if you set a burst size of 8 (equal to
|
|
||||||
half the depth) the first burst goes into FIFO without any issues,
|
|
||||||
but due the latency involved (the time the data leaves the DMA
|
|
||||||
engine to the time it arrives at the FIFO), the DMA might trigger
|
|
||||||
another burst of 8. But given that there is no space for 2 additonal
|
|
||||||
bursts of 8, this would result in a failure. Therefore, we have to
|
|
||||||
keep the burst size for TX to 4 to accomodate for an extra burst.
|
|
||||||
|
|
||||||
For the read (RX) scenario, the DMA request line goes high when
|
|
||||||
there is at least 8 entries in the FIFO (half full), and we can
|
|
||||||
program the burst size to be 8 because the risk of accidental burst
|
|
||||||
does not exist. The DMA engine will not trigger another read until
|
|
||||||
the read data for all the burst it has sent out has been received.
|
|
||||||
|
|
||||||
While here, move the burst size setting outside of the if/else branches
|
|
||||||
as they have the same value for both 8 and 32 bit data widths.
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-img-spfi.c | 6 ++----
|
|
||||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-img-spfi.c
|
|
||||||
+++ b/drivers/spi/spi-img-spfi.c
|
|
||||||
@@ -346,12 +346,11 @@ static int img_spfi_start_dma(struct spi
|
|
||||||
if (xfer->len % 4 == 0) {
|
|
||||||
rxconf.src_addr = spfi->phys + SPFI_RX_32BIT_VALID_DATA;
|
|
||||||
rxconf.src_addr_width = 4;
|
|
||||||
- rxconf.src_maxburst = 4;
|
|
||||||
} else {
|
|
||||||
rxconf.src_addr = spfi->phys + SPFI_RX_8BIT_VALID_DATA;
|
|
||||||
rxconf.src_addr_width = 1;
|
|
||||||
- rxconf.src_maxburst = 4;
|
|
||||||
}
|
|
||||||
+ rxconf.src_maxburst = 8;
|
|
||||||
dmaengine_slave_config(spfi->rx_ch, &rxconf);
|
|
||||||
|
|
||||||
rxdesc = dmaengine_prep_slave_sg(spfi->rx_ch, xfer->rx_sg.sgl,
|
|
||||||
@@ -370,12 +369,11 @@ static int img_spfi_start_dma(struct spi
|
|
||||||
if (xfer->len % 4 == 0) {
|
|
||||||
txconf.dst_addr = spfi->phys + SPFI_TX_32BIT_VALID_DATA;
|
|
||||||
txconf.dst_addr_width = 4;
|
|
||||||
- txconf.dst_maxburst = 4;
|
|
||||||
} else {
|
|
||||||
txconf.dst_addr = spfi->phys + SPFI_TX_8BIT_VALID_DATA;
|
|
||||||
txconf.dst_addr_width = 1;
|
|
||||||
- txconf.dst_maxburst = 4;
|
|
||||||
}
|
|
||||||
+ txconf.dst_maxburst = 4;
|
|
||||||
dmaengine_slave_config(spfi->tx_ch, &txconf);
|
|
||||||
|
|
||||||
txdesc = dmaengine_prep_slave_sg(spfi->tx_ch, xfer->tx_sg.sgl,
|
|
|
@ -1,120 +0,0 @@
|
||||||
From 5fcca3fd4b621d7b5bdeca18d36dfc6ca6cfe383 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Date: Wed, 10 Aug 2016 11:42:26 +0100
|
|
||||||
Subject: spi: img-spfi: finish every transfer cleanly
|
|
||||||
|
|
||||||
Before this change, the interrupt status bit that signaled
|
|
||||||
the end of a tranfers was cleared in the wait_all_done
|
|
||||||
function. That functionality triggered issues for DMA
|
|
||||||
duplex transactions where the wait function was called
|
|
||||||
twice, in both the TX and RX callbacks.
|
|
||||||
|
|
||||||
In order to fix the issue, clear all interrupt data bits
|
|
||||||
at the end of a PIO transfer or at the end of both TX and RX
|
|
||||||
duplex transfers, if the transfer is not a pending tranfer
|
|
||||||
(command waiting for data). After that, the status register
|
|
||||||
is checked for new incoming data or new data requests to be
|
|
||||||
signaled. If SPFI finished cleanly, no new interrupt data
|
|
||||||
bits should be set.
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-img-spfi.c | 49 +++++++++++++++++++++++++++++++++-------------
|
|
||||||
1 file changed, 35 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-img-spfi.c
|
|
||||||
+++ b/drivers/spi/spi-img-spfi.c
|
|
||||||
@@ -83,6 +83,14 @@
|
|
||||||
#define SPFI_INTERRUPT_SDE BIT(1)
|
|
||||||
#define SPFI_INTERRUPT_SDTRIG BIT(0)
|
|
||||||
|
|
||||||
+#define SPFI_INTERRUPT_DATA_BITS (SPFI_INTERRUPT_SDHF |\
|
|
||||||
+ SPFI_INTERRUPT_SDFUL |\
|
|
||||||
+ SPFI_INTERRUPT_GDEX32BIT |\
|
|
||||||
+ SPFI_INTERRUPT_GDHF |\
|
|
||||||
+ SPFI_INTERRUPT_GDFUL |\
|
|
||||||
+ SPFI_INTERRUPT_ALLDONETRIG |\
|
|
||||||
+ SPFI_INTERRUPT_GDEX8BIT)
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* There are four parallel FIFOs of 16 bytes each. The word buffer
|
|
||||||
* (*_32BIT_VALID_DATA) accesses all four FIFOs at once, resulting in an
|
|
||||||
@@ -144,6 +152,23 @@ static inline void spfi_reset(struct img
|
|
||||||
spfi_writel(spfi, 0, SPFI_CONTROL);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline void spfi_finish(struct img_spfi *spfi)
|
|
||||||
+{
|
|
||||||
+ if (!(spfi->complete))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* Clear data bits as all transfers(TX and RX) have finished */
|
|
||||||
+ spfi_writel(spfi, SPFI_INTERRUPT_DATA_BITS, SPFI_INTERRUPT_CLEAR);
|
|
||||||
+ if (spfi_readl(spfi, SPFI_INTERRUPT_STATUS) & SPFI_INTERRUPT_DATA_BITS) {
|
|
||||||
+ dev_err(spfi->dev, "SPFI did not finish transfer cleanly.\n");
|
|
||||||
+ spfi_reset(spfi);
|
|
||||||
+ }
|
|
||||||
+ /* Disable SPFI for it not to interfere with pending transactions */
|
|
||||||
+ spfi_writel(spfi,
|
|
||||||
+ spfi_readl(spfi, SPFI_CONTROL) & ~SPFI_CONTROL_SPFI_EN,
|
|
||||||
+ SPFI_CONTROL);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int spfi_wait_all_done(struct img_spfi *spfi)
|
|
||||||
{
|
|
||||||
unsigned long timeout = jiffies + msecs_to_jiffies(50);
|
|
||||||
@@ -152,19 +177,9 @@ static int spfi_wait_all_done(struct img
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (time_before(jiffies, timeout)) {
|
|
||||||
- u32 status = spfi_readl(spfi, SPFI_INTERRUPT_STATUS);
|
|
||||||
-
|
|
||||||
- if (status & SPFI_INTERRUPT_ALLDONETRIG) {
|
|
||||||
- spfi_writel(spfi, SPFI_INTERRUPT_ALLDONETRIG,
|
|
||||||
- SPFI_INTERRUPT_CLEAR);
|
|
||||||
- /*
|
|
||||||
- * Disable SPFI for it not to interfere with
|
|
||||||
- * pending transactions
|
|
||||||
- */
|
|
||||||
- spfi_writel(spfi, spfi_readl(spfi, SPFI_CONTROL)
|
|
||||||
- & ~SPFI_CONTROL_SPFI_EN, SPFI_CONTROL);
|
|
||||||
+ if (spfi_readl(spfi, SPFI_INTERRUPT_STATUS) &
|
|
||||||
+ SPFI_INTERRUPT_ALLDONETRIG)
|
|
||||||
return 0;
|
|
||||||
- }
|
|
||||||
cpu_relax();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -296,6 +311,8 @@ static int img_spfi_start_pio(struct spi
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = spfi_wait_all_done(spfi);
|
|
||||||
+ spfi_finish(spfi);
|
|
||||||
+
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
@@ -311,8 +328,10 @@ static void img_spfi_dma_rx_cb(void *dat
|
|
||||||
|
|
||||||
spin_lock_irqsave(&spfi->lock, flags);
|
|
||||||
spfi->rx_dma_busy = false;
|
|
||||||
- if (!spfi->tx_dma_busy)
|
|
||||||
+ if (!spfi->tx_dma_busy) {
|
|
||||||
+ spfi_finish(spfi);
|
|
||||||
spi_finalize_current_transfer(spfi->master);
|
|
||||||
+ }
|
|
||||||
spin_unlock_irqrestore(&spfi->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -325,8 +344,10 @@ static void img_spfi_dma_tx_cb(void *dat
|
|
||||||
|
|
||||||
spin_lock_irqsave(&spfi->lock, flags);
|
|
||||||
spfi->tx_dma_busy = false;
|
|
||||||
- if (!spfi->rx_dma_busy)
|
|
||||||
+ if (!spfi->rx_dma_busy) {
|
|
||||||
+ spfi_finish(spfi);
|
|
||||||
spi_finalize_current_transfer(spfi->master);
|
|
||||||
+ }
|
|
||||||
spin_unlock_irqrestore(&spfi->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
From b46f8c74afdd30cd52bfdcc2231470a0bab04416 Mon Sep 17 00:00:00 2001
|
|
||||||
From: James Hogan <james.hogan@imgtec.com>
|
|
||||||
Date: Fri, 22 Apr 2016 18:22:45 +0100
|
|
||||||
Subject: clockevents: Retry programming min delta up to 10 times
|
|
||||||
|
|
||||||
Under virtualisation it is possible to get unexpected latency during a
|
|
||||||
clockevent device's set_next_event() callback which can make it return
|
|
||||||
-ETIME even for a delta based on min_delta_ns.
|
|
||||||
|
|
||||||
The clockevents_program_min_delta() implementation for
|
|
||||||
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=n doesn't handle retries when this
|
|
||||||
happens, nor does clockevents_program_event() or its callers when force
|
|
||||||
is true (for example hrtimer_reprogram()). This can result in hangs
|
|
||||||
until the clock event device does a full period.
|
|
||||||
|
|
||||||
It isn't appropriate to use MIN_ADJUST in this case as occasional
|
|
||||||
hypervisor induced high latency will cause min_delta_ns to quickly
|
|
||||||
increase to the maximum.
|
|
||||||
Instead, borrow the retry pattern from the MIN_ADJUST case, but without
|
|
||||||
making adjustments. We retry up to 10 times before giving up.
|
|
||||||
|
|
||||||
(picked https://patchwork.kernel.org/patch/8909491/)
|
|
||||||
|
|
||||||
Signed-off-by: James Hogan <james.hogan@imgtec.com>
|
|
||||||
---
|
|
||||||
kernel/time/clockevents.c | 26 +++++++++++++++++++-------
|
|
||||||
1 file changed, 19 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
--- a/kernel/time/clockevents.c
|
|
||||||
+++ b/kernel/time/clockevents.c
|
|
||||||
@@ -281,16 +281,28 @@ static int clockevents_program_min_delta
|
|
||||||
{
|
|
||||||
unsigned long long clc;
|
|
||||||
int64_t delta;
|
|
||||||
+ int i;
|
|
||||||
|
|
||||||
- delta = dev->min_delta_ns;
|
|
||||||
- dev->next_event = ktime_add_ns(ktime_get(), delta);
|
|
||||||
+ for (i = 0;;) {
|
|
||||||
+ delta = dev->min_delta_ns;
|
|
||||||
+ dev->next_event = ktime_add_ns(ktime_get(), delta);
|
|
||||||
|
|
||||||
- if (clockevent_state_shutdown(dev))
|
|
||||||
- return 0;
|
|
||||||
+ if (clockevent_state_shutdown(dev))
|
|
||||||
+ return 0;
|
|
||||||
|
|
||||||
- dev->retries++;
|
|
||||||
- clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
|
|
||||||
- return dev->set_next_event((unsigned long) clc, dev);
|
|
||||||
+ dev->retries++;
|
|
||||||
+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
|
|
||||||
+ if (dev->set_next_event((unsigned long) clc, dev) == 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ if (++i > 9) {
|
|
||||||
+ /*
|
|
||||||
+ * We tried 10 times to program the device with the
|
|
||||||
+ * given min_delta_ns. Get out of here.
|
|
||||||
+ */
|
|
||||||
+ return -ETIME;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
|
|
|
@ -1,49 +0,0 @@
|
||||||
From 3642843a06025ec333d7e92580cf52cb8db2a652 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Govindraj Raja <Govindraj.Raja@imgtec.com>
|
|
||||||
Date: Fri, 8 Jan 2016 16:36:07 +0000
|
|
||||||
Subject: clk: pistachio: Fix wrong SDHost card speed
|
|
||||||
|
|
||||||
The SDHost currently clocks the card 4x slower than it
|
|
||||||
should do, because there is fixed divide by 4 in the
|
|
||||||
sdhost wrapper that is not present in the clock tree.
|
|
||||||
To model this add a fixed divide by 4 clock node in
|
|
||||||
the SDHost clock path.
|
|
||||||
|
|
||||||
This will ensure the right clock frequency is selected when
|
|
||||||
the mmc driver tries to configure frequency on card insert.
|
|
||||||
|
|
||||||
Signed-off-by: Govindraj Raja <Govindraj.Raja@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/clk/pistachio/clk-pistachio.c | 3 ++-
|
|
||||||
include/dt-bindings/clock/pistachio-clk.h | 1 +
|
|
||||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/drivers/clk/pistachio/clk-pistachio.c
|
|
||||||
+++ b/drivers/clk/pistachio/clk-pistachio.c
|
|
||||||
@@ -44,7 +44,7 @@ static struct pistachio_gate pistachio_g
|
|
||||||
GATE(CLK_AUX_ADC_INTERNAL, "aux_adc_internal", "sys_internal_div",
|
|
||||||
0x104, 22),
|
|
||||||
GATE(CLK_AUX_ADC, "aux_adc", "aux_adc_div", 0x104, 23),
|
|
||||||
- GATE(CLK_SD_HOST, "sd_host", "sd_host_div", 0x104, 24),
|
|
||||||
+ GATE(CLK_SD_HOST, "sd_host", "sd_host_div4", 0x104, 24),
|
|
||||||
GATE(CLK_BT, "bt", "bt_div", 0x104, 25),
|
|
||||||
GATE(CLK_BT_DIV4, "bt_div4", "bt_div4_div", 0x104, 26),
|
|
||||||
GATE(CLK_BT_DIV8, "bt_div8", "bt_div8_div", 0x104, 27),
|
|
||||||
@@ -54,6 +54,7 @@ static struct pistachio_gate pistachio_g
|
|
||||||
static struct pistachio_fixed_factor pistachio_ffs[] __initdata = {
|
|
||||||
FIXED_FACTOR(CLK_WIFI_DIV4, "wifi_div4", "wifi_pll", 4),
|
|
||||||
FIXED_FACTOR(CLK_WIFI_DIV8, "wifi_div8", "wifi_pll", 8),
|
|
||||||
+ FIXED_FACTOR(CLK_SDHOST_DIV4, "sd_host_div4", "sd_host_div", 4),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pistachio_div pistachio_divs[] __initdata = {
|
|
||||||
--- a/include/dt-bindings/clock/pistachio-clk.h
|
|
||||||
+++ b/include/dt-bindings/clock/pistachio-clk.h
|
|
||||||
@@ -21,6 +21,7 @@
|
|
||||||
/* Fixed-factor clocks */
|
|
||||||
#define CLK_WIFI_DIV4 16
|
|
||||||
#define CLK_WIFI_DIV8 17
|
|
||||||
+#define CLK_SDHOST_DIV4 18
|
|
||||||
|
|
||||||
/* Gate clocks */
|
|
||||||
#define CLK_MIPS 32
|
|
|
@ -1,47 +0,0 @@
|
||||||
From 981c1d416af45eff207227aec106381ac23aac99 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
Date: Mon, 20 Feb 2017 10:00:52 +0000
|
|
||||||
Subject: MIPS: DTS: img: marduk: switch mmc to 1 bit mode
|
|
||||||
|
|
||||||
The mmc block in Pistachio allows 1 to 8 data bits to be used.
|
|
||||||
Marduk uses 4 bits allowing the upper 4 bits to be allocated
|
|
||||||
to the Mikrobus ports. However these bits are still connected
|
|
||||||
internally meaning the mmc block recieves signals on all data lines
|
|
||||||
and seems the internal HW CRC checks get corrupted by this erroneous
|
|
||||||
data.
|
|
||||||
|
|
||||||
We cannot control what data is sent on these lines because they go
|
|
||||||
to external ports. 1 bit mode does not exhibit the issue hence the
|
|
||||||
safe default is to use this. If a user knows that in their use case
|
|
||||||
they will not use the upper bits then they can set to 4 bit mode in
|
|
||||||
order to improve performance.
|
|
||||||
|
|
||||||
Also make sure that the upper 4 bits don't get allocated to the mmc
|
|
||||||
driver (the default is to assign all 8 pins) so they can be allocated
|
|
||||||
to other drivers. Allocating all 4 despite setting 1 bit mode as this
|
|
||||||
matches what is there in hardware.
|
|
||||||
|
|
||||||
Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
---
|
|
||||||
arch/mips/boot/dts/img/pistachio_marduk.dts | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
+++ b/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
@@ -120,7 +120,7 @@
|
|
||||||
|
|
||||||
&sdhost {
|
|
||||||
status = "okay";
|
|
||||||
- bus-width = <4>;
|
|
||||||
+ bus-width = <1>;
|
|
||||||
disable-wp;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -130,6 +130,7 @@
|
|
||||||
|
|
||||||
&pin_sdhost_data {
|
|
||||||
drive-strength = <2>;
|
|
||||||
+ pins = "mfio17", "mfio18", "mfio19", "mfio20";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pwm {
|
|
|
@ -1,34 +0,0 @@
|
||||||
From f32bc2aa01edcba2f2ed5db151cf183eac9ef919 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com>
|
|
||||||
Date: Sat, 25 Feb 2017 16:42:50 +0000
|
|
||||||
Subject: mtd: nor: support mtd name from device tree
|
|
||||||
|
|
||||||
Signed-off-by: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/mtd/spi-nor/spi-nor.c | 8 +++++++-
|
|
||||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
|
||||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
|
||||||
@@ -1541,6 +1541,7 @@ int spi_nor_scan(struct spi_nor *nor, co
|
|
||||||
struct device *dev = nor->dev;
|
|
||||||
struct mtd_info *mtd = &nor->mtd;
|
|
||||||
struct device_node *np = spi_nor_get_flash_node(nor);
|
|
||||||
+ const char __maybe_unused *of_mtd_name = NULL;
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
@@ -1606,7 +1607,12 @@ int spi_nor_scan(struct spi_nor *nor, co
|
|
||||||
spi_nor_wait_till_ready(nor);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!mtd->name)
|
|
||||||
+#ifdef CONFIG_MTD_OF_PARTS
|
|
||||||
+ of_property_read_string(np, "linux,mtd-name", &of_mtd_name);
|
|
||||||
+#endif
|
|
||||||
+ if (of_mtd_name)
|
|
||||||
+ mtd->name = of_mtd_name;
|
|
||||||
+ else if (!mtd->name)
|
|
||||||
mtd->name = dev_name(dev);
|
|
||||||
mtd->priv = nor;
|
|
||||||
mtd->type = MTD_NORFLASH;
|
|
|
@ -1,33 +0,0 @@
|
||||||
From 42ebff638003be18fab503b37de4ad7853244e95 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Date: Sat, 25 Feb 2017 15:58:22 +0000
|
|
||||||
Subject: mtd: nand: Check length of ID before reading bits per cell
|
|
||||||
|
|
||||||
The table-based NAND identification currently reads the number
|
|
||||||
of bits per cell from the 3rd byte of the extended ID. This is done
|
|
||||||
for the so-called 'full ID' devices; i.e. devices that have a known
|
|
||||||
length ID.
|
|
||||||
|
|
||||||
However, if the ID length is shorter than three, there's no 3rd byte,
|
|
||||||
and so it's wrong to read the bits per cell from there. Fix this by
|
|
||||||
adding a check for the ID length.
|
|
||||||
|
|
||||||
(picked from http://lists.infradead.org/pipermail/linux-mtd/2014-December/056764.html)
|
|
||||||
|
|
||||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/mtd/nand/nand_base.c | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/drivers/mtd/nand/nand_base.c
|
|
||||||
+++ b/drivers/mtd/nand/nand_base.c
|
|
||||||
@@ -4046,7 +4046,8 @@ static bool find_full_id_nand(struct mtd
|
|
||||||
mtd->erasesize = type->erasesize;
|
|
||||||
mtd->oobsize = type->oobsize;
|
|
||||||
|
|
||||||
- chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
|
|
||||||
+ if (type->id_len > 2)
|
|
||||||
+ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
|
|
||||||
chip->chipsize = (uint64_t)type->chipsize << 20;
|
|
||||||
chip->options |= type->options;
|
|
||||||
chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
|
|
|
@ -1,35 +0,0 @@
|
||||||
From a4bc33b205fd9b1db862f1e45173dba57b0fa57f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Date: Sat, 25 Feb 2017 15:43:09 +0000
|
|
||||||
Subject: mtd: nand: Add JEDEC manufacturer ID for Gigadevice
|
|
||||||
|
|
||||||
This commit adds Gigadevice to the list of manufacturer ID and name strings.
|
|
||||||
|
|
||||||
(picked from http://lists.infradead.org/pipermail/linux-mtd/2014-December/056765.html)
|
|
||||||
|
|
||||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/mtd/nand/nand_ids.c | 1 +
|
|
||||||
include/linux/mtd/nand.h | 1 +
|
|
||||||
2 files changed, 2 insertions(+)
|
|
||||||
|
|
||||||
--- a/drivers/mtd/nand/nand_ids.c
|
|
||||||
+++ b/drivers/mtd/nand/nand_ids.c
|
|
||||||
@@ -182,6 +182,7 @@ struct nand_manufacturers nand_manuf_ids
|
|
||||||
{NAND_MFR_SANDISK, "SanDisk"},
|
|
||||||
{NAND_MFR_INTEL, "Intel"},
|
|
||||||
{NAND_MFR_ATO, "ATO"},
|
|
||||||
+ {NAND_MFR_GIGADEVICE, "Gigadevice"},
|
|
||||||
{NAND_MFR_WINBOND, "Winbond"},
|
|
||||||
{0x0, "Unknown"}
|
|
||||||
};
|
|
||||||
--- a/include/linux/mtd/nand.h
|
|
||||||
+++ b/include/linux/mtd/nand.h
|
|
||||||
@@ -928,6 +928,7 @@ static inline void nand_set_controller_d
|
|
||||||
#define NAND_MFR_SANDISK 0x45
|
|
||||||
#define NAND_MFR_INTEL 0x89
|
|
||||||
#define NAND_MFR_ATO 0x9b
|
|
||||||
+#define NAND_MFR_GIGADEVICE 0xc8
|
|
||||||
#define NAND_MFR_WINBOND 0xef
|
|
||||||
|
|
||||||
/* The maximum expected count of bytes in the NAND ID sequence */
|
|
|
@ -1,706 +0,0 @@
|
||||||
From 082a89a78e29b15008284df90441747cb742f149 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Date: Tue, 2 Dec 2014 09:58:52 -0300
|
|
||||||
Subject: mtd: Introduce SPI NAND framework
|
|
||||||
|
|
||||||
Add a new framework, to support SPI NAND devices. The framework registers
|
|
||||||
a NAND chip and handles the generic SPI NAND protocol, calling device-specific
|
|
||||||
hooks for each SPI NAND command.
|
|
||||||
|
|
||||||
The following is the stack design, from userspace to hardware. This commit
|
|
||||||
adds the "SPI NAND core" layer.
|
|
||||||
|
|
||||||
Userspace
|
|
||||||
------------------
|
|
||||||
MTD
|
|
||||||
------------------
|
|
||||||
NAND core
|
|
||||||
------------------
|
|
||||||
SPI NAND core
|
|
||||||
------------------
|
|
||||||
SPI NAND device
|
|
||||||
------------------
|
|
||||||
SPI core
|
|
||||||
------------------
|
|
||||||
SPI master
|
|
||||||
------------------
|
|
||||||
Hardware
|
|
||||||
|
|
||||||
(based on http://lists.infradead.org/pipermail/linux-mtd/2014-December/056763.html)
|
|
||||||
|
|
||||||
Signed-off-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
|
|
||||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/mtd/Kconfig | 2 +
|
|
||||||
drivers/mtd/Makefile | 1 +
|
|
||||||
drivers/mtd/spi-nand/Kconfig | 7 +
|
|
||||||
drivers/mtd/spi-nand/Makefile | 1 +
|
|
||||||
drivers/mtd/spi-nand/spi-nand-base.c | 566 +++++++++++++++++++++++++++++++++++
|
|
||||||
include/linux/mtd/spi-nand.h | 54 ++++
|
|
||||||
6 files changed, 631 insertions(+)
|
|
||||||
create mode 100644 drivers/mtd/spi-nand/Kconfig
|
|
||||||
create mode 100644 drivers/mtd/spi-nand/Makefile
|
|
||||||
create mode 100644 drivers/mtd/spi-nand/spi-nand-base.c
|
|
||||||
create mode 100644 include/linux/mtd/spi-nand.h
|
|
||||||
|
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -373,6 +373,8 @@ source "drivers/mtd/onenand/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/mtd/lpddr/Kconfig"
|
|
||||||
|
|
||||||
+source "drivers/mtd/spi-nand/Kconfig"
|
|
||||||
+
|
|
||||||
source "drivers/mtd/spi-nor/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/mtd/ubi/Kconfig"
|
|
||||||
--- a/drivers/mtd/Makefile
|
|
||||||
+++ b/drivers/mtd/Makefile
|
|
||||||
@@ -36,5 +36,6 @@ inftl-objs := inftlcore.o inftlmount.o
|
|
||||||
|
|
||||||
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
|
|
||||||
|
|
||||||
+obj-$(CONFIG_MTD_SPI_NAND) += spi-nand/
|
|
||||||
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
|
|
||||||
obj-$(CONFIG_MTD_UBI) += ubi/
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/mtd/spi-nand/Kconfig
|
|
||||||
@@ -0,0 +1,7 @@
|
|
||||||
+menuconfig MTD_SPI_NAND
|
|
||||||
+ tristate "SPI NAND device support"
|
|
||||||
+ depends on MTD
|
|
||||||
+ select MTD_NAND
|
|
||||||
+ help
|
|
||||||
+ This is the framework for the SPI NAND.
|
|
||||||
+
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/mtd/spi-nand/Makefile
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+obj-$(CONFIG_MTD_SPI_NAND) += spi-nand-base.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/mtd/spi-nand/spi-nand-base.c
|
|
||||||
@@ -0,0 +1,566 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2014 Imagination Technologies Ltd.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; version 2 of the License.
|
|
||||||
+ *
|
|
||||||
+ * Notes:
|
|
||||||
+ * 1. Erase and program operations need to call write_enable() first,
|
|
||||||
+ * to clear the enable bit. This bit is cleared automatically after
|
|
||||||
+ * the erase or program operation.
|
|
||||||
+ *
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/device.h>
|
|
||||||
+#include <linux/err.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/mtd/nand.h>
|
|
||||||
+#include <linux/mtd/mtd.h>
|
|
||||||
+#include <linux/mtd/partitions.h>
|
|
||||||
+#include <linux/mtd/spi-nand.h>
|
|
||||||
+#include <linux/of.h>
|
|
||||||
+#include <linux/slab.h>
|
|
||||||
+
|
|
||||||
+/* Registers common to all devices */
|
|
||||||
+#define SPI_NAND_LOCK_REG 0xa0
|
|
||||||
+#define SPI_NAND_PROT_UNLOCK_ALL 0x0
|
|
||||||
+
|
|
||||||
+#define SPI_NAND_FEATURE_REG 0xb0
|
|
||||||
+#define SPI_NAND_ECC_EN BIT(4)
|
|
||||||
+#define SPI_NAND_QUAD_EN BIT(0)
|
|
||||||
+
|
|
||||||
+#define SPI_NAND_STATUS_REG 0xc0
|
|
||||||
+#define SPI_NAND_STATUS_REG_ECC_MASK 0x3
|
|
||||||
+#define SPI_NAND_STATUS_REG_ECC_SHIFT 4
|
|
||||||
+#define SPI_NAND_STATUS_REG_PROG_FAIL BIT(3)
|
|
||||||
+#define SPI_NAND_STATUS_REG_ERASE_FAIL BIT(2)
|
|
||||||
+#define SPI_NAND_STATUS_REG_WREN BIT(1)
|
|
||||||
+#define SPI_NAND_STATUS_REG_BUSY BIT(0)
|
|
||||||
+
|
|
||||||
+#define SPI_NAND_CMD_BUF_LEN 8
|
|
||||||
+
|
|
||||||
+/* Rewind and fill the buffer with 0xff */
|
|
||||||
+static void spi_nand_clear_buffer(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ snand->buf_start = 0;
|
|
||||||
+ memset(snand->data_buf, 0xff, snand->buf_size);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_enable_ecc(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ snand->buf[0] |= SPI_NAND_ECC_EN;
|
|
||||||
+ ret = snand->write_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+ snand->ecc = true;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_disable_ecc(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ snand->buf[0] &= ~SPI_NAND_ECC_EN;
|
|
||||||
+ ret = snand->write_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+ snand->ecc = false;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_enable_quad(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ snand->buf[0] |= SPI_NAND_QUAD_EN;
|
|
||||||
+ ret = snand->write_reg(snand, SPI_NAND_FEATURE_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+/*
|
|
||||||
+ * Wait until the status register busy bit is cleared.
|
|
||||||
+ * Returns a negatie errno on error or time out, and a non-negative status
|
|
||||||
+ * value if the device is ready.
|
|
||||||
+ */
|
|
||||||
+static int spi_nand_wait_till_ready(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ unsigned long deadline = jiffies + msecs_to_jiffies(100);
|
|
||||||
+ bool timeout = false;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Perhaps we should set a different timeout for each
|
|
||||||
+ * operation (reset, read, write, erase).
|
|
||||||
+ */
|
|
||||||
+ while (!timeout) {
|
|
||||||
+ if (time_after_eq(jiffies, deadline))
|
|
||||||
+ timeout = true;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_reg(snand, SPI_NAND_STATUS_REG, snand->buf);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error reading status register\n");
|
|
||||||
+ return ret;
|
|
||||||
+ } else if (!(snand->buf[0] & SPI_NAND_STATUS_REG_BUSY)) {
|
|
||||||
+ return snand->buf[0];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ cond_resched();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ dev_err(snand->dev, "operation timed out\n");
|
|
||||||
+
|
|
||||||
+ return -ETIMEDOUT;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_reset(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->reset(snand);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "reset command failed\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The NAND core won't wait after a device reset, so we need
|
|
||||||
+ * to do that here.
|
|
||||||
+ */
|
|
||||||
+ ret = spi_nand_wait_till_ready(snand);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ return ret;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_status(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret, status;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_reg(snand, SPI_NAND_STATUS_REG, snand->buf);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error reading status register\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ status = snand->buf[0];
|
|
||||||
+
|
|
||||||
+ /* Convert this into standard NAND_STATUS values */
|
|
||||||
+ if (status & SPI_NAND_STATUS_REG_BUSY)
|
|
||||||
+ snand->buf[0] = 0;
|
|
||||||
+ else
|
|
||||||
+ snand->buf[0] = NAND_STATUS_READY;
|
|
||||||
+
|
|
||||||
+ if (status & SPI_NAND_STATUS_REG_PROG_FAIL ||
|
|
||||||
+ status & SPI_NAND_STATUS_REG_ERASE_FAIL)
|
|
||||||
+ snand->buf[0] |= NAND_STATUS_FAIL;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Since we unlock the entire device at initialization, unconditionally
|
|
||||||
+ * set the WP bit to indicate it's not protected.
|
|
||||||
+ */
|
|
||||||
+ snand->buf[0] |= NAND_STATUS_WP;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_erase(struct spi_nand *snand, int page_addr)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->write_enable(snand);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "write enable command failed\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = snand->block_erase(snand, page_addr);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "block erase command failed\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_write(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ /* Enable quad mode */
|
|
||||||
+ ret = spi_nand_enable_quad(snand);
|
|
||||||
+ if (ret) {
|
|
||||||
+ dev_err(snand->dev, "error %d enabling quad mode\n", ret);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ /* Store the page to cache */
|
|
||||||
+ ret = snand->store_cache(snand, 0, snand->buf_size, snand->data_buf);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error %d storing page 0x%x to cache\n",
|
|
||||||
+ ret, snand->page_addr);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = snand->write_enable(snand);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "write enable command failed\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Get page from the device cache into our internal buffer */
|
|
||||||
+ ret = snand->write_page(snand, snand->page_addr);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error %d reading page 0x%x from cache\n",
|
|
||||||
+ ret, snand->page_addr);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_read_id(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = snand->read_id(snand, snand->data_buf);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error %d reading ID\n", ret);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_read_page(struct spi_nand *snand, unsigned int page_addr,
|
|
||||||
+ unsigned int page_offset, size_t length)
|
|
||||||
+{
|
|
||||||
+ unsigned int corrected = 0, ecc_error = 0;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ /* Load a page into the cache register */
|
|
||||||
+ ret = snand->load_page(snand, page_addr);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error %d loading page 0x%x to cache\n",
|
|
||||||
+ ret, page_addr);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = spi_nand_wait_till_ready(snand);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ if (snand->ecc) {
|
|
||||||
+ snand->get_ecc_status(ret, &corrected, &ecc_error);
|
|
||||||
+ snand->bitflips = corrected;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * If there's an ECC error, print a message and notify MTD
|
|
||||||
+ * about it. Then complete the read, to load actual data on
|
|
||||||
+ * the buffer (instead of the status result).
|
|
||||||
+ */
|
|
||||||
+ if (ecc_error) {
|
|
||||||
+ dev_err(snand->dev,
|
|
||||||
+ "internal ECC error reading page 0x%x\n",
|
|
||||||
+ page_addr);
|
|
||||||
+ snand->nand_chip.mtd.ecc_stats.failed++;
|
|
||||||
+ } else {
|
|
||||||
+ snand->nand_chip.mtd.ecc_stats.corrected += corrected;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Enable quad mode */
|
|
||||||
+ ret = spi_nand_enable_quad(snand);
|
|
||||||
+ if (ret) {
|
|
||||||
+ dev_err(snand->dev, "error %d enabling quad mode\n", ret);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ /* Get page from the device cache into our internal buffer */
|
|
||||||
+ ret = snand->read_cache(snand, page_offset, length, snand->data_buf);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ dev_err(snand->dev, "error %d reading page 0x%x from cache\n",
|
|
||||||
+ ret, page_addr);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static u8 spi_nand_read_byte(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+ char val = 0xff;
|
|
||||||
+
|
|
||||||
+ if (snand->buf_start < snand->buf_size)
|
|
||||||
+ val = snand->data_buf[snand->buf_start++];
|
|
||||||
+ return val;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void spi_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
|
|
||||||
+{
|
|
||||||
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+ size_t n = min_t(size_t, len, snand->buf_size - snand->buf_start);
|
|
||||||
+
|
|
||||||
+ memcpy(snand->data_buf + snand->buf_start, buf, n);
|
|
||||||
+ snand->buf_start += n;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void spi_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
|
|
||||||
+{
|
|
||||||
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+ size_t n = min_t(size_t, len, snand->buf_size - snand->buf_start);
|
|
||||||
+
|
|
||||||
+ memcpy(buf, snand->data_buf + snand->buf_start, n);
|
|
||||||
+ snand->buf_start += n;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_write_page_hwecc(struct mtd_info *mtd,
|
|
||||||
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
|
|
||||||
+ int page)
|
|
||||||
+{
|
|
||||||
+ chip->write_buf(mtd, buf, mtd->writesize);
|
|
||||||
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_read_page_hwecc(struct mtd_info *mtd,
|
|
||||||
+ struct nand_chip *chip, uint8_t *buf, int oob_required,
|
|
||||||
+ int page)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+
|
|
||||||
+ chip->read_buf(mtd, buf, mtd->writesize);
|
|
||||||
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
+
|
|
||||||
+ return snand->bitflips;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = spi_nand_wait_till_ready(snand);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ return NAND_STATUS_FAIL;
|
|
||||||
+ } else if (ret & SPI_NAND_STATUS_REG_PROG_FAIL) {
|
|
||||||
+ dev_err(snand->dev, "page program failed\n");
|
|
||||||
+ return NAND_STATUS_FAIL;
|
|
||||||
+ } else if (ret & SPI_NAND_STATUS_REG_ERASE_FAIL) {
|
|
||||||
+ dev_err(snand->dev, "block erase failed\n");
|
|
||||||
+ return NAND_STATUS_FAIL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return NAND_STATUS_READY;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void spi_nand_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|
||||||
+ int column, int page_addr)
|
|
||||||
+{
|
|
||||||
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
||||||
+ struct spi_nand *snand = nand_get_controller_data(chip);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * In case there's any unsupported command, let's make sure
|
|
||||||
+ * we don't keep garbage around in the buffer.
|
|
||||||
+ */
|
|
||||||
+ if (command != NAND_CMD_PAGEPROG) {
|
|
||||||
+ spi_nand_clear_buffer(snand);
|
|
||||||
+ snand->page_addr = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ switch (command) {
|
|
||||||
+ case NAND_CMD_READ0:
|
|
||||||
+ spi_nand_read_page(snand, page_addr, 0, mtd->writesize);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_READOOB:
|
|
||||||
+ spi_nand_disable_ecc(snand);
|
|
||||||
+ spi_nand_read_page(snand, page_addr, mtd->writesize,
|
|
||||||
+ mtd->oobsize);
|
|
||||||
+ spi_nand_enable_ecc(snand);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_READID:
|
|
||||||
+ spi_nand_read_id(snand);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_ERASE1:
|
|
||||||
+ spi_nand_erase(snand, page_addr);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_ERASE2:
|
|
||||||
+ /* There's nothing to do here, as the erase is one-step */
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_SEQIN:
|
|
||||||
+ snand->buf_start = column;
|
|
||||||
+ snand->page_addr = page_addr;
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_PAGEPROG:
|
|
||||||
+ spi_nand_write(snand);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_STATUS:
|
|
||||||
+ spi_nand_status(snand);
|
|
||||||
+ break;
|
|
||||||
+ case NAND_CMD_RESET:
|
|
||||||
+ spi_nand_reset(snand);
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ dev_err(&mtd->dev, "unknown command 0x%x\n", command);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void spi_nand_select_chip(struct mtd_info *mtd, int chip)
|
|
||||||
+{
|
|
||||||
+ /* We need this to override the default */
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spi_nand_check(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ if (!snand->dev)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->read_cache)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->load_page)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->store_cache)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->write_page)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->write_reg)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->read_reg)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->block_erase)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->reset)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->write_enable)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->write_disable)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ if (!snand->get_ecc_status)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spi_nand_register(struct spi_nand *snand, struct nand_flash_dev *flash_ids)
|
|
||||||
+{
|
|
||||||
+ struct nand_chip *chip = &snand->nand_chip;
|
|
||||||
+ struct mtd_info *mtd = nand_to_mtd(chip);
|
|
||||||
+ struct device_node *np = snand->dev->of_node;
|
|
||||||
+ const char __maybe_unused *of_mtd_name = NULL;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ /* Let's check all the hooks are in-place so we don't panic later */
|
|
||||||
+ ret = spi_nand_check(snand);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ nand_set_controller_data(chip, snand);
|
|
||||||
+ nand_set_flash_node(chip, np);
|
|
||||||
+ chip->read_buf = spi_nand_read_buf;
|
|
||||||
+ chip->write_buf = spi_nand_write_buf;
|
|
||||||
+ chip->read_byte = spi_nand_read_byte;
|
|
||||||
+ chip->cmdfunc = spi_nand_cmdfunc;
|
|
||||||
+ chip->waitfunc = spi_nand_waitfunc;
|
|
||||||
+ chip->select_chip = spi_nand_select_chip;
|
|
||||||
+ chip->options |= NAND_NO_SUBPAGE_WRITE;
|
|
||||||
+ chip->bits_per_cell = 1;
|
|
||||||
+
|
|
||||||
+ mtd_set_ooblayout(mtd, snand->ooblayout);
|
|
||||||
+ chip->ecc.read_page = spi_nand_read_page_hwecc;
|
|
||||||
+ chip->ecc.write_page = spi_nand_write_page_hwecc;
|
|
||||||
+ chip->ecc.mode = NAND_ECC_HW;
|
|
||||||
+
|
|
||||||
+ if (of_property_read_bool(np, "nand-on-flash-bbt"))
|
|
||||||
+ chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_MTD_OF_PARTS
|
|
||||||
+ of_property_read_string(np, "linux,mtd-name", &of_mtd_name);
|
|
||||||
+#endif
|
|
||||||
+ if (of_mtd_name)
|
|
||||||
+ mtd->name = of_mtd_name;
|
|
||||||
+ else
|
|
||||||
+ mtd->name = snand->name;
|
|
||||||
+ mtd->owner = THIS_MODULE;
|
|
||||||
+
|
|
||||||
+ /* Allocate buffer to be used to read/write the internal registers */
|
|
||||||
+ snand->buf = kmalloc(SPI_NAND_CMD_BUF_LEN, GFP_KERNEL);
|
|
||||||
+ if (!snand->buf)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ /* This is enabled at device power up but we'd better make sure */
|
|
||||||
+ ret = spi_nand_enable_ecc(snand);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* Preallocate buffer for flash identification (NAND_CMD_READID) */
|
|
||||||
+ snand->buf_size = SPI_NAND_CMD_BUF_LEN;
|
|
||||||
+ snand->data_buf = kmalloc(snand->buf_size, GFP_KERNEL);
|
|
||||||
+
|
|
||||||
+ ret = nand_scan_ident(mtd, 1, flash_ids);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * SPI NAND has on-die ECC, which means we can correct as much as
|
|
||||||
+ * we are required to. This must be done after identification of
|
|
||||||
+ * the device.
|
|
||||||
+ */
|
|
||||||
+ chip->ecc.strength = chip->ecc_strength_ds;
|
|
||||||
+ chip->ecc.size = chip->ecc_step_ds;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Unlock all the device before calling nand_scan_tail. This is needed
|
|
||||||
+ * in case the in-flash bad block table needs to be created.
|
|
||||||
+ * We could override __nand_unlock(), but since it's not currently used
|
|
||||||
+ * by the NAND core we call this explicitly.
|
|
||||||
+ */
|
|
||||||
+ snand->buf[0] = SPI_NAND_PROT_UNLOCK_ALL;
|
|
||||||
+ ret = snand->write_reg(snand, SPI_NAND_LOCK_REG, snand->buf);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* Free the buffer and allocate a good one, to fit a page plus OOB */
|
|
||||||
+ kfree(snand->data_buf);
|
|
||||||
+
|
|
||||||
+ snand->buf_size = mtd->writesize + mtd->oobsize;
|
|
||||||
+ snand->data_buf = kmalloc(snand->buf_size, GFP_KERNEL);
|
|
||||||
+ if (!snand->data_buf)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ ret = nand_scan_tail(mtd);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ return mtd_device_register(mtd, NULL, 0);
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(spi_nand_register);
|
|
||||||
+
|
|
||||||
+void spi_nand_unregister(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ kfree(snand->buf);
|
|
||||||
+ kfree(snand->data_buf);
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(spi_nand_unregister);
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@imgtec.com>");
|
|
||||||
+MODULE_DESCRIPTION("Framework for SPI NAND");
|
|
||||||
+MODULE_LICENSE("GPL v2");
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/linux/mtd/spi-nand.h
|
|
||||||
@@ -0,0 +1,54 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2014 Imagination Technologies Ltd.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; version 2 of the License.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __LINUX_MTD_SPI_NAND_H
|
|
||||||
+#define __LINUX_MTD_SPI_NAND_H
|
|
||||||
+
|
|
||||||
+#include <linux/mtd/mtd.h>
|
|
||||||
+#include <linux/mtd/nand.h>
|
|
||||||
+
|
|
||||||
+struct spi_nand {
|
|
||||||
+ struct nand_chip nand_chip;
|
|
||||||
+ struct device *dev;
|
|
||||||
+ const char *name;
|
|
||||||
+
|
|
||||||
+ u8 *buf, *data_buf;
|
|
||||||
+ size_t buf_size;
|
|
||||||
+ off_t buf_start;
|
|
||||||
+ unsigned int page_addr;
|
|
||||||
+ unsigned int bitflips;
|
|
||||||
+ bool ecc;
|
|
||||||
+ struct mtd_ooblayout_ops *ooblayout;
|
|
||||||
+
|
|
||||||
+ int (*reset)(struct spi_nand *snand);
|
|
||||||
+ int (*read_id)(struct spi_nand *snand, u8 *buf);
|
|
||||||
+
|
|
||||||
+ int (*write_disable)(struct spi_nand *snand);
|
|
||||||
+ int (*write_enable)(struct spi_nand *snand);
|
|
||||||
+
|
|
||||||
+ int (*read_reg)(struct spi_nand *snand, u8 opcode, u8 *buf);
|
|
||||||
+ int (*write_reg)(struct spi_nand *snand, u8 opcode, u8 *buf);
|
|
||||||
+ void (*get_ecc_status)(unsigned int status,
|
|
||||||
+ unsigned int *corrected,
|
|
||||||
+ unsigned int *ecc_errors);
|
|
||||||
+
|
|
||||||
+ int (*store_cache)(struct spi_nand *snand, unsigned int page_offset,
|
|
||||||
+ size_t length, u8 *write_buf);
|
|
||||||
+ int (*write_page)(struct spi_nand *snand, unsigned int page_addr);
|
|
||||||
+ int (*load_page)(struct spi_nand *snand, unsigned int page_addr);
|
|
||||||
+ int (*read_cache)(struct spi_nand *snand, unsigned int page_offset,
|
|
||||||
+ size_t length, u8 *read_buf);
|
|
||||||
+ int (*block_erase)(struct spi_nand *snand, unsigned int page_addr);
|
|
||||||
+
|
|
||||||
+ void *priv;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+int spi_nand_register(struct spi_nand *snand, struct nand_flash_dev *flash_ids);
|
|
||||||
+void spi_nand_unregister(struct spi_nand *snand);
|
|
||||||
+
|
|
||||||
+#endif
|
|
|
@ -1,524 +0,0 @@
|
||||||
From 7723e59d483a883578115a73eb87eb7fff0ff724 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Date: Tue, 28 Feb 2017 10:37:24 +0000
|
|
||||||
Subject: mtd: spi-nand: Support Gigadevice GD5F
|
|
||||||
|
|
||||||
This commit uses the recently introduced SPI NAND framework to support
|
|
||||||
the Gigadevice GD5F serial NAND device.
|
|
||||||
|
|
||||||
The current support includes:
|
|
||||||
|
|
||||||
* Page read and page program operations (using on-die ECC)
|
|
||||||
* Page out-of-band read
|
|
||||||
* Erase
|
|
||||||
* Reset
|
|
||||||
* Device status retrieval
|
|
||||||
* Device ID retrieval
|
|
||||||
|
|
||||||
(based on http://lists.infradead.org/pipermail/linux-mtd/2014-December/056769.html)
|
|
||||||
|
|
||||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
|
|
||||||
Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
---
|
|
||||||
drivers/mtd/spi-nand/Kconfig | 10 +
|
|
||||||
drivers/mtd/spi-nand/Makefile | 1 +
|
|
||||||
drivers/mtd/spi-nand/spi-nand-device.c | 472 +++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 483 insertions(+)
|
|
||||||
create mode 100644 drivers/mtd/spi-nand/spi-nand-device.c
|
|
||||||
|
|
||||||
--- a/drivers/mtd/spi-nand/Kconfig
|
|
||||||
+++ b/drivers/mtd/spi-nand/Kconfig
|
|
||||||
@@ -5,3 +5,13 @@ menuconfig MTD_SPI_NAND
|
|
||||||
help
|
|
||||||
This is the framework for the SPI NAND.
|
|
||||||
|
|
||||||
+if MTD_SPI_NAND
|
|
||||||
+
|
|
||||||
+config MTD_SPI_NAND_DEVICES
|
|
||||||
+ tristate "Support for SPI NAND devices"
|
|
||||||
+ default y
|
|
||||||
+ depends on MTD_SPI_NAND
|
|
||||||
+ help
|
|
||||||
+ Select this option if you require support for SPI NAND devices.
|
|
||||||
+
|
|
||||||
+endif # MTD_SPI_NAND
|
|
||||||
--- a/drivers/mtd/spi-nand/Makefile
|
|
||||||
+++ b/drivers/mtd/spi-nand/Makefile
|
|
||||||
@@ -1 +1,2 @@
|
|
||||||
obj-$(CONFIG_MTD_SPI_NAND) += spi-nand-base.o
|
|
||||||
+obj-$(CONFIG_MTD_SPI_NAND_DEVICES) += spi-nand-device.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/mtd/spi-nand/spi-nand-device.c
|
|
||||||
@@ -0,0 +1,472 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2014 Imagination Technologies Ltd.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; version 2 of the License.
|
|
||||||
+ *
|
|
||||||
+ * Notes:
|
|
||||||
+ * 1. We avoid using a stack-allocated buffer for SPI messages. Using
|
|
||||||
+ * a kmalloced buffer is probably better, given we shouldn't assume
|
|
||||||
+ * any particular usage by SPI core.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/device.h>
|
|
||||||
+#include <linux/err.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/mtd/mtd.h>
|
|
||||||
+#include <linux/mtd/partitions.h>
|
|
||||||
+#include <linux/mtd/spi-nand.h>
|
|
||||||
+#include <linux/sizes.h>
|
|
||||||
+#include <linux/spi/spi.h>
|
|
||||||
+
|
|
||||||
+/* SPI NAND commands */
|
|
||||||
+#define SPI_NAND_WRITE_ENABLE 0x06
|
|
||||||
+#define SPI_NAND_WRITE_DISABLE 0x04
|
|
||||||
+#define SPI_NAND_GET_FEATURE 0x0f
|
|
||||||
+#define SPI_NAND_SET_FEATURE 0x1f
|
|
||||||
+#define SPI_NAND_PAGE_READ 0x13
|
|
||||||
+#define SPI_NAND_READ_CACHE 0x03
|
|
||||||
+#define SPI_NAND_FAST_READ_CACHE 0x0b
|
|
||||||
+#define SPI_NAND_READ_CACHE_X2 0x3b
|
|
||||||
+#define SPI_NAND_READ_CACHE_X4 0x6b
|
|
||||||
+#define SPI_NAND_READ_CACHE_DUAL_IO 0xbb
|
|
||||||
+#define SPI_NAND_READ_CACHE_QUAD_IO 0xeb
|
|
||||||
+#define SPI_NAND_READ_ID 0x9f
|
|
||||||
+#define SPI_NAND_PROGRAM_LOAD 0x02
|
|
||||||
+#define SPI_NAND_PROGRAM_LOAD4 0x32
|
|
||||||
+#define SPI_NAND_PROGRAM_EXEC 0x10
|
|
||||||
+#define SPI_NAND_PROGRAM_LOAD_RANDOM 0x84
|
|
||||||
+#define SPI_NAND_PROGRAM_LOAD_RANDOM4 0xc4
|
|
||||||
+#define SPI_NAND_BLOCK_ERASE 0xd8
|
|
||||||
+#define SPI_NAND_RESET 0xff
|
|
||||||
+
|
|
||||||
+#define SPI_NAND_GD5F_READID_LEN 2
|
|
||||||
+
|
|
||||||
+#define SPI_NAND_GD5F_ECC_MASK (BIT(0) | BIT(1) | BIT(2))
|
|
||||||
+#define SPI_NAND_GD5F_ECC_UNCORR (BIT(0) | BIT(1) | BIT(2))
|
|
||||||
+#define SPI_NAND_GD5F_ECC_SHIFT 4
|
|
||||||
+
|
|
||||||
+static int spi_nand_gd5f_ooblayout_256_ecc(struct mtd_info *mtd, int section,
|
|
||||||
+ struct mtd_oob_region *oobregion)
|
|
||||||
+{
|
|
||||||
+ if (section)
|
|
||||||
+ return -ERANGE;
|
|
||||||
+
|
|
||||||
+ oobregion->offset = 128;
|
|
||||||
+ oobregion->length = 128;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_gd5f_ooblayout_256_free(struct mtd_info *mtd, int section,
|
|
||||||
+ struct mtd_oob_region *oobregion)
|
|
||||||
+{
|
|
||||||
+ if (section)
|
|
||||||
+ return -ERANGE;
|
|
||||||
+
|
|
||||||
+ oobregion->offset = 1;
|
|
||||||
+ oobregion->length = 127;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const struct mtd_ooblayout_ops spi_nand_gd5f_oob_256_ops = {
|
|
||||||
+ .ecc = spi_nand_gd5f_ooblayout_256_ecc,
|
|
||||||
+ .free = spi_nand_gd5f_ooblayout_256_free,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct nand_flash_dev spi_nand_flash_ids[] = {
|
|
||||||
+ {
|
|
||||||
+ .name = "SPI NAND 512MiB 3,3V",
|
|
||||||
+ .id = { NAND_MFR_GIGADEVICE, 0xb4 },
|
|
||||||
+ .chipsize = 512,
|
|
||||||
+ .pagesize = SZ_4K,
|
|
||||||
+ .erasesize = SZ_256K,
|
|
||||||
+ .id_len = 2,
|
|
||||||
+ .oobsize = 256,
|
|
||||||
+ .ecc.strength_ds = 8,
|
|
||||||
+ .ecc.step_ds = 512,
|
|
||||||
+ },
|
|
||||||
+ {
|
|
||||||
+ .name = "SPI NAND 512MiB 1,8V",
|
|
||||||
+ .id = { NAND_MFR_GIGADEVICE, 0xa4 },
|
|
||||||
+ .chipsize = 512,
|
|
||||||
+ .pagesize = SZ_4K,
|
|
||||||
+ .erasesize = SZ_256K,
|
|
||||||
+ .id_len = 2,
|
|
||||||
+ .oobsize = 256,
|
|
||||||
+ .ecc.strength_ds = 8,
|
|
||||||
+ .ecc.step_ds = 512,
|
|
||||||
+ },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+enum spi_nand_device_variant {
|
|
||||||
+ SPI_NAND_GENERIC,
|
|
||||||
+ SPI_NAND_GD5F,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct spi_nand_device_cmd {
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Command and address. I/O errors have been observed if a
|
|
||||||
+ * separate spi_transfer is used for command and address,
|
|
||||||
+ * so keep them together.
|
|
||||||
+ */
|
|
||||||
+ u32 n_cmd;
|
|
||||||
+ u8 cmd[5];
|
|
||||||
+
|
|
||||||
+ /* Tx data */
|
|
||||||
+ u32 n_tx;
|
|
||||||
+ u8 *tx_buf;
|
|
||||||
+
|
|
||||||
+ /* Rx data */
|
|
||||||
+ u32 n_rx;
|
|
||||||
+ u8 *rx_buf;
|
|
||||||
+ u8 rx_nbits;
|
|
||||||
+ u8 tx_nbits;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct spi_nand_device {
|
|
||||||
+ struct spi_nand spi_nand;
|
|
||||||
+ struct spi_device *spi;
|
|
||||||
+
|
|
||||||
+ struct spi_nand_device_cmd cmd;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int spi_nand_send_command(struct spi_device *spi,
|
|
||||||
+ struct spi_nand_device_cmd *cmd)
|
|
||||||
+{
|
|
||||||
+ struct spi_message message;
|
|
||||||
+ struct spi_transfer x[2];
|
|
||||||
+
|
|
||||||
+ if (!cmd->n_cmd) {
|
|
||||||
+ dev_err(&spi->dev, "cannot send an empty command\n");
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (cmd->n_tx && cmd->n_rx) {
|
|
||||||
+ dev_err(&spi->dev, "cannot send and receive data at the same time\n");
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ spi_message_init(&message);
|
|
||||||
+ memset(x, 0, sizeof(x));
|
|
||||||
+
|
|
||||||
+ /* Command and address */
|
|
||||||
+ x[0].len = cmd->n_cmd;
|
|
||||||
+ x[0].tx_buf = cmd->cmd;
|
|
||||||
+ x[0].tx_nbits = cmd->tx_nbits;
|
|
||||||
+ spi_message_add_tail(&x[0], &message);
|
|
||||||
+
|
|
||||||
+ /* Data to be transmitted */
|
|
||||||
+ if (cmd->n_tx) {
|
|
||||||
+ x[1].len = cmd->n_tx;
|
|
||||||
+ x[1].tx_buf = cmd->tx_buf;
|
|
||||||
+ x[1].tx_nbits = cmd->tx_nbits;
|
|
||||||
+ spi_message_add_tail(&x[1], &message);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Data to be received */
|
|
||||||
+ if (cmd->n_rx) {
|
|
||||||
+ x[1].len = cmd->n_rx;
|
|
||||||
+ x[1].rx_buf = cmd->rx_buf;
|
|
||||||
+ x[1].rx_nbits = cmd->rx_nbits;
|
|
||||||
+ spi_message_add_tail(&x[1], &message);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return spi_sync(spi, &message);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_reset(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 1;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_RESET;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s\n", __func__);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_read_reg(struct spi_nand *snand, u8 opcode, u8 *buf)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 2;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_GET_FEATURE;
|
|
||||||
+ cmd->cmd[1] = opcode;
|
|
||||||
+ cmd->n_rx = 1;
|
|
||||||
+ cmd->rx_buf = buf;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: reg 0%x\n", __func__, opcode);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_write_reg(struct spi_nand *snand, u8 opcode, u8 *buf)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 2;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_SET_FEATURE;
|
|
||||||
+ cmd->cmd[1] = opcode;
|
|
||||||
+ cmd->n_tx = 1;
|
|
||||||
+ cmd->tx_buf = buf;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: reg 0%x\n", __func__, opcode);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_write_enable(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 1;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_WRITE_ENABLE;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s\n", __func__);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_write_disable(struct spi_nand *snand)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 1;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_WRITE_DISABLE;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s\n", __func__);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_write_page(struct spi_nand *snand,
|
|
||||||
+ unsigned int page_addr)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 4;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_PROGRAM_EXEC;
|
|
||||||
+ cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
|
|
||||||
+ cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
|
|
||||||
+ cmd->cmd[3] = (u8)(page_addr & 0xff);
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: page 0x%x\n", __func__, page_addr);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_store_cache(struct spi_nand *snand,
|
|
||||||
+ unsigned int page_offset, size_t length,
|
|
||||||
+ u8 *write_buf)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+ struct spi_device *spi = snand_dev->spi;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 3;
|
|
||||||
+ cmd->cmd[0] = spi->mode & SPI_TX_QUAD ? SPI_NAND_PROGRAM_LOAD4 :
|
|
||||||
+ SPI_NAND_PROGRAM_LOAD;
|
|
||||||
+ cmd->cmd[1] = (u8)((page_offset & 0xff00) >> 8);
|
|
||||||
+ cmd->cmd[2] = (u8)(page_offset & 0xff);
|
|
||||||
+ cmd->n_tx = length;
|
|
||||||
+ cmd->tx_buf = write_buf;
|
|
||||||
+ cmd->tx_nbits = spi->mode & SPI_TX_QUAD ? 4 : 1;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: offset 0x%x\n", __func__, page_offset);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_load_page(struct spi_nand *snand,
|
|
||||||
+ unsigned int page_addr)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 4;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_PAGE_READ;
|
|
||||||
+ cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
|
|
||||||
+ cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
|
|
||||||
+ cmd->cmd[3] = (u8)(page_addr & 0xff);
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: page 0x%x\n", __func__, page_addr);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_read_cache(struct spi_nand *snand,
|
|
||||||
+ unsigned int page_offset, size_t length,
|
|
||||||
+ u8 *read_buf)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+ struct spi_device *spi = snand_dev->spi;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ if ((spi->mode & SPI_RX_DUAL) || (spi->mode & SPI_RX_QUAD))
|
|
||||||
+ cmd->n_cmd = 5;
|
|
||||||
+ else
|
|
||||||
+ cmd->n_cmd = 4;
|
|
||||||
+ cmd->cmd[0] = (spi->mode & SPI_RX_QUAD) ? SPI_NAND_READ_CACHE_X4 :
|
|
||||||
+ ((spi->mode & SPI_RX_DUAL) ? SPI_NAND_READ_CACHE_X2 :
|
|
||||||
+ SPI_NAND_READ_CACHE);
|
|
||||||
+ cmd->cmd[1] = 0; /* dummy byte */
|
|
||||||
+ cmd->cmd[2] = (u8)((page_offset & 0xff00) >> 8);
|
|
||||||
+ cmd->cmd[3] = (u8)(page_offset & 0xff);
|
|
||||||
+ cmd->cmd[4] = 0; /* dummy byte */
|
|
||||||
+ cmd->n_rx = length;
|
|
||||||
+ cmd->rx_buf = read_buf;
|
|
||||||
+ cmd->rx_nbits = (spi->mode & SPI_RX_QUAD) ? 4 :
|
|
||||||
+ ((spi->mode & SPI_RX_DUAL) ? 2 : 1);
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: offset 0x%x\n", __func__, page_offset);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_block_erase(struct spi_nand *snand,
|
|
||||||
+ unsigned int page_addr)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 4;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_BLOCK_ERASE;
|
|
||||||
+ cmd->cmd[1] = (u8)((page_addr & 0xff0000) >> 16);
|
|
||||||
+ cmd->cmd[2] = (u8)((page_addr & 0xff00) >> 8);
|
|
||||||
+ cmd->cmd[3] = (u8)(page_addr & 0xff);
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s: block 0x%x\n", __func__, page_addr);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_gd5f_read_id(struct spi_nand *snand, u8 *buf)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand_device *snand_dev = snand->priv;
|
|
||||||
+ struct spi_nand_device_cmd *cmd = &snand_dev->cmd;
|
|
||||||
+
|
|
||||||
+ memset(cmd, 0, sizeof(struct spi_nand_device_cmd));
|
|
||||||
+ cmd->n_cmd = 1;
|
|
||||||
+ cmd->cmd[0] = SPI_NAND_READ_ID;
|
|
||||||
+ cmd->n_rx = SPI_NAND_GD5F_READID_LEN;
|
|
||||||
+ cmd->rx_buf = buf;
|
|
||||||
+
|
|
||||||
+ dev_dbg(snand->dev, "%s\n", __func__);
|
|
||||||
+
|
|
||||||
+ return spi_nand_send_command(snand_dev->spi, cmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void spi_nand_gd5f_ecc_status(unsigned int status,
|
|
||||||
+ unsigned int *corrected,
|
|
||||||
+ unsigned int *ecc_error)
|
|
||||||
+{
|
|
||||||
+ unsigned int ecc_status = (status >> SPI_NAND_GD5F_ECC_SHIFT) &
|
|
||||||
+ SPI_NAND_GD5F_ECC_MASK;
|
|
||||||
+
|
|
||||||
+ *ecc_error = (ecc_status == SPI_NAND_GD5F_ECC_UNCORR) ? 1 : 0;
|
|
||||||
+ if (*ecc_error == 0)
|
|
||||||
+ *corrected = (ecc_status > 1) ? (2 + ecc_status) : 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_probe(struct spi_device *spi)
|
|
||||||
+{
|
|
||||||
+ enum spi_nand_device_variant variant;
|
|
||||||
+ struct spi_nand_device *priv;
|
|
||||||
+ struct spi_nand *snand;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
|
|
||||||
+ if (!priv)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ snand = &priv->spi_nand;
|
|
||||||
+
|
|
||||||
+ snand->read_cache = spi_nand_device_read_cache;
|
|
||||||
+ snand->load_page = spi_nand_device_load_page;
|
|
||||||
+ snand->store_cache = spi_nand_device_store_cache;
|
|
||||||
+ snand->write_page = spi_nand_device_write_page;
|
|
||||||
+ snand->write_reg = spi_nand_device_write_reg;
|
|
||||||
+ snand->read_reg = spi_nand_device_read_reg;
|
|
||||||
+ snand->block_erase = spi_nand_device_block_erase;
|
|
||||||
+ snand->reset = spi_nand_device_reset;
|
|
||||||
+ snand->write_enable = spi_nand_device_write_enable;
|
|
||||||
+ snand->write_disable = spi_nand_device_write_disable;
|
|
||||||
+ snand->dev = &spi->dev;
|
|
||||||
+ snand->priv = priv;
|
|
||||||
+
|
|
||||||
+ /* This'll mean we won't need to specify any specific compatible string
|
|
||||||
+ * for a given device, and instead just support spi-nand.
|
|
||||||
+ */
|
|
||||||
+ variant = spi_get_device_id(spi)->driver_data;
|
|
||||||
+ switch (variant) {
|
|
||||||
+ case SPI_NAND_GD5F:
|
|
||||||
+ snand->read_id = spi_nand_gd5f_read_id;
|
|
||||||
+ snand->get_ecc_status = spi_nand_gd5f_ecc_status;
|
|
||||||
+ snand->ooblayout = &spi_nand_gd5f_oob_256_ops;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ dev_err(snand->dev, "unknown device\n");
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ spi_set_drvdata(spi, snand);
|
|
||||||
+ priv->spi = spi;
|
|
||||||
+
|
|
||||||
+ ret = spi_nand_register(snand, spi_nand_flash_ids);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int spi_nand_device_remove(struct spi_device *spi)
|
|
||||||
+{
|
|
||||||
+ struct spi_nand *snand = spi_get_drvdata(spi);
|
|
||||||
+
|
|
||||||
+ spi_nand_unregister(snand);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+const struct spi_device_id spi_nand_id_table[] = {
|
|
||||||
+ { "spi-nand", SPI_NAND_GENERIC },
|
|
||||||
+ { "gd5f", SPI_NAND_GD5F },
|
|
||||||
+ { },
|
|
||||||
+};
|
|
||||||
+MODULE_DEVICE_TABLE(spi, spi_nand_id_table);
|
|
||||||
+
|
|
||||||
+static struct spi_driver spi_nand_device_driver = {
|
|
||||||
+ .driver = {
|
|
||||||
+ .name = "spi_nand_device",
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+ },
|
|
||||||
+ .id_table = spi_nand_id_table,
|
|
||||||
+ .probe = spi_nand_device_probe,
|
|
||||||
+ .remove = spi_nand_device_remove,
|
|
||||||
+};
|
|
||||||
+module_spi_driver(spi_nand_device_driver);
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@imgtec.com>");
|
|
||||||
+MODULE_DESCRIPTION("SPI NAND device support");
|
|
||||||
+MODULE_LICENSE("GPL v2");
|
|
|
@ -1,35 +0,0 @@
|
||||||
From 5e84aec87108e0481af7495a1e9a9953d8590d70 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Xue Liu <liuxuenetmail@gmail.com>
|
|
||||||
Date: Mon, 6 Feb 2017 17:43:19 +0000
|
|
||||||
Subject: net: micrel: Disable PME
|
|
||||||
|
|
||||||
Disable PME for Micrel phy driver allowing the Ethernet ports LED
|
|
||||||
driver to work on marduk platform.
|
|
||||||
|
|
||||||
Signed-off-by: Xue Liu <liuxuenetmail@gmail.com>
|
|
||||||
---
|
|
||||||
drivers/net/phy/micrel.c | 6 ++++++
|
|
||||||
1 file changed, 6 insertions(+)
|
|
||||||
|
|
||||||
--- a/drivers/net/phy/micrel.c
|
|
||||||
+++ b/drivers/net/phy/micrel.c
|
|
||||||
@@ -273,6 +273,7 @@ static int kszphy_config_init(struct phy
|
|
||||||
struct kszphy_priv *priv = phydev->priv;
|
|
||||||
const struct kszphy_type *type;
|
|
||||||
int ret;
|
|
||||||
+ int temp = 0;
|
|
||||||
|
|
||||||
if (!priv)
|
|
||||||
return 0;
|
|
||||||
@@ -308,6 +309,11 @@ static int kszphy_config_init(struct phy
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* disable PME */
|
|
||||||
+ temp = phy_read(phydev, 0x16);
|
|
||||||
+ temp &= ~(1 << 15);
|
|
||||||
+ phy_write(phydev, 0x16, temp);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
From b5f49b448cd3c7ab930f1a53c88f739a86071df8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
Date: Mon, 20 Feb 2017 10:38:07 +0000
|
|
||||||
Subject: MIPS: DTS: img: marduk: add nor partition name
|
|
||||||
|
|
||||||
Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
|
|
||||||
---
|
|
||||||
arch/mips/boot/dts/img/pistachio_marduk.dts | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
--- a/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
+++ b/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
@@ -90,6 +90,7 @@
|
|
||||||
compatible = "spansion,s25fl016k", "jedec,spi-nor";
|
|
||||||
reg = <0>;
|
|
||||||
spi-max-frequency = <50000000>;
|
|
||||||
+ linux,mtd-name = "spi-nor";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
From c13cfb3a49cf1578bb85f19a7066f262503a39ba Mon Sep 17 00:00:00 2001
|
|
||||||
From: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com>
|
|
||||||
Date: Thu, 24 Nov 2016 19:26:46 +0530
|
|
||||||
Subject: MIPS: DTS: img: marduk: add nand device support
|
|
||||||
|
|
||||||
Signed-off-by: Abhimanyu Vishwakarma <Abhimanyu.Vishwakarma@imgtec.com>
|
|
||||||
---
|
|
||||||
arch/mips/boot/dts/img/pistachio_marduk.dts | 11 +++++++++++
|
|
||||||
1 file changed, 11 insertions(+)
|
|
||||||
|
|
||||||
--- a/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
+++ b/arch/mips/boot/dts/img/pistachio_marduk.dts
|
|
||||||
@@ -92,6 +92,17 @@
|
|
||||||
spi-max-frequency = <50000000>;
|
|
||||||
linux,mtd-name = "spi-nor";
|
|
||||||
};
|
|
||||||
+ flash@1 {
|
|
||||||
+ compatible = "gigadevice,gd5f";
|
|
||||||
+ reg = <1>;
|
|
||||||
+ spi-max-frequency = <50000000>;
|
|
||||||
+ nand-on-flash-bbt;
|
|
||||||
+ spi-rx-bus-width = <2>;
|
|
||||||
+ spi-tx-bus-width = <4>;
|
|
||||||
+ #address-cells = <1>;
|
|
||||||
+ #size-cells = <1>;
|
|
||||||
+ linux,mtd-name = "spi-nand";
|
|
||||||
+ };
|
|
||||||
};
|
|
||||||
|
|
||||||
&uart0 {
|
|
Loading…
Reference in a new issue