diff options
Diffstat (limited to 'target/linux/bcm53xx')
27 files changed, 0 insertions, 6622 deletions
diff --git a/target/linux/bcm53xx/Makefile b/target/linux/bcm53xx/Makefile deleted file mode 100644 index f9d7e32..0000000 --- a/target/linux/bcm53xx/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (C) 2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk - -ARCH:=arm -BOARD:=bcm53xx -BOARDNAME:=Broadcom BCM47xx/53xx (ARM) -FEATURES:=squashfs usb pci pcie gpio -MAINTAINER:=Hauke Mehrtens <hauke@hauke-m.de> -CPU_TYPE:=cortex-a9 - -LINUX_VERSION:=3.14.16 - -include $(INCLUDE_DIR)/target.mk - -define Target/Description - Build firmware images for Broadcom based BCM47xx/53xx routers with ARM CPU, *not* MIPS. -endef - -KERNELNAME:="zImage dtbs" - -DEFAULT_PACKAGES += swconfig wpad-mini - -$(eval $(call BuildTarget)) diff --git a/target/linux/bcm53xx/base-files.mk b/target/linux/bcm53xx/base-files.mk deleted file mode 100644 index fdd2c71..0000000 --- a/target/linux/bcm53xx/base-files.mk +++ /dev/null @@ -1,3 +0,0 @@ -define Package/base-files/install-target - rm -f $(1)/etc/config/network -endef diff --git a/target/linux/bcm53xx/base-files/etc/uci-defaults/02_network b/target/linux/bcm53xx/base-files/etc/uci-defaults/02_network deleted file mode 100644 index 7517d07..0000000 --- a/target/linux/bcm53xx/base-files/etc/uci-defaults/02_network +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2011 OpenWrt.org -# - -[ -e /etc/config/network ] && exit 0 - -touch /etc/config/network - -. /lib/functions/uci-defaults.sh - -ucidef_set_interface_loopback - -ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" -ucidef_add_switch "switch0" "1" "1" -ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 5t" -ucidef_add_switch_vlan "switch0" "2" "4 5t" - -uci commit network - -exit 0 diff --git a/target/linux/bcm53xx/config-3.14 b/target/linux/bcm53xx/config-3.14 deleted file mode 100644 index f703522..0000000 --- a/target/linux/bcm53xx/config-3.14 +++ /dev/null @@ -1,235 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_BCM=y -CONFIG_ARCH_BCM_5301X=y -# CONFIG_ARCH_BCM_MOBILE is not set -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y -CONFIG_ARCH_HAS_TICK_BROADCAST=y -CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_MULTI_CPU_AUTO is not set -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set -CONFIG_ARCH_NR_GPIO=0 -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -# CONFIG_ARM_ATAG_DTB_COMPAT is not set -# CONFIG_ARM_CPU_SUSPEND is not set -CONFIG_ARM_GIC=y -CONFIG_ARM_GLOBAL_TIMER=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -# CONFIG_ARM_LPAE is not set -CONFIG_ARM_NR_BANKS=8 -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_THUMB=y -# CONFIG_ARM_THUMBEE is not set -CONFIG_ARM_VIRT_EXT=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_B53=y -# CONFIG_B53_MMAP_DRIVER is not set -# CONFIG_B53_PHY_DRIVER is not set -CONFIG_B53_SRAB_DRIVER=y -CONFIG_BCM47XX_NVRAM=y -CONFIG_BCM53XX_SPROM=y -CONFIG_BCMA=y -CONFIG_BCMA_BLOCKIO=y -CONFIG_BCMA_DEBUG=y -CONFIG_BCMA_DRIVER_GMAC_CMN=y -CONFIG_BCMA_HOST_PCI=y -CONFIG_BCMA_HOST_PCI_POSSIBLE=y -CONFIG_BCMA_HOST_SOC=y -# CONFIG_BCM_KONA_WDT is not set -CONFIG_BGMAC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CLKDEV_LOOKUP=y -CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y -CONFIG_CLKSRC_OF=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_HAS_ASID=y -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_BCM_5301X=y -# CONFIG_DEBUG_BCM_KONA_UART is not set -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_INCLUDE="debug/pl01x.S" -# CONFIG_DEBUG_LL_UART_8250 is not set -# CONFIG_DEBUG_LL_UART_PL01X is not set -# CONFIG_DEBUG_UART_8250 is not set -CONFIG_DEBUG_UART_PHYS=0x18000300 -CONFIG_DEBUG_UART_PL01X=y -CONFIG_DEBUG_UART_VIRT=0xf1000300 -CONFIG_DEBUG_UNCOMPRESS=y -CONFIG_DEBUG_USER=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_FRAME_POINTER=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IO=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_NET_UTILS=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set -CONFIG_HAVE_BPF_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_DMA_API_DEBUG=y -CONFIG_HAVE_DMA_ATTRS=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=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_TIME_ACCOUNTING=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZ4=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_KERNEL_XZ=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_NET_DSA=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_SMP=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_UID16=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HZ_FIXED=0 -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IOMMU_HELPER=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -CONFIG_KTIME_SCALAR=y -CONFIG_MDIO_BOARDINFO=y -CONFIG_MIGHT_HAVE_PCI=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_BCM47XX_PARTS=y -# CONFIG_MTD_PHYSMAP_OF is not set -CONFIG_MTD_SPI_NOR=y -CONFIG_MULTI_IRQ_HANDLER=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NO_BOOTMEM=y -CONFIG_NR_CPUS=4 -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_IRQ=y -CONFIG_OF_MDIO=y -CONFIG_OF_MTD=y -CONFIG_OF_NET=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PCI=y -CONFIG_PCI_BCMA=y -CONFIG_PCI_DOMAINS=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PHYLIB=y -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_PL310_ERRATA_769419 is not set -# CONFIG_PREEMPT_RCU is not set -CONFIG_RCU_STALL_COMMON=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_SCHED_HRTICK=y -# CONFIG_SCSI_DMA is not set -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_BCM53XX=y -CONFIG_SPI_MASTER=y -CONFIG_STOP_MACHINE=y -CONFIG_SWCONFIG=y -CONFIG_SWIOTLB=y -# CONFIG_SWP_EMULATE is not set -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_THUMB2_KERNEL is not set -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_UID16=y -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_VFP is not set -# CONFIG_XEN is not set -CONFIG_XPS=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/bcm53xx/image/Makefile b/target/linux/bcm53xx/image/Makefile deleted file mode 100644 index 61bc39c..0000000 --- a/target/linux/bcm53xx/image/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/image.mk - -define Image/Prepare - rm -f $(KDIR)/fs_mark - echo -ne '\xde\xad\xc0\xde' > $(KDIR)/fs_mark - $(call prepare_generic_squashfs,$(KDIR)/fs_mark) -endef - -define Image/Build/Initramfs - $(call Image/Build/Initramfs/Chk,bcm4708-netgear-r6250,U12H245T00_NETGEAR,2,initramfs) -endef - -define Image/Build/Initramfs/Chk - $(call Image/Build/Initramfs/DTB,$(1)) - $(STAGING_DIR_HOST)/bin/mkchkimg -o $(BIN_DIR)/openwrt-$(1)-$(4).chk -k $(KDIR)/$(IMG_PREFIX)-$(4)-$(1).trx -b $(2) -r $(3) -endef - -define Image/Build/Initramfs/DTB - $(call Image/Build/DTB,zImage-initramfs,$(1)) - $(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/$(IMG_PREFIX)-initramfs-$(1).trx \ - -f $(KDIR)/zImage-initramfs-$(1).lzma -endef - -define Image/Build/squashfs/DTB - $(call Image/Build/DTB,zImage,$(1)) - $(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/$(IMG_PREFIX)-squashfs-$(1).trx \ - -f $(KDIR)/zImage-$(1).lzma \ - -a 1024 -f $(KDIR)/root.squashfs -a 0x10000 -A $(KDIR)/fs_mark -endef - -define Image/Build/squashfs/Chk - $(call Image/Build/squashfs/DTB,$(1)) - $(STAGING_DIR_HOST)/bin/mkchkimg -o $(BIN_DIR)/openwrt-$(1)-$(4).chk -k $(KDIR)/$(IMG_PREFIX)-$(4)-$(1).trx -b $(2) -r $(3) -endef - -define Image/Build/DTB - rm -f $(KDIR)/$(1)-$(2).lzma - rm -f $(KDIR)/$(1)-$(2).dts - cat $(KDIR)/$(1) $(DTS_DIR)/$(2).dtb > $(KDIR)/$(1)-$(2).dts; - $(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/$(1)-$(2).dts $(KDIR)/$(1)-$(2).lzma -d16 -endef - -define Image/Build - $(call Image/Build/$(1),$(1)) - $(call Image/Build/squashfs/Chk,bcm4708-netgear-r6250,U12H245T00_NETGEAR,2,squashfs) -endef - - -$(eval $(call BuildImage)) diff --git a/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch b/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch deleted file mode 100644 index fb916ca..0000000 --- a/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch +++ /dev/null @@ -1,2443 +0,0 @@ -This patches adds the SPI-NOR device support code form kernel 3.17-rc1. -This patch does not contain any further code not in this mainline kernel. - ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -394,6 +394,8 @@ source "drivers/mtd/onenand/Kconfig" - - source "drivers/mtd/lpddr/Kconfig" - -+source "drivers/mtd/spi-nor/Kconfig" -+ - source "drivers/mtd/ubi/Kconfig" - - endif # MTD ---- a/drivers/mtd/Makefile -+++ b/drivers/mtd/Makefile -@@ -39,4 +39,5 @@ inftl-objs := inftlcore.o inftlmount.o - - obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ - -+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ - obj-$(CONFIG_MTD_UBI) += ubi/ ---- /dev/null -+++ b/drivers/mtd/spi-nor/fsl-quadspi.c -@@ -0,0 +1,1009 @@ -+/* -+ * Freescale QuadSPI driver. -+ * -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * -+ * 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; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/interrupt.h> -+#include <linux/errno.h> -+#include <linux/platform_device.h> -+#include <linux/sched.h> -+#include <linux/delay.h> -+#include <linux/io.h> -+#include <linux/clk.h> -+#include <linux/err.h> -+#include <linux/of.h> -+#include <linux/of_device.h> -+#include <linux/timer.h> -+#include <linux/jiffies.h> -+#include <linux/completion.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+#include <linux/mtd/spi-nor.h> -+ -+/* The registers */ -+#define QUADSPI_MCR 0x00 -+#define QUADSPI_MCR_RESERVED_SHIFT 16 -+#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT) -+#define QUADSPI_MCR_MDIS_SHIFT 14 -+#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT) -+#define QUADSPI_MCR_CLR_TXF_SHIFT 11 -+#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT) -+#define QUADSPI_MCR_CLR_RXF_SHIFT 10 -+#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT) -+#define QUADSPI_MCR_DDR_EN_SHIFT 7 -+#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT) -+#define QUADSPI_MCR_END_CFG_SHIFT 2 -+#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT) -+#define QUADSPI_MCR_SWRSTHD_SHIFT 1 -+#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT) -+#define QUADSPI_MCR_SWRSTSD_SHIFT 0 -+#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT) -+ -+#define QUADSPI_IPCR 0x08 -+#define QUADSPI_IPCR_SEQID_SHIFT 24 -+#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT) -+ -+#define QUADSPI_BUF0CR 0x10 -+#define QUADSPI_BUF1CR 0x14 -+#define QUADSPI_BUF2CR 0x18 -+#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe -+ -+#define QUADSPI_BUF3CR 0x1c -+#define QUADSPI_BUF3CR_ALLMST_SHIFT 31 -+#define QUADSPI_BUF3CR_ALLMST (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) -+ -+#define QUADSPI_BFGENCR 0x20 -+#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 -+#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT)) -+#define QUADSPI_BFGENCR_SEQID_SHIFT 12 -+#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT) -+ -+#define QUADSPI_BUF0IND 0x30 -+#define QUADSPI_BUF1IND 0x34 -+#define QUADSPI_BUF2IND 0x38 -+#define QUADSPI_SFAR 0x100 -+ -+#define QUADSPI_SMPR 0x108 -+#define QUADSPI_SMPR_DDRSMP_SHIFT 16 -+#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT) -+#define QUADSPI_SMPR_FSDLY_SHIFT 6 -+#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT) -+#define QUADSPI_SMPR_FSPHS_SHIFT 5 -+#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT) -+#define QUADSPI_SMPR_HSENA_SHIFT 0 -+#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT) -+ -+#define QUADSPI_RBSR 0x10c -+#define QUADSPI_RBSR_RDBFL_SHIFT 8 -+#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT) -+ -+#define QUADSPI_RBCT 0x110 -+#define QUADSPI_RBCT_WMRK_MASK 0x1F -+#define QUADSPI_RBCT_RXBRD_SHIFT 8 -+#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT) -+ -+#define QUADSPI_TBSR 0x150 -+#define QUADSPI_TBDR 0x154 -+#define QUADSPI_SR 0x15c -+#define QUADSPI_SR_IP_ACC_SHIFT 1 -+#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT) -+#define QUADSPI_SR_AHB_ACC_SHIFT 2 -+#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT) -+ -+#define QUADSPI_FR 0x160 -+#define QUADSPI_FR_TFF_MASK 0x1 -+ -+#define QUADSPI_SFA1AD 0x180 -+#define QUADSPI_SFA2AD 0x184 -+#define QUADSPI_SFB1AD 0x188 -+#define QUADSPI_SFB2AD 0x18c -+#define QUADSPI_RBDR 0x200 -+ -+#define QUADSPI_LUTKEY 0x300 -+#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0 -+ -+#define QUADSPI_LCKCR 0x304 -+#define QUADSPI_LCKER_LOCK 0x1 -+#define QUADSPI_LCKER_UNLOCK 0x2 -+ -+#define QUADSPI_RSER 0x164 -+#define QUADSPI_RSER_TFIE (0x1 << 0) -+ -+#define QUADSPI_LUT_BASE 0x310 -+ -+/* -+ * The definition of the LUT register shows below: -+ * -+ * --------------------------------------------------- -+ * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | -+ * --------------------------------------------------- -+ */ -+#define OPRND0_SHIFT 0 -+#define PAD0_SHIFT 8 -+#define INSTR0_SHIFT 10 -+#define OPRND1_SHIFT 16 -+ -+/* Instruction set for the LUT register. */ -+#define LUT_STOP 0 -+#define LUT_CMD 1 -+#define LUT_ADDR 2 -+#define LUT_DUMMY 3 -+#define LUT_MODE 4 -+#define LUT_MODE2 5 -+#define LUT_MODE4 6 -+#define LUT_READ 7 -+#define LUT_WRITE 8 -+#define LUT_JMP_ON_CS 9 -+#define LUT_ADDR_DDR 10 -+#define LUT_MODE_DDR 11 -+#define LUT_MODE2_DDR 12 -+#define LUT_MODE4_DDR 13 -+#define LUT_READ_DDR 14 -+#define LUT_WRITE_DDR 15 -+#define LUT_DATA_LEARN 16 -+ -+/* -+ * The PAD definitions for LUT register. -+ * -+ * The pad stands for the lines number of IO[0:3]. -+ * For example, the Quad read need four IO lines, so you should -+ * set LUT_PAD4 which means we use four IO lines. -+ */ -+#define LUT_PAD1 0 -+#define LUT_PAD2 1 -+#define LUT_PAD4 2 -+ -+/* Oprands for the LUT register. */ -+#define ADDR24BIT 0x18 -+#define ADDR32BIT 0x20 -+ -+/* Macros for constructing the LUT register. */ -+#define LUT0(ins, pad, opr) \ -+ (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ -+ ((LUT_##ins) << INSTR0_SHIFT)) -+ -+#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT) -+ -+/* other macros for LUT register. */ -+#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4) -+#define QUADSPI_LUT_NUM 64 -+ -+/* SEQID -- we can have 16 seqids at most. */ -+#define SEQID_QUAD_READ 0 -+#define SEQID_WREN 1 -+#define SEQID_WRDI 2 -+#define SEQID_RDSR 3 -+#define SEQID_SE 4 -+#define SEQID_CHIP_ERASE 5 -+#define SEQID_PP 6 -+#define SEQID_RDID 7 -+#define SEQID_WRSR 8 -+#define SEQID_RDCR 9 -+#define SEQID_EN4B 10 -+#define SEQID_BRWR 11 -+ -+enum fsl_qspi_devtype { -+ FSL_QUADSPI_VYBRID, -+ FSL_QUADSPI_IMX6SX, -+}; -+ -+struct fsl_qspi_devtype_data { -+ enum fsl_qspi_devtype devtype; -+ int rxfifo; -+ int txfifo; -+}; -+ -+static struct fsl_qspi_devtype_data vybrid_data = { -+ .devtype = FSL_QUADSPI_VYBRID, -+ .rxfifo = 128, -+ .txfifo = 64 -+}; -+ -+static struct fsl_qspi_devtype_data imx6sx_data = { -+ .devtype = FSL_QUADSPI_IMX6SX, -+ .rxfifo = 128, -+ .txfifo = 512 -+}; -+ -+#define FSL_QSPI_MAX_CHIP 4 -+struct fsl_qspi { -+ struct mtd_info mtd[FSL_QSPI_MAX_CHIP]; -+ struct spi_nor nor[FSL_QSPI_MAX_CHIP]; -+ void __iomem *iobase; -+ void __iomem *ahb_base; /* Used when read from AHB bus */ -+ u32 memmap_phy; -+ struct clk *clk, *clk_en; -+ struct device *dev; -+ struct completion c; -+ struct fsl_qspi_devtype_data *devtype_data; -+ u32 nor_size; -+ u32 nor_num; -+ u32 clk_rate; -+ unsigned int chip_base_addr; /* We may support two chips. */ -+}; -+ -+static inline int is_vybrid_qspi(struct fsl_qspi *q) -+{ -+ return q->devtype_data->devtype == FSL_QUADSPI_VYBRID; -+} -+ -+static inline int is_imx6sx_qspi(struct fsl_qspi *q) -+{ -+ return q->devtype_data->devtype == FSL_QUADSPI_IMX6SX; -+} -+ -+/* -+ * An IC bug makes us to re-arrange the 32-bit data. -+ * The following chips, such as IMX6SLX, have fixed this bug. -+ */ -+static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) -+{ -+ return is_vybrid_qspi(q) ? __swab32(a) : a; -+} -+ -+static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q) -+{ -+ writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); -+ writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); -+} -+ -+static inline void fsl_qspi_lock_lut(struct fsl_qspi *q) -+{ -+ writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); -+ writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); -+} -+ -+static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) -+{ -+ struct fsl_qspi *q = dev_id; -+ u32 reg; -+ -+ /* clear interrupt */ -+ reg = readl(q->iobase + QUADSPI_FR); -+ writel(reg, q->iobase + QUADSPI_FR); -+ -+ if (reg & QUADSPI_FR_TFF_MASK) -+ complete(&q->c); -+ -+ dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", q->chip_base_addr, reg); -+ return IRQ_HANDLED; -+} -+ -+static void fsl_qspi_init_lut(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ int rxfifo = q->devtype_data->rxfifo; -+ u32 lut_base; -+ u8 cmd, addrlen, dummy; -+ int i; -+ -+ fsl_qspi_unlock_lut(q); -+ -+ /* Clear all the LUT table */ -+ for (i = 0; i < QUADSPI_LUT_NUM; i++) -+ writel(0, base + QUADSPI_LUT_BASE + i * 4); -+ -+ /* Quad Read */ -+ lut_base = SEQID_QUAD_READ * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_READ_1_1_4; -+ addrlen = ADDR24BIT; -+ dummy = 8; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_READ_1_1_4; -+ addrlen = ADDR32BIT; -+ dummy = 8; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo), -+ base + QUADSPI_LUT(lut_base + 1)); -+ -+ /* Write enable */ -+ lut_base = SEQID_WREN * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base)); -+ -+ /* Page Program */ -+ lut_base = SEQID_PP * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_PP; -+ addrlen = ADDR24BIT; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_PP; -+ addrlen = ADDR32BIT; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1)); -+ -+ /* Read Status */ -+ lut_base = SEQID_RDSR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(READ, PAD1, 0x1), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Erase a sector */ -+ lut_base = SEQID_SE * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_SE; -+ addrlen = ADDR24BIT; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_SE; -+ addrlen = ADDR32BIT; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Erase the whole chip */ -+ lut_base = SEQID_CHIP_ERASE * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* READ ID */ -+ lut_base = SEQID_RDID * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(READ, PAD1, 0x8), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Write Register */ -+ lut_base = SEQID_WRSR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(WRITE, PAD1, 0x2), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Read Configuration Register */ -+ lut_base = SEQID_RDCR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(READ, PAD1, 0x1), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Write disable */ -+ lut_base = SEQID_WRDI * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base)); -+ -+ /* Enter 4 Byte Mode (Micron) */ -+ lut_base = SEQID_EN4B * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base)); -+ -+ /* Enter 4 Byte Mode (Spansion) */ -+ lut_base = SEQID_BRWR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base)); -+ -+ fsl_qspi_lock_lut(q); -+} -+ -+/* Get the SEQID for the command */ -+static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) -+{ -+ switch (cmd) { -+ case SPINOR_OP_READ_1_1_4: -+ return SEQID_QUAD_READ; -+ case SPINOR_OP_WREN: -+ return SEQID_WREN; -+ case SPINOR_OP_WRDI: -+ return SEQID_WRDI; -+ case SPINOR_OP_RDSR: -+ return SEQID_RDSR; -+ case SPINOR_OP_SE: -+ return SEQID_SE; -+ case SPINOR_OP_CHIP_ERASE: -+ return SEQID_CHIP_ERASE; -+ case SPINOR_OP_PP: -+ return SEQID_PP; -+ case SPINOR_OP_RDID: -+ return SEQID_RDID; -+ case SPINOR_OP_WRSR: -+ return SEQID_WRSR; -+ case SPINOR_OP_RDCR: -+ return SEQID_RDCR; -+ case SPINOR_OP_EN4B: -+ return SEQID_EN4B; -+ case SPINOR_OP_BRWR: -+ return SEQID_BRWR; -+ default: -+ dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); -+ break; -+ } -+ return -EINVAL; -+} -+ -+static int -+fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) -+{ -+ void __iomem *base = q->iobase; -+ int seqid; -+ u32 reg, reg2; -+ int err; -+ -+ init_completion(&q->c); -+ dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n", -+ q->chip_base_addr, addr, len, cmd); -+ -+ /* save the reg */ -+ reg = readl(base + QUADSPI_MCR); -+ -+ writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR); -+ writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, -+ base + QUADSPI_RBCT); -+ writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); -+ -+ do { -+ reg2 = readl(base + QUADSPI_SR); -+ if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) { -+ udelay(1); -+ dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2); -+ continue; -+ } -+ break; -+ } while (1); -+ -+ /* trigger the LUT now */ -+ seqid = fsl_qspi_get_seqid(q, cmd); -+ writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR); -+ -+ /* Wait for the interrupt. */ -+ err = wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000)); -+ if (!err) { -+ dev_err(q->dev, -+ "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n", -+ cmd, addr, readl(base + QUADSPI_FR), -+ readl(base + QUADSPI_SR)); -+ err = -ETIMEDOUT; -+ } else { -+ err = 0; -+ } -+ -+ /* restore the MCR */ -+ writel(reg, base + QUADSPI_MCR); -+ -+ return err; -+} -+ -+/* Read out the data from the QUADSPI_RBDR buffer registers. */ -+static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf) -+{ -+ u32 tmp; -+ int i = 0; -+ -+ while (len > 0) { -+ tmp = readl(q->iobase + QUADSPI_RBDR + i * 4); -+ tmp = fsl_qspi_endian_xchg(q, tmp); -+ dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n", -+ q->chip_base_addr, tmp); -+ -+ if (len >= 4) { -+ *((u32 *)rxbuf) = tmp; -+ rxbuf += 4; -+ } else { -+ memcpy(rxbuf, &tmp, len); -+ break; -+ } -+ -+ len -= 4; -+ i++; -+ } -+} -+ -+/* -+ * If we have changed the content of the flash by writing or erasing, -+ * we need to invalidate the AHB buffer. If we do not do so, we may read out -+ * the wrong data. The spec tells us reset the AHB domain and Serial Flash -+ * domain at the same time. -+ */ -+static inline void fsl_qspi_invalid(struct fsl_qspi *q) -+{ -+ u32 reg; -+ -+ reg = readl(q->iobase + QUADSPI_MCR); -+ reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; -+ writel(reg, q->iobase + QUADSPI_MCR); -+ -+ /* -+ * The minimum delay : 1 AHB + 2 SFCK clocks. -+ * Delay 1 us is enough. -+ */ -+ udelay(1); -+ -+ reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); -+ writel(reg, q->iobase + QUADSPI_MCR); -+} -+ -+static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, -+ u8 opcode, unsigned int to, u32 *txbuf, -+ unsigned count, size_t *retlen) -+{ -+ int ret, i, j; -+ u32 tmp; -+ -+ dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n", -+ q->chip_base_addr, to, count); -+ -+ /* clear the TX FIFO. */ -+ tmp = readl(q->iobase + QUADSPI_MCR); -+ writel(tmp | QUADSPI_MCR_CLR_RXF_MASK, q->iobase + QUADSPI_MCR); -+ -+ /* fill the TX data to the FIFO */ -+ for (j = 0, i = ((count + 3) / 4); j < i; j++) { -+ tmp = fsl_qspi_endian_xchg(q, *txbuf); -+ writel(tmp, q->iobase + QUADSPI_TBDR); -+ txbuf++; -+ } -+ -+ /* Trigger it */ -+ ret = fsl_qspi_runcmd(q, opcode, to, count); -+ -+ if (ret == 0 && retlen) -+ *retlen += count; -+ -+ return ret; -+} -+ -+static void fsl_qspi_set_map_addr(struct fsl_qspi *q) -+{ -+ int nor_size = q->nor_size; -+ void __iomem *base = q->iobase; -+ -+ writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); -+ writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); -+ writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); -+ writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); -+} -+ -+/* -+ * There are two different ways to read out the data from the flash: -+ * the "IP Command Read" and the "AHB Command Read". -+ * -+ * The IC guy suggests we use the "AHB Command Read" which is faster -+ * then the "IP Command Read". (What's more is that there is a bug in -+ * the "IP Command Read" in the Vybrid.) -+ * -+ * After we set up the registers for the "AHB Command Read", we can use -+ * the memcpy to read the data directly. A "missed" access to the buffer -+ * causes the controller to clear the buffer, and use the sequence pointed -+ * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. -+ */ -+static void fsl_qspi_init_abh_read(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ int seqid; -+ -+ /* AHB configuration for access buffer 0/1/2 .*/ -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); -+ writel(QUADSPI_BUF3CR_ALLMST, base + QUADSPI_BUF3CR); -+ -+ /* We only use the buffer3 */ -+ writel(0, base + QUADSPI_BUF0IND); -+ writel(0, base + QUADSPI_BUF1IND); -+ writel(0, base + QUADSPI_BUF2IND); -+ -+ /* Set the default lut sequence for AHB Read. */ -+ seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); -+ writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT, -+ q->iobase + QUADSPI_BFGENCR); -+} -+ -+/* We use this function to do some basic init for spi_nor_scan(). */ -+static int fsl_qspi_nor_setup(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ u32 reg; -+ int ret; -+ -+ /* the default frequency, we will change it in the future.*/ -+ ret = clk_set_rate(q->clk, 66000000); -+ if (ret) -+ return ret; -+ -+ /* Init the LUT table. */ -+ fsl_qspi_init_lut(q); -+ -+ /* Disable the module */ -+ writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, -+ base + QUADSPI_MCR); -+ -+ reg = readl(base + QUADSPI_SMPR); -+ writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK -+ | QUADSPI_SMPR_FSPHS_MASK -+ | QUADSPI_SMPR_HSENA_MASK -+ | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); -+ -+ /* Enable the module */ -+ writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, -+ base + QUADSPI_MCR); -+ -+ /* enable the interrupt */ -+ writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); -+ -+ return 0; -+} -+ -+static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) -+{ -+ unsigned long rate = q->clk_rate; -+ int ret; -+ -+ if (is_imx6sx_qspi(q)) -+ rate *= 4; -+ -+ ret = clk_set_rate(q->clk, rate); -+ if (ret) -+ return ret; -+ -+ /* Init the LUT table again. */ -+ fsl_qspi_init_lut(q); -+ -+ /* Init for AHB read */ -+ fsl_qspi_init_abh_read(q); -+ -+ return 0; -+} -+ -+static struct of_device_id fsl_qspi_dt_ids[] = { -+ { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, -+ { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); -+ -+static void fsl_qspi_set_base_addr(struct fsl_qspi *q, struct spi_nor *nor) -+{ -+ q->chip_base_addr = q->nor_size * (nor - q->nor); -+} -+ -+static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -+{ -+ int ret; -+ struct fsl_qspi *q = nor->priv; -+ -+ ret = fsl_qspi_runcmd(q, opcode, 0, len); -+ if (ret) -+ return ret; -+ -+ fsl_qspi_read_data(q, len, buf); -+ return 0; -+} -+ -+static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+ int write_enable) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ if (!buf) { -+ ret = fsl_qspi_runcmd(q, opcode, 0, 1); -+ if (ret) -+ return ret; -+ -+ if (opcode == SPINOR_OP_CHIP_ERASE) -+ fsl_qspi_invalid(q); -+ -+ } else if (len > 0) { -+ ret = fsl_qspi_nor_write(q, nor, opcode, 0, -+ (u32 *)buf, len, NULL); -+ } else { -+ dev_err(q->dev, "invalid cmd %d\n", opcode); -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static void fsl_qspi_write(struct spi_nor *nor, loff_t to, -+ size_t len, size_t *retlen, const u_char *buf) -+{ -+ struct fsl_qspi *q = nor->priv; -+ -+ fsl_qspi_nor_write(q, nor, nor->program_opcode, to, -+ (u32 *)buf, len, retlen); -+ -+ /* invalid the data in the AHB buffer. */ -+ fsl_qspi_invalid(q); -+} -+ -+static int fsl_qspi_read(struct spi_nor *nor, loff_t from, -+ size_t len, size_t *retlen, u_char *buf) -+{ -+ struct fsl_qspi *q = nor->priv; -+ u8 cmd = nor->read_opcode; -+ int ret; -+ -+ dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n", -+ cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len); -+ -+ /* Wait until the previous command is finished. */ -+ ret = nor->wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Read out the data directly from the AHB buffer.*/ -+ memcpy(buf, q->ahb_base + q->chip_base_addr + from, len); -+ -+ *retlen += len; -+ return 0; -+} -+ -+static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", -+ nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); -+ -+ /* Wait until finished previous write command. */ -+ ret = nor->wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Send write enable, then erase commands. */ -+ ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -+ if (ret) -+ return ret; -+ -+ ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); -+ if (ret) -+ return ret; -+ -+ fsl_qspi_invalid(q); -+ return 0; -+} -+ -+static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ ret = clk_enable(q->clk_en); -+ if (ret) -+ return ret; -+ -+ ret = clk_enable(q->clk); -+ if (ret) { -+ clk_disable(q->clk_en); -+ return ret; -+ } -+ -+ fsl_qspi_set_base_addr(q, nor); -+ return 0; -+} -+ -+static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ struct fsl_qspi *q = nor->priv; -+ -+ clk_disable(q->clk); -+ clk_disable(q->clk_en); -+} -+ -+static int fsl_qspi_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct mtd_part_parser_data ppdata; -+ struct device *dev = &pdev->dev; -+ struct fsl_qspi *q; -+ struct resource *res; -+ struct spi_nor *nor; -+ struct mtd_info *mtd; -+ int ret, i = 0; -+ bool has_second_chip = false; -+ const struct of_device_id *of_id = -+ of_match_device(fsl_qspi_dt_ids, &pdev->dev); -+ -+ q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); -+ if (!q) -+ return -ENOMEM; -+ -+ q->nor_num = of_get_child_count(dev->of_node); -+ if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP) -+ return -ENODEV; -+ -+ /* find the resources */ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); -+ q->iobase = devm_ioremap_resource(dev, res); -+ if (IS_ERR(q->iobase)) { -+ ret = PTR_ERR(q->iobase); -+ goto map_failed; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "QuadSPI-memory"); -+ q->ahb_base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(q->ahb_base)) { -+ ret = PTR_ERR(q->ahb_base); -+ goto map_failed; -+ } -+ q->memmap_phy = res->start; -+ -+ /* find the clocks */ -+ q->clk_en = devm_clk_get(dev, "qspi_en"); -+ if (IS_ERR(q->clk_en)) { -+ ret = PTR_ERR(q->clk_en); -+ goto map_failed; -+ } -+ -+ q->clk = devm_clk_get(dev, "qspi"); -+ if (IS_ERR(q->clk)) { -+ ret = PTR_ERR(q->clk); -+ goto map_failed; -+ } -+ -+ ret = clk_prepare_enable(q->clk_en); -+ if (ret) { -+ dev_err(dev, "can not enable the qspi_en clock\n"); -+ goto map_failed; -+ } -+ -+ ret = clk_prepare_enable(q->clk); -+ if (ret) { -+ clk_disable_unprepare(q->clk_en); -+ dev_err(dev, "can not enable the qspi clock\n"); -+ goto map_failed; -+ } -+ -+ /* find the irq */ -+ ret = platform_get_irq(pdev, 0); -+ if (ret < 0) { -+ dev_err(dev, "failed to get the irq\n"); -+ goto irq_failed; -+ } -+ -+ ret = devm_request_irq(dev, ret, -+ fsl_qspi_irq_handler, 0, pdev->name, q); -+ if (ret) { -+ dev_err(dev, "failed to request irq.\n"); -+ goto irq_failed; -+ } -+ -+ q->dev = dev; -+ q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data; -+ platform_set_drvdata(pdev, q); -+ -+ ret = fsl_qspi_nor_setup(q); -+ if (ret) -+ goto irq_failed; -+ -+ if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) -+ has_second_chip = true; -+ -+ /* iterate the subnodes. */ -+ for_each_available_child_of_node(dev->of_node, np) { -+ const struct spi_device_id *id; -+ char modalias[40]; -+ -+ /* skip the holes */ -+ if (!has_second_chip) -+ i *= 2; -+ -+ nor = &q->nor[i]; -+ mtd = &q->mtd[i]; -+ -+ nor->mtd = mtd; -+ nor->dev = dev; -+ nor->priv = q; -+ mtd->priv = nor; -+ -+ /* fill the hooks */ -+ nor->read_reg = fsl_qspi_read_reg; -+ nor->write_reg = fsl_qspi_write_reg; -+ nor->read = fsl_qspi_read; -+ nor->write = fsl_qspi_write; -+ nor->erase = fsl_qspi_erase; -+ -+ nor->prepare = fsl_qspi_prep; -+ nor->unprepare = fsl_qspi_unprep; -+ -+ if (of_modalias_node(np, modalias, sizeof(modalias)) < 0) -+ goto map_failed; -+ -+ id = spi_nor_match_id(modalias); -+ if (!id) -+ goto map_failed; -+ -+ ret = of_property_read_u32(np, "spi-max-frequency", -+ &q->clk_rate); -+ if (ret < 0) -+ goto map_failed; -+ -+ /* set the chip address for READID */ -+ fsl_qspi_set_base_addr(q, nor); -+ -+ ret = spi_nor_scan(nor, id, SPI_NOR_QUAD); -+ if (ret) -+ goto map_failed; -+ -+ ppdata.of_node = np; -+ ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); -+ if (ret) -+ goto map_failed; -+ -+ /* Set the correct NOR size now. */ -+ if (q->nor_size == 0) { -+ q->nor_size = mtd->size; -+ -+ /* Map the SPI NOR to accessiable address */ -+ fsl_qspi_set_map_addr(q); -+ } -+ -+ /* -+ * The TX FIFO is 64 bytes in the Vybrid, but the Page Program -+ * may writes 265 bytes per time. The write is working in the -+ * unit of the TX FIFO, not in the unit of the SPI NOR's page -+ * size. -+ * -+ * So shrink the spi_nor->page_size if it is larger then the -+ * TX FIFO. -+ */ -+ if (nor->page_size > q->devtype_data->txfifo) -+ nor->page_size = q->devtype_data->txfifo; -+ -+ i++; -+ } -+ -+ /* finish the rest init. */ -+ ret = fsl_qspi_nor_setup_last(q); -+ if (ret) -+ goto last_init_failed; -+ -+ clk_disable(q->clk); -+ clk_disable(q->clk_en); -+ dev_info(dev, "QuadSPI SPI NOR flash driver\n"); -+ return 0; -+ -+last_init_failed: -+ for (i = 0; i < q->nor_num; i++) -+ mtd_device_unregister(&q->mtd[i]); -+ -+irq_failed: -+ clk_disable_unprepare(q->clk); -+ clk_disable_unprepare(q->clk_en); -+map_failed: -+ dev_err(dev, "Freescale QuadSPI probe failed\n"); -+ return ret; -+} -+ -+static int fsl_qspi_remove(struct platform_device *pdev) -+{ -+ struct fsl_qspi *q = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < q->nor_num; i++) -+ mtd_device_unregister(&q->mtd[i]); -+ -+ /* disable the hardware */ -+ writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); -+ writel(0x0, q->iobase + QUADSPI_RSER); -+ -+ clk_unprepare(q->clk); -+ clk_unprepare(q->clk_en); -+ return 0; -+} -+ -+static struct platform_driver fsl_qspi_driver = { -+ .driver = { -+ .name = "fsl-quadspi", -+ .bus = &platform_bus_type, -+ .owner = THIS_MODULE, -+ .of_match_table = fsl_qspi_dt_ids, -+ }, -+ .probe = fsl_qspi_probe, -+ .remove = fsl_qspi_remove, -+}; -+module_platform_driver(fsl_qspi_driver); -+ -+MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver"); -+MODULE_AUTHOR("Freescale Semiconductor Inc."); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/mtd/spi-nor/Kconfig -@@ -0,0 +1,17 @@ -+menuconfig MTD_SPI_NOR -+ tristate "SPI-NOR device support" -+ depends on MTD -+ help -+ This is the framework for the SPI NOR which can be used by the SPI -+ device drivers and the SPI-NOR device driver. -+ -+if MTD_SPI_NOR -+ -+config SPI_FSL_QUADSPI -+ tristate "Freescale Quad SPI controller" -+ depends on ARCH_MXC -+ help -+ This enables support for the Quad SPI controller in master mode. -+ We only connect the NOR to this controller now. -+ -+endif # MTD_SPI_NOR ---- /dev/null -+++ b/drivers/mtd/spi-nor/Makefile -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o -+obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o ---- /dev/null -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -0,0 +1,1160 @@ -+/* -+ * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with -+ * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c -+ * -+ * Copyright (C) 2005, Intec Automation Inc. -+ * Copyright (C) 2014, Freescale Semiconductor, Inc. -+ * -+ * This code 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 <linux/err.h> -+#include <linux/errno.h> -+#include <linux/module.h> -+#include <linux/device.h> -+#include <linux/mutex.h> -+#include <linux/math64.h> -+ -+#include <linux/mtd/cfi.h> -+#include <linux/mtd/mtd.h> -+#include <linux/of_platform.h> -+#include <linux/spi/flash.h> -+#include <linux/mtd/spi-nor.h> -+ -+/* Define max times to check status register before we give up. */ -+#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ -+ -+#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) -+ -+/* -+ * Read the status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_sr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading SR\n", (int) ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read the flag status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_fsr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading FSR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read configuration register, returning its value in the -+ * location. Return the configuration register value. -+ * Returns negative if error occured. -+ */ -+static int read_cr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading CR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Dummy Cycle calculation for different type of read. -+ * It can be used to support more commands with -+ * different dummy cycle requirements. -+ */ -+static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) -+{ -+ switch (nor->flash_read) { -+ case SPI_NOR_FAST: -+ case SPI_NOR_DUAL: -+ case SPI_NOR_QUAD: -+ return 1; -+ case SPI_NOR_NORMAL: -+ return 0; -+ } -+ return 0; -+} -+ -+/* -+ * Write status register 1 byte -+ * Returns negative if error occurred. -+ */ -+static inline int write_sr(struct spi_nor *nor, u8 val) -+{ -+ nor->cmd_buf[0] = val; -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -+} -+ -+/* -+ * Set write enable latch with Write Enable command. -+ * Returns negative if error occurred. -+ */ -+static inline int write_enable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -+} -+ -+/* -+ * Send write disble instruction to the chip. -+ */ -+static inline int write_disable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0); -+} -+ -+static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) -+{ -+ return mtd->priv; -+} -+ -+/* Enable/disable 4-byte addressing mode. */ -+static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) -+{ -+ int status; -+ bool need_wren = false; -+ u8 cmd; -+ -+ switch (JEDEC_MFR(jedec_id)) { -+ case CFI_MFR_ST: /* Micron, actually */ -+ /* Some Micron need WREN command; all will accept it */ -+ need_wren = true; -+ case CFI_MFR_MACRONIX: -+ case 0xEF /* winbond */: -+ if (need_wren) -+ write_enable(nor); -+ -+ cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; -+ status = nor->write_reg(nor, cmd, NULL, 0, 0); -+ if (need_wren) -+ write_disable(nor); -+ -+ return status; -+ default: -+ /* Spansion style */ -+ nor->cmd_buf[0] = enable << 7; -+ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); -+ } -+} -+ -+static int spi_nor_wait_till_ready(struct spi_nor *nor) -+{ -+ unsigned long deadline; -+ int sr; -+ -+ deadline = jiffies + MAX_READY_WAIT_JIFFIES; -+ -+ do { -+ cond_resched(); -+ -+ sr = read_sr(nor); -+ if (sr < 0) -+ break; -+ else if (!(sr & SR_WIP)) -+ return 0; -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ return -ETIMEDOUT; -+} -+ -+static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) -+{ -+ unsigned long deadline; -+ int sr; -+ int fsr; -+ -+ deadline = jiffies + MAX_READY_WAIT_JIFFIES; -+ -+ do { -+ cond_resched(); -+ -+ sr = read_sr(nor); -+ if (sr < 0) { -+ break; -+ } else if (!(sr & SR_WIP)) { -+ fsr = read_fsr(nor); -+ if (fsr < 0) -+ break; -+ if (fsr & FSR_READY) -+ return 0; -+ } -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ return -ETIMEDOUT; -+} -+ -+/* -+ * Service routine to read status register until ready, or timeout occurs. -+ * Returns non-zero if error. -+ */ -+static int wait_till_ready(struct spi_nor *nor) -+{ -+ return nor->wait_till_ready(nor); -+} -+ -+/* -+ * Erase the whole flash memory -+ * -+ * Returns 0 if successful, non-zero otherwise. -+ */ -+static int erase_chip(struct spi_nor *nor) -+{ -+ int ret; -+ -+ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Send write enable, then erase commands. */ -+ write_enable(nor); -+ -+ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); -+} -+ -+static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ int ret = 0; -+ -+ mutex_lock(&nor->lock); -+ -+ if (nor->prepare) { -+ ret = nor->prepare(nor, ops); -+ if (ret) { -+ dev_err(nor->dev, "failed in the preparation.\n"); -+ mutex_unlock(&nor->lock); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ if (nor->unprepare) -+ nor->unprepare(nor, ops); -+ mutex_unlock(&nor->lock); -+} -+ -+/* -+ * Erase an address range on the nor chip. The address range may extend -+ * one or more erase sectors. Return an error is there is a problem erasing. -+ */ -+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 addr, len; -+ uint32_t rem; -+ int ret; -+ -+ dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, -+ (long long)instr->len); -+ -+ div_u64_rem(instr->len, mtd->erasesize, &rem); -+ if (rem) -+ return -EINVAL; -+ -+ addr = instr->addr; -+ len = instr->len; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE); -+ if (ret) -+ return ret; -+ -+ /* whole-chip erase? */ -+ if (len == mtd->size) { -+ if (erase_chip(nor)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ /* REVISIT in some cases we could speed up erasing large regions -+ * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up -+ * to use "small sector erase", but that's not always optimal. -+ */ -+ -+ /* "sector"-at-a-time erase */ -+ } else { -+ while (len) { -+ if (nor->erase(nor, addr)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ addr += mtd->erasesize; -+ len -= mtd->erasesize; -+ } -+ } -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ -+ instr->state = MTD_ERASE_DONE; -+ mtd_erase_callback(instr); -+ -+ return ret; -+ -+erase_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ instr->state = MTD_ERASE_FAILED; -+ return ret; -+} -+ -+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ uint32_t offset = ofs; -+ uint8_t status_old, status_new; -+ int ret = 0; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous command */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto err; -+ -+ status_old = read_sr(nor); -+ -+ if (offset < mtd->size - (mtd->size / 2)) -+ status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 4)) -+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -+ else if (offset < mtd->size - (mtd->size / 8)) -+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 16)) -+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+ else if (offset < mtd->size - (mtd->size / 32)) -+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 64)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+ else -+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -+ -+ /* Only modify protection if it will not unlock other areas */ -+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) > -+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+ write_enable(nor); -+ ret = write_sr(nor, status_new); -+ if (ret) -+ goto err; -+ } -+ -+err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+ return ret; -+} -+ -+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ uint32_t offset = ofs; -+ uint8_t status_old, status_new; -+ int ret = 0; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous command */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto err; -+ -+ status_old = read_sr(nor); -+ -+ if (offset+len > mtd->size - (mtd->size / 64)) -+ status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); -+ else if (offset+len > mtd->size - (mtd->size / 32)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -+ else if (offset+len > mtd->size - (mtd->size / 16)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+ else if (offset+len > mtd->size - (mtd->size / 8)) -+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+ else if (offset+len > mtd->size - (mtd->size / 4)) -+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+ else if (offset+len > mtd->size - (mtd->size / 2)) -+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+ else -+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -+ -+ /* Only modify protection if it will not lock other areas */ -+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < -+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+ write_enable(nor); -+ ret = write_sr(nor, status_new); -+ if (ret) -+ goto err; -+ } -+ -+err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); -+ return ret; -+} -+ -+struct flash_info { -+ /* JEDEC id zero means "no ID" (most older chips); otherwise it has -+ * a high byte of zero plus three data bytes: the manufacturer id, -+ * then a two byte device id. -+ */ -+ u32 jedec_id; -+ u16 ext_id; -+ -+ /* The size listed here is what works with SPINOR_OP_SE, which isn't -+ * necessarily called a "sector" by the vendor. -+ */ -+ unsigned sector_size; -+ u16 n_sectors; -+ -+ u16 page_size; -+ u16 addr_width; -+ -+ u16 flags; -+#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -+#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -+#define SST_WRITE 0x04 /* use SST byte programming */ -+#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -+#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -+#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -+#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -+#define USE_FSR 0x80 /* use flag status register */ -+}; -+ -+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+ ((kernel_ulong_t)&(struct flash_info) { \ -+ .jedec_id = (_jedec_id), \ -+ .ext_id = (_ext_id), \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+ .flags = (_flags), \ -+ }) -+ -+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ -+ ((kernel_ulong_t)&(struct flash_info) { \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = (_page_size), \ -+ .addr_width = (_addr_width), \ -+ .flags = (_flags), \ -+ }) -+ -+/* NOTE: double check command sets and memory organization when you add -+ * more nor chips. This current list focusses on newer chips, which -+ * have been converging on command sets which including JEDEC ID. -+ */ -+const struct spi_device_id spi_nor_ids[] = { -+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */ -+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, -+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, -+ -+ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, -+ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, -+ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, -+ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, -+ -+ /* EON -- en25xxx */ -+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, -+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, -+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, -+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, -+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, -+ -+ /* ESMT */ -+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Everspin */ -+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ -+ /* GigaDevice */ -+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* Intel/Numonyx -- xxxs33b */ -+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -+ -+ /* Macronix */ -+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, -+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, -+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, -+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, -+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, -+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, -+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, -+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) }, -+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -+ -+ /* Micron */ -+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, -+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, -+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, -+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, -+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, -+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, -+ -+ /* PMC */ -+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, -+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Spansion -- single (large) sector size only, at least -+ * for the chips listed here (without boot sectors). -+ */ -+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, -+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, -+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, -+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, -+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, -+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, -+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, -+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, -+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, -+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, -+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */ -+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, -+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, -+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, -+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, -+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, -+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, -+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, -+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ -+ /* ST Microelectronics -- newer production may have feature updates */ -+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, -+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, -+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, -+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, -+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, -+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, -+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, -+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, -+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, -+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, -+ -+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, -+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, -+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, -+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, -+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, -+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, -+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, -+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, -+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, -+ -+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, -+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, -+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, -+ -+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) }, -+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, -+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, -+ -+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) }, -+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, -+ -+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ -+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, -+ -+ /* Catalyst / On Semiconductor -- non-JEDEC */ -+ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { }, -+}; -+EXPORT_SYMBOL_GPL(spi_nor_ids); -+ -+static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) -+{ -+ int tmp; -+ u8 id[5]; -+ u32 jedec; -+ u16 ext_jedec; -+ struct flash_info *info; -+ -+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); -+ if (tmp < 0) { -+ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); -+ return ERR_PTR(tmp); -+ } -+ jedec = id[0]; -+ jedec = jedec << 8; -+ jedec |= id[1]; -+ jedec = jedec << 8; -+ jedec |= id[2]; -+ -+ ext_jedec = id[3] << 8 | id[4]; -+ -+ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { -+ info = (void *)spi_nor_ids[tmp].driver_data; -+ if (info->jedec_id == jedec) { -+ if (info->ext_id == 0 || info->ext_id == ext_jedec) -+ return &spi_nor_ids[tmp]; -+ } -+ } -+ dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); -+ return ERR_PTR(-ENODEV); -+} -+ -+static const struct spi_device_id *jedec_probe(struct spi_nor *nor) -+{ -+ return nor->read_id(nor); -+} -+ -+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ); -+ if (ret) -+ return ret; -+ -+ ret = nor->read(nor, from, len, retlen, buf); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); -+ return ret; -+} -+ -+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ size_t actual; -+ int ret; -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+ write_enable(nor); -+ -+ nor->sst_write_second = false; -+ -+ actual = to % 2; -+ /* Start write from odd address. */ -+ if (actual) { -+ nor->program_opcode = SPINOR_OP_BP; -+ -+ /* write one byte. */ -+ nor->write(nor, to, 1, retlen, buf); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ } -+ to += actual; -+ -+ /* Write out most of the data here. */ -+ for (; actual < len - 1; actual += 2) { -+ nor->program_opcode = SPINOR_OP_AAI_WP; -+ -+ /* write two bytes. */ -+ nor->write(nor, to, 2, retlen, buf + actual); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ to += 2; -+ nor->sst_write_second = true; -+ } -+ nor->sst_write_second = false; -+ -+ write_disable(nor); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+ /* Write out trailing byte if it exists. */ -+ if (actual != len) { -+ write_enable(nor); -+ -+ nor->program_opcode = SPINOR_OP_BP; -+ nor->write(nor, to, 1, retlen, buf + actual); -+ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ write_disable(nor); -+ } -+time_out: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return ret; -+} -+ -+/* -+ * Write an address range to the nor chip. Data must be written in -+ * FLASH_PAGESIZE chunks. The address range may be any size provided -+ * it is within the physical boundaries. -+ */ -+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 page_offset, page_size, i; -+ int ret; -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto write_err; -+ -+ write_enable(nor); -+ -+ page_offset = to & (nor->page_size - 1); -+ -+ /* do all the bytes fit onto one page? */ -+ if (page_offset + len <= nor->page_size) { -+ nor->write(nor, to, len, retlen, buf); -+ } else { -+ /* the size of data remaining on the first page */ -+ page_size = nor->page_size - page_offset; -+ nor->write(nor, to, page_size, retlen, buf); -+ -+ /* write everything in nor->page_size chunks */ -+ for (i = page_size; i < len; i += page_size) { -+ page_size = len - i; -+ if (page_size > nor->page_size) -+ page_size = nor->page_size; -+ -+ wait_till_ready(nor); -+ write_enable(nor); -+ -+ nor->write(nor, to + i, page_size, retlen, buf + i); -+ } -+ } -+ -+write_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return 0; -+} -+ -+static int macronix_quad_enable(struct spi_nor *nor) -+{ -+ int ret, val; -+ -+ val = read_sr(nor); -+ write_enable(nor); -+ -+ nor->cmd_buf[0] = val | SR_QUAD_EN_MX; -+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -+ -+ if (wait_till_ready(nor)) -+ return 1; -+ -+ ret = read_sr(nor); -+ if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { -+ dev_err(nor->dev, "Macronix Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Write status Register and configuration register with 2 bytes -+ * The first byte will be written to the status register, while the -+ * second byte will be written to the configuration register. -+ * Return negative if error occured. -+ */ -+static int write_sr_cr(struct spi_nor *nor, u16 val) -+{ -+ nor->cmd_buf[0] = val & 0xff; -+ nor->cmd_buf[1] = (val >> 8); -+ -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0); -+} -+ -+static int spansion_quad_enable(struct spi_nor *nor) -+{ -+ int ret; -+ int quad_en = CR_QUAD_EN_SPAN << 8; -+ -+ write_enable(nor); -+ -+ ret = write_sr_cr(nor, quad_en); -+ if (ret < 0) { -+ dev_err(nor->dev, -+ "error while writing configuration register\n"); -+ return -EINVAL; -+ } -+ -+ /* read back and check it */ -+ ret = read_cr(nor); -+ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { -+ dev_err(nor->dev, "Spansion Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) -+{ -+ int status; -+ -+ switch (JEDEC_MFR(jedec_id)) { -+ case CFI_MFR_MACRONIX: -+ status = macronix_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Macronix quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ default: -+ status = spansion_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Spansion quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ } -+} -+ -+static int spi_nor_check(struct spi_nor *nor) -+{ -+ if (!nor->dev || !nor->read || !nor->write || -+ !nor->read_reg || !nor->write_reg || !nor->erase) { -+ pr_err("spi-nor: please fill all the necessary fields!\n"); -+ return -EINVAL; -+ } -+ -+ if (!nor->read_id) -+ nor->read_id = spi_nor_read_id; -+ if (!nor->wait_till_ready) -+ nor->wait_till_ready = spi_nor_wait_till_ready; -+ -+ return 0; -+} -+ -+int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -+ enum read_mode mode) -+{ -+ struct flash_info *info; -+ struct flash_platform_data *data; -+ struct device *dev = nor->dev; -+ struct mtd_info *mtd = nor->mtd; -+ struct device_node *np = dev->of_node; -+ int ret; -+ int i; -+ -+ ret = spi_nor_check(nor); -+ if (ret) -+ return ret; -+ -+ /* Platform data helps sort out which chip type we have, as -+ * well as how this board partitions it. If we don't have -+ * a chip ID, try the JEDEC id commands; they'll work for most -+ * newer chips, even if we don't recognize the particular chip. -+ */ -+ data = dev_get_platdata(dev); -+ if (data && data->type) { -+ const struct spi_device_id *plat_id; -+ -+ for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { -+ plat_id = &spi_nor_ids[i]; -+ if (strcmp(data->type, plat_id->name)) -+ continue; -+ break; -+ } -+ -+ if (i < ARRAY_SIZE(spi_nor_ids) - 1) -+ id = plat_id; -+ else -+ dev_warn(dev, "unrecognized id %s\n", data->type); -+ } -+ -+ info = (void *)id->driver_data; -+ -+ if (info->jedec_id) { -+ const struct spi_device_id *jid; -+ -+ jid = jedec_probe(nor); -+ if (IS_ERR(jid)) { -+ return PTR_ERR(jid); -+ } else if (jid != id) { -+ /* -+ * JEDEC knows better, so overwrite platform ID. We -+ * can't trust partitions any longer, but we'll let -+ * mtd apply them anyway, since some partitions may be -+ * marked read-only, and we don't want to lose that -+ * information, even if it's not 100% accurate. -+ */ -+ dev_warn(dev, "found %s, expected %s\n", -+ jid->name, id->name); -+ id = jid; -+ info = (void *)jid->driver_data; -+ } -+ } -+ -+ mutex_init(&nor->lock); -+ -+ /* -+ * Atmel, SST and Intel/Numonyx serial nor tend to power -+ * up with the software protection bits set -+ */ -+ -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || -+ JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || -+ JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { -+ write_enable(nor); -+ write_sr(nor, 0); -+ } -+ -+ if (data && data->name) -+ mtd->name = data->name; -+ else -+ mtd->name = dev_name(dev); -+ -+ mtd->type = MTD_NORFLASH; -+ mtd->writesize = 1; -+ mtd->flags = MTD_CAP_NORFLASH; -+ mtd->size = info->sector_size * info->n_sectors; -+ mtd->_erase = spi_nor_erase; -+ mtd->_read = spi_nor_read; -+ -+ /* nor protection support for STmicro chips */ -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { -+ mtd->_lock = spi_nor_lock; -+ mtd->_unlock = spi_nor_unlock; -+ } -+ -+ /* sst nor chips use AAI word program */ -+ if (info->flags & SST_WRITE) -+ mtd->_write = sst_write; -+ else -+ mtd->_write = spi_nor_write; -+ -+ if ((info->flags & USE_FSR) && -+ nor->wait_till_ready == spi_nor_wait_till_ready) -+ nor->wait_till_ready = spi_nor_wait_till_fsr_ready; -+ -+ /* prefer "small sector" erase if possible */ -+ if (info->flags & SECT_4K) { -+ nor->erase_opcode = SPINOR_OP_BE_4K; -+ mtd->erasesize = 4096; -+ } else if (info->flags & SECT_4K_PMC) { -+ nor->erase_opcode = SPINOR_OP_BE_4K_PMC; -+ mtd->erasesize = 4096; -+ } else { -+ nor->erase_opcode = SPINOR_OP_SE; -+ mtd->erasesize = info->sector_size; -+ } -+ -+ if (info->flags & SPI_NOR_NO_ERASE) -+ mtd->flags |= MTD_NO_ERASE; -+ -+ mtd->dev.parent = dev; -+ nor->page_size = info->page_size; -+ mtd->writebufsize = nor->page_size; -+ -+ if (np) { -+ /* If we were instantiated by DT, use it */ -+ if (of_property_read_bool(np, "m25p,fast-read")) -+ nor->flash_read = SPI_NOR_FAST; -+ else -+ nor->flash_read = SPI_NOR_NORMAL; -+ } else { -+ /* If we weren't instantiated by DT, default to fast-read */ -+ nor->flash_read = SPI_NOR_FAST; -+ } -+ -+ /* Some devices cannot do fast-read, no matter what DT tells us */ -+ if (info->flags & SPI_NOR_NO_FR) -+ nor->flash_read = SPI_NOR_NORMAL; -+ -+ /* Quad/Dual-read mode takes precedence over fast/normal */ -+ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -+ ret = set_quad_mode(nor, info->jedec_id); -+ if (ret) { -+ dev_err(dev, "quad mode not supported\n"); -+ return ret; -+ } -+ nor->flash_read = SPI_NOR_QUAD; -+ } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { -+ nor->flash_read = SPI_NOR_DUAL; -+ } -+ -+ /* Default commands */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ; -+ break; -+ default: -+ dev_err(dev, "No Read opcode defined\n"); -+ return -EINVAL; -+ } -+ -+ nor->program_opcode = SPINOR_OP_PP; -+ -+ if (info->addr_width) -+ nor->addr_width = info->addr_width; -+ else if (mtd->size > 0x1000000) { -+ /* enable 4-byte addressing if the device exceeds 16MiB */ -+ nor->addr_width = 4; -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { -+ /* Dedicated 4-byte command set */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ4_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ4; -+ break; -+ } -+ nor->program_opcode = SPINOR_OP_PP_4B; -+ /* No small sector erase for 4-byte command set */ -+ nor->erase_opcode = SPINOR_OP_SE_4B; -+ mtd->erasesize = info->sector_size; -+ } else -+ set_4byte(nor, info->jedec_id, 1); -+ } else { -+ nor->addr_width = 3; -+ } -+ -+ nor->read_dummy = spi_nor_read_dummy_cycles(nor); -+ -+ dev_info(dev, "%s (%lld Kbytes)\n", id->name, -+ (long long)mtd->size >> 10); -+ -+ dev_dbg(dev, -+ "mtd .name = %s, .size = 0x%llx (%lldMiB), " -+ ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", -+ mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), -+ mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); -+ -+ if (mtd->numeraseregions) -+ for (i = 0; i < mtd->numeraseregions; i++) -+ dev_dbg(dev, -+ "mtd.eraseregions[%d] = { .offset = 0x%llx, " -+ ".erasesize = 0x%.8x (%uKiB), " -+ ".numblocks = %d }\n", -+ i, (long long)mtd->eraseregions[i].offset, -+ mtd->eraseregions[i].erasesize, -+ mtd->eraseregions[i].erasesize / 1024, -+ mtd->eraseregions[i].numblocks); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_nor_scan); -+ -+const struct spi_device_id *spi_nor_match_id(char *name) -+{ -+ const struct spi_device_id *id = spi_nor_ids; -+ -+ while (id->name[0]) { -+ if (!strcmp(name, id->name)) -+ return id; -+ id++; -+ } -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(spi_nor_match_id); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>"); -+MODULE_AUTHOR("Mike Lavender"); -+MODULE_DESCRIPTION("framework for SPI NOR"); ---- /dev/null -+++ b/include/linux/mtd/spi-nor.h -@@ -0,0 +1,218 @@ -+/* -+ * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * -+ * 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; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef __LINUX_MTD_SPI_NOR_H -+#define __LINUX_MTD_SPI_NOR_H -+ -+/* -+ * Note on opcode nomenclature: some opcodes have a format like -+ * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number -+ * of I/O lines used for the opcode, address, and data (respectively). The -+ * FUNCTION has an optional suffix of '4', to represent an opcode which -+ * requires a 4-byte (32-bit) address. -+ */ -+ -+/* Flash opcodes. */ -+#define SPINOR_OP_WREN 0x06 /* Write enable */ -+#define SPINOR_OP_RDSR 0x05 /* Read status register */ -+#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ -+#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ -+#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ -+#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ -+#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ -+#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ -+#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ -+#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ -+#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */ -+#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ -+#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ -+#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ -+#define SPINOR_OP_RDCR 0x35 /* Read configuration register */ -+#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ -+ -+/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ -+#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ -+#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ -+#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ -+#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ -+#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ -+#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ -+ -+/* Used for SST flashes only. */ -+#define SPINOR_OP_BP 0x02 /* Byte program */ -+#define SPINOR_OP_WRDI 0x04 /* Write disable */ -+#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */ -+ -+/* Used for Macronix and Winbond flashes. */ -+#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ -+#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ -+ -+/* Used for Spansion flashes only. */ -+#define SPINOR_OP_BRWR 0x17 /* Bank register write */ -+ -+/* Status Register bits. */ -+#define SR_WIP 1 /* Write in progress */ -+#define SR_WEL 2 /* Write enable latch */ -+/* meaning of other SR_* bits may differ between vendors */ -+#define SR_BP0 4 /* Block protect 0 */ -+#define SR_BP1 8 /* Block protect 1 */ -+#define SR_BP2 0x10 /* Block protect 2 */ -+#define SR_SRWD 0x80 /* SR write protect */ -+ -+#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ -+ -+/* Flag Status Register bits */ -+#define FSR_READY 0x80 -+ -+/* Configuration Register bits. */ -+#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ -+ -+enum read_mode { -+ SPI_NOR_NORMAL = 0, -+ SPI_NOR_FAST, -+ SPI_NOR_DUAL, -+ SPI_NOR_QUAD, -+}; -+ -+/** -+ * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer -+ * @wren: command for "Write Enable", or 0x00 for not required -+ * @cmd: command for operation -+ * @cmd_pins: number of pins to send @cmd (1, 2, 4) -+ * @addr: address for operation -+ * @addr_pins: number of pins to send @addr (1, 2, 4) -+ * @addr_width: number of address bytes -+ * (3,4, or 0 for address not required) -+ * @mode: mode data -+ * @mode_pins: number of pins to send @mode (1, 2, 4) -+ * @mode_cycles: number of mode cycles (0 for mode not required) -+ * @dummy_cycles: number of dummy cycles (0 for dummy not required) -+ */ -+struct spi_nor_xfer_cfg { -+ u8 wren; -+ u8 cmd; -+ u8 cmd_pins; -+ u32 addr; -+ u8 addr_pins; -+ u8 addr_width; -+ u8 mode; -+ u8 mode_pins; -+ u8 mode_cycles; -+ u8 dummy_cycles; -+}; -+ -+#define SPI_NOR_MAX_CMD_SIZE 8 -+enum spi_nor_ops { -+ SPI_NOR_OPS_READ = 0, -+ SPI_NOR_OPS_WRITE, -+ SPI_NOR_OPS_ERASE, -+ SPI_NOR_OPS_LOCK, -+ SPI_NOR_OPS_UNLOCK, -+}; -+ -+/** -+ * struct spi_nor - Structure for defining a the SPI NOR layer -+ * @mtd: point to a mtd_info structure -+ * @lock: the lock for the read/write/erase/lock/unlock operations -+ * @dev: point to a spi device, or a spi nor controller device. -+ * @page_size: the page size of the SPI NOR -+ * @addr_width: number of address bytes -+ * @erase_opcode: the opcode for erasing a sector -+ * @read_opcode: the read opcode -+ * @read_dummy: the dummy needed by the read operation -+ * @program_opcode: the program opcode -+ * @flash_read: the mode of the read -+ * @sst_write_second: used by the SST write operation -+ * @cfg: used by the read_xfer/write_xfer -+ * @cmd_buf: used by the write_reg -+ * @prepare: [OPTIONAL] do some preparations for the -+ * read/write/erase/lock/unlock operations -+ * @unprepare: [OPTIONAL] do some post work after the -+ * read/write/erase/lock/unlock operations -+ * @read_xfer: [OPTIONAL] the read fundamental primitive -+ * @write_xfer: [OPTIONAL] the writefundamental primitive -+ * @read_reg: [DRIVER-SPECIFIC] read out the register -+ * @write_reg: [DRIVER-SPECIFIC] write data to the register -+ * @read_id: [REPLACEABLE] read out the ID data, and find -+ * the proper spi_device_id -+ * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready -+ * @read: [DRIVER-SPECIFIC] read data from the SPI NOR -+ * @write: [DRIVER-SPECIFIC] write data to the SPI NOR -+ * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR -+ * at the offset @offs -+ * @priv: the private data -+ */ -+struct spi_nor { -+ struct mtd_info *mtd; -+ struct mutex lock; -+ struct device *dev; -+ u32 page_size; -+ u8 addr_width; -+ u8 erase_opcode; -+ u8 read_opcode; -+ u8 read_dummy; -+ u8 program_opcode; -+ enum read_mode flash_read; -+ bool sst_write_second; -+ struct spi_nor_xfer_cfg cfg; -+ u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; -+ -+ int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+ void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+ int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+ u8 *buf, size_t len); -+ int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+ u8 *buf, size_t len); -+ int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); -+ int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+ int write_enable); -+ const struct spi_device_id *(*read_id)(struct spi_nor *nor); -+ int (*wait_till_ready)(struct spi_nor *nor); -+ -+ int (*read)(struct spi_nor *nor, loff_t from, -+ size_t len, size_t *retlen, u_char *read_buf); -+ void (*write)(struct spi_nor *nor, loff_t to, -+ size_t len, size_t *retlen, const u_char *write_buf); -+ int (*erase)(struct spi_nor *nor, loff_t offs); -+ -+ void *priv; -+}; -+ -+/** -+ * spi_nor_scan() - scan the SPI NOR -+ * @nor: the spi_nor structure -+ * @id: the spi_device_id provided by the driver -+ * @mode: the read mode supported by the driver -+ * -+ * The drivers can use this fuction to scan the SPI NOR. -+ * In the scanning, it will try to get all the necessary information to -+ * fill the mtd_info{} and the spi_nor{}. -+ * -+ * The board may assigns a spi_device_id with @id which be used to compared with -+ * the spi_device_id detected by the scanning. -+ * -+ * Return: 0 for success, others for failure. -+ */ -+int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -+ enum read_mode mode); -+extern const struct spi_device_id spi_nor_ids[]; -+ -+/** -+ * spi_nor_match_id() - find the spi_device_id by the name -+ * @name: the name of the spi_device_id -+ * -+ * The drivers use this function to find the spi_device_id -+ * specified by the @name. -+ * -+ * Return: returns the right spi_device_id pointer on success, -+ * and returns NULL on failure. -+ */ -+const struct spi_device_id *spi_nor_match_id(char *name); -+ -+#endif diff --git a/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch b/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch deleted file mode 100644 index c12d8df..0000000 --- a/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 5b293ebe757213993ae93b6cbbf5e1d09b75ac2f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:43 +0100 -Subject: [PATCH 1/3] ARM: BCM5301X: initial support for the BCM5301X/BCM470X - SoCs with ARM CPU - -This patch adds support for the BCM5301X/BCM470X SoCs with an ARM CPUs. -Currently just booting to a shell is working and nothing else, no -Ethernet, wifi, flash, ... -I have some pending patches to make Ethernet work for this device. -Mostly device tree support for bcma is missing. - -This SoC is used in small office and home router with Broadcom SoCs -it's internal name is Northstar. This code should support the BCM4707, -BCM4708, BCM4709, BCM53010, BCM53011 and BCM53012 SoC. It uses one or -two ARM Cortex A9 Cores, some highlights are 2 PCIe 2.0 controllers, -4 Gigabit Ethernet MACs and a USB 3.0 host controller. - -This SoC uses a dual core CPU, but this is currently not implemented. -More information about this SoC can be found here: -http://www.anandtech.com/show/5925/broadcom-announces-bcm4708x-and-bcm5301x-socs-for-80211ac-routers - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - Documentation/devicetree/bindings/arm/bcm4708.txt | 8 ++++++ - MAINTAINERS | 8 ++++++ - arch/arm/configs/multi_v7_defconfig | 1 + - arch/arm/mach-bcm/Kconfig | 26 +++++++++++++++++++ - arch/arm/mach-bcm/Makefile | 1 + - arch/arm/mach-bcm/bcm_5301x.c | 28 +++++++++++++++++++++ - 6 files changed, 72 insertions(+) - create mode 100644 Documentation/devicetree/bindings/arm/bcm4708.txt - create mode 100644 arch/arm/mach-bcm/bcm_5301x.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/bcm4708.txt -@@ -0,0 +1,8 @@ -+Broadcom BCM4708 device tree bindings -+------------------------------------------- -+ -+Boards with the BCM4708 SoC shall have the following properties: -+ -+Required root node property: -+ -+compatible = "brcm,bcm4708"; ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1883,6 +1883,14 @@ F: arch/arm/boot/dts/bcm2835* - F: arch/arm/configs/bcm2835_defconfig - F: drivers/*/*bcm2835* - -+BROADCOM BCM5301X ARM ARCHICTURE -+M: Hauke Mehrtens <hauke@hauke-m.de> -+L: linux-arm-kernel@lists.infradead.org -+S: Maintained -+F: arch/arm/mach-bcm/bcm_5301x.c -+F: arch/arm/boot/dts/bcm5301x.dtsi -+F: arch/arm/boot/dts/bcm470* -+ - BROADCOM TG3 GIGABIT ETHERNET DRIVER - M: Nithin Nayak Sujir <nsujir@broadcom.com> - M: Michael Chan <mchan@broadcom.com> ---- a/arch/arm/configs/multi_v7_defconfig -+++ b/arch/arm/configs/multi_v7_defconfig -@@ -11,6 +11,7 @@ CONFIG_ARCH_MVEBU=y - CONFIG_MACH_ARMADA_370=y - CONFIG_MACH_ARMADA_XP=y - CONFIG_ARCH_BCM=y -+CONFIG_ARCH_BCM_5301X=y - CONFIG_ARCH_BCM_MOBILE=y - CONFIG_ARCH_BERLIN=y - CONFIG_MACH_BERLIN_BG2=y ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -32,6 +32,32 @@ config ARCH_BCM_MOBILE - BCM11130, BCM11140, BCM11351, BCM28145 and - BCM28155 variants. - -+config ARCH_BCM_5301X -+ bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 -+ depends on MMU -+ select ARM_GIC -+ select CACHE_L2X0 -+ select HAVE_ARM_SCU if SMP -+ select HAVE_ARM_TWD if SMP -+ select HAVE_SMP -+ select COMMON_CLK -+ select GENERIC_CLOCKEVENTS -+ select ARM_GLOBAL_TIMER -+ select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK -+ select MIGHT_HAVE_PCI -+ help -+ Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. -+ -+ This is a network SoC line mostly used in home routers and -+ wifi access points, it's internal name is Northstar. -+ This inclused the following SoC: BCM53010, BCM53011, BCM53012, -+ BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707, -+ BCM4708 and BCM4709. -+ -+ Do not confuse this with the BCM4760 which is a totally -+ different SoC or with the older BCM47XX and BCM53XX based -+ network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx -+ - endmenu - - endif ---- a/arch/arm/mach-bcm/Makefile -+++ b/arch/arm/mach-bcm/Makefile -@@ -13,3 +13,4 @@ - obj-$(CONFIG_ARCH_BCM_MOBILE) := board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o - plus_sec := $(call as-instr,.arch_extension sec,+sec) - AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) -+obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o ---- /dev/null -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -0,0 +1,28 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * -+ * Copyright 2013 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+#include <linux/of_platform.h> -+#include <asm/hardware/cache-l2x0.h> -+ -+#include <asm/mach/arch.h> -+ -+ -+static void __init bcm5301x_dt_init(void) -+{ -+ l2x0_of_init(0, ~0UL); -+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -+} -+ -+static const char __initconst *bcm5301x_dt_compat[] = { -+ "brcm,bcm4708", -+ NULL, -+}; -+ -+DT_MACHINE_START(BCM5301X, "BCM5301X") -+ .init_machine = bcm5301x_dt_init, -+ .dt_compat = bcm5301x_dt_compat, -+MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch b/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch deleted file mode 100644 index 2e028a8..0000000 --- a/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 065802756b20d878c83290c115f212fc1631cba7 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:44 +0100 -Subject: [PATCH 2/3] ARM: BCM5301X: add early debugging support - -This adds support for early debugging of BCM5301X SoC. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/Kconfig.debug | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -106,6 +106,11 @@ choice - depends on ARCH_BCM2835 - select DEBUG_UART_PL01X - -+ config DEBUG_BCM_5301X -+ bool "Kernel low-level debugging on BCM5301X UART1" -+ depends on ARCH_BCM_5301X -+ select DEBUG_UART_PL01X -+ - config DEBUG_BCM_KONA_UART - bool "Kernel low-level debugging messages via BCM KONA UART" - depends on ARCH_BCM -@@ -1023,6 +1028,7 @@ config DEBUG_UART_PHYS - default 0x101f1000 if ARCH_VERSATILE - default 0x101fb000 if DEBUG_NOMADIK_UART - default 0x16000000 if ARCH_INTEGRATOR -+ default 0x18000300 if DEBUG_BCM_5301X - default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1 - default 0x20060000 if DEBUG_RK29_UART0 - default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 -@@ -1071,6 +1077,7 @@ config DEBUG_UART_VIRT - default 0xf0009000 if DEBUG_CNS3XXX - default 0xf01fb000 if DEBUG_NOMADIK_UART - default 0xf0201000 if DEBUG_BCM2835 -+ default 0xf1000300 if DEBUG_BCM_5301X - default 0xf11f1000 if ARCH_VERSATILE - default 0xf1600000 if ARCH_INTEGRATOR - default 0xf1c28000 if DEBUG_SUNXI_UART0 diff --git a/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch b/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch deleted file mode 100644 index 41a9dd1..0000000 --- a/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch +++ /dev/null @@ -1,93 +0,0 @@ -From fdf4850cb5b2e5e549a18b8b41abb001bfb19e9c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:46 +0100 -Subject: [PATCH 3/3] ARM: BCM5301X: workaround suppress fault - -Without this patch I am getting a unhandled fault exception like this -one after "Freeing unused kernel memory": - -Freeing unused kernel memory: 1260K (c02c1000 - c03fc000) -Unhandled fault: imprecise external abort (0x1c06) at 0xb6f89005 -Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000007 - -The address which is here 0xb6f89005 changes from boot to boot, with a -new build the changes are bigger. With kernel 3.10 I have also seen -this fault at different places in the boot process, but starting with -3.11 they are always occurring after the "Freeing unused kernel memory" -message. I never was able to completely boot to userspace without this -handler. The abort code is constant 0x1c06. This fault just happens -once in the boot process I have never seen it happing twice or more. - -I also tried changing the CPSR.A bit to 0 in init_early, with this code -like Afzal suggested, but that did not change anything: -asm volatile("mrs r12, cpsr\n" - "bic r12, r12, #0x00000100\n" - "msr cpsr_c, r12" ::: "r12", "cc", "memory"); - -Disabling the L2 cache by building with CONFIG_CACHE_L2X0 unset did not -help. - -This workaround was copied from the vendor code including most of the -comments. It says it they think this is caused by the CFE boot loader -used on this device. I do not have any access to any datasheet or -errata document to check this. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/mach-bcm/bcm_5301x.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- a/arch/arm/mach-bcm/bcm_5301x.c -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -9,8 +9,40 @@ - #include <asm/hardware/cache-l2x0.h> - - #include <asm/mach/arch.h> -+#include <asm/siginfo.h> -+#include <asm/signal.h> - - -+static bool first_fault = true; -+ -+static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, -+ struct pt_regs *regs) -+{ -+ if (fsr == 0x1c06 && first_fault) { -+ first_fault = false; -+ -+ /* -+ * These faults with code 0x1c06 happens for no good reason, -+ * possibly left over from the CFE boot loader. -+ */ -+ pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", -+ addr, fsr); -+ -+ /* Returning non-zero causes fault display and panic */ -+ return 0; -+ } -+ -+ /* Others should cause a fault */ -+ return 1; -+} -+ -+static void __init bcm5301x_init_early(void) -+{ -+ /* Install our hook */ -+ hook_fault_code(16 + 6, bcm5301x_abort_handler, SIGBUS, BUS_OBJERR, -+ "imprecise external abort"); -+} -+ - static void __init bcm5301x_dt_init(void) - { - l2x0_of_init(0, ~0UL); -@@ -23,6 +55,7 @@ static const char __initconst *bcm5301x_ - }; - - DT_MACHINE_START(BCM5301X, "BCM5301X") -+ .init_early = bcm5301x_init_early, - .init_machine = bcm5301x_dt_init, - .dt_compat = bcm5301x_dt_compat, - MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch b/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch deleted file mode 100644 index 4e98ec8..0000000 --- a/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch +++ /dev/null @@ -1,204 +0,0 @@ -From d27509f19b5f93ea3425cfef782bb3c6541cd44d Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:45 +0100 -Subject: [PATCH] ARM: BCM5301X: add dts files for BCM4708 SoC - -This uses the newly added BCM5301X SoC code. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 35 ++++++++++ - arch/arm/boot/dts/bcm4708.dtsi | 34 ++++++++++ - arch/arm/boot/dts/bcm5301x.dtsi | 95 +++++++++++++++++++++++++++ - 4 files changed, 165 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm4708-netgear-r6250.dts - create mode 100644 arch/arm/boot/dts/bcm4708.dtsi - create mode 100644 arch/arm/boot/dts/bcm5301x.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rp - dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \ - bcm28155-ap.dtb - dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb -+dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -0,0 +1,35 @@ -+/* -+ * Broadcom BCM470X / BCM5301X arm platform code. -+ * DTS for Netgear R6250 V1 -+ * -+ * Copyright 2013 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "netgear,r6250v1", "brcm,bcm4708"; -+ model = "Netgear R6250 V1 (BCM4708)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708.dtsi -@@ -0,0 +1,34 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for BCM4708 SoC. -+ * -+ * Copyright 2013-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include "bcm5301x.dtsi" -+ -+/ { -+ compatible = "brcm,bcm4708"; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x1>; -+ }; -+ }; -+ -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -0,0 +1,95 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, -+ * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs -+ * -+ * Copyright 2013-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include <dt-bindings/interrupt-controller/irq.h> -+#include <dt-bindings/interrupt-controller/arm-gic.h> -+#include "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&gic>; -+ -+ chipcommonA { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x18000000 0x00001000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@0300 { -+ compatible = "ns16550"; -+ reg = <0x0300 0x100>; -+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; -+ clock-frequency = <100000000>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@0400 { -+ compatible = "ns16550"; -+ reg = <0x0400 0x100>; -+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; -+ clock-frequency = <100000000>; -+ status = "disabled"; -+ }; -+ }; -+ -+ mpcore { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19020000 0x00003000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ scu@0000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x0000 0x100>; -+ }; -+ -+ timer@0200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x0200 0x100>; -+ interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clk_periph>; -+ }; -+ -+ local-timer@0600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x0600 0x100>; -+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clk_periph>; -+ }; -+ -+ gic: interrupt-controller@1000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x1000 0x1000>, -+ <0x0100 0x100>; -+ }; -+ -+ L2: cache-controller@2000 { -+ compatible = "arm,pl310-cache"; -+ reg = <0x2000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* As long as we do not have a real clock driver us this -+ * fixed clock */ -+ clk_periph: periph { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <400000000>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/110-bcm47xx-move-the-nvram-header-file-into-common-space.patch b/target/linux/bcm53xx/patches-3.14/110-bcm47xx-move-the-nvram-header-file-into-common-space.patch deleted file mode 100644 index 85b9ab3..0000000 --- a/target/linux/bcm53xx/patches-3.14/110-bcm47xx-move-the-nvram-header-file-into-common-space.patch +++ /dev/null @@ -1,270 +0,0 @@ -From bd489dfe8c0d7495645cbc8b8c283217ba816fab Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 4 May 2014 16:35:42 +0200 -Subject: [PATCH 02/15] bcm47xx: move the nvram header file into common space - -Moving mach-bcm47xx/bcm47xx_nvram.h makes it possible to reuse this -header on the arm bcm47xx (BCM5301X) devices. This way a driver gets -the correct functions to access the nvram depending on the SoC it boots -for. ---- - arch/mips/bcm47xx/board.c | 2 +- - arch/mips/bcm47xx/nvram.c | 2 +- - arch/mips/bcm47xx/setup.c | 2 +- - arch/mips/bcm47xx/sprom.c | 2 +- - arch/mips/bcm47xx/time.c | 2 +- - arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h | 53 ------------------ - drivers/net/ethernet/broadcom/b44.c | 8 +-- - drivers/net/ethernet/broadcom/bgmac.c | 2 +- - drivers/ssb/driver_chipcommon_pmu.c | 6 +- - include/linux/bcm47xx_nvram.h | 65 ++++++++++++++++++++++ - 10 files changed, 73 insertions(+), 71 deletions(-) - delete mode 100644 arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h - create mode 100644 include/linux/bcm47xx_nvram.h - ---- a/arch/mips/bcm47xx/board.c -+++ b/arch/mips/bcm47xx/board.c -@@ -2,7 +2,7 @@ - #include <linux/export.h> - #include <linux/string.h> - #include <bcm47xx_board.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - - struct bcm47xx_board_type { - const enum bcm47xx_board board; ---- a/arch/mips/bcm47xx/nvram.c -+++ b/arch/mips/bcm47xx/nvram.c -@@ -17,7 +17,7 @@ - #include <linux/kernel.h> - #include <linux/string.h> - #include <asm/addrspace.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - #include <asm/mach-bcm47xx/bcm47xx.h> - - static char nvram_buf[NVRAM_SPACE]; ---- a/arch/mips/bcm47xx/setup.c -+++ b/arch/mips/bcm47xx/setup.c -@@ -42,7 +42,7 @@ - #include <asm/reboot.h> - #include <asm/time.h> - #include <bcm47xx.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - #include <bcm47xx_board.h> - - union bcm47xx_bus bcm47xx_bus; ---- a/arch/mips/bcm47xx/sprom.c -+++ b/arch/mips/bcm47xx/sprom.c -@@ -27,7 +27,7 @@ - */ - - #include <bcm47xx.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - - static void create_key(const char *prefix, const char *postfix, - const char *name, char *buf, int len) ---- a/arch/mips/bcm47xx/time.c -+++ b/arch/mips/bcm47xx/time.c -@@ -27,7 +27,7 @@ - #include <linux/ssb/ssb.h> - #include <asm/time.h> - #include <bcm47xx.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - #include <bcm47xx_board.h> - - void __init plat_time_init(void) ---- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h -+++ /dev/null -@@ -1,53 +0,0 @@ --/* -- * Copyright (C) 2005, Broadcom Corporation -- * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> -- * -- * 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; either version 2 of the License, or (at your -- * option) any later version. -- */ -- --#ifndef __BCM47XX_NVRAM_H --#define __BCM47XX_NVRAM_H -- --#include <linux/types.h> --#include <linux/kernel.h> -- --struct nvram_header { -- u32 magic; -- u32 len; -- u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ -- u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ -- u32 config_ncdl; /* ncdl values for memc */ --}; -- --#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ --#define NVRAM_VERSION 1 --#define NVRAM_HEADER_SIZE 20 --#define NVRAM_SPACE 0x8000 -- --#define FLASH_MIN 0x00020000 /* Minimum flash size */ -- --#define NVRAM_MAX_VALUE_LEN 255 --#define NVRAM_MAX_PARAM_LEN 64 -- --extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len); -- --static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) --{ -- if (strchr(buf, ':')) -- sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], -- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], -- &macaddr[5]); -- else if (strchr(buf, '-')) -- sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], -- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], -- &macaddr[5]); -- else -- printk(KERN_WARNING "Can not parse mac address: %s\n", buf); --} -- --int bcm47xx_nvram_gpio_pin(const char *name); -- --#endif /* __BCM47XX_NVRAM_H */ ---- a/drivers/net/ethernet/broadcom/b44.c -+++ b/drivers/net/ethernet/broadcom/b44.c -@@ -31,6 +31,7 @@ - #include <linux/ssb/ssb.h> - #include <linux/slab.h> - #include <linux/phy.h> -+#include <linux/bcm47xx_nvram.h> - - #include <asm/uaccess.h> - #include <asm/io.h> -@@ -399,8 +400,6 @@ static void b44_set_flow_ctrl(struct b44 - __b44_set_flow_ctrl(bp, pause_enab); - } - --#ifdef CONFIG_BCM47XX --#include <bcm47xx_nvram.h> - static void b44_wap54g10_workaround(struct b44 *bp) - { - char buf[20]; -@@ -429,11 +428,6 @@ static void b44_wap54g10_workaround(stru - error: - pr_warning("PHY: cannot reset MII transceiver isolate bit\n"); - } --#else --static inline void b44_wap54g10_workaround(struct b44 *bp) --{ --} --#endif - - static int b44_setup_phy(struct b44 *bp) - { ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -17,7 +17,7 @@ - #include <linux/interrupt.h> - #include <linux/dma-mapping.h> - #include <linux/platform_data/b53.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - - static const struct bcma_device_id bgmac_bcma_tbl[] = { - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), ---- a/drivers/ssb/driver_chipcommon_pmu.c -+++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -13,9 +13,7 @@ - #include <linux/ssb/ssb_driver_chipcommon.h> - #include <linux/delay.h> - #include <linux/export.h> --#ifdef CONFIG_BCM47XX --#include <bcm47xx_nvram.h> --#endif -+#include <linux/bcm47xx_nvram.h> - - #include "ssb_private.h" - -@@ -320,11 +318,9 @@ static void ssb_pmu_pll_init(struct ssb_ - u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ - - if (bus->bustype == SSB_BUSTYPE_SSB) { --#ifdef CONFIG_BCM47XX - char buf[20]; - if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) - crystalfreq = simple_strtoul(buf, NULL, 0); --#endif - } - - switch (bus->chip_id) { ---- /dev/null -+++ b/include/linux/bcm47xx_nvram.h -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (C) 2005, Broadcom Corporation -+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> -+ * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * 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; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#ifndef __BCM47XX_NVRAM_H -+#define __BCM47XX_NVRAM_H -+ -+#include <linux/types.h> -+#include <linux/kernel.h> -+ -+struct nvram_header { -+ u32 magic; -+ u32 len; -+ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ -+ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ -+ u32 config_ncdl; /* ncdl values for memc */ -+}; -+ -+#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ -+#define NVRAM_VERSION 1 -+#define NVRAM_HEADER_SIZE 20 -+#define NVRAM_SPACE 0x8000 -+ -+#define FLASH_MIN 0x00020000 /* Minimum flash size */ -+ -+#define NVRAM_MAX_VALUE_LEN 255 -+#define NVRAM_MAX_PARAM_LEN 64 -+ -+#ifdef CONFIG_BCM47XX -+int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); -+ -+int bcm47xx_nvram_gpio_pin(const char *name); -+#else -+static inline int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) -+{ -+ return -ENXIO; -+} -+ -+static inline int bcm47xx_nvram_gpio_pin(const char *name) -+{ -+ return -ENXIO; -+} -+#endif -+ -+static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) -+{ -+ if (strchr(buf, ':')) -+ sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], -+ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], -+ &macaddr[5]); -+ else if (strchr(buf, '-')) -+ sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], -+ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], -+ &macaddr[5]); -+ else -+ pr_warn("Can not parse mac address: %s\n", buf); -+} -+#endif /* __BCM47XX_NVRAM_H */ diff --git a/target/linux/bcm53xx/patches-3.14/111-bcm47xx-nvram-add-new-nvram-driver-with-dt-support.patch b/target/linux/bcm53xx/patches-3.14/111-bcm47xx-nvram-add-new-nvram-driver-with-dt-support.patch deleted file mode 100644 index a53e86d..0000000 --- a/target/linux/bcm53xx/patches-3.14/111-bcm47xx-nvram-add-new-nvram-driver-with-dt-support.patch +++ /dev/null @@ -1,520 +0,0 @@ -From 60a413ed5bc7917f1612df441240f458163b10c1 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sat, 3 May 2014 22:54:59 +0200 -Subject: [PATCH 03/15] bcm47xx-nvram: add new nvram driver with dt support - -This adds a new nvrm driver which uses device tree to provide nvram -access to other drivers. You have to specify the memory ranges where -the flash chip is mapped and this driver will search there for some -nvram and parse it. Other drivers can use this driver to access the -device nvram. The nvram is used to store board configurations like the -mac address and also for configuration values in the vendor firmware. ---- - arch/mips/bcm47xx/board.c | 36 +++--- - arch/mips/bcm47xx/nvram.c | 7 +- - arch/mips/bcm47xx/setup.c | 4 +- - arch/mips/bcm47xx/sprom.c | 4 +- - arch/mips/bcm47xx/time.c | 2 +- - drivers/misc/Kconfig | 5 + - drivers/misc/Makefile | 1 + - drivers/misc/bcm47xx-nvram.c | 211 ++++++++++++++++++++++++++++++++++ - drivers/net/ethernet/broadcom/b44.c | 2 +- - drivers/net/ethernet/broadcom/bgmac.c | 4 +- - drivers/ssb/driver_chipcommon_pmu.c | 2 +- - include/linux/bcm47xx_nvram.h | 16 ++- - 12 files changed, 259 insertions(+), 35 deletions(-) - create mode 100644 drivers/misc/bcm47xx-nvram.c - ---- a/arch/mips/bcm47xx/board.c -+++ b/arch/mips/bcm47xx/board.c -@@ -196,50 +196,50 @@ static __init const struct bcm47xx_board - const struct bcm47xx_board_type_list2 *e2; - const struct bcm47xx_board_type_list3 *e3; - -- if (bcm47xx_nvram_getenv("model_name", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "model_name", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_model_name; e1->value1; e1++) { - if (!strcmp(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "model_no", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) { - if (strstarts(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "machine_name", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) { - if (strstarts(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "hardware_version", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) { - if (strstarts(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "productid", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) { - if (!strcmp(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("ModelId", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "ModelId", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_ModelId; e1->value1; e1++) { - if (!strcmp(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("melco_id", buf1, sizeof(buf1)) >= 0 || -- bcm47xx_nvram_getenv("buf1falo_id", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "melco_id", buf1, sizeof(buf1)) >= 0 || -+ bcm47xx_nvram_getenv(NULL, "buf1falo_id", buf1, sizeof(buf1)) >= 0) { - /* buffalo hardware, check id for specific hardware matches */ - for (e1 = bcm47xx_board_list_melco_id; e1->value1; e1++) { - if (!strcmp(buf1, e1->value1)) -@@ -247,8 +247,8 @@ static __init const struct bcm47xx_board - } - } - -- if (bcm47xx_nvram_getenv("boot_hw_model", buf1, sizeof(buf1)) >= 0 && -- bcm47xx_nvram_getenv("boot_hw_ver", buf2, sizeof(buf2)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "boot_hw_model", buf1, sizeof(buf1)) >= 0 && -+ bcm47xx_nvram_getenv(NULL, "boot_hw_ver", buf2, sizeof(buf2)) >= 0) { - for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) { - if (!strcmp(buf1, e2->value1) && - !strcmp(buf2, e2->value2)) -@@ -256,16 +256,16 @@ static __init const struct bcm47xx_board - } - } - -- if (bcm47xx_nvram_getenv("board_id", buf1, sizeof(buf1)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "board_id", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_board_id; e1->value1; e1++) { - if (!strcmp(buf1, e1->value1)) - return &e1->board; - } - } - -- if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 && -- bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0 && -- bcm47xx_nvram_getenv("boardrev", buf3, sizeof(buf3)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "boardtype", buf1, sizeof(buf1)) >= 0 && -+ bcm47xx_nvram_getenv(NULL, "boardnum", buf2, sizeof(buf2)) >= 0 && -+ bcm47xx_nvram_getenv(NULL, "boardrev", buf3, sizeof(buf3)) >= 0) { - for (e3 = bcm47xx_board_list_board; e3->value1; e3++) { - if (!strcmp(buf1, e3->value1) && - !strcmp(buf2, e3->value2) && -@@ -286,7 +286,7 @@ void __init bcm47xx_board_detect(void) - return; - - /* check if the nvram is available */ -- err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)); -+ err = bcm47xx_nvram_getenv(NULL, "boardtype", buf, sizeof(buf)); - - /* init of nvram failed, probably too early now */ - if (err == -ENXIO) { ---- a/arch/mips/bcm47xx/nvram.c -+++ b/arch/mips/bcm47xx/nvram.c -@@ -158,7 +158,8 @@ static int nvram_init(void) - return -ENXIO; - } - --int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len) -+int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val, -+ size_t val_len) - { - char *var, *value, *end, *eq; - int err; -@@ -190,7 +191,7 @@ int bcm47xx_nvram_getenv(char *name, cha - } - EXPORT_SYMBOL(bcm47xx_nvram_getenv); - --int bcm47xx_nvram_gpio_pin(const char *name) -+int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name) - { - int i, err; - char nvram_var[10]; -@@ -200,7 +201,7 @@ int bcm47xx_nvram_gpio_pin(const char *n - err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i); - if (err <= 0) - continue; -- err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)); -+ err = bcm47xx_nvram_getenv(dev, nvram_var, buf, sizeof(buf)); - if (err <= 0) - continue; - if (!strcmp(name, buf)) ---- a/arch/mips/bcm47xx/setup.c -+++ b/arch/mips/bcm47xx/setup.c -@@ -123,7 +123,7 @@ static int bcm47xx_get_invariants(struct - memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); - bcm47xx_fill_sprom(&iv->sprom, NULL, false); - -- if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) -+ if (bcm47xx_nvram_getenv(NULL, "cardbus", buf, sizeof(buf)) >= 0) - iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); - - return 0; -@@ -146,7 +146,7 @@ static void __init bcm47xx_register_ssb( - panic("Failed to initialize SSB bus (err %d)", err); - - mcore = &bcm47xx_bus.ssb.mipscore; -- if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { -+ if (bcm47xx_nvram_getenv(NULL, "kernel_args", buf, sizeof(buf)) >= 0) { - if (strstr(buf, "console=ttyS1")) { - struct ssb_serial_port port; - ---- a/arch/mips/bcm47xx/sprom.c -+++ b/arch/mips/bcm47xx/sprom.c -@@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre - - create_key(prefix, postfix, name, key, sizeof(key)); - -- err = bcm47xx_nvram_getenv(key, buf, len); -+ err = bcm47xx_nvram_getenv(NULL, key, buf, len); - if (fallback && err == -ENOENT && prefix) { - create_key(NULL, postfix, name, key, sizeof(key)); -- err = bcm47xx_nvram_getenv(key, buf, len); -+ err = bcm47xx_nvram_getenv(NULL, key, buf, len); - } - return err; - } ---- a/arch/mips/bcm47xx/time.c -+++ b/arch/mips/bcm47xx/time.c -@@ -61,7 +61,7 @@ void __init plat_time_init(void) - } - - if (chip_id == 0x5354) { -- len = bcm47xx_nvram_getenv("clkfreq", buf, sizeof(buf)); -+ len = bcm47xx_nvram_getenv(NULL, "clkfreq", buf, sizeof(buf)); - if (len >= 0 && !strncmp(buf, "200", 4)) - hz = 100000000; - } ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -515,6 +515,11 @@ config SRAM - the genalloc API. It is supposed to be used for small on-chip SRAM - areas found on many SoCs. - -+config BCM47XX_NVRAM -+ tristate "BCM47XX nvram driver" -+ help -+ This adds support for the brcm47xx nvram driver. -+ - source "drivers/misc/c2port/Kconfig" - source "drivers/misc/eeprom/Kconfig" - source "drivers/misc/cb710/Kconfig" ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lat - obj-$(CONFIG_SRAM) += sram.o - obj-y += mic/ - obj-$(CONFIG_GENWQE) += genwqe/ -+obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o ---- /dev/null -+++ b/drivers/misc/bcm47xx-nvram.c -@@ -0,0 +1,211 @@ -+/* -+ * BCM947xx nvram variable access -+ * -+ * Copyright (C) 2005 Broadcom Corporation -+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> -+ * Copyright (C) 2010-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * 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; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include <linux/types.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/string.h> -+#include <linux/of_address.h> -+#include <linux/device.h> -+#include <linux/platform_device.h> -+#include <linux/io.h> -+#include <linux/bcm47xx_nvram.h> -+ -+struct bcm47xx_nvram { -+ size_t nvram_len; -+ char *nvram_buf; -+}; -+ -+static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; -+ -+static u32 find_nvram_size(void __iomem *end) -+{ -+ struct nvram_header *header; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { -+ header = (struct nvram_header *)(end - nvram_sizes[i]); -+ if (header->magic == NVRAM_HEADER) -+ return nvram_sizes[i]; -+ } -+ -+ return 0; -+} -+ -+/* Probe for NVRAM header */ -+static int nvram_find_and_copy(struct device *dev, void __iomem *base, -+ size_t len, char **nvram_buf, -+ size_t *nvram_len) -+{ -+ struct nvram_header *header; -+ int i; -+ u32 off; -+ u32 *src, *dst; -+ u32 size; -+ -+ /* TODO: when nvram is on nand flash check for bad blocks first. */ -+ off = FLASH_MIN; -+ while (off <= len) { -+ /* Windowed flash access */ -+ size = find_nvram_size(base + off); -+ if (size) { -+ header = (struct nvram_header *)(base + off - size); -+ goto found; -+ } -+ off <<= 1; -+ } -+ -+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -+ header = (struct nvram_header *)(base + 4096); -+ if (header->magic == NVRAM_HEADER) { -+ size = NVRAM_SPACE; -+ goto found; -+ } -+ -+ header = (struct nvram_header *)(base + 1024); -+ if (header->magic == NVRAM_HEADER) { -+ size = NVRAM_SPACE; -+ goto found; -+ } -+ -+ *nvram_buf = NULL; -+ *nvram_len = 0; -+ pr_err("no nvram found\n"); -+ return -ENXIO; -+ -+found: -+ if (header->len > size) -+ pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n"); -+ *nvram_len = min_t(u32, header->len, size); -+ -+ *nvram_buf = devm_kzalloc(dev, *nvram_len, GFP_KERNEL); -+ if (!*nvram_buf) -+ return -ENOMEM; -+ -+ src = (u32 *) header; -+ dst = (u32 *) *nvram_buf; -+ for (i = 0; i < sizeof(struct nvram_header); i += 4) -+ *dst++ = *src++; -+ for (; i < *nvram_len; i += 4) -+ *dst++ = le32_to_cpu(*src++); -+ -+ return 0; -+} -+ -+int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val, size_t val_len) -+{ -+ char *var, *value, *end, *eq; -+ struct bcm47xx_nvram *nvram; -+ -+ if (!dev) -+ return -ENODEV; -+ -+ nvram = dev_get_drvdata(dev); -+ -+ if (!name || !nvram || !nvram->nvram_len) -+ return -EINVAL; -+ -+ /* Look for name=value and return value */ -+ var = nvram->nvram_buf + sizeof(struct nvram_header); -+ end = nvram->nvram_buf + nvram->nvram_len - 2; -+ end[0] = end[1] = '\0'; -+ for (; *var; var = value + strlen(value) + 1) { -+ eq = strchr(var, '='); -+ if (!eq) -+ break; -+ value = eq + 1; -+ if ((eq - var) == strlen(name) && -+ strncmp(var, name, (eq - var)) == 0) { -+ return snprintf(val, val_len, "%s", value); -+ } -+ } -+ return -ENOENT; -+} -+EXPORT_SYMBOL(bcm47xx_nvram_getenv); -+ -+int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name) -+{ -+ int i, err; -+ char nvram_var[10]; -+ char buf[30]; -+ -+ if (!dev) -+ return -ENODEV; -+ -+ for (i = 0; i < 32; i++) { -+ err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i); -+ if (err <= 0) -+ continue; -+ err = bcm47xx_nvram_getenv(dev, nvram_var, buf, sizeof(buf)); -+ if (err <= 0) -+ continue; -+ if (!strcmp(name, buf)) -+ return i; -+ } -+ return -ENOENT; -+} -+EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin); -+ -+static int bcm47xx_nvram_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct bcm47xx_nvram *nvram; -+ int err; -+ struct resource flash_mem; -+ void __iomem *mmio; -+ -+ /* Alloc */ -+ nvram = devm_kzalloc(dev, sizeof(*nvram), GFP_KERNEL); -+ if (!nvram) -+ return -ENOMEM; -+ -+ err = of_address_to_resource(np, 0, &flash_mem); -+ if (err) -+ return err; -+ -+ mmio = ioremap_nocache(flash_mem.start, resource_size(&flash_mem)); -+ if (!mmio) -+ return -ENOMEM; -+ -+ err = nvram_find_and_copy(dev, mmio, resource_size(&flash_mem), &nvram->nvram_buf, &nvram->nvram_len); -+ if (err) -+ goto err_unmap_mmio; -+ -+ platform_set_drvdata(pdev, nvram); -+ -+err_unmap_mmio: -+ iounmap(mmio); -+ return err; -+} -+ -+static const struct of_device_id bcm47xx_nvram_of_match_table[] = { -+ { .compatible = "brcm,bcm47xx-nvram", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table); -+ -+static struct platform_driver bcm47xx_nvram_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "bcm47xx-nvram", -+ .of_match_table = bcm47xx_nvram_of_match_table, -+ /* driver unloading/unbinding currently not supported */ -+ .suppress_bind_attrs = true, -+ }, -+ .probe = bcm47xx_nvram_probe, -+}; -+module_platform_driver(bcm47xx_nvram_driver); -+ -+MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); -+MODULE_LICENSE("GPLv2"); ---- a/drivers/net/ethernet/broadcom/b44.c -+++ b/drivers/net/ethernet/broadcom/b44.c -@@ -411,7 +411,7 @@ static void b44_wap54g10_workaround(stru - * see https://dev.openwrt.org/ticket/146 - * check and reset bit "isolate" - */ -- if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0) -+ if (bcm47xx_nvram_getenv(NULL, "boardnum", buf, sizeof(buf)) < 0) - return; - if (simple_strtoul(buf, NULL, 0) == 2) { - err = __b44_readphy(bp, 0, MII_BMCR, &val); ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -974,7 +974,7 @@ static void bgmac_chip_reset(struct bgma - BGMAC_CHIPCTL_1_IF_TYPE_MII; - char buf[4]; - -- if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) { -+ if (bcm47xx_nvram_getenv(NULL, "et_swtype", buf, sizeof(buf)) > 0) { - if (kstrtou8(buf, 0, &et_swtype)) - bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n", - buf); -@@ -1534,7 +1534,7 @@ static int bgmac_probe(struct bcma_devic - } - - bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK; -- if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0) -+ if (bcm47xx_nvram_getenv(NULL, "et0_no_txint", NULL, 0) == 0) - bgmac->int_mask &= ~BGMAC_IS_TX_MASK; - - /* TODO: reset the external phy. Specs are needed */ ---- a/drivers/ssb/driver_chipcommon_pmu.c -+++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -319,7 +319,7 @@ static void ssb_pmu_pll_init(struct ssb_ - - if (bus->bustype == SSB_BUSTYPE_SSB) { - char buf[20]; -- if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) -+ if (bcm47xx_nvram_getenv(NULL, "xtalfreq", buf, sizeof(buf)) >= 0) - crystalfreq = simple_strtoul(buf, NULL, 0); - } - ---- a/include/linux/bcm47xx_nvram.h -+++ b/include/linux/bcm47xx_nvram.h -@@ -15,6 +15,8 @@ - #include <linux/types.h> - #include <linux/kernel.h> - -+struct device; -+ - struct nvram_header { - u32 magic; - u32 len; -@@ -33,17 +35,21 @@ struct nvram_header { - #define NVRAM_MAX_VALUE_LEN 255 - #define NVRAM_MAX_PARAM_LEN 64 - --#ifdef CONFIG_BCM47XX --int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); -+#if defined(CONFIG_BCM47XX) || defined(CONFIG_BCM47XX_NVRAM) -+int bcm47xx_nvram_getenv(const struct device *dev, const char *name, char *val, -+ size_t val_len); - --int bcm47xx_nvram_gpio_pin(const char *name); -+int bcm47xx_nvram_gpio_pin(const struct device *dev, const char *name); - #else --static inline int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) -+static inline int bcm47xx_nvram_getenv(const struct device *dev, -+ const char *name, char *val, -+ size_t val_len) - { - return -ENXIO; - } - --static inline int bcm47xx_nvram_gpio_pin(const char *name) -+static inline int bcm47xx_nvram_gpio_pin(const struct device *dev, -+ const char *name) - { - return -ENXIO; - } diff --git a/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch b/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch deleted file mode 100644 index d8cdeb5..0000000 --- a/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch +++ /dev/null @@ -1,667 +0,0 @@ -From b113f9d3e140f18e63cbf3408b3dcde372242dc8 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 4 May 2014 13:19:20 +0200 -Subject: [PATCH 04/15] bcm53xx-sprom: add sprom driver - -This driver needs an nvram driver and fetches the sprom values from the -sprom and provides it to any other driver. The calibration data for the -wifi chip the mac address and some more board description data is -stores in the sprom. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/misc/Kconfig | 5 + - drivers/misc/Makefile | 1 + - drivers/misc/bcm53xx-sprom.c | 625 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 631 insertions(+) - create mode 100644 drivers/misc/bcm53xx-sprom.c - ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -520,6 +520,11 @@ config BCM47XX_NVRAM - help - This adds support for the brcm47xx nvram driver. - -+config BCM53XX_SPROM -+ tristate "BCM53XX sprom driver" -+ help -+ This adds support for the brcm53xx sprom driver. -+ - source "drivers/misc/c2port/Kconfig" - source "drivers/misc/eeprom/Kconfig" - source "drivers/misc/cb710/Kconfig" ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -55,3 +55,4 @@ obj-$(CONFIG_SRAM) += sram.o - obj-y += mic/ - obj-$(CONFIG_GENWQE) += genwqe/ - obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o -+obj-$(CONFIG_BCM53XX_SPROM) += bcm53xx-sprom.o ---- /dev/null -+++ b/drivers/misc/bcm53xx-sprom.c -@@ -0,0 +1,625 @@ -+/* -+ * BCM947xx nvram variable access -+ * -+ * Copyright (C) 2005 Broadcom Corporation -+ * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> -+ * Copyright (C) 2006 Michael Buesch <m@bues.ch> -+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org> -+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> -+ * Copyright (C) 2010-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * 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; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include <linux/types.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/string.h> -+#include <linux/of_address.h> -+#include <linux/device.h> -+#include <linux/platform_device.h> -+#include <linux/of_platform.h> -+#include <linux/io.h> -+#include <linux/ssb/ssb.h> -+#include <linux/bcm47xx_nvram.h> -+ -+struct bcm53xx_sprom_fill { -+ const char *prefix; -+ bool fallback; -+ int (*getenv)(const struct bcm53xx_sprom_fill *fill, const char *name, char *val, size_t val_len); -+ const void *priv; -+}; -+ -+static void create_key(const char *prefix, const char *postfix, -+ const char *name, char *buf, int len) -+{ -+ if (prefix && postfix) -+ snprintf(buf, len, "%s%s%s", prefix, name, postfix); -+ else if (prefix) -+ snprintf(buf, len, "%s%s", prefix, name); -+ else if (postfix) -+ snprintf(buf, len, "%s%s", name, postfix); -+ else -+ snprintf(buf, len, "%s", name); -+} -+ -+static int get_nvram_var(const struct bcm53xx_sprom_fill *fill, const char *postfix, -+ const char *name, char *buf, int len) -+{ -+ char key[40]; -+ int err; -+ -+ create_key(fill->prefix, postfix, name, key, sizeof(key)); -+ -+ err = fill->getenv(fill, key, buf, len); -+ if (fill->fallback && err == -ENOENT && fill->prefix) { -+ create_key(NULL, postfix, name, key, sizeof(key)); -+ err = fill->getenv(fill, key, buf, len); -+ } -+ return err; -+} -+ -+#define NVRAM_READ_VAL(type) \ -+static void nvram_read_ ## type (const struct bcm53xx_sprom_fill *fill, \ -+ const char *postfix, const char *name, \ -+ type *val, type allset) \ -+{ \ -+ char buf[100]; \ -+ int err; \ -+ type var; \ -+ \ -+ err = get_nvram_var(fill, postfix, name, buf, sizeof(buf)); \ -+ if (err < 0) \ -+ return; \ -+ err = kstrto ## type(strim(buf), 0, &var); \ -+ if (err) { \ -+ pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \ -+ fill->prefix, name, postfix, buf, err); \ -+ return; \ -+ } \ -+ if (allset && var == allset) \ -+ return; \ -+ *val = var; \ -+} -+ -+NVRAM_READ_VAL(u8) -+NVRAM_READ_VAL(s8) -+NVRAM_READ_VAL(u16) -+NVRAM_READ_VAL(u32) -+ -+#undef NVRAM_READ_VAL -+ -+static void nvram_read_u32_2(const struct bcm53xx_sprom_fill *fill, const char *name, -+ u16 *val_lo, u16 *val_hi) -+{ -+ char buf[100]; -+ int err; -+ u32 val; -+ -+ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf)); -+ if (err < 0) -+ return; -+ err = kstrtou32(strim(buf), 0, &val); -+ if (err) { -+ pr_warn("can not parse nvram name %s%s with value %s got %i\n", -+ fill->prefix, name, buf, err); -+ return; -+ } -+ *val_lo = (val & 0x0000FFFFU); -+ *val_hi = (val & 0xFFFF0000U) >> 16; -+} -+ -+static void nvram_read_leddc(const struct bcm53xx_sprom_fill *fill, const char *name, -+ u8 *leddc_on_time, u8 *leddc_off_time) -+{ -+ char buf[100]; -+ int err; -+ u32 val; -+ -+ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf)); -+ if (err < 0) -+ return; -+ err = kstrtou32(strim(buf), 0, &val); -+ if (err) { -+ pr_warn("can not parse nvram name %s%s with value %s got %i\n", -+ fill->prefix, name, buf, err); -+ return; -+ } -+ -+ if (val == 0xffff || val == 0xffffffff) -+ return; -+ -+ *leddc_on_time = val & 0xff; -+ *leddc_off_time = (val >> 16) & 0xff; -+} -+ -+static void nvram_read_macaddr(const struct bcm53xx_sprom_fill *fill, const char *name, -+ u8 val[6]) -+{ -+ char buf[100]; -+ int err; -+ -+ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf)); -+ if (err < 0) -+ return; -+ -+ bcm47xx_nvram_parse_macaddr(buf, val); -+} -+ -+static void nvram_read_alpha2(const struct bcm53xx_sprom_fill *fill, const char *name, -+ char val[2]) -+{ -+ char buf[10]; -+ int err; -+ -+ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf)); -+ if (err < 0) -+ return; -+ if (buf[0] == '0') -+ return; -+ if (strlen(buf) > 2) { -+ pr_warn("alpha2 is too long %s\n", buf); -+ return; -+ } -+ memcpy(val, buf, 2); -+} -+ -+static void bcm53xx_sprom_fill_r1234589(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "ledbh0", &sprom->gpio0, 0xff); -+ nvram_read_u8(fill, NULL, "ledbh1", &sprom->gpio1, 0xff); -+ nvram_read_u8(fill, NULL, "ledbh2", &sprom->gpio2, 0xff); -+ nvram_read_u8(fill, NULL, "ledbh3", &sprom->gpio3, 0xff); -+ nvram_read_u8(fill, NULL, "aa2g", &sprom->ant_available_bg, 0); -+ nvram_read_u8(fill, NULL, "aa5g", &sprom->ant_available_a, 0); -+ nvram_read_s8(fill, NULL, "ag0", &sprom->antenna_gain.a0, 0); -+ nvram_read_s8(fill, NULL, "ag1", &sprom->antenna_gain.a1, 0); -+ nvram_read_alpha2(fill, "ccode", sprom->alpha2); -+} -+ -+static void bcm53xx_sprom_fill_r12389(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u16(fill, NULL, "pa0b0", &sprom->pa0b0, 0); -+ nvram_read_u16(fill, NULL, "pa0b1", &sprom->pa0b1, 0); -+ nvram_read_u16(fill, NULL, "pa0b2", &sprom->pa0b2, 0); -+ nvram_read_u8(fill, NULL, "pa0itssit", &sprom->itssi_bg, 0); -+ nvram_read_u8(fill, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0); -+ nvram_read_u16(fill, NULL, "pa1b0", &sprom->pa1b0, 0); -+ nvram_read_u16(fill, NULL, "pa1b1", &sprom->pa1b1, 0); -+ nvram_read_u16(fill, NULL, "pa1b2", &sprom->pa1b2, 0); -+ nvram_read_u8(fill, NULL, "pa1itssit", &sprom->itssi_a, 0); -+ nvram_read_u8(fill, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0); -+} -+ -+static void bcm53xx_sprom_fill_r1(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u16(fill, NULL, "boardflags", &sprom->boardflags_lo, 0); -+ nvram_read_u8(fill, NULL, "cc", &sprom->country_code, 0); -+} -+ -+static void bcm53xx_sprom_fill_r2389(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "opo", &sprom->opo, 0); -+ nvram_read_u16(fill, NULL, "pa1lob0", &sprom->pa1lob0, 0); -+ nvram_read_u16(fill, NULL, "pa1lob1", &sprom->pa1lob1, 0); -+ nvram_read_u16(fill, NULL, "pa1lob2", &sprom->pa1lob2, 0); -+ nvram_read_u16(fill, NULL, "pa1hib0", &sprom->pa1hib0, 0); -+ nvram_read_u16(fill, NULL, "pa1hib1", &sprom->pa1hib1, 0); -+ nvram_read_u16(fill, NULL, "pa1hib2", &sprom->pa1hib2, 0); -+ nvram_read_u8(fill, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0); -+ nvram_read_u8(fill, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0); -+} -+ -+static void bcm53xx_sprom_fill_r389(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "bxa2g", &sprom->bxa2g, 0); -+ nvram_read_u8(fill, NULL, "rssisav2g", &sprom->rssisav2g, 0); -+ nvram_read_u8(fill, NULL, "rssismc2g", &sprom->rssismc2g, 0); -+ nvram_read_u8(fill, NULL, "rssismf2g", &sprom->rssismf2g, 0); -+ nvram_read_u8(fill, NULL, "bxa5g", &sprom->bxa5g, 0); -+ nvram_read_u8(fill, NULL, "rssisav5g", &sprom->rssisav5g, 0); -+ nvram_read_u8(fill, NULL, "rssismc5g", &sprom->rssismc5g, 0); -+ nvram_read_u8(fill, NULL, "rssismf5g", &sprom->rssismf5g, 0); -+ nvram_read_u8(fill, NULL, "tri2g", &sprom->tri2g, 0); -+ nvram_read_u8(fill, NULL, "tri5g", &sprom->tri5g, 0); -+ nvram_read_u8(fill, NULL, "tri5gl", &sprom->tri5gl, 0); -+ nvram_read_u8(fill, NULL, "tri5gh", &sprom->tri5gh, 0); -+ nvram_read_s8(fill, NULL, "rxpo2g", &sprom->rxpo2g, 0); -+ nvram_read_s8(fill, NULL, "rxpo5g", &sprom->rxpo5g, 0); -+} -+ -+static void bcm53xx_sprom_fill_r3(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0); -+ nvram_read_leddc(fill, "leddc", &sprom->leddc_on_time, -+ &sprom->leddc_off_time); -+} -+ -+static void bcm53xx_sprom_fill_r4589(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "regrev", &sprom->regrev, 0); -+ nvram_read_s8(fill, NULL, "ag2", &sprom->antenna_gain.a2, 0); -+ nvram_read_s8(fill, NULL, "ag3", &sprom->antenna_gain.a3, 0); -+ nvram_read_u8(fill, NULL, "txchain", &sprom->txchain, 0xf); -+ nvram_read_u8(fill, NULL, "rxchain", &sprom->rxchain, 0xf); -+ nvram_read_u8(fill, NULL, "antswitch", &sprom->antswitch, 0xff); -+ nvram_read_leddc(fill, "leddc", &sprom->leddc_on_time, -+ &sprom->leddc_off_time); -+} -+ -+static void bcm53xx_sprom_fill_r458(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u16(fill, NULL, "cck2gpo", &sprom->cck2gpo, 0); -+ nvram_read_u32(fill, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0); -+ nvram_read_u32(fill, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0); -+ nvram_read_u32(fill, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0); -+ nvram_read_u32(fill, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0); -+ nvram_read_u16(fill, NULL, "cddpo", &sprom->cddpo, 0); -+ nvram_read_u16(fill, NULL, "stbcpo", &sprom->stbcpo, 0); -+ nvram_read_u16(fill, NULL, "bw40po", &sprom->bw40po, 0); -+ nvram_read_u16(fill, NULL, "bwduppo", &sprom->bwduppo, 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0); -+ nvram_read_u16(fill, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0); -+ nvram_read_u16(fill, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0); -+ nvram_read_u16(fill, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0); -+ nvram_read_u16(fill, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0); -+} -+ -+static void bcm53xx_sprom_fill_r45(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "txpid2ga0", &sprom->txpid2g[0], 0); -+ nvram_read_u8(fill, NULL, "txpid2ga1", &sprom->txpid2g[1], 0); -+ nvram_read_u8(fill, NULL, "txpid2ga2", &sprom->txpid2g[2], 0); -+ nvram_read_u8(fill, NULL, "txpid2ga3", &sprom->txpid2g[3], 0); -+ nvram_read_u8(fill, NULL, "txpid5ga0", &sprom->txpid5g[0], 0); -+ nvram_read_u8(fill, NULL, "txpid5ga1", &sprom->txpid5g[1], 0); -+ nvram_read_u8(fill, NULL, "txpid5ga2", &sprom->txpid5g[2], 0); -+ nvram_read_u8(fill, NULL, "txpid5ga3", &sprom->txpid5g[3], 0); -+ nvram_read_u8(fill, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0); -+ nvram_read_u8(fill, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0); -+ nvram_read_u8(fill, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0); -+ nvram_read_u8(fill, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0); -+ nvram_read_u8(fill, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0); -+ nvram_read_u8(fill, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0); -+ nvram_read_u8(fill, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0); -+ nvram_read_u8(fill, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0); -+} -+ -+static void bcm53xx_sprom_fill_r89(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u8(fill, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0); -+ nvram_read_u8(fill, NULL, "extpagain2g", &sprom->fem.ghz2.extpa_gain, 0); -+ nvram_read_u8(fill, NULL, "pdetrange2g", &sprom->fem.ghz2.pdet_range, 0); -+ nvram_read_u8(fill, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0); -+ nvram_read_u8(fill, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0); -+ nvram_read_u8(fill, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0); -+ nvram_read_u8(fill, NULL, "extpagain5g", &sprom->fem.ghz5.extpa_gain, 0); -+ nvram_read_u8(fill, NULL, "pdetrange5g", &sprom->fem.ghz5.pdet_range, 0); -+ nvram_read_u8(fill, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0); -+ nvram_read_u8(fill, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0); -+ nvram_read_u8(fill, NULL, "tempthresh", &sprom->tempthresh, 0); -+ nvram_read_u8(fill, NULL, "tempoffset", &sprom->tempoffset, 0); -+ nvram_read_u16(fill, NULL, "rawtempsense", &sprom->rawtempsense, 0); -+ nvram_read_u8(fill, NULL, "measpower", &sprom->measpower, 0); -+ nvram_read_u8(fill, NULL, "tempsense_slope", &sprom->tempsense_slope, 0); -+ nvram_read_u8(fill, NULL, "tempcorrx", &sprom->tempcorrx, 0); -+ nvram_read_u8(fill, NULL, "tempsense_option", &sprom->tempsense_option, 0); -+ nvram_read_u8(fill, NULL, "freqoffset_corr", &sprom->freqoffset_corr, 0); -+ nvram_read_u8(fill, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0); -+ nvram_read_u8(fill, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0); -+ nvram_read_u8(fill, NULL, "elna2g", &sprom->elna2g, 0); -+ nvram_read_u8(fill, NULL, "elna5g", &sprom->elna5g, 0); -+ nvram_read_u8(fill, NULL, "phycal_tempdelta", &sprom->phycal_tempdelta, 0); -+ nvram_read_u8(fill, NULL, "temps_period", &sprom->temps_period, 0); -+ nvram_read_u8(fill, NULL, "temps_hysteresis", &sprom->temps_hysteresis, 0); -+ nvram_read_u8(fill, NULL, "measpower1", &sprom->measpower1, 0); -+ nvram_read_u8(fill, NULL, "measpower2", &sprom->measpower2, 0); -+ nvram_read_u8(fill, NULL, "rxgainerr2ga0", &sprom->rxgainerr2ga[0], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr2ga1", &sprom->rxgainerr2ga[1], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr2ga2", &sprom->rxgainerr2ga[2], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gla0", &sprom->rxgainerr5gla[0], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gla1", &sprom->rxgainerr5gla[1], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gla2", &sprom->rxgainerr5gla[2], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gma0", &sprom->rxgainerr5gma[0], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gma1", &sprom->rxgainerr5gma[1], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gma2", &sprom->rxgainerr5gma[2], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gha0", &sprom->rxgainerr5gha[0], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gha1", &sprom->rxgainerr5gha[1], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gha2", &sprom->rxgainerr5gha[2], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gua0", &sprom->rxgainerr5gua[0], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gua1", &sprom->rxgainerr5gua[1], 0); -+ nvram_read_u8(fill, NULL, "rxgainerr5gua2", &sprom->rxgainerr5gua[2], 0); -+ nvram_read_u8(fill, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0); -+ nvram_read_u8(fill, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0); -+ nvram_read_u8(fill, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gla0", &sprom->noiselvl5gla[0], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gla1", &sprom->noiselvl5gla[1], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gla2", &sprom->noiselvl5gla[2], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gma0", &sprom->noiselvl5gma[0], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gma1", &sprom->noiselvl5gma[1], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gma2", &sprom->noiselvl5gma[2], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gha0", &sprom->noiselvl5gha[0], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gha1", &sprom->noiselvl5gha[1], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gha2", &sprom->noiselvl5gha[2], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gua0", &sprom->noiselvl5gua[0], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gua1", &sprom->noiselvl5gua[1], 0); -+ nvram_read_u8(fill, NULL, "noiselvl5gua2", &sprom->noiselvl5gua[2], 0); -+ nvram_read_u8(fill, NULL, "pcieingress_war", &sprom->pcieingress_war, 0); -+} -+ -+static void bcm53xx_sprom_fill_r9(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u16(fill, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0); -+ nvram_read_u16(fill, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw202gpo", &sprom->legofdmbw202gpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw20ul2gpo", &sprom->legofdmbw20ul2gpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw205glpo", &sprom->legofdmbw205glpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw20ul5glpo", &sprom->legofdmbw20ul5glpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw205gmpo", &sprom->legofdmbw205gmpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw20ul5gmpo", &sprom->legofdmbw20ul5gmpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw205ghpo", &sprom->legofdmbw205ghpo, 0); -+ nvram_read_u32(fill, NULL, "legofdmbw20ul5ghpo", &sprom->legofdmbw20ul5ghpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw20ul5glpo", &sprom->mcsbw20ul5glpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw20ul5gmpo", &sprom->mcsbw20ul5gmpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw20ul5ghpo", &sprom->mcsbw20ul5ghpo, 0); -+ nvram_read_u32(fill, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0); -+ nvram_read_u16(fill, NULL, "mcs32po", &sprom->mcs32po, 0); -+ nvram_read_u16(fill, NULL, "legofdm40duppo", &sprom->legofdm40duppo, 0); -+ nvram_read_u8(fill, NULL, "sar2g", &sprom->sar2g, 0); -+ nvram_read_u8(fill, NULL, "sar5g", &sprom->sar5g, 0); -+} -+ -+static void bcm53xx_sprom_fill_path_r4589(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ char postfix[2]; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { -+ struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i]; -+ snprintf(postfix, sizeof(postfix), "%i", i); -+ nvram_read_u8(fill, postfix, "maxp2ga", &pwr_info->maxpwr_2g, 0); -+ nvram_read_u8(fill, postfix, "itt2ga", &pwr_info->itssi_2g, 0); -+ nvram_read_u8(fill, postfix, "itt5ga", &pwr_info->itssi_5g, 0); -+ nvram_read_u16(fill, postfix, "pa2gw0a", &pwr_info->pa_2g[0], 0); -+ nvram_read_u16(fill, postfix, "pa2gw1a", &pwr_info->pa_2g[1], 0); -+ nvram_read_u16(fill, postfix, "pa2gw2a", &pwr_info->pa_2g[2], 0); -+ nvram_read_u8(fill, postfix, "maxp5ga", &pwr_info->maxpwr_5g, 0); -+ nvram_read_u8(fill, postfix, "maxp5gha", &pwr_info->maxpwr_5gh, 0); -+ nvram_read_u8(fill, postfix, "maxp5gla", &pwr_info->maxpwr_5gl, 0); -+ nvram_read_u16(fill, postfix, "pa5gw0a", &pwr_info->pa_5g[0], 0); -+ nvram_read_u16(fill, postfix, "pa5gw1a", &pwr_info->pa_5g[1], 0); -+ nvram_read_u16(fill, postfix, "pa5gw2a", &pwr_info->pa_5g[2], 0); -+ nvram_read_u16(fill, postfix, "pa5glw0a", &pwr_info->pa_5gl[0], 0); -+ nvram_read_u16(fill, postfix, "pa5glw1a", &pwr_info->pa_5gl[1], 0); -+ nvram_read_u16(fill, postfix, "pa5glw2a", &pwr_info->pa_5gl[2], 0); -+ nvram_read_u16(fill, postfix, "pa5ghw0a", &pwr_info->pa_5gh[0], 0); -+ nvram_read_u16(fill, postfix, "pa5ghw1a", &pwr_info->pa_5gh[1], 0); -+ nvram_read_u16(fill, postfix, "pa5ghw2a", &pwr_info->pa_5gh[2], 0); -+ } -+} -+ -+static void bcm53xx_sprom_fill_path_r45(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ char postfix[2]; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) { -+ struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i]; -+ snprintf(postfix, sizeof(postfix), "%i", i); -+ nvram_read_u16(fill, postfix, "pa2gw3a", &pwr_info->pa_2g[3], 0); -+ nvram_read_u16(fill, postfix, "pa5gw3a", &pwr_info->pa_5g[3], 0); -+ nvram_read_u16(fill, postfix, "pa5glw3a", &pwr_info->pa_5gl[3], 0); -+ nvram_read_u16(fill, postfix, "pa5ghw3a", &pwr_info->pa_5gh[3], 0); -+ } -+} -+ -+static void bcm53xx_sprom_fill_ethernet(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_macaddr(fill, "et0macaddr", sprom->et0mac); -+ nvram_read_u8(fill, NULL, "et0mdcport", &sprom->et0mdcport, 0); -+ nvram_read_u8(fill, NULL, "et0phyaddr", &sprom->et0phyaddr, 0); -+ -+ nvram_read_macaddr(fill, "et1macaddr", sprom->et1mac); -+ nvram_read_u8(fill, NULL, "et1mdcport", &sprom->et1mdcport, 0); -+ nvram_read_u8(fill, NULL, "et1phyaddr", &sprom->et1phyaddr, 0); -+ -+ nvram_read_macaddr(fill, "macaddr", sprom->il0mac); -+ nvram_read_macaddr(fill, "il0macaddr", sprom->il0mac); -+} -+ -+static void bcm53xx_sprom_fill_board_data(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ nvram_read_u16(fill, NULL, "boardrev", &sprom->board_rev, 0); -+ nvram_read_u16(fill, NULL, "boardnum", &sprom->board_num, 0); -+ nvram_read_u16(fill, NULL, "boardtype", &sprom->board_type, 0); -+ nvram_read_u32_2(fill, "boardflags", &sprom->boardflags_lo, -+ &sprom->boardflags_hi); -+ nvram_read_u32_2(fill, "boardflags2", &sprom->boardflags2_lo, -+ &sprom->boardflags2_hi); -+} -+ -+static void bcm53xx_sprom_fill(struct ssb_sprom *sprom, -+ const struct bcm53xx_sprom_fill *fill) -+{ -+ bcm53xx_sprom_fill_ethernet(sprom, fill); -+ bcm53xx_sprom_fill_board_data(sprom, fill); -+ -+ nvram_read_u8(fill, NULL, "sromrev", &sprom->revision, 0); -+ -+ switch (sprom->revision) { -+ case 1: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r1(sprom, fill); -+ break; -+ case 2: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r2389(sprom, fill); -+ break; -+ case 3: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r2389(sprom, fill); -+ bcm53xx_sprom_fill_r389(sprom, fill); -+ bcm53xx_sprom_fill_r3(sprom, fill); -+ break; -+ case 4: -+ case 5: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r4589(sprom, fill); -+ bcm53xx_sprom_fill_r458(sprom, fill); -+ bcm53xx_sprom_fill_r45(sprom, fill); -+ bcm53xx_sprom_fill_path_r4589(sprom, fill); -+ bcm53xx_sprom_fill_path_r45(sprom, fill); -+ break; -+ case 8: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r2389(sprom, fill); -+ bcm53xx_sprom_fill_r389(sprom, fill); -+ bcm53xx_sprom_fill_r4589(sprom, fill); -+ bcm53xx_sprom_fill_r458(sprom, fill); -+ bcm53xx_sprom_fill_r89(sprom, fill); -+ bcm53xx_sprom_fill_path_r4589(sprom, fill); -+ break; -+ case 9: -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r2389(sprom, fill); -+ bcm53xx_sprom_fill_r389(sprom, fill); -+ bcm53xx_sprom_fill_r4589(sprom, fill); -+ bcm53xx_sprom_fill_r89(sprom, fill); -+ bcm53xx_sprom_fill_r9(sprom, fill); -+ bcm53xx_sprom_fill_path_r4589(sprom, fill); -+ break; -+ default: -+ pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", -+ sprom->revision); -+ sprom->revision = 1; -+ bcm53xx_sprom_fill_r1234589(sprom, fill); -+ bcm53xx_sprom_fill_r12389(sprom, fill); -+ bcm53xx_sprom_fill_r1(sprom, fill); -+ } -+} -+ -+static int bcm53xx_sprom_getenv(const struct bcm53xx_sprom_fill *fill, -+ const char *name, char *val, size_t val_len) -+{ -+ const struct platform_device *nvram_dev = fill->priv; -+ -+ return bcm47xx_nvram_getenv(&nvram_dev->dev, name, val, val_len); -+}; -+ -+static int bcm53xx_sprom_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct ssb_sprom *sprom; -+ const phandle *handle; -+ struct device_node *nvram_node; -+ struct platform_device *nvram_dev; -+ struct bcm53xx_sprom_fill fill; -+ -+ /* Alloc */ -+ sprom = devm_kzalloc(dev, sizeof(*sprom), GFP_KERNEL); -+ if (!sprom) -+ return -ENOMEM; -+ -+ handle = of_get_property(np, "nvram", NULL); -+ if (!handle) -+ return -ENOMEM; -+ -+ nvram_node = of_find_node_by_phandle(be32_to_cpup(handle)); -+ if (!nvram_node) -+ return -ENOMEM; -+ -+ nvram_dev = of_find_device_by_node(nvram_node); -+ if (!nvram_dev) -+ return -ENOMEM; -+ -+ fill.prefix = NULL; -+ fill.fallback = false; -+ fill.getenv = bcm53xx_sprom_getenv; -+ fill.priv = nvram_dev; -+ -+ bcm53xx_sprom_fill(sprom, &fill); -+ -+ platform_set_drvdata(pdev, sprom); -+ -+ return 0; -+} -+ -+static const struct of_device_id bcm53xx_sprom_of_match_table[] = { -+ { .compatible = "brcm,bcm53xx-sprom", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table); -+ -+static struct platform_driver bcm53xx_sprom_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "bcm53xx-sprom", -+ .of_match_table = bcm53xx_sprom_of_match_table, -+ /* driver unloading/unbinding currently not supported */ -+ .suppress_bind_attrs = true, -+ }, -+ .probe = bcm53xx_sprom_probe, -+}; -+module_platform_driver(bcm53xx_sprom_driver); -+ -+MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); -+MODULE_LICENSE("GPLv2"); diff --git a/target/linux/bcm53xx/patches-3.14/120-bcma-register-bcma-as-device-tree-driver.patch b/target/linux/bcm53xx/patches-3.14/120-bcma-register-bcma-as-device-tree-driver.patch deleted file mode 100644 index 0db670a..0000000 --- a/target/linux/bcm53xx/patches-3.14/120-bcma-register-bcma-as-device-tree-driver.patch +++ /dev/null @@ -1,115 +0,0 @@ -From bb5d497aeceb8d9f36a1d990538389b54748dfcd Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 6 Jan 2014 23:29:15 +0100 -Subject: [PATCH 05/15] bcma: register bcma as device tree driver - -This driver is used by the bcm53xx ARM SoC code.Now it is possible to -give the address of the chipcommon core in device tree. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/host_soc.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/bcma/bcma.h | 2 ++ - 2 files changed, 72 insertions(+) - ---- a/drivers/bcma/host_soc.c -+++ b/drivers/bcma/host_soc.c -@@ -7,6 +7,9 @@ - - #include "bcma_private.h" - #include "scan.h" -+#include <linux/slab.h> -+#include <linux/module.h> -+#include <linux/of_address.h> - #include <linux/bcma/bcma.h> - #include <linux/bcma/bcma_soc.h> - -@@ -173,6 +176,7 @@ int __init bcma_host_soc_register(struct - /* Host specific */ - bus->hosttype = BCMA_HOSTTYPE_SOC; - bus->ops = &bcma_host_soc_ops; -+ bus->host_pdev = NULL; - - /* Register */ - err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); -@@ -181,3 +185,69 @@ int __init bcma_host_soc_register(struct - - return err; - } -+ -+#ifdef CONFIG_OF -+static int bcma_host_soc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct bcma_bus *bus; -+ int err; -+ -+ /* Alloc */ -+ bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL); -+ if (!bus) -+ return -ENOMEM; -+ -+ /* Map MMIO */ -+ bus->mmio = of_iomap(np, 0); -+ if (!bus->mmio) -+ return -ENOMEM; -+ -+ /* Host specific */ -+ bus->hosttype = BCMA_HOSTTYPE_SOC; -+ bus->ops = &bcma_host_soc_ops; -+ bus->host_pdev = pdev; -+ -+ /* Register */ -+ err = bcma_bus_register(bus); -+ if (err) -+ goto err_unmap_mmio; -+ -+ platform_set_drvdata(pdev, bus); -+ -+ return err; -+ -+err_unmap_mmio: -+ iounmap(bus->mmio); -+ return err; -+} -+ -+static int bcma_host_soc_remove(struct platform_device *pdev) -+{ -+ struct bcma_bus *bus = platform_get_drvdata(pdev); -+ -+ bcma_bus_unregister(bus); -+ iounmap(bus->mmio); -+ platform_set_drvdata(pdev, NULL); -+ -+ return 0; -+} -+ -+static const struct of_device_id bcma_host_soc_of_match[] = { -+ { .compatible = "brcm,bus-aix", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match); -+ -+static struct platform_driver bcma_host_soc_driver = { -+ .driver = { -+ .name = "bcma-host-soc", -+ .owner = THIS_MODULE, -+ .of_match_table = bcma_host_soc_of_match, -+ }, -+ .probe = bcma_host_soc_probe, -+ .remove = bcma_host_soc_remove, -+}; -+module_platform_driver(bcma_host_soc_driver); -+#endif /* CONFIG_OF */ ---- a/include/linux/bcma/bcma.h -+++ b/include/linux/bcma/bcma.h -@@ -323,6 +323,8 @@ struct bcma_bus { - struct pci_dev *host_pci; - /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ - struct sdio_func *host_sdio; -+ /* Pointer to platform device (only for BCMA_HOSTTYPE_SOC) */ -+ struct platform_device *host_pdev; - }; - - struct bcma_chipinfo chipinfo; diff --git a/target/linux/bcm53xx/patches-3.14/121-bcma-get-irqs-from-dt.patch b/target/linux/bcm53xx/patches-3.14/121-bcma-get-irqs-from-dt.patch deleted file mode 100644 index f81541f..0000000 --- a/target/linux/bcm53xx/patches-3.14/121-bcma-get-irqs-from-dt.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 3e59da41882a408064cd23f4c9124a7938bdb91f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Thu, 9 Jan 2014 19:40:14 +0100 -Subject: [PATCH 06/15] bcma: get irqs from dt - -If bcma was registered with device tree it will search for some nodes -with the irq number and add it to the core configuration. ---- - drivers/bcma/main.c | 42 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 41 insertions(+), 1 deletion(-) - ---- a/drivers/bcma/main.c -+++ b/drivers/bcma/main.c -@@ -10,6 +10,8 @@ - #include <linux/platform_device.h> - #include <linux/bcma/bcma.h> - #include <linux/slab.h> -+#include <linux/of_irq.h> -+#include <linux/of_address.h> - - MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); - MODULE_LICENSE("GPL"); -@@ -120,6 +122,38 @@ static void bcma_release_core_dev(struct - kfree(core); - } - -+static struct device_node *bcma_of_find_child_device(struct platform_device *parent, -+ struct bcma_device *core) -+{ -+ struct device_node *node; -+ u64 size; -+ const __be32 *reg; -+ -+ if (!parent || !parent->dev.of_node) -+ return NULL; -+ -+ for_each_child_of_node(parent->dev.of_node, node) { -+ reg = of_get_address(node, 0, &size, 0); -+ if (!reg) -+ continue; -+ if (be32_to_cpup(reg) == core->addr) -+ return node; -+ } -+ return NULL; -+} -+ -+static void bcma_of_fill_device(struct platform_device *parent, -+ struct bcma_device *core) -+{ -+ struct device_node *node; -+ -+ node = bcma_of_find_child_device(parent, core); -+ if (!node) -+ return; -+ core->dev.of_node = node; -+ core->irq = irq_of_parse_and_map(node, 0); -+} -+ - static int bcma_register_cores(struct bcma_bus *bus) - { - struct bcma_device *core; -@@ -155,7 +189,13 @@ static int bcma_register_cores(struct bc - break; - case BCMA_HOSTTYPE_SOC: - core->dev.dma_mask = &core->dev.coherent_dma_mask; -- core->dma_dev = &core->dev; -+ if (bus->host_pdev) { -+ core->dma_dev = &bus->host_pdev->dev; -+ core->dev.parent = &bus->host_pdev->dev; -+ bcma_of_fill_device(bus->host_pdev, core); -+ } else { -+ core->dma_dev = &core->dev; -+ } - break; - case BCMA_HOSTTYPE_SDIO: - break; diff --git a/target/linux/bcm53xx/patches-3.14/123-bcma-get-sprom-from-devicetree.patch b/target/linux/bcm53xx/patches-3.14/123-bcma-get-sprom-from-devicetree.patch deleted file mode 100644 index 0bf1308..0000000 --- a/target/linux/bcm53xx/patches-3.14/123-bcma-get-sprom-from-devicetree.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 5d94449a92e4121b408e7cb8931a47984135eeea Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 4 May 2014 14:34:31 +0200 -Subject: [PATCH 07/15] bcma: get sprom from devicetree - -This patch make it possible to device an sprom provider in device tree -and get the sprom from this driver. Every time there is such a provider -it gets asked for a sprom. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/sprom.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 50 insertions(+), 1 deletion(-) - ---- a/drivers/bcma/sprom.c -+++ b/drivers/bcma/sprom.c -@@ -15,6 +15,8 @@ - #include <linux/io.h> - #include <linux/dma-mapping.h> - #include <linux/slab.h> -+#include <linux/of.h> -+#include <linux/of_platform.h> - - static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out); - -@@ -46,6 +48,46 @@ int bcma_arch_register_fallback_sprom(in - return 0; - } - -+#ifdef CONFIG_OF -+static int bcma_fill_sprom_with_dt(struct bcma_bus *bus, -+ struct ssb_sprom *out) -+{ -+ const phandle *handle; -+ struct device_node *sprom_node; -+ struct platform_device *sprom_dev; -+ struct ssb_sprom *sprom; -+ -+ if (!bus->host_pdev || !bus->host_pdev->dev.of_node) -+ return -ENOENT; -+ -+ handle = of_get_property(bus->host_pdev->dev.of_node, "sprom", NULL); -+ if (!handle) -+ return -ENOENT; -+ -+ sprom_node = of_find_node_by_phandle(be32_to_cpup(handle)); -+ if (!sprom_node) -+ return -ENOENT; -+ -+ sprom_dev = of_find_device_by_node(sprom_node); -+ if (!sprom_dev) -+ return -ENOENT; -+ -+ sprom = platform_get_drvdata(sprom_dev); -+ if (!sprom) -+ return -ENOENT; -+ -+ memcpy(out, sprom, sizeof(*out)); -+ -+ return 0; -+} -+#else -+static int bcma_fill_sprom_with_dt(struct bcma_bus *bus, -+ struct ssb_sprom *out) -+{ -+ return -ENOENT; -+} -+#endif -+ - static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, - struct ssb_sprom *out) - { -@@ -580,7 +622,14 @@ int bcma_sprom_get(struct bcma_bus *bus) - u16 *sprom; - size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, - SSB_SPROMSIZE_WORDS_R10, }; -- int i, err = 0; -+ int i, err; -+ -+ err = bcma_fill_sprom_with_dt(bus, &bus->sprom); -+ if (err == 0) { -+ bcma_info(bus, "Found sprom from device tree provider\n"); -+ return 0; -+ } -+ err = 0; - - if (!bus->drv_cc.core) - return -EOPNOTSUPP; diff --git a/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch b/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch deleted file mode 100644 index 9d01f33..0000000 --- a/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 23bcd5e7cb2aaee48ba8b2351f032a230d948b6f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sat, 25 Jan 2014 17:03:07 +0100 -Subject: [PATCH 08/15] ARM: BCM5301X: register bcma bus - ---- - arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 58 insertions(+) - ---- a/arch/arm/boot/dts/bcm4708.dtsi -+++ b/arch/arm/boot/dts/bcm4708.dtsi -@@ -31,4 +31,62 @@ - }; - }; - -+ nvram0: nvram@0 { -+ compatible = "brcm,bcm47xx-nvram"; -+ reg = <0x1c000000 0x01000000>; -+ }; -+ -+ sprom0: sprom@0 { -+ compatible = "brcm,bcm53xx-sprom"; -+ nvram = <&nvram0>; -+ }; -+ -+ aix@18000000 { -+ compatible = "brcm,bus-aix"; -+ reg = <0x18000000 0x1000>; -+ ranges = <0x00000000 0x18000000 0x00100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ sprom = <&sprom0>; -+ -+ usb2@0 { -+ reg = <0x18021000 0x1000>; -+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ usb3@0 { -+ reg = <0x18023000 0x1000>; -+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ gmac@0 { -+ reg = <0x18024000 0x1000>; -+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ gmac@1 { -+ reg = <0x18025000 0x1000>; -+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ gmac@2 { -+ reg = <0x18026000 0x1000>; -+ interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ gmac@3 { -+ reg = <0x18027000 0x1000>; -+ interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ pcie@0 { -+ reg = <0x18012000 0x1000>; -+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ pcie@1 { -+ reg = <0x18013000 0x1000>; -+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ }; - }; diff --git a/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch b/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch deleted file mode 100644 index 46464dc..0000000 --- a/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 28b11a8b1258214b3b5d58bb6e3bbcb0fc9fd4fe Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 31 Jul 2014 07:28:05 +0200 -Subject: [PATCH] ARM: BCM5301X: add restart support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/mach-bcm/bcm_5301x.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - ---- a/arch/arm/mach-bcm/bcm_5301x.c -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -12,9 +12,26 @@ - #include <asm/siginfo.h> - #include <asm/signal.h> - -+#include <linux/bcma/bcma.h> - - static bool first_fault = true; - -+static struct bcma_bus *bcm5301x_get_bcma_bus(void) -+{ -+ struct device_node *np; -+ struct platform_device *pdev; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bus-aix"); -+ if (!np) -+ return NULL; -+ -+ pdev = of_find_device_by_node(np); -+ if (!pdev) -+ return NULL; -+ -+ return platform_get_drvdata(pdev); -+} -+ - static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) - { -@@ -49,6 +66,19 @@ static void __init bcm5301x_dt_init(void - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - } - -+static void bcm5301x_restart(enum reboot_mode mode, const char *cmd) -+{ -+ struct bcma_bus *bus = bcm5301x_get_bcma_bus(); -+ -+ if (bus) -+ bcma_chipco_watchdog_timer_set(&bus->drv_cc, 1); -+ else -+ pr_warn("Unable to access bcma bus\n"); -+ -+ while (1) -+ ; -+} -+ - static const char __initconst *bcm5301x_dt_compat[] = { - "brcm,bcm4708", - NULL, -@@ -57,5 +87,6 @@ static const char __initconst *bcm5301x_ - DT_MACHINE_START(BCM5301X, "BCM5301X") - .init_early = bcm5301x_init_early, - .init_machine = bcm5301x_dt_init, -+ .restart = bcm5301x_restart, - .dt_compat = bcm5301x_dt_compat, - MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/140-bcma-only-map-wrap-if-it-is-not-null.patch b/target/linux/bcm53xx/patches-3.14/140-bcma-only-map-wrap-if-it-is-not-null.patch deleted file mode 100644 index 30e03e3..0000000 --- a/target/linux/bcm53xx/patches-3.14/140-bcma-only-map-wrap-if-it-is-not-null.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f8ea60bbaf880d8d8d99fde3b5155f472e00141f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 12 May 2014 20:16:39 +0200 -Subject: [PATCH 09/15] bcma: only map wrap if it is not null - -The chipcommon B core does not have a wrap address and it would fail here. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/scan.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/bcma/scan.c -+++ b/drivers/bcma/scan.c -@@ -421,10 +421,13 @@ static int bcma_get_next_core(struct bcm - core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE); - if (!core->io_addr) - return -ENOMEM; -- core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE); -- if (!core->io_wrap) { -- iounmap(core->io_addr); -- return -ENOMEM; -+ if (core->wrap) { -+ core->io_wrap = ioremap_nocache(core->wrap, -+ BCMA_CORE_SIZE); -+ if (!core->io_wrap) { -+ iounmap(core->io_addr); -+ return -ENOMEM; -+ } - } - } - return 0; diff --git a/target/linux/bcm53xx/patches-3.14/141-bcma-store-more-alternative-addresses.patch b/target/linux/bcm53xx/patches-3.14/141-bcma-store-more-alternative-addresses.patch deleted file mode 100644 index bb3ce62..0000000 --- a/target/linux/bcm53xx/patches-3.14/141-bcma-store-more-alternative-addresses.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 9317024aa1d8df94d3b021bc23b57f02a435e96c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 12 May 2014 21:57:53 +0200 -Subject: [PATCH 10/15] bcma: store more alternative addresses - -Each core could have more than one alternative address. There are cores -with 8 alternative addresses for different functions. The PHY control -in the Chip common B core is done through the 2. alternative address -and not the first one. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/scan.c | 9 +++++---- - drivers/usb/host/bcma-hcd.c | 2 +- - include/linux/bcma/bcma.h | 2 +- - 3 files changed, 7 insertions(+), 6 deletions(-) - ---- a/drivers/bcma/scan.c -+++ b/drivers/bcma/scan.c -@@ -276,7 +276,7 @@ static int bcma_get_next_core(struct bcm - struct bcma_device *core) - { - u32 tmp; -- u8 i, j; -+ u8 i, j, k; - s32 cia, cib; - u8 ports[2], wrappers[2]; - -@@ -367,6 +367,7 @@ static int bcma_get_next_core(struct bcm - core->addr = tmp; - - /* get & parse slave ports */ -+ k = 0; - for (i = 0; i < ports[1]; i++) { - for (j = 0; ; j++) { - tmp = bcma_erom_get_addr_desc(bus, eromptr, -@@ -376,9 +377,9 @@ static int bcma_get_next_core(struct bcm - /* pr_debug("erom: slave port %d " - * "has %d descriptors\n", i, j); */ - break; -- } else { -- if (i == 0 && j == 0) -- core->addr1 = tmp; -+ } else if (k < 8) { -+ core->addr_s[k] = tmp; -+ k++; - } - } - } ---- a/drivers/usb/host/bcma-hcd.c -+++ b/drivers/usb/host/bcma-hcd.c -@@ -237,7 +237,7 @@ static int bcma_hcd_probe(struct bcma_de - bcma_hcd_init_chip(dev); - - /* In AI chips EHCI is addrspace 0, OHCI is 1 */ -- ohci_addr = dev->addr1; -+ ohci_addr = dev->addr_s[0]; - if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749) - && chipinfo->rev == 0) - ohci_addr = 0x18009000; ---- a/include/linux/bcma/bcma.h -+++ b/include/linux/bcma/bcma.h -@@ -267,7 +267,7 @@ struct bcma_device { - u8 core_unit; - - u32 addr; -- u32 addr1; -+ u32 addr_s[8]; - u32 wrap; - - void __iomem *io_addr; diff --git a/target/linux/bcm53xx/patches-3.14/142-bcma-add-support-for-chipcommon-B-core.patch b/target/linux/bcm53xx/patches-3.14/142-bcma-add-support-for-chipcommon-B-core.patch deleted file mode 100644 index 312f63b..0000000 --- a/target/linux/bcm53xx/patches-3.14/142-bcma-add-support-for-chipcommon-B-core.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 6c0df4a483e41ef129caa8948b3bcde7f91de197 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 12 May 2014 20:33:15 +0200 -Subject: [PATCH 11/15] bcma: add support for chipcommon B core - -This core is used on BCM4708 to configure the PCIe and USB3 PHYs and it -contains the addresses to the Device Management unit. This will be used -by the PCIe driver first. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/Makefile | 1 + - drivers/bcma/bcma_private.h | 4 ++ - drivers/bcma/driver_chipcommon_b.c | 59 +++++++++++++++++++++++++++++ - drivers/bcma/main.c | 10 +++++ - drivers/bcma/scan.c | 1 + - include/linux/bcma/bcma.h | 1 + - include/linux/bcma/bcma_driver_chipcommon.h | 8 ++++ - 7 files changed, 84 insertions(+) - create mode 100644 drivers/bcma/driver_chipcommon_b.c - ---- a/drivers/bcma/Makefile -+++ b/drivers/bcma/Makefile -@@ -1,5 +1,6 @@ - bcma-y += main.o scan.o core.o sprom.o - bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o -+bcma-y += driver_chipcommon_b.o - bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o - bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o - bcma-y += driver_pci.o ---- a/drivers/bcma/bcma_private.h -+++ b/drivers/bcma/bcma_private.h -@@ -50,6 +50,10 @@ void bcma_chipco_serial_init(struct bcma - extern struct platform_device bcma_pflash_dev; - #endif /* CONFIG_BCMA_DRIVER_MIPS */ - -+/* driver_chipcommon_b.c */ -+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb); -+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb); -+ - /* driver_chipcommon_pmu.c */ - u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); - u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); ---- /dev/null -+++ b/drivers/bcma/driver_chipcommon_b.c -@@ -0,0 +1,59 @@ -+/* -+ * Broadcom specific AMBA -+ * ChipCommon B Unit driver -+ * -+ * Copyright 2011, 2014, Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include "bcma_private.h" -+#include <linux/export.h> -+#include <linux/bcma/bcma.h> -+ -+static bool bcma_wait_reg(void __iomem *addr, u32 mask, u32 value, -+ int timeout) -+{ -+ unsigned long deadline = jiffies + timeout; -+ u32 val; -+ -+ do { -+ val = readl(addr); -+ if ((val & mask) == value) -+ return true; -+ cpu_relax(); -+ udelay(10); -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ pr_warn("Timeout waiting for register %p!\n", addr); -+ -+ return false; -+} -+ -+void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value) -+{ -+ writel(offset, ccb->mii + 0x00); -+ bcma_wait_reg(ccb->mii + 0x00, 0x0100, 0x0000, 100); -+ writel(value, ccb->mii + 0x04); -+ bcma_wait_reg(ccb->mii + 0x00, 0x0100, 0x0000, 100); -+} -+EXPORT_SYMBOL_GPL(bcma_chipco_b_mii_write); -+ -+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb) -+{ -+ if (ccb->setup_done) -+ return 0; -+ -+ ccb->setup_done = 1; -+ ccb->mii = ioremap_nocache(ccb->core->addr_s[1], BCMA_CORE_SIZE); -+ if (!ccb->mii) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb) -+{ -+ if (ccb->mii) -+ iounmap(ccb->mii); -+} ---- a/drivers/bcma/main.c -+++ b/drivers/bcma/main.c -@@ -164,6 +164,7 @@ static int bcma_register_cores(struct bc - switch (core->id.id) { - case BCMA_CORE_4706_CHIPCOMMON: - case BCMA_CORE_CHIPCOMMON: -+ case BCMA_CORE_NS_CHIPCOMMON_B: - case BCMA_CORE_PCI: - case BCMA_CORE_PCIE: - case BCMA_CORE_PCIE2: -@@ -301,6 +302,13 @@ int bcma_bus_register(struct bcma_bus *b - bcma_core_chipcommon_init(&bus->drv_cc); - } - -+ /* Init CC core */ -+ core = bcma_find_core(bus, BCMA_CORE_NS_CHIPCOMMON_B); -+ if (core) { -+ bus->drv_cc_b.core = core; -+ bcma_core_chipcommon_b_init(&bus->drv_cc_b); -+ } -+ - /* Init MIPS core */ - core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); - if (core) { -@@ -355,6 +363,8 @@ void bcma_bus_unregister(struct bcma_bus - else if (err) - bcma_err(bus, "Can not unregister GPIO driver: %i\n", err); - -+ bcma_core_chipcommon_b_free(&bus->drv_cc_b); -+ - cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); - cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); - cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); ---- a/drivers/bcma/scan.c -+++ b/drivers/bcma/scan.c -@@ -314,6 +314,7 @@ static int bcma_get_next_core(struct bcm - /* Some specific cores don't need wrappers */ - switch (core->id.id) { - case BCMA_CORE_4706_MAC_GBIT_COMMON: -+ case BCMA_CORE_NS_CHIPCOMMON_B: - /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ - break; - default: ---- a/include/linux/bcma/bcma.h -+++ b/include/linux/bcma/bcma.h -@@ -338,6 +338,7 @@ struct bcma_bus { - u8 num; - - struct bcma_drv_cc drv_cc; -+ struct bcma_drv_cc_b drv_cc_b; - struct bcma_drv_pci drv_pci[2]; - struct bcma_drv_pcie2 drv_pcie2; - struct bcma_drv_mips drv_mips; ---- a/include/linux/bcma/bcma_driver_chipcommon.h -+++ b/include/linux/bcma/bcma_driver_chipcommon.h -@@ -644,6 +644,12 @@ struct bcma_drv_cc { - #endif - }; - -+struct bcma_drv_cc_b { -+ struct bcma_device *core; -+ u8 setup_done:1; -+ void __iomem *mii; -+}; -+ - /* Register access */ - #define bcma_cc_read32(cc, offset) \ - bcma_read32((cc)->core, offset) -@@ -699,4 +705,6 @@ extern void bcma_pmu_spuravoid_pllupdate - - extern u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc); - -+void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value); -+ - #endif /* LINUX_BCMA_DRIVER_CC_H_ */ diff --git a/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch b/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch deleted file mode 100644 index 23e8a02..0000000 --- a/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch +++ /dev/null @@ -1,29 +0,0 @@ -From ea422113a5d2778347db6136d95f45a50e2f2d29 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Thu, 29 May 2014 20:54:15 +0200 -Subject: [PATCH 13/15] pci: do not probe too early - -Probing is done before the PCIe bridge is fully activated and the -address spaces does not get assigned to the PCIe devices. Without the -address space the driver can not register to this device. With this -patch the driver reregistration is done later. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/pci/probe.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -1912,7 +1912,10 @@ struct pci_bus *pci_scan_root_bus(struct - if (!found) - pci_bus_update_busn_res_end(b, max); - -- pci_bus_add_devices(b); -+ /* this should be done in arch/arm/kernel/bios32.c, because the -+ resources for the PCI devices are initilized later and doing -+ it here will fail. */ -+ /* pci_bus_add_devices(b); */ - return b; - } - EXPORT_SYMBOL(pci_scan_root_bus); diff --git a/target/linux/bcm53xx/patches-3.14/160-bcma-add-PCI-IDs-for-more-devices.patch b/target/linux/bcm53xx/patches-3.14/160-bcma-add-PCI-IDs-for-more-devices.patch deleted file mode 100644 index 83b72b4..0000000 --- a/target/linux/bcm53xx/patches-3.14/160-bcma-add-PCI-IDs-for-more-devices.patch +++ /dev/null @@ -1,23 +0,0 @@ -From a0d83e0ad20f6dde0a71ed07da12ca3be8bbdc01 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 18 May 2014 17:15:24 +0200 -Subject: [PATCH 12/15] bcma: add PCI IDs for more devices - -This adds the PCI IDs for the BCM4360 and BCM43227. -Both devices were found on a Netgear R6250 with a BCM4708 ARM SoC. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/bcma/host_pci.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/bcma/host_pci.c -+++ b/drivers/bcma/host_pci.c -@@ -282,6 +282,7 @@ static const struct pci_device_id bcma_p - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, - { 0, }, - }; - MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); diff --git a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch deleted file mode 100644 index 4e32ed8..0000000 --- a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch +++ /dev/null @@ -1,645 +0,0 @@ -From 7475eee716d11f487076f78f26a6e403c06d0c76 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 12 May 2014 11:55:20 +0200 -Subject: [PATCH 14/15] pcie2-bcma: add new PCIe2 driver for bcma - -This driver supports the PCIe controller found on the BCM4708 and -similar SoCs. The controller itself is automatically detected by bcma. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/mach-bcm/Kconfig | 1 + - drivers/pci/host/Kconfig | 7 + - drivers/pci/host/Makefile | 1 + - drivers/pci/host/pcie2-bcma.c | 594 ++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 603 insertions(+) - create mode 100644 drivers/pci/host/pcie2-bcma.c - ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -45,6 +45,7 @@ config ARCH_BCM_5301X - select ARM_GLOBAL_TIMER - select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - select MIGHT_HAVE_PCI -+ select PCI_DOMAINS if PCI - help - Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. - ---- a/drivers/pci/host/Kconfig -+++ b/drivers/pci/host/Kconfig -@@ -33,4 +33,11 @@ config PCI_RCAR_GEN2 - There are 3 internal PCI controllers available with a single - built-in EHCI/OHCI host controller present on each one. - -+config PCI_BCMA -+ bool "BCMA PCIe2 host controller" -+ depends on BCMA && OF -+ help -+ Say Y here if you want to support a simple generic PCI host -+ controller, such as the one emulated by kvmtool. -+ - endmenu ---- a/drivers/pci/host/Makefile -+++ b/drivers/pci/host/Makefile -@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o - obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o - obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o - obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o -+obj-$(CONFIG_PCI_BCMA) += pcie2-bcma.o ---- /dev/null -+++ b/drivers/pci/host/pcie2-bcma.c -@@ -0,0 +1,594 @@ -+/* -+ * Northstar PCI-Express driver -+ * Only supports Root-Complex (RC) mode -+ * -+ * Notes: -+ * PCI Domains are being used to identify the PCIe port 1:1. -+ * -+ * Only MEM access is supported, PAX does not support IO. -+ * -+ * TODO: -+ * MSI interrupts, -+ * DRAM > 128 MBytes (e.g. DMA zones) -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/bug.h> -+#include <linux/delay.h> -+#include <linux/pci.h> -+#include <linux/io.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+#include <linux/bcma/bcma.h> -+ -+#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -+ -+/* -+ * Register offset definitions -+ */ -+#define SOC_PCIE_CONTROL 0x000 /* a.k.a. CLK_CONTROL reg */ -+#define SOC_PCIE_PM_STATUS 0x008 -+#define SOC_PCIE_PM_CONTROL 0x00c /* in EP mode only ! */ -+ -+#define SOC_PCIE_EXT_CFG_ADDR 0x120 -+#define SOC_PCIE_EXT_CFG_DATA 0x124 -+#define SOC_PCIE_CFG_ADDR 0x1f8 -+#define SOC_PCIE_CFG_DATA 0x1fc -+ -+#define SOC_PCIE_SYS_RC_INTX_EN 0x330 -+#define SOC_PCIE_SYS_RC_INTX_CSR 0x334 -+#define SOC_PCIE_SYS_HOST_INTR_EN 0x344 -+#define SOC_PCIE_SYS_HOST_INTR_CSR 0x348 -+ -+#define SOC_PCIE_HDR_OFF 0x400 /* 256 bytes per function */ -+ -+/* 32-bit 4KB in-bound mapping windows for Function 0..3, n=0..7 */ -+#define SOC_PCIE_SYS_IMAP0(f, n) (0xc00 + ((f) << 9)((n) << 2)) -+/* 64-bit in-bound mapping windows for func 0..3 */ -+#define SOC_PCIE_SYS_IMAP1(f) (0xc80 + ((f) << 3)) -+#define SOC_PCIE_SYS_IMAP2(f) (0xcc0 + ((f) << 3)) -+/* 64-bit in-bound address range n=0..2 */ -+#define SOC_PCIE_SYS_IARR(n) (0xd00 + ((n) << 3)) -+/* 64-bit out-bound address filter n=0..2 */ -+#define SOC_PCIE_SYS_OARR(n) (0xd20 + ((n) << 3)) -+/* 64-bit out-bound mapping windows n=0..2 */ -+#define SOC_PCIE_SYS_OMAP(n) (0xd40 + ((n) << 3)) -+ -+#define BCM4360_D11AC_ID 0x43a0 -+#define BCM4360_D11AC2G_ID 0x43a1 -+#define BCM4360_D11AC5G_ID 0x43a2 -+#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ -+#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ -+#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ -+ -+static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) -+{ -+ struct pci_sys_data *sys = pdev->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ return bdev->irq; -+} -+ -+static u32 bcma_pcie2_cfg_base(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where) -+{ -+ int slot = PCI_SLOT(devfn); -+ int fn = PCI_FUNC(devfn); -+ u32 addr_reg; -+ -+ if (busno == 0) { -+ if (slot >= 1) -+ return 0; -+ bcma_write32(bdev, SOC_PCIE_EXT_CFG_ADDR, where & 0xffc); -+ return SOC_PCIE_EXT_CFG_DATA; -+ } else { -+ if (fn > 1) -+ return 0; -+ addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) | -+ (where & 0xffc) | (1 & 0x3); -+ -+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg); -+ return SOC_PCIE_CFG_DATA; -+ } -+} -+ -+static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, int size) -+{ -+ u32 base; -+ u32 data_reg; -+ -+ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); -+ -+ if (!base) -+ return ~0UL; -+ -+ data_reg = bcma_read32(bdev, base); -+ -+ /* NS: CLASS field is R/O, and set to wrong 0x200 value */ -+ if (busno == 0 && devfn == 0) { -+ /* -+ * RC's class is 0x0280, but Linux PCI driver needs 0x604 -+ * for a PCIe bridge. So we must fixup the class code -+ * to 0x604 here. -+ */ -+ if ((where & 0xffc) == PCI_CLASS_REVISION) { -+ data_reg &= 0xff; -+ data_reg |= 0x604 << 16; -+ } -+ } -+ /* HEADER_TYPE=00 indicates the port in EP mode */ -+ -+ if (size == 4) { -+ return data_reg; -+ } else { -+ u32 mask = (1 << (size * 8)) - 1; -+ int shift = (where % 4) * 8; -+ return (data_reg >> shift) & mask; -+ } -+} -+ -+static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, int size, -+ u32 val) -+{ -+ u32 base; -+ u32 data_reg; -+ -+ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); -+ -+ if (!base) -+ return; -+ -+ if (size < 4) { -+ u32 mask = (1 << (size * 8)) - 1; -+ int shift = (where % 4) * 8; -+ data_reg = bcma_read32(bdev, base); -+ data_reg &= ~(mask << shift); -+ data_reg |= (val & mask) << shift; -+ } else { -+ data_reg = val; -+ } -+ -+ bcma_write32(bdev, base, data_reg); -+} -+ -+static u8 bcma_pcie2_read_config8(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where) -+{ -+ return bcma_pcie2_read_config(bdev, busno, devfn, where, 1); -+} -+ -+static u16 bcma_pcie2_read_config16(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where) -+{ -+ return bcma_pcie2_read_config(bdev, busno, devfn, where, 2); -+} -+ -+static u32 bcma_pcie2_read_config32(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where) -+{ -+ return bcma_pcie2_read_config(bdev, busno, devfn, where, 4); -+} -+ -+static void bcma_pcie2_write_config8(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, u8 val) -+{ -+ return bcma_pcie2_write_config(bdev, busno, devfn, where, 1, val); -+} -+ -+static void bcma_pcie2_write_config16(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, u16 val) -+{ -+ return bcma_pcie2_write_config(bdev, busno, devfn, where, 2, val); -+} -+ -+static void bcma_pcie2_write_config32(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, u32 val) -+{ -+ return bcma_pcie2_write_config(bdev, busno, devfn, where, 4, val); -+} -+ -+static int bcma_pcie2_read_config_pci(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 *val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ *val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int bcma_pcie2_write_config_pci(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+/* -+ * Check link status, return 0 if link is up in RC mode, -+ * otherwise return non-zero -+ */ -+static int bcma_pcie2_check_link(struct bcma_device *bdev, u32 allow_gen2) -+{ -+ u32 devfn = 0; -+ u8 tmp8; -+ u32 tmp32; -+ -+ tmp32 = bcma_pcie2_read_config32(bdev, 0, devfn, 0xdc); -+ tmp32 &= ~0xf; -+ if (allow_gen2) -+ tmp32 |= 2; -+ else { -+ /* force PCIE GEN1 */ -+ tmp32 |= 1; -+ } -+ bcma_pcie2_write_config32(bdev, 0, devfn, 0xdc, tmp32); -+ -+ /* See if the port is in EP mode, indicated by header type 00 */ -+ tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_HEADER_TYPE); -+ if (tmp8 != PCI_HEADER_TYPE_BRIDGE) { -+ dev_info(&bdev->dev, "Port %d in End-Point mode - ignored\n", -+ bdev->core_unit); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Initializte the PCIe controller -+ */ -+static void bcma_pcie2_hw_init(struct bcma_device *bdev) -+{ -+ u32 devfn = 0; -+ u32 tmp32; -+ u16 tmp16; -+ -+ /* Change MPS and MRRS to 512 */ -+ tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, 0x4d4); -+ tmp16 &= ~7; -+ tmp16 |= 2; -+ bcma_pcie2_write_config16(bdev, 0, devfn, 0x4d4, tmp16); -+ -+ tmp32 = bcma_pcie2_read_config32(bdev, 0, devfn, 0xb4); -+ tmp32 &= ~((7 << 12) | (7 << 5)); -+ tmp32 |= (2 << 12) | (2 << 5); -+ bcma_pcie2_write_config32(bdev, 0, devfn, 0xb4, tmp32); -+ -+ /* Turn-on Root-Complex (RC) mode, from reset defailt of EP */ -+ -+ /* The mode is set by straps, can be overwritten via DMU -+ register <cru_straps_control> bit 5, "1" means RC -+ */ -+ -+ /* Send a downstream reset */ -+ bcma_write32(bdev, SOC_PCIE_CONTROL, 0x3); -+ udelay(250); -+ bcma_write32(bdev, SOC_PCIE_CONTROL, 0x1); -+ mdelay(250); -+ -+ /* TBD: take care of PM, check we're on */ -+} -+ -+/* -+ * Setup the address translation -+ */ -+static void bcma_pcie2_map_init(struct bcma_device *bdev) -+{ -+ unsigned size, i; -+ u32 addr; -+ -+ /* -+ * NOTE: -+ * All PCI-to-CPU address mapping are 1:1 for simplicity -+ */ -+ -+ /* Outbound address translation setup */ -+ size = SZ_128M; -+ addr = bdev->addr_s[0]; -+ BUG_ON(!addr); -+ BUG_ON(addr & ((1 << 25) - 1)); /* 64MB alignment */ -+ -+ for (i = 0; i < 3; i++) { -+ const unsigned win_size = SZ_64M; -+ /* 64-bit LE regs, write low word, high is 0 at reset */ -+ bcma_write32(bdev, SOC_PCIE_SYS_OMAP(i), addr); -+ bcma_write32(bdev, SOC_PCIE_SYS_OARR(i), addr|0x1); -+ addr += win_size; -+ if (size >= win_size) -+ size -= win_size; -+ if (size == 0) -+ break; -+ } -+ WARN_ON(size > 0); -+ -+ /* -+ * Inbound address translation setup -+ * Northstar only maps up to 128 MiB inbound, DRAM could be up to 1 GiB. -+ * -+ * For now allow access to entire DRAM, assuming it is less than 128MiB, -+ * otherwise DMA bouncing mechanism may be required. -+ * Also consider DMA mask to limit DMA physical address -+ */ -+ size = SZ_128M; -+ addr = PHYS_OFFSET; -+ -+ size >>= 20; /* In MB */ -+ size &= 0xff; /* Size is an 8-bit field */ -+ -+ WARN_ON(size == 0); -+ /* 64-bit LE regs, write low word, high is 0 at reset */ -+ bcma_write32(bdev, SOC_PCIE_SYS_IMAP1(0), addr | 0x1); -+ bcma_write32(bdev, SOC_PCIE_SYS_IARR(1), addr | size); -+ -+#ifdef CONFIG_SPARSEMEM -+ addr = PHYS_OFFSET2; -+ bcma_write32(bdev, SOC_PCIE_SYS_IMAP2(0), addr | 0x1); -+ bcma_write32(bdev, SOC_PCIE_SYS_IARR(2), addr | size); -+#endif -+} -+ -+/* -+ * Setup PCIE Host bridge -+ */ -+static void bcma_pcie2_bridge_init(struct bcma_device *bdev) -+{ -+ u32 devfn = 0; -+ u8 tmp8; -+ u16 tmp16; -+ -+ bcma_pcie2_write_config8(bdev, 0, devfn, PCI_PRIMARY_BUS, 0); -+ bcma_pcie2_write_config8(bdev, 0, devfn, PCI_SECONDARY_BUS, 1); -+ bcma_pcie2_write_config8(bdev, 0, devfn, PCI_SUBORDINATE_BUS, 4); -+ -+ tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_PRIMARY_BUS); -+ tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_SECONDARY_BUS); -+ tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_SUBORDINATE_BUS); -+ -+ /* MEM_BASE, MEM_LIM require 1MB alignment */ -+ BUG_ON((bdev->addr_s[0] >> 16) & 0xf); -+ bcma_pcie2_write_config16(bdev, 0, devfn, PCI_MEMORY_BASE, -+ bdev->addr_s[0] >> 16); -+ BUG_ON(((bdev->addr_s[0] + SZ_128M) >> 16) & 0xf); -+ bcma_pcie2_write_config16(bdev, 0, devfn, PCI_MEMORY_LIMIT, -+ (bdev->addr_s[0] + SZ_128M) >> 16); -+ -+ /* These registers are not supported on the NS */ -+ bcma_pcie2_write_config16(bdev, 0, devfn, PCI_IO_BASE_UPPER16, 0); -+ bcma_pcie2_write_config16(bdev, 0, devfn, PCI_IO_LIMIT_UPPER16, 0); -+ -+ /* Force class to that of a Bridge */ -+ bcma_pcie2_write_config16(bdev, 0, devfn, PCI_CLASS_DEVICE, -+ PCI_CLASS_BRIDGE_PCI); -+ -+ tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_CLASS_DEVICE); -+ tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_MEMORY_BASE); -+ tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_MEMORY_LIMIT); -+} -+ -+static int bcma_pcie2_allow_gen2_rc(struct bcma_device *bdev) -+{ -+ u32 vendorid, devid, chipid, chiprev; -+ u32 val, bar; -+ void __iomem *base; -+ int allow = 1; -+ -+ /* Read PCI vendor/device ID's */ -+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x0); -+ val = bcma_read32(bdev, SOC_PCIE_CFG_DATA); -+ vendorid = val & 0xffff; -+ devid = val >> 16; -+ if (vendorid == PCI_VENDOR_ID_BROADCOM && -+ (devid == BCMA_CHIP_ID_BCM4360 || devid == BCM4360_D11AC_ID || -+ devid == BCM4360_D11AC2G_ID || devid == BCM4360_D11AC5G_ID || -+ devid == BCM4352_D11AC_ID || devid == BCM4352_D11AC2G_ID || -+ devid == BCM4352_D11AC5G_ID)) { -+ /* Config BAR0 */ -+ bar = bdev->addr_s[0]; -+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x10); -+ bcma_write32(bdev, SOC_PCIE_CFG_DATA, bar); -+ /* Config BAR0 window to access chipc */ -+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x80); -+ bcma_write32(bdev, SOC_PCIE_CFG_DATA, SI_ENUM_BASE); -+ -+ /* Enable memory resource */ -+ bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x4); -+ val = bcma_read32(bdev, SOC_PCIE_CFG_DATA); -+ val |= PCI_COMMAND_MEMORY; -+ bcma_write32(bdev, SOC_PCIE_CFG_DATA, val); -+ /* Enable memory and bus master */ -+ bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6); -+ -+ /* Read CHIP ID */ -+ base = ioremap(bar, 0x1000); -+ val = __raw_readl(base); -+ iounmap(base); -+ chipid = val & 0xffff; -+ chiprev = (val >> 16) & 0xf; -+ if ((chipid == BCMA_CHIP_ID_BCM4360 || -+ chipid == BCMA_CHIP_ID_BCM43460 || -+ chipid == BCMA_CHIP_ID_BCM4352) && (chiprev < 3)) -+ allow = 0; -+ } -+ return allow; -+} -+ -+static void bcma_pcie2_3rd_init(struct bcma_bus *bus) -+{ -+ /* PCIE PLL block register (base 0x8000) */ -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x57fe8000); -+ /* Check PCIE PLL lock status */ -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x67c60000); -+} -+ -+/* To improve PCIE phy jitter */ -+static void bcma_pcie2_improve_phy_jitter(struct bcma_bus *bus, int phyaddr) -+{ -+ u32 val; -+ -+ /* Change blkaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x1f << 18) | -+ (2 << 16) | (0x863 << 4); -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+ -+ /* Write 0x0190 to 0x13 regaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x13 << 18) | -+ (2 << 16) | 0x0190; -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+ -+ /* Write 0x0191 to 0x19 regaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x19 << 18) | -+ (2 << 16) | 0x0191; -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+} -+ -+static int bcma_pcie2_setup(int nr, struct pci_sys_data *sys) -+{ -+ struct bcma_device *bdev = sys->private_data; -+ struct bcma_bus *bus = bdev->bus; -+ struct resource *res; -+ struct bcma_device *arm_core; -+ u32 cru_straps_ctrl; -+ int allow_gen2, linkfail; -+ int phyaddr; -+ -+ if (bdev->core_unit == 2) { -+ arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9); -+ cru_straps_ctrl = bcma_read32(arm_core, 0x2a0); -+ -+ /* 3rd PCIE is not selected */ -+ if (cru_straps_ctrl & 0x10) -+ return -ENODEV; -+ -+ bcma_pcie2_3rd_init(bus); -+ phyaddr = 0xf; -+ } else { -+ phyaddr = bdev->core_unit; -+ } -+ bcma_pcie2_improve_phy_jitter(bus, phyaddr); -+ -+ /* create mem resource */ -+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); -+ if (!res) { -+ dev_info(&bdev->dev, "requesting resource at 0x%x failed\n", -+ bdev->addr_s[0]); -+ return -EINVAL; -+ } -+ res->start = bdev->addr_s[0]; -+ res->end = res->start + SZ_128M - 1; -+ res->name = "PCIe Configuration Space"; -+ res->flags = IORESOURCE_MEM; -+ -+ pci_add_resource(&sys->resources, res); -+ -+ /* This PCIe controller does not support IO Mem, so use a dummy one. */ -+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); -+ if (!res) { -+ dev_info(&bdev->dev, "requesting resource at 0x%x failed\n", -+ bdev->addr_s[0]); -+ return -EINVAL; -+ } -+ res->start = bdev->addr_s[0]; -+ res->end = res->start + SZ_128M - 1; -+ res->name = "PCIe Configuration Space"; -+ res->flags = IORESOURCE_IO; -+ -+ pci_add_resource(&sys->resources, res); -+ -+ for (allow_gen2 = 0; allow_gen2 <= 1; allow_gen2++) { -+ bcma_pcie2_hw_init(bdev); -+ bcma_pcie2_map_init(bdev); -+ -+ /* -+ * Skip inactive ports - -+ * will need to change this for hot-plugging -+ */ -+ linkfail = bcma_pcie2_check_link(bdev, allow_gen2); -+ if (linkfail) -+ break; -+ -+ bcma_pcie2_bridge_init(bdev); -+ -+ if (allow_gen2 == 0) { -+ if (bcma_pcie2_allow_gen2_rc(bdev) == 0) -+ break; -+ dev_info(&bdev->dev, "switching to GEN2\n"); -+ } -+ } -+ -+ if (linkfail) -+ return -1; -+ -+ return 1; -+} -+ -+/* -+ * Methods for accessing configuration registers -+ */ -+static struct pci_ops bcma_pcie2_ops = { -+ .read = bcma_pcie2_read_config_pci, -+ .write = bcma_pcie2_write_config_pci, -+}; -+ -+static int bcma_pcie2_probe(struct bcma_device *bdev) -+{ -+ struct hw_pci hw; -+ -+ dev_info(&bdev->dev, "scanning bus\n"); -+ -+ hw = (struct hw_pci) { -+ .nr_controllers = 1, -+ .domain = bdev->core_unit, -+ .private_data = (void **)&bdev, -+ .setup = bcma_pcie2_setup, -+ .map_irq = bcma_pcie2_map_irq, -+ .ops = &bcma_pcie2_ops, -+ }; -+ -+ /* Announce this port to ARM/PCI common code */ -+ pci_common_init_dev(&bdev->dev, &hw); -+ -+ /* Setup virtual-wire interrupts */ -+ bcma_write32(bdev, SOC_PCIE_SYS_RC_INTX_EN, 0xf); -+ -+ /* Enable memory and bus master */ -+ bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6); -+ -+ return 0; -+} -+ -+static const struct bcma_device_id bcma_pcie2_table[] = { -+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS), -+ BCMA_CORETABLE_END -+}; -+MODULE_DEVICE_TABLE(bcma, bcma_pcie2_table); -+ -+static struct bcma_driver bcma_pcie2_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = bcma_pcie2_table, -+ .probe = bcma_pcie2_probe, -+}; -+ -+static int __init bcma_pcie2_init(void) -+{ -+ return bcma_driver_register(&bcma_pcie2_driver); -+} -+module_init(bcma_pcie2_init); -+ -+static void __exit bcma_pcie2_exit(void) -+{ -+ bcma_driver_unregister(&bcma_pcie2_driver); -+} -+module_exit(bcma_pcie2_exit); -+ -+MODULE_AUTHOR("Hauke Mehrtens"); -+MODULE_DESCRIPTION("PCIe Gen2 driver for BCMA"); -+MODULE_LICENSE("GPLv2"); diff --git a/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch b/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch deleted file mode 100644 index f79e729..0000000 --- a/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch +++ /dev/null @@ -1,435 +0,0 @@ -From a59f3fa1dd4cb284171a53cb7a614ad947c544f6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 13 Aug 2014 14:11:39 +0200 -Subject: [PATCH V2] spi: bcm53xx: driver for SPI controller on Broadcom bcma - SoC -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Broadcom 53xx ARM SoCs use bcma bus that contains various cores (AKA -devices). If board has a serial flash, it's connected over SPI and the -bcma bus includes a SPI controller. Example log from such a board: -bus0: Found chip with id 53010, rev 0x00 and package 0x02 -(...) -bus0: Core 18 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0) - -This patch adds a bcma driver for SPI core, it registers SPI master -controller and "bcm53xxspiflash" SPI device. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- -Since RFC: Add Signed-off-by - Update to compile on top of for-next -V2: Use wait timeout - Describe bcm53xxspi_calc_timeout a bit - Use devm_spi_register_master - -Thanks Mark for your comments! ---- - drivers/spi/Kconfig | 6 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-bcm53xx.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++ - drivers/spi/spi-bcm53xx.h | 72 +++++++++++ - 4 files changed, 374 insertions(+) - create mode 100644 drivers/spi/spi-bcm53xx.c - create mode 100644 drivers/spi/spi-bcm53xx.h - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -112,6 +112,12 @@ config SPI_AU1550 - If you say yes to this option, support will be included for the - PSC SPI controller found on Au1550, Au1200 and Au1300 series. - -+config SPI_BCM53XX -+ tristate "Broadcom BCM53xx SPI controller" -+ depends on ARCH_BCM_5301X -+ help -+ Enable support for the SPI controller on Broadcom BCM53xx ARM SoCs. -+ - config SPI_BCM63XX - tristate "Broadcom BCM63xx SPI controller" - depends on BCM63XX ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o - obj-$(CONFIG_SPI_ATH79) += spi-ath79.o - obj-$(CONFIG_SPI_AU1550) += spi-au1550.o - obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o -+obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o - obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o - obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o - obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o ---- /dev/null -+++ b/drivers/spi/spi-bcm53xx.c -@@ -0,0 +1,295 @@ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/bcma/bcma.h> -+#include <linux/spi/spi.h> -+ -+#include "spi-bcm53xx.h" -+ -+#define BCM53XXSPI_MAX_SPI_BAUD 13500000 /* 216 MHz? */ -+ -+/* The longest observed required wait was 19 ms */ -+#define BCM53XXSPI_SPE_TIMEOUT_MS 80 -+ -+struct bcm53xxspi { -+ struct bcma_device *core; -+ struct spi_master *master; -+ -+ size_t read_offset; -+}; -+ -+static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset) -+{ -+ return bcma_read32(b53spi->core, offset); -+} -+ -+static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset, -+ u32 value) -+{ -+ bcma_write32(b53spi->core, offset, value); -+} -+ -+static inline unsigned int bcm53xxspi_calc_timeout(size_t len) -+{ -+ /* Do some magic calculation based on length and buad. Add 10% and 1. */ -+ return (len * 9000 / BCM53XXSPI_MAX_SPI_BAUD * 110 / 100) + 1; -+} -+ -+static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms) -+{ -+ unsigned long deadline; -+ u32 tmp; -+ -+ /* SPE bit has to be 0 before we read MSPI STATUS */ -+ deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000; -+ do { -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ if (!(tmp & B53SPI_MSPI_SPCR2_SPE)) -+ break; -+ udelay(5); -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ if (tmp & B53SPI_MSPI_SPCR2_SPE) -+ goto spi_timeout; -+ -+ /* Check status */ -+ deadline = jiffies + timeout_ms * HZ / 1000; -+ do { -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS); -+ if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) { -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); -+ return 0; -+ } -+ -+ cpu_relax(); -+ udelay(100); -+ } while (!time_after_eq(jiffies, deadline)); -+ -+spi_timeout: -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); -+ -+ pr_err("Timeout waiting for SPI to be ready!\n"); -+ -+ return -EBUSY; -+} -+ -+static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf, -+ size_t len, bool cont) -+{ -+ u32 tmp; -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ /* Transmit Register File MSB */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_TXRAM + 4 * (i * 2), -+ (unsigned int)w_buf[i]); -+ } -+ -+ for (i = 0; i < len; i++) { -+ tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | -+ B53SPI_CDRAM_PCS_DSCK; -+ if (!cont && i == len - 1) -+ tmp &= ~B53SPI_CDRAM_CONT; -+ tmp &= ~0x1; -+ /* Command Register File */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); -+ } -+ -+ /* Set queue pointers */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); -+ -+ if (cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); -+ -+ /* Start SPI transfer */ -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ tmp |= B53SPI_MSPI_SPCR2_SPE; -+ if (cont) -+ tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); -+ -+ /* Wait for SPI to finish */ -+ bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); -+ -+ if (!cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); -+ -+ b53spi->read_offset = len; -+} -+ -+static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, -+ size_t len, bool cont) -+{ -+ u32 tmp; -+ int i; -+ -+ for (i = 0; i < b53spi->read_offset + len; i++) { -+ tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | -+ B53SPI_CDRAM_PCS_DSCK; -+ if (!cont && i == b53spi->read_offset + len - 1) -+ tmp &= ~B53SPI_CDRAM_CONT; -+ tmp &= ~0x1; -+ /* Command Register File */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); -+ } -+ -+ /* Set queue pointers */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, -+ b53spi->read_offset + len - 1); -+ -+ if (cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); -+ -+ /* Start SPI transfer */ -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ tmp |= B53SPI_MSPI_SPCR2_SPE; -+ if (cont) -+ tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); -+ -+ /* Wait for SPI to finish */ -+ bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); -+ -+ if (!cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); -+ -+ for (i = 0; i < len; ++i) { -+ int offset = b53spi->read_offset + i; -+ -+ /* Data stored in the transmit register file LSB */ -+ r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); -+ } -+ -+ b53spi->read_offset = 0; -+} -+ -+static int bcm53xxspi_transfer_one(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *t) -+{ -+ struct bcm53xxspi *b53spi = spi_master_get_devdata(master); -+ u8 *buf; -+ size_t left; -+ -+ if (t->tx_buf) { -+ buf = (u8 *)t->tx_buf; -+ left = t->len; -+ while (left) { -+ size_t to_write = min_t(size_t, 16, left); -+ bool cont = left - to_write > 0; -+ -+ bcm53xxspi_buf_write(b53spi, buf, to_write, cont); -+ left -= to_write; -+ buf += to_write; -+ } -+ } -+ -+ if (t->rx_buf) { -+ buf = (u8 *)t->rx_buf; -+ left = t->len; -+ while (left) { -+ size_t to_read = min_t(size_t, 16 - b53spi->read_offset, -+ left); -+ bool cont = left - to_read > 0; -+ -+ bcm53xxspi_buf_read(b53spi, buf, to_read, cont); -+ left -= to_read; -+ buf += to_read; -+ } -+ } -+ -+ return 0; -+} -+ -+/************************************************** -+ * BCMA -+ **************************************************/ -+ -+struct spi_board_info bcm53xx_info = { -+ .modalias = "bcm53xxspiflash", -+}; -+ -+static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { -+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), -+ BCMA_CORETABLE_END -+}; -+MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); -+ -+static int bcm53xxspi_bcma_probe(struct bcma_device *core) -+{ -+ struct bcm53xxspi *b53spi; -+ struct spi_master *master; -+ int err; -+ -+ if (core->bus->drv_cc.core->id.rev != 42) { -+ pr_err("SPI on SoC with unsupported ChipCommon rev\n"); -+ return -ENOTSUPP; -+ } -+ -+ master = spi_alloc_master(&core->dev, sizeof(*b53spi)); -+ if (!master) -+ return -ENOMEM; -+ -+ b53spi = spi_master_get_devdata(master); -+ b53spi->master = master; -+ b53spi->core = core; -+ -+ master->transfer_one = bcm53xxspi_transfer_one; -+ -+ bcma_set_drvdata(core, b53spi); -+ -+ err = devm_spi_register_master(&core->dev, master); -+ if (err) { -+ spi_master_put(master); -+ bcma_set_drvdata(core, NULL); -+ goto out; -+ } -+ -+ /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */ -+ spi_new_device(master, &bcm53xx_info); -+ -+out: -+ return err; -+} -+ -+static void bcm53xxspi_bcma_remove(struct bcma_device *core) -+{ -+ struct bcm53xxspi *b53spi = bcma_get_drvdata(core); -+ -+ spi_unregister_master(b53spi->master); -+} -+ -+static struct bcma_driver bcm53xxspi_bcma_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = bcm53xxspi_bcma_tbl, -+ .probe = bcm53xxspi_bcma_probe, -+ .remove = bcm53xxspi_bcma_remove, -+}; -+ -+/************************************************** -+ * Init & exit -+ **************************************************/ -+ -+static int __init bcm53xxspi_module_init(void) -+{ -+ int err = 0; -+ -+ err = bcma_driver_register(&bcm53xxspi_bcma_driver); -+ if (err) -+ pr_err("Failed to register bcma driver: %d\n", err); -+ -+ return err; -+} -+ -+static void __exit bcm53xxspi_module_exit(void) -+{ -+ bcma_driver_unregister(&bcm53xxspi_bcma_driver); -+} -+ -+module_init(bcm53xxspi_module_init); -+module_exit(bcm53xxspi_module_exit); ---- /dev/null -+++ b/drivers/spi/spi-bcm53xx.h -@@ -0,0 +1,72 @@ -+#ifndef SPI_BCM53XX_H -+#define SPI_BCM53XX_H -+ -+#define B53SPI_BSPI_REVISION_ID 0x000 -+#define B53SPI_BSPI_SCRATCH 0x004 -+#define B53SPI_BSPI_MAST_N_BOOT_CTRL 0x008 -+#define B53SPI_BSPI_BUSY_STATUS 0x00c -+#define B53SPI_BSPI_INTR_STATUS 0x010 -+#define B53SPI_BSPI_B0_STATUS 0x014 -+#define B53SPI_BSPI_B0_CTRL 0x018 -+#define B53SPI_BSPI_B1_STATUS 0x01c -+#define B53SPI_BSPI_B1_CTRL 0x020 -+#define B53SPI_BSPI_STRAP_OVERRIDE_CTRL 0x024 -+#define B53SPI_BSPI_FLEX_MODE_ENABLE 0x028 -+#define B53SPI_BSPI_BITS_PER_CYCLE 0x02c -+#define B53SPI_BSPI_BITS_PER_PHASE 0x030 -+#define B53SPI_BSPI_CMD_AND_MODE_BYTE 0x034 -+#define B53SPI_BSPI_BSPI_FLASH_UPPER_ADDR_BYTE 0x038 -+#define B53SPI_BSPI_BSPI_XOR_VALUE 0x03c -+#define B53SPI_BSPI_BSPI_XOR_ENABLE 0x040 -+#define B53SPI_BSPI_BSPI_PIO_MODE_ENABLE 0x044 -+#define B53SPI_BSPI_BSPI_PIO_IODIR 0x048 -+#define B53SPI_BSPI_BSPI_PIO_DATA 0x04c -+ -+/* RAF */ -+#define B53SPI_RAF_START_ADDR 0x100 -+#define B53SPI_RAF_NUM_WORDS 0x104 -+#define B53SPI_RAF_CTRL 0x108 -+#define B53SPI_RAF_FULLNESS 0x10c -+#define B53SPI_RAF_WATERMARK 0x110 -+#define B53SPI_RAF_STATUS 0x114 -+#define B53SPI_RAF_READ_DATA 0x118 -+#define B53SPI_RAF_WORD_CNT 0x11c -+#define B53SPI_RAF_CURR_ADDR 0x120 -+ -+/* MSPI */ -+#define B53SPI_MSPI_SPCR0_LSB 0x200 -+#define B53SPI_MSPI_SPCR0_MSB 0x204 -+#define B53SPI_MSPI_SPCR1_LSB 0x208 -+#define B53SPI_MSPI_SPCR1_MSB 0x20c -+#define B53SPI_MSPI_NEWQP 0x210 -+#define B53SPI_MSPI_ENDQP 0x214 -+#define B53SPI_MSPI_SPCR2 0x218 -+#define B53SPI_MSPI_SPCR2_SPE 0x00000040 -+#define B53SPI_MSPI_SPCR2_CONT_AFTER_CMD 0x00000080 -+#define B53SPI_MSPI_MSPI_STATUS 0x220 -+#define B53SPI_MSPI_MSPI_STATUS_SPIF 0x00000001 -+#define B53SPI_MSPI_CPTQP 0x224 -+#define B53SPI_MSPI_TXRAM 0x240 /* 32 registers, up to 0x2b8 */ -+#define B53SPI_MSPI_RXRAM 0x2c0 /* 32 registers, up to 0x33c */ -+#define B53SPI_MSPI_CDRAM 0x340 /* 16 registers, up to 0x37c */ -+#define B53SPI_CDRAM_PCS_PCS0 0x00000001 -+#define B53SPI_CDRAM_PCS_PCS1 0x00000002 -+#define B53SPI_CDRAM_PCS_PCS2 0x00000004 -+#define B53SPI_CDRAM_PCS_PCS3 0x00000008 -+#define B53SPI_CDRAM_PCS_DISABLE_ALL 0x0000000f -+#define B53SPI_CDRAM_PCS_DSCK 0x00000010 -+#define B53SPI_CDRAM_BITSE 0x00000040 -+#define B53SPI_CDRAM_CONT 0x00000080 -+#define B53SPI_MSPI_WRITE_LOCK 0x380 -+#define B53SPI_MSPI_DISABLE_FLUSH_GEN 0x384 -+ -+/* Interrupt */ -+#define B53SPI_INTR_RAF_LR_FULLNESS_REACHED 0x3a0 -+#define B53SPI_INTR_RAF_LR_TRUNCATED 0x3a4 -+#define B53SPI_INTR_RAF_LR_IMPATIENT 0x3a8 -+#define B53SPI_INTR_RAF_LR_SESSION_DONE 0x3ac -+#define B53SPI_INTR_RAF_LR_OVERREAD 0x3b0 -+#define B53SPI_INTR_MSPI_DONE 0x3b4 -+#define B53SPI_INTR_MSPI_HALT_SET_TRANSACTION_DONE 0x3b8 -+ -+#endif /* SPI_BCM53XX_H */ diff --git a/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch b/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch deleted file mode 100644 index caf2f33..0000000 --- a/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0bd576e93a188fd3aab769b622fb3d35fa9bc7a7 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sat, 3 May 2014 19:55:38 +0200 -Subject: [PATCH 15/15] bgmac: some fixes to get bgmac work - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/net/ethernet/broadcom/Kconfig | 2 +- - drivers/net/phy/phy_device.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -131,7 +131,7 @@ config BNX2X_SRIOV - - config BGMAC - tristate "BCMA bus GBit core support" -- depends on BCMA_HOST_SOC && HAS_DMA && BCM47XX -+ depends on BCMA_HOST_SOC && HAS_DMA - select PHYLIB - ---help--- - This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -898,7 +898,7 @@ int genphy_update_link(struct phy_device - return status; - - if ((status & BMSR_LSTATUS) == 0) -- phydev->link = 0; -+ phydev->link = 1; - else - phydev->link = 1; - diff --git a/target/linux/bcm53xx/profiles/100-Generic.mk b/target/linux/bcm53xx/profiles/100-Generic.mk deleted file mode 100644 index ce5a826..0000000 --- a/target/linux/bcm53xx/profiles/100-Generic.mk +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (C) 2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/Generic - NAME:=Broadcom SoC, BCM43xx WiFi (b43, default) - PACKAGES:=kmod-b43 -endef - -define Profile/Generic/Description - Package set compatible with hardware any Broadcom BCM47xx or BCM535x - SoC with a ARM CPU like the BCM4707, BCM4708, BCM4709, BCM53010 -endef - -$(eval $(call Profile,Generic)) - |