mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 15:56:49 +00:00
bcm53xx: initial support for kernel 3.18
This adds initial support for kernel 3.18. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> SVN-Revision: 43097
This commit is contained in:
parent
d8d692342f
commit
7fc9bb1aca
304
target/linux/bcm53xx/config-3.18
Normal file
304
target/linux/bcm53xx/config-3.18
Normal file
@ -0,0 +1,304 @@
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_BCM=y
|
||||
CONFIG_ARCH_BCM_5301X=y
|
||||
# CONFIG_ARCH_BCM_63XX is not set
|
||||
# CONFIG_ARCH_BCM_MOBILE is not set
|
||||
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
|
||||
# CONFIG_ARCH_BRCMSTB is not set
|
||||
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
|
||||
CONFIG_ARCH_HAS_SG_CHAIN=y
|
||||
CONFIG_ARCH_HAS_TICK_BROADCAST=y
|
||||
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
# CONFIG_ARCH_HISI is not set
|
||||
# CONFIG_ARCH_MEDIATEK is not set
|
||||
# CONFIG_ARCH_MESON is not set
|
||||
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
||||
# CONFIG_ARCH_MSM is not set
|
||||
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_QCOM is not set
|
||||
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
|
||||
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
|
||||
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
|
||||
CONFIG_ARCH_SUPPORTS_UPROBES=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_ARCH_WANT_OPTIONAL_GPIOLIB=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_ERRATA_754322=y
|
||||
CONFIG_ARM_ERRATA_764369=y
|
||||
CONFIG_ARM_ERRATA_775420=y
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_GLOBAL_TIMER=y
|
||||
CONFIG_ARM_HAS_SG_CHAIN=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=6
|
||||
CONFIG_ARM_L1_CACHE_SHIFT_6=y
|
||||
# CONFIG_ARM_LPAE is not set
|
||||
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_ATMEL_PIT is not set
|
||||
# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
|
||||
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_BCM47XX_SPROM=y
|
||||
CONFIG_BCMA=y
|
||||
CONFIG_BCMA_BLOCKIO=y
|
||||
CONFIG_BCMA_DEBUG=y
|
||||
CONFIG_BCMA_DRIVER_GMAC_CMN=y
|
||||
CONFIG_BCMA_DRIVER_GPIO=y
|
||||
CONFIG_BCMA_HOST_PCI=y
|
||||
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
|
||||
CONFIG_BCMA_HOST_SOC=y
|
||||
CONFIG_BGMAC=y
|
||||
# CONFIG_BUILD_BIN2C is not set
|
||||
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_COMMON_CLK_PXA is not set
|
||||
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_CRC16=y
|
||||
CONFIG_CRYPTO_DEFLATE=y
|
||||
CONFIG_CRYPTO_LZO=y
|
||||
CONFIG_CRYPTO_XZ=y
|
||||
# CONFIG_CXL_BASE is not set
|
||||
CONFIG_DCACHE_WORD_ACCESS=y
|
||||
CONFIG_DEBUG_BCM_5301X=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_LL=y
|
||||
CONFIG_DEBUG_LL_INCLUDE="debug/8250.S"
|
||||
# CONFIG_DEBUG_LL_UART_8250 is not set
|
||||
# CONFIG_DEBUG_LL_UART_PL01X is not set
|
||||
CONFIG_DEBUG_UART_8250=y
|
||||
# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set
|
||||
CONFIG_DEBUG_UART_8250_SHIFT=0
|
||||
# CONFIG_DEBUG_UART_BCM63XX is not set
|
||||
CONFIG_DEBUG_UART_PHYS=0x18000300
|
||||
# CONFIG_DEBUG_UART_PL01X is not set
|
||||
CONFIG_DEBUG_UART_VIRT=0xf1000300
|
||||
CONFIG_DEBUG_UNCOMPRESS=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
# CONFIG_EM_TIMER_STI is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_GENERIC_ALLOCATOR=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_GPIOLIB=y
|
||||
CONFIG_GPIO_DEVRES=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_HANDLE_DOMAIN_IRQ=y
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT_MAP=y
|
||||
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
|
||||
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
|
||||
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_KERNFS=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_MDIO_BOARDINFO=y
|
||||
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
|
||||
CONFIG_MIGHT_HAVE_PCI=y
|
||||
CONFIG_MODULES_USE_ELF_REL=y
|
||||
# CONFIG_MODULE_COMPRESS is not set
|
||||
CONFIG_MTD_BCM47XX_PARTS=y
|
||||
CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_BCM=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
|
||||
# CONFIG_MTD_PHYSMAP_OF is not set
|
||||
# CONFIG_MTD_SM_COMMON is not set
|
||||
CONFIG_MTD_SPI_BCM53XXSPIFLASH=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_BEB_LIMIT=20
|
||||
CONFIG_MTD_UBI_BLOCK=y
|
||||
# CONFIG_MTD_UBI_FASTMAP is not set
|
||||
# CONFIG_MTD_UBI_GLUEBI is not set
|
||||
CONFIG_MTD_UBI_WL_THRESHOLD=4096
|
||||
CONFIG_MULTI_IRQ_HANDLER=y
|
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NET_FLOW_LIMIT=y
|
||||
# CONFIG_NET_PTP_CLASSIFY is not set
|
||||
# CONFIG_NET_UDP_TUNNEL is not set
|
||||
CONFIG_NO_BOOTMEM=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_ADDRESS_PCI=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
CONFIG_OF_FLATTREE=y
|
||||
CONFIG_OF_GPIO=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_OF_RESERVED_MEM=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_RWSEM_SPIN_ON_OWNER=y
|
||||
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
|
||||
CONFIG_SCHED_HRTICK=y
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
CONFIG_SERIAL_EARLYCON=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
# CONFIG_SH_TIMER_CMT is not set
|
||||
# CONFIG_SH_TIMER_MTU2 is not set
|
||||
# CONFIG_SH_TIMER_TMU is not set
|
||||
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=y
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
# CONFIG_THUMB2_KERNEL is not set
|
||||
CONFIG_TICK_CPU_ACCOUNTING=y
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
|
||||
CONFIG_UBIFS_FS_LZO=y
|
||||
CONFIG_UBIFS_FS_XZ=y
|
||||
CONFIG_UBIFS_FS_ZLIB=y
|
||||
CONFIG_UID16=y
|
||||
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
|
||||
# CONFIG_UPROBES is not set
|
||||
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_ZLIB_DEFLATE=y
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
@ -0,0 +1,33 @@
|
||||
From 310a267714f7565dba8934dd51cdead6adc3b630 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 14 Sep 2014 21:02:35 +0200
|
||||
Subject: [PATCH 4/4] ARM: BCM5301X: fix early serial console
|
||||
|
||||
This device actually has a 8250 serial with a shift of 0.
|
||||
Tested this on a BCM4708.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/arm/Kconfig.debug | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm/Kconfig.debug
|
||||
+++ b/arch/arm/Kconfig.debug
|
||||
@@ -113,7 +113,7 @@ choice
|
||||
config DEBUG_BCM_5301X
|
||||
bool "Kernel low-level debugging on BCM5301X UART1"
|
||||
depends on ARCH_BCM_5301X
|
||||
- select DEBUG_UART_PL01X
|
||||
+ select DEBUG_UART_8250
|
||||
|
||||
config DEBUG_BCM_KONA_UART
|
||||
bool "Kernel low-level debugging messages via BCM KONA UART"
|
||||
@@ -1249,7 +1249,7 @@ config DEBUG_UART_VIRT
|
||||
config DEBUG_UART_8250_SHIFT
|
||||
int "Register offset shift for the 8250 debug UART"
|
||||
depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
|
||||
- default 0 if FOOTBRIDGE || ARCH_IOP32X
|
||||
+ default 0 if FOOTBRIDGE || ARCH_IOP32X || DEBUG_BCM_5301X
|
||||
default 2
|
||||
|
||||
config DEBUG_UART_8250_WORD
|
@ -0,0 +1,29 @@
|
||||
From e7b1065712e769eb4de7b9d4aa222a4531c2b8fd Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Sat, 20 Sep 2014 18:21:19 +0200
|
||||
Subject: [PATCH V2] ARM: BCM5301X: select GPIOLIB as optional
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
All routers (or 99% of them) based on BCM5301X use GPIOs to control LEDs
|
||||
and buttons.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
V2: Don't select GPIOLIB. We may still think about making it default at
|
||||
some point, but we dont' really require it to boot successfully.
|
||||
---
|
||||
arch/arm/mach-bcm/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm/mach-bcm/Kconfig
|
||||
+++ b/arch/arm/mach-bcm/Kconfig
|
||||
@@ -119,6 +119,7 @@ config ARCH_BCM_63XX
|
||||
config ARCH_BRCMSTB
|
||||
bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
|
||||
depends on MMU
|
||||
+ select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select ARM_GIC
|
||||
select MIGHT_HAVE_PCI
|
||||
select HAVE_SMP
|
@ -0,0 +1,43 @@
|
||||
From a2533caee935fff97e3e8dbfad5cc159e6bf6034 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 1 Oct 2014 09:21:07 +0200
|
||||
Subject: [PATCH 1/2] ARM: BCM5301X: Add Broadcom's bus-axi to the DTS file
|
||||
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/boot/dts/bcm5301x.dtsi | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
@@ -8,6 +8,7 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include "skeleton.dtsi"
|
||||
@@ -92,4 +93,19 @@
|
||||
clock-frequency = <400000000>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ axi@18000000 {
|
||||
+ compatible = "brcm,bus-axi";
|
||||
+ reg = <0x18000000 0x1000>;
|
||||
+ ranges = <0x00000000 0x18000000 0x00100000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ chipcommon: chipcommon@0 {
|
||||
+ reg = <0x00000000 0x1000>;
|
||||
+
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
@ -0,0 +1,54 @@
|
||||
From b7e4d148906685882a081e7e50692313c5a8724e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 1 Oct 2014 09:23:09 +0200
|
||||
Subject: [PATCH 2/2] ARM: BCM5301X: Add LEDs for Netgear R6250 V1
|
||||
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/boot/dts/bcm4708-netgear-r6250.dts | 34 +++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
|
||||
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
|
||||
@@ -32,4 +32,38 @@
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ logo {
|
||||
+ label = "bcm53xx:white:logo";
|
||||
+ gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ power0 {
|
||||
+ label = "bcm53xx:green:power";
|
||||
+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+
|
||||
+ power1 {
|
||||
+ label = "bcm53xx:amber:power";
|
||||
+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ usb {
|
||||
+ label = "bcm53xx:blue:usb";
|
||||
+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+
|
||||
+ wireless {
|
||||
+ label = "bcm53xx:blue:wireless";
|
||||
+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+ };
|
||||
};
|
@ -0,0 +1,279 @@
|
||||
From 7063a1583166abe1a9cefed38c2f53a0e14a0005 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 01/17] MIPS: BCM47XX: move the nvram header file into common
|
||||
space
|
||||
|
||||
Moving mach-bcm47xx/bcm47xx_nvram.h to include/linux/bcm47xx_nvram.h
|
||||
makes it possible to reuse this header on the ARM based bcm47xx/bcm53xx
|
||||
SoCs (e.g. BCM5301X devices). Broadcom uses ARM CPUs in their new SoC
|
||||
form the bcm47xx and bcm53xx line, but many other things like nvram
|
||||
stayed the same.
|
||||
|
||||
This is a preparation for adding a new nvram driver, which can be used
|
||||
by the ARM SoC and the MIPS SoC code. The device drivers accessing
|
||||
nvram do not have to care about ARM or MIPS SoC version.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
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 | 66 ++++++++++++++++++++++
|
||||
10 files changed, 74 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>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
--- 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_warn("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,66 @@
|
||||
+/*
|
||||
+ * 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 */
|
@ -0,0 +1,588 @@
|
||||
From 71a6bff8656a1713615ffdd9139a83d65ba46c6d 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 02/17] bcm47xx-nvram: add new broadcom nvram driver with dt
|
||||
support
|
||||
|
||||
This adds a new driver which searches at a given memory range for a
|
||||
nvram like it is used on the bcm47xx and bcm53xx SoCs with ARM and MIPS
|
||||
CPUs. This driver provides acces to this nvram to other device in the
|
||||
device tree. You have to specify the memory ranges where the content of
|
||||
the flash chip is memory 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 addresses, the switch configuration and the calibration data for
|
||||
the wifi devices.
|
||||
|
||||
This was copied from arch/mips/bcm47xx/nvram.c and modified to interact
|
||||
with device tree. My plan is to make the MIPS bcm47xx also use this new
|
||||
driver some time later.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
.../devicetree/bindings/misc/bcm47xx-nvram.txt | 19 ++
|
||||
arch/mips/bcm47xx/board.c | 40 ++--
|
||||
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 | 215 +++++++++++++++++++++
|
||||
drivers/net/ethernet/broadcom/b44.c | 2 +-
|
||||
drivers/net/ethernet/broadcom/bgmac.c | 5 +-
|
||||
drivers/ssb/driver_chipcommon_pmu.c | 3 +-
|
||||
include/linux/bcm47xx_nvram.h | 17 +-
|
||||
13 files changed, 286 insertions(+), 38 deletions(-)
|
||||
create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
|
||||
create mode 100644 drivers/misc/bcm47xx-nvram.c
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/misc/bcm47xx-nvram.txt
|
||||
@@ -0,0 +1,19 @@
|
||||
+Broadcom bcm47xx/bcm53xx nvram access driver
|
||||
+
|
||||
+This driver provides access to the nvram for other drivers.
|
||||
+
|
||||
+Required properties:
|
||||
+
|
||||
+- compatible : brcm,bcm47xx-nvram
|
||||
+
|
||||
+- reg : iomem address range
|
||||
+
|
||||
+On NorthStar ARM SoCs the NAND flash is available at 0x1c000000 and the
|
||||
+NOR flash is at 0x1e000000
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+nvram0: nvram@0 {
|
||||
+ compatible = "brcm,bcm47xx-nvram";
|
||||
+ reg = <0x1c000000 0x01000000>;
|
||||
+};
|
||||
--- a/arch/mips/bcm47xx/board.c
|
||||
+++ b/arch/mips/bcm47xx/board.c
|
||||
@@ -218,36 +218,36 @@ 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("hardware_version", buf1, sizeof(buf1)) >= 0 &&
|
||||
- bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
|
||||
+ if (bcm47xx_nvram_getenv(NULL, "hardware_version", buf1, sizeof(buf1)) >= 0 &&
|
||||
+ bcm47xx_nvram_getenv(NULL, "boardtype", buf2, sizeof(buf2)) >= 0) {
|
||||
for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
|
||||
if (!strstarts(buf1, e2->value1) &&
|
||||
!strcmp(buf2, e2->value2))
|
||||
@@ -255,22 +255,22 @@ static __init const struct bcm47xx_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))
|
||||
@@ -278,8 +278,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))
|
||||
@@ -287,16 +287,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) &&
|
||||
@@ -305,9 +305,9 @@ static __init const struct bcm47xx_board
|
||||
}
|
||||
}
|
||||
|
||||
- if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
|
||||
- bcm47xx_nvram_getenv("boardrev", buf2, sizeof(buf2)) >= 0 &&
|
||||
- bcm47xx_nvram_getenv("boardnum", buf3, sizeof(buf3)) == -ENOENT) {
|
||||
+ if (bcm47xx_nvram_getenv(NULL, "boardtype", buf1, sizeof(buf1)) >= 0 &&
|
||||
+ bcm47xx_nvram_getenv(NULL, "boardrev", buf2, sizeof(buf2)) >= 0 &&
|
||||
+ bcm47xx_nvram_getenv(NULL, "boardnum", buf3, sizeof(buf3)) == -ENOENT) {
|
||||
for (e2 = bcm47xx_board_list_board_type_rev; e2->value1; e2++) {
|
||||
if (!strcmp(buf1, e2->value1) &&
|
||||
!strcmp(buf2, e2->value2))
|
||||
@@ -327,7 +327,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
|
||||
@@ -132,7 +132,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;
|
||||
@@ -155,7 +155,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
|
||||
@@ -52,10 +52,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 VEXPRESS_SYSCFG
|
||||
bus. System Configuration interface is one of the possible means
|
||||
of generating transactions on this bus.
|
||||
|
||||
+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
|
||||
@@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/
|
||||
obj-$(CONFIG_ECHO) += echo/
|
||||
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
|
||||
obj-$(CONFIG_CXL_BASE) += cxl/
|
||||
+obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/misc/bcm47xx-nvram.c
|
||||
@@ -0,0 +1,215 @@
|
||||
+/*
|
||||
+ * 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 __iomem *header;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
|
||||
+ header = (struct nvram_header __iomem *)(end - nvram_sizes[i]);
|
||||
+ if (__raw_readl(&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 __iomem *header;
|
||||
+ int i;
|
||||
+ u32 off;
|
||||
+ u32 *dst;
|
||||
+ __le32 __iomem *src;
|
||||
+ 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 __iomem *)
|
||||
+ (base + off - size);
|
||||
+ goto found;
|
||||
+ }
|
||||
+ off += 0x10000;
|
||||
+ }
|
||||
+
|
||||
+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
|
||||
+ header = (struct nvram_header __iomem *)(base + 4096);
|
||||
+ if (__raw_readl(&header->magic) == NVRAM_HEADER) {
|
||||
+ size = NVRAM_SPACE;
|
||||
+ goto found;
|
||||
+ }
|
||||
+
|
||||
+ header = (struct nvram_header __iomem *)(base + 1024);
|
||||
+ if (__raw_readl(&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 (readl(&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, readl(&header->len), size);
|
||||
+
|
||||
+ *nvram_buf = devm_kzalloc(dev, *nvram_len, GFP_KERNEL);
|
||||
+ if (!*nvram_buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ src = (__le32 __iomem *) header;
|
||||
+ dst = (u32 *) *nvram_buf;
|
||||
+ for (i = 0; i < sizeof(struct nvram_header); i += 4)
|
||||
+ *dst++ = __raw_readl(src++);
|
||||
+ for (; i < *nvram_len; i += 4)
|
||||
+ *dst++ = readl(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,8 @@ 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 +1535,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,8 @@ 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,9 +15,11 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
+struct device;
|
||||
+
|
||||
struct nvram_header {
|
||||
u32 magic;
|
||||
- u32 len;
|
||||
+ __le32 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 */
|
||||
@@ -33,18 +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,
|
||||
+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;
|
||||
}
|
@ -0,0 +1,762 @@
|
||||
From 4e0ab3269a6d260a41a3673157753147f5f71341 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 03/17] bcm47xx-sprom: add Broadcom sprom parser driver
|
||||
|
||||
This driver needs an nvram driver and fetches the sprom values from the
|
||||
nvram 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.
|
||||
|
||||
This is based on a copy of arch/mips/bcm47xx/sprom.c and my plan is to
|
||||
make the bcm47xx MIPS SoCs also use this driver some time later.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
.../devicetree/bindings/misc/bcm47xx-sprom.txt | 16 +
|
||||
drivers/misc/Kconfig | 11 +
|
||||
drivers/misc/Makefile | 1 +
|
||||
drivers/misc/bcm47xx-sprom.c | 690 +++++++++++++++++++++
|
||||
4 files changed, 718 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
|
||||
create mode 100644 drivers/misc/bcm47xx-sprom.c
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
|
||||
@@ -0,0 +1,16 @@
|
||||
+Broadcom bcm47xx/bcm53xx sprom converter
|
||||
+
|
||||
+This driver provbides an sprom based on a given nvram.
|
||||
+
|
||||
+Required properties:
|
||||
+
|
||||
+- compatible : brcm,bcm47xx-sprom
|
||||
+
|
||||
+- nvram : reference to a nvram driver, e.g. bcm47xx-nvram
|
||||
+
|
||||
+Example:
|
||||
+
|
||||
+sprom0: sprom@0 {
|
||||
+ compatible = "brcm,bcm47xx-sprom";
|
||||
+ nvram = <&nvram0>;
|
||||
+};
|
||||
--- a/drivers/misc/Kconfig
|
||||
+++ b/drivers/misc/Kconfig
|
||||
@@ -520,6 +520,17 @@ config BCM47XX_NVRAM
|
||||
help
|
||||
This adds support for the brcm47xx nvram driver.
|
||||
|
||||
+config BCM47XX_SPROM
|
||||
+ tristate "BCM47XX sprom driver"
|
||||
+ help
|
||||
+ This driver parses the sprom from a given nvram which is found on
|
||||
+ Broadcom bcm47xx and bcm53xx SoCs.
|
||||
+
|
||||
+ The sprom contains board configuration data like the
|
||||
+ calibration data fro the wifi chips, the mac addresses used
|
||||
+ by the board and many other board configuration data. This
|
||||
+ driver will provide the sprom to bcma.
|
||||
+
|
||||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
--- a/drivers/misc/Makefile
|
||||
+++ b/drivers/misc/Makefile
|
||||
@@ -57,3 +57,4 @@ obj-$(CONFIG_ECHO) += echo/
|
||||
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
|
||||
obj-$(CONFIG_CXL_BASE) += cxl/
|
||||
obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx-nvram.o
|
||||
+obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx-sprom.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/misc/bcm47xx-sprom.c
|
||||
@@ -0,0 +1,690 @@
|
||||
+/*
|
||||
+ * BCM47xx/BCM53xx 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>
|
||||
+#include <linux/if_ether.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+
|
||||
+struct bcm47xx_sprom_fill {
|
||||
+ const char *prefix;
|
||||
+ bool fallback;
|
||||
+ int (*getenv)(const struct bcm47xx_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 bcm47xx_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 bcm47xx_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 bcm47xx_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 bcm47xx_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 bcm47xx_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 bcm47xx_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 bcm47xx_sprom_fill_r1234589(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_sprom_fill *fill)
|
||||
+{
|
||||
+ nvram_read_u16(fill, NULL, "devid", &sprom->dev_id, 0);
|
||||
+ 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 bcm47xx_sprom_fill_r12389(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r1(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r2389(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r389(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r3(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r4589(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r458(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r45(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r89(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_r9(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_path_r4589(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill_path_r45(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bool bcm47xx_is_valid_mac(u8 *mac)
|
||||
+{
|
||||
+ return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
|
||||
+}
|
||||
+
|
||||
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
|
||||
+{
|
||||
+ u8 *oui = mac + ETH_ALEN/2 - 1;
|
||||
+ u8 *p = mac + ETH_ALEN - 1;
|
||||
+
|
||||
+ do {
|
||||
+ (*p) += num;
|
||||
+ if (*p > num)
|
||||
+ break;
|
||||
+ p--;
|
||||
+ num = 1;
|
||||
+ } while (p != oui);
|
||||
+
|
||||
+ if (p == oui) {
|
||||
+ pr_err("unable to fetch mac address\n");
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * This is a global counter because different instances of sprom will
|
||||
+ * access the same nvram.
|
||||
+ */
|
||||
+static int mac_addr_used = 2;
|
||||
+
|
||||
+static void bcm47xx_sprom_fill_ethernet(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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);
|
||||
+
|
||||
+ /*
|
||||
+ * The address prefix 00:90:4C is used by Broadcom in their initial
|
||||
+ * configuration. When a mac address with the prefix 00:90:4C is used
|
||||
+ * all devices from the same series are sharing the same mac address.
|
||||
+ * To prevent mac address collisions we replace them with a mac address
|
||||
+ * based on the base address.
|
||||
+ */
|
||||
+ if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
|
||||
+ u8 mac[6];
|
||||
+ struct bcm47xx_sprom_fill fill_no_prefix;
|
||||
+
|
||||
+ memcpy(&fill_no_prefix, fill, sizeof(fill_no_prefix));
|
||||
+ fill_no_prefix.prefix = NULL;
|
||||
+
|
||||
+ nvram_read_macaddr(&fill_no_prefix, "et0macaddr", mac);
|
||||
+ if (bcm47xx_is_valid_mac(mac)) {
|
||||
+ int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
|
||||
+
|
||||
+ if (!err) {
|
||||
+ ether_addr_copy(sprom->il0mac, mac);
|
||||
+ mac_addr_used++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void bcm47xx_sprom_fill_board_data(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_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 bcm47xx_sprom_fill(struct ssb_sprom *sprom,
|
||||
+ const struct bcm47xx_sprom_fill *fill)
|
||||
+{
|
||||
+ bcm47xx_sprom_fill_ethernet(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_board_data(sprom, fill);
|
||||
+
|
||||
+ nvram_read_u8(fill, NULL, "sromrev", &sprom->revision, 0);
|
||||
+
|
||||
+ switch (sprom->revision) {
|
||||
+ case 1:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r1(sprom, fill);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r2389(sprom, fill);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r2389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r3(sprom, fill);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ case 5:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r4589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r458(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r45(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_path_r4589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_path_r45(sprom, fill);
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r2389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r4589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r458(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r89(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_path_r4589(sprom, fill);
|
||||
+ break;
|
||||
+ case 9:
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r2389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r4589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r89(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r9(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_path_r4589(sprom, fill);
|
||||
+ break;
|
||||
+ default:
|
||||
+ pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
|
||||
+ sprom->revision);
|
||||
+ sprom->revision = 1;
|
||||
+ bcm47xx_sprom_fill_r1234589(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r12389(sprom, fill);
|
||||
+ bcm47xx_sprom_fill_r1(sprom, fill);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int bcm47xx_sprom_getenv(const struct bcm47xx_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 bcm47xx_sprom_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct device_node *np = dev->of_node;
|
||||
+ struct ssb_sprom *sprom;
|
||||
+ const __be32 *handle;
|
||||
+ struct device_node *nvram_node;
|
||||
+ struct platform_device *nvram_dev;
|
||||
+ struct bcm47xx_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 = of_get_property(np, "prefix", NULL);
|
||||
+
|
||||
+ fill.fallback = false;
|
||||
+ fill.getenv = bcm47xx_sprom_getenv;
|
||||
+ fill.priv = nvram_dev;
|
||||
+
|
||||
+ bcm47xx_sprom_fill(sprom, &fill);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, sprom);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id bcm47xx_sprom_of_match_table[] = {
|
||||
+ { .compatible = "brcm,bcm47xx-sprom", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
|
||||
+
|
||||
+static struct platform_driver bcm47xx_sprom_driver = {
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "bcm47xx-sprom",
|
||||
+ .of_match_table = bcm47xx_sprom_of_match_table,
|
||||
+ /* driver unloading/unbinding currently not supported */
|
||||
+ .suppress_bind_attrs = true,
|
||||
+ },
|
||||
+ .probe = bcm47xx_sprom_probe,
|
||||
+};
|
||||
+module_platform_driver(bcm47xx_sprom_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
|
||||
+MODULE_LICENSE("GPL v2");
|
@ -0,0 +1,38 @@
|
||||
From 6611afa6c49434780096cdf2c1028f0ac277f9bc 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 v3 2/2] bcma: get IRQ numbers from dt
|
||||
|
||||
It is not possible to auto detect the irq numbers used by the cores on
|
||||
an arm SoC. If bcma was registered with device tree it will search for
|
||||
some device tree nodes with the irq number and add it to the core
|
||||
configuration.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 48 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#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");
|
||||
@@ -159,8 +160,10 @@ static void bcma_of_fill_device(struct p
|
||||
struct device_node *node;
|
||||
|
||||
node = bcma_of_find_child_device(parent, core);
|
||||
- if (node)
|
||||
- core->dev.of_node = node;
|
||||
+ if (!node)
|
||||
+ return;
|
||||
+ core->dev.of_node = node;
|
||||
+ core->irq = irq_of_parse_and_map(node, 0);
|
||||
}
|
||||
#else
|
||||
static void bcma_of_fill_device(struct platform_device *parent,
|
@ -0,0 +1,65 @@
|
||||
From 487b997353e2e3afe9c452b20ff5e4320d76e9c3 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 2 Oct 2014 12:28:54 +0200
|
||||
Subject: [PATCH][RFC] bcma: fill core details for every device
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We were setting things like dma_dev, IRQ, etc. during core registration
|
||||
only. We need such info for cores handled internally (e.g. ChipCommon)
|
||||
as well.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 1 +
|
||||
drivers/bcma/main.c | 9 ++++++---
|
||||
drivers/bcma/scan.c | 1 +
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -24,6 +24,7 @@ struct bcma_bus;
|
||||
/* main.c */
|
||||
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
||||
int timeout);
|
||||
+void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
|
||||
int bcma_bus_register(struct bcma_bus *bus);
|
||||
void bcma_bus_unregister(struct bcma_bus *bus);
|
||||
int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -172,10 +172,8 @@ static void bcma_of_fill_device(struct p
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
-static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
+void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
{
|
||||
- int err;
|
||||
-
|
||||
core->dev.release = bcma_release_core_dev;
|
||||
core->dev.bus = &bcma_bus_type;
|
||||
dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
|
||||
@@ -199,6 +197,11 @@ static void bcma_register_core(struct bc
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
break;
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
+{
|
||||
+ int err;
|
||||
|
||||
err = device_register(&core->dev);
|
||||
if (err) {
|
||||
--- a/drivers/bcma/scan.c
|
||||
+++ b/drivers/bcma/scan.c
|
||||
@@ -505,6 +505,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
bus->nr_cores++;
|
||||
other_core = bcma_find_core_reverse(bus, core->id.id);
|
||||
core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
|
||||
+ bcma_prepare_core(bus, core);
|
||||
|
||||
bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
|
||||
core->core_index, bcma_device_name(&core->id),
|
@ -0,0 +1,88 @@
|
||||
From bd9106f5907080b467026bdaaea979fac8c7badb 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 06/17] 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 __be32 *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;
|
@ -0,0 +1,114 @@
|
||||
From 414f0ad9b3a8e8ee6eaf09c6d79d5f448ac28630 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 07/17] ARM: BCM5301X: register bcma bus
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 58 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
@@ -94,18 +94,102 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ nvram0: nvram@1c000000 {
|
||||
+ compatible = "brcm,bcm47xx-nvram";
|
||||
+ reg = <0x1c000000 0x01000000>;
|
||||
+ };
|
||||
+
|
||||
+ sprom0: sprom@0 {
|
||||
+ compatible = "brcm,bcm47xx-sprom";
|
||||
+ nvram = <&nvram0>;
|
||||
+ };
|
||||
+
|
||||
axi@18000000 {
|
||||
compatible = "brcm,bus-axi";
|
||||
reg = <0x18000000 0x1000>;
|
||||
ranges = <0x00000000 0x18000000 0x00100000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
+ sprom = <&sprom0>;
|
||||
|
||||
chipcommon: chipcommon@0 {
|
||||
reg = <0x00000000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
+
|
||||
+ pcie@12000 {
|
||||
+ reg = <0x00012000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ pcie@13000 {
|
||||
+ reg = <0x00013000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ pcie@14000 {
|
||||
+ reg = <0x00014000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ usb2@21000 {
|
||||
+ reg = <0x00021000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ usb3@23000 {
|
||||
+ reg = <0x00023000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ ethernet@24000 {
|
||||
+ reg = <0x00024000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ ethernet@25000 {
|
||||
+ reg = <0x00025000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ ethernet@26000 {
|
||||
+ reg = <0x00026000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ ethernet@27000 {
|
||||
+ reg = <0x00027000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
+
|
||||
+ nand@28000 {
|
||||
+ reg = <0x00028000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ };
|
||||
};
|
||||
};
|
@ -0,0 +1,69 @@
|
||||
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-axi");
|
||||
+ 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)
|
||||
{
|
||||
@@ -43,6 +60,19 @@ static void __init bcm5301x_init_early(v
|
||||
"imprecise external abort");
|
||||
}
|
||||
|
||||
+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,
|
||||
@@ -52,5 +82,6 @@ DT_MACHINE_START(BCM5301X, "BCM5301X")
|
||||
.l2c_aux_val = 0,
|
||||
.l2c_aux_mask = ~0,
|
||||
.init_early = bcm5301x_init_early,
|
||||
+ .restart = bcm5301x_restart,
|
||||
.dt_compat = bcm5301x_dt_compat,
|
||||
MACHINE_END
|
@ -0,0 +1,29 @@
|
||||
From cf72936c001056de1cfcb27dd9a232f5484ec59c 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 12/17] 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
|
||||
@@ -2093,7 +2093,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);
|
@ -0,0 +1,670 @@
|
||||
From cc2cda651fcbc498bf513a6b802dca19944bcb37 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 13/17] 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 | 2 +
|
||||
drivers/pci/host/Kconfig | 7 +
|
||||
drivers/pci/host/Makefile | 1 +
|
||||
drivers/pci/host/pcie2-bcma.c | 591 ++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 601 insertions(+)
|
||||
create mode 100644 drivers/pci/host/pcie2-bcma.c
|
||||
|
||||
--- a/arch/arm/mach-bcm/Kconfig
|
||||
+++ b/arch/arm/mach-bcm/Kconfig
|
||||
@@ -86,6 +86,7 @@ config ARCH_BCM_5301X
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select ARM_GLOBAL_TIMER
|
||||
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
|
||||
+ 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
|
||||
@@ -91,4 +91,11 @@ config PCI_XGENE
|
||||
There are 5 internal PCIe ports available. Each port is GEN3 capable
|
||||
and have varied lanes from x1 to x8.
|
||||
|
||||
+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
|
||||
@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spe
|
||||
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
|
||||
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
|
||||
obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
|
||||
+obj-$(CONFIG_PCI_BCMA) += pcie2-bcma.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pci/host/pcie2-bcma.c
|
||||
@@ -0,0 +1,619 @@
|
||||
+/*
|
||||
+ * 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 struct pci_ops bcma_pcie2_ops;
|
||||
+
|
||||
+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;
|
||||
+ }
|
||||
+ 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;
|
||||
+ u32 mask;
|
||||
+ int shift;
|
||||
+
|
||||
+ 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;
|
||||
+
|
||||
+ mask = (1 << (size * 8)) - 1;
|
||||
+ 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,
|
||||
+ struct pci_sys_data *sys, u32 allow_gen2)
|
||||
+{
|
||||
+ u32 devfn = 0;
|
||||
+ u32 tmp32;
|
||||
+ u16 tmp16;
|
||||
+ u8 tmp8;
|
||||
+ int pos;
|
||||
+ bool link = false;
|
||||
+ /*
|
||||
+ * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before
|
||||
+ * creating bus root, so we don't have it here yet. On the other hand
|
||||
+ * we really want to use pci_bus_find_capability helper to check NLW.
|
||||
+ * Let's fake simple pci_bus just to query for capabilities.
|
||||
+ */
|
||||
+ struct pci_bus bus = {
|
||||
+ .number = 0,
|
||||
+ .ops = &bcma_pcie2_ops,
|
||||
+ .sysdata = sys,
|
||||
+ };
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ /* NS PAX only changes NLW field when card is present */
|
||||
+ pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
|
||||
+ if (pos) {
|
||||
+ u8 nlw;
|
||||
+
|
||||
+ pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_LNKSTA,
|
||||
+ &tmp16);
|
||||
+ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
|
||||
+ link = (tmp16 & PCI_EXP_LNKSTA_DLLLA) || nlw != 0;
|
||||
+ }
|
||||
+
|
||||
+ return link ? 0 : -ENODEV;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * 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)
|
||||
+ 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)
|
||||
+ 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, sys, 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");
|
@ -0,0 +1,195 @@
|
||||
From 26023cdfacaf116545b1087b9d1fe50dc6fbda10 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 24 Sep 2014 22:14:07 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache for decompression
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Without this fix kernel was randomly hanging in ~25% of tries during
|
||||
early init. Hangs used to happen at random places in the start_kernel.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
arch/arm/boot/compressed/Makefile | 5 +
|
||||
arch/arm/boot/compressed/head-bcm_5301x-mpcore.S | 37 +++++++
|
||||
arch/arm/boot/compressed/mpcore_cache.S | 118 +++++++++++++++++++++++
|
||||
3 files changed, 160 insertions(+)
|
||||
create mode 100644 arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
|
||||
create mode 100644 arch/arm/boot/compressed/mpcore_cache.S
|
||||
|
||||
--- a/arch/arm/boot/compressed/Makefile
|
||||
+++ b/arch/arm/boot/compressed/Makefile
|
||||
@@ -46,6 +46,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
|
||||
OBJS += ll_char_wr.o font.o
|
||||
endif
|
||||
|
||||
+ifeq ($(CONFIG_ARCH_BCM_5301X),y)
|
||||
+OBJS += head-bcm_5301x-mpcore.o
|
||||
+OBJS += mpcore_cache.o
|
||||
+endif
|
||||
+
|
||||
ifeq ($(CONFIG_ARCH_SA1100),y)
|
||||
OBJS += head-sa1100.o
|
||||
endif
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
|
||||
@@ -0,0 +1,37 @@
|
||||
+/*
|
||||
+ *
|
||||
+ * Platform specific tweaks. This is merged into head.S by the linker.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/linkage.h>
|
||||
+#include <asm/assembler.h>
|
||||
+#include <asm/cp15.h>
|
||||
+
|
||||
+ .section ".start", "ax"
|
||||
+
|
||||
+/*
|
||||
+ * This code section is spliced into the head code by the linker
|
||||
+ */
|
||||
+
|
||||
+__plat_uncompress_start:
|
||||
+
|
||||
+ @ Preserve r8/r7 i.e. kernel entry values
|
||||
+ mov r12, r8
|
||||
+
|
||||
+ @ Clear MMU enable and Dcache enable bits
|
||||
+ mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR
|
||||
+ bic r0, #CR_C|CR_M
|
||||
+ mcr p15, 0, r0, c1, c0, 0 @ Write SCTLR
|
||||
+ nop
|
||||
+
|
||||
+ @ Call the cache invalidation routine
|
||||
+ bl v7_all_dcache_invalidate
|
||||
+ nop
|
||||
+ mov r0,#0
|
||||
+ ldr r3, =0x19022000 @ L2 cache controller, control reg
|
||||
+ str r0, [r3, #0x100] @ Disable L2 cache
|
||||
+ nop
|
||||
+
|
||||
+ @ Restore
|
||||
+ mov r8, r12
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/compressed/mpcore_cache.S
|
||||
@@ -0,0 +1,118 @@
|
||||
+/*****************************************************************************
|
||||
+* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.
|
||||
+*
|
||||
+* Unless you and Broadcom execute a separate written software license
|
||||
+* agreement governing use of this software, this software is licensed to you
|
||||
+* under the terms of the GNU General Public License version 2, available at
|
||||
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
+*
|
||||
+* Notwithstanding the above, under no circumstances may you combine this
|
||||
+* software in any way with any other Broadcom software provided under a
|
||||
+* license other than the GPL, without Broadcom's express prior written
|
||||
+* consent.
|
||||
+*****************************************************************************/
|
||||
+
|
||||
+#include <linux/linkage.h>
|
||||
+#include <linux/init.h>
|
||||
+
|
||||
+ __INIT
|
||||
+
|
||||
+/*
|
||||
+ * v7_l1_cache_invalidate
|
||||
+ *
|
||||
+ * Invalidate contents of L1 cache without flushing its contents
|
||||
+ * into outer cache and memory. This is needed when the contents
|
||||
+ * of the cache are unpredictable after power-up.
|
||||
+ *
|
||||
+ * corrupts r0-r6
|
||||
+ */
|
||||
+
|
||||
+ENTRY(v7_l1_cache_invalidate)
|
||||
+ mov r0, #0
|
||||
+ mcr p15, 2, r0, c0, c0, 0 @ set cache level to 1
|
||||
+ mrc p15, 1, r0, c0, c0, 0 @ read CLIDR
|
||||
+
|
||||
+ ldr r1, =0x7fff
|
||||
+ and r2, r1, r0, lsr #13 @ get max # of index size
|
||||
+
|
||||
+ ldr r1, =0x3ff
|
||||
+ and r3, r1, r0, lsr #3 @ NumWays - 1
|
||||
+ add r2, r2, #1 @ NumSets
|
||||
+
|
||||
+ and r0, r0, #0x7
|
||||
+ add r0, r0, #4 @ SetShift
|
||||
+
|
||||
+ clz r1, r3 @ WayShift
|
||||
+ add r4, r3, #1 @ NumWays
|
||||
+1: sub r2, r2, #1 @ NumSets--
|
||||
+ mov r3, r4 @ Temp = NumWays
|
||||
+2: subs r3, r3, #1 @ Temp--
|
||||
+ mov r5, r3, lsl r1
|
||||
+ mov r6, r2, lsl r0
|
||||
+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
|
||||
+ mcr p15, 0, r5, c7, c6, 2 @ Invalidate line
|
||||
+ bgt 2b
|
||||
+ cmp r2, #0
|
||||
+ bgt 1b
|
||||
+ dsb
|
||||
+ mov r0,#0
|
||||
+ mcr p15,0,r0,c7,c5,0 /* Invalidate icache */
|
||||
+ isb
|
||||
+ mov pc, lr
|
||||
+ENDPROC(v7_l1_cache_invalidate)
|
||||
+
|
||||
+/*
|
||||
+ * v7_all_dcache_invalidate
|
||||
+ *
|
||||
+ * Invalidate without flushing the contents of all cache levels
|
||||
+ * accesible by the current processor core.
|
||||
+ * This is useful when the contents of cache memory are undetermined
|
||||
+ * at power-up.
|
||||
+ * Corrupted registers: r0-r7, r9-r11
|
||||
+ *
|
||||
+ * Based on cache-v7.S: v7_flush_dcache_all()
|
||||
+ */
|
||||
+
|
||||
+ENTRY(v7_all_dcache_invalidate)
|
||||
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
|
||||
+ ands r3, r0, #0x7000000 @ extract loc from clidr
|
||||
+ mov r3, r3, lsr #23 @ left align loc bit field
|
||||
+ beq finished @ if loc is 0, then no need to clean
|
||||
+ mov r10, #0 @ start clean at cache level 0
|
||||
+loop1:
|
||||
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
|
||||
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
|
||||
+ and r1, r1, #7 @ mask of bits for current cache only
|
||||
+ cmp r1, #2 @ see what cache we have at this level
|
||||
+ blt skip @ skip if no cache, or just i-cache
|
||||
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
||||
+ isb @ isb to sych the new cssr&csidr
|
||||
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
|
||||
+ and r2, r1, #7 @ extract the length of the cache lines
|
||||
+ add r2, r2, #4 @ add 4 (line length offset)
|
||||
+ ldr r4, =0x3ff
|
||||
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
|
||||
+ clz r5, r4 @ find bit pos of way size increment
|
||||
+ ldr r7, =0x7fff
|
||||
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
|
||||
+loop2:
|
||||
+ mov r9, r4 @ create working copy of max way size
|
||||
+loop3:
|
||||
+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
|
||||
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
|
||||
+ mcr p15, 0, r11, c7, c6, 2 @ Invalidate line
|
||||
+ subs r9, r9, #1 @ decrement the way
|
||||
+ bge loop3
|
||||
+ subs r7, r7, #1 @ decrement the index
|
||||
+ bge loop2
|
||||
+skip:
|
||||
+ add r10, r10, #2 @ increment cache number
|
||||
+ cmp r3, r10
|
||||
+ bgt loop1
|
||||
+finished:
|
||||
+ mov r10, #0 @ swith back to cache level 0
|
||||
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
||||
+ dsb
|
||||
+ isb
|
||||
+ mov pc, lr
|
||||
+ENDPROC(v7_all_dcache_invalidate)
|
@ -0,0 +1,59 @@
|
||||
From e1b44fc2e3cf76be1213bde07fc37c47eff39158 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 2 Oct 2014 13:49:13 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Add buttons support for Netgear R6250
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We use "gpio-keys-polled" for now, as ChipCommon/GPIO interrupts are
|
||||
not implemented yet.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 25 +++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/bcm5301x.dtsi | 1 +
|
||||
2 files changed, 26 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
|
||||
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
|
||||
@@ -66,4 +66,29 @@
|
||||
linux,default-trigger = "default-off";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <200>;
|
||||
+
|
||||
+ wps {
|
||||
+ label = "WPS";
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ rfkill {
|
||||
+ label = "WiFi";
|
||||
+ linux,code = <KEY_RFKILL>;
|
||||
+ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ restart {
|
||||
+ label = "Reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
+#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include "skeleton.dtsi"
|
@ -0,0 +1,125 @@
|
||||
From 788069f86c7fc1ce54661651e695943fb47a5188 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 2 Oct 2014 21:02:33 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Add DT for Netgear R6300 V2
|
||||
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/boot/dts/Makefile | 4 ++-
|
||||
arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 35 ++++++++++++++++++++++++++
|
||||
2 files changed, 38 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -54,7 +54,9 @@ dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4e
|
||||
dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
|
||||
dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
|
||||
-dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
|
||||
+dtb-$(CONFIG_ARCH_BCM_5301X) += \
|
||||
+ bcm4708-netgear-r6250.dtb \
|
||||
+ bcm4708-netgear-r6300-v2.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
|
||||
bcm21664-garnet.dtb
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
|
||||
@@ -0,0 +1,94 @@
|
||||
+/*
|
||||
+ * Broadcom BCM470X / BCM5301X arm platform code.
|
||||
+ * DTS for Netgear R6300 V2
|
||||
+ *
|
||||
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "bcm4708.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "netgear,r6300v2", "brcm,bcm4708";
|
||||
+ model = "Netgear R6300 V2 (BCM4708)";
|
||||
+
|
||||
+ chosen {
|
||||
+ bootargs = "console=ttyS0,115200";
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x00000000 0x08000000>;
|
||||
+ };
|
||||
+
|
||||
+ chipcommonA {
|
||||
+ uart0: serial@0300 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ uart1: serial@0400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ logo {
|
||||
+ label = "bcm53xx:white:logo";
|
||||
+ gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ power0 {
|
||||
+ label = "bcm53xx:green:power";
|
||||
+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+
|
||||
+ power1 {
|
||||
+ label = "bcm53xx:amber:power";
|
||||
+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ usb {
|
||||
+ label = "bcm53xx:blue:usb";
|
||||
+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+
|
||||
+ wireless {
|
||||
+ label = "bcm53xx:blue:wireless";
|
||||
+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <200>;
|
||||
+
|
||||
+ wps {
|
||||
+ label = "WPS";
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ rfkill {
|
||||
+ label = "WiFi";
|
||||
+ linux,code = <KEY_RFKILL>;
|
||||
+ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ restart {
|
||||
+ label = "Reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
@ -0,0 +1,102 @@
|
||||
From b7620da56595c5505e4a10b8779cec0362b59db2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 9 Oct 2014 18:04:28 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WZR-1750DHP
|
||||
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/boot/dts/Makefile | 1 +
|
||||
arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 74 +++++++++++++++++++++++
|
||||
2 files changed, 75 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -55,6 +55,7 @@ dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.
|
||||
dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_5301X) += \
|
||||
+ bcm4708-buffalo-wzr-1750dhp.dtb \
|
||||
bcm4708-netgear-r6250.dtb \
|
||||
bcm4708-netgear-r6300-v2.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Broadcom BCM470X / BCM5301X arm platform code.
|
||||
+ * DTS for Buffalo WZR-1750DHP
|
||||
+ *
|
||||
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "bcm4708.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "buffalo,wzr-1750dhp", "brcm,bcm4708";
|
||||
+ model = "Buffalo WZR-1750DHP (BCM4708)";
|
||||
+
|
||||
+ chosen {
|
||||
+ bootargs = "console=ttyS0,115200";
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x00000000 0x08000000>;
|
||||
+ };
|
||||
+
|
||||
+ chipcommonA {
|
||||
+ uart0: serial@0300 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ uart1: serial@0400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <200>;
|
||||
+
|
||||
+ restart {
|
||||
+ label = "Reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ aoss {
|
||||
+ label = "AOSS";
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ /* Commit mode set by switch? */
|
||||
+ mode {
|
||||
+ label = "Mode";
|
||||
+ linux,code = <KEY_SETUP>;
|
||||
+ gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ /* Switch: AP mode */
|
||||
+ sw_ap {
|
||||
+ label = "AP";
|
||||
+ linux,code = <BTN_0>;
|
||||
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ eject {
|
||||
+ label = "USB eject";
|
||||
+ linux,code = <KEY_EJECTCD>;
|
||||
+ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
@ -0,0 +1,160 @@
|
||||
From 89fe6f9b7875f74e7d63a90ae3a51d84d3cf9369 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 9 Oct 2014 18:16:26 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-N18U
|
||||
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/boot/dts/Makefile | 3 +-
|
||||
arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 88 +++++++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/bcm47081.dtsi | 26 +++++++++
|
||||
arch/arm/mach-bcm/bcm_5301x.c | 1 +
|
||||
4 files changed, 117 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
|
||||
create mode 100644 arch/arm/boot/dts/bcm47081.dtsi
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -57,7 +57,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rp
|
||||
dtb-$(CONFIG_ARCH_BCM_5301X) += \
|
||||
bcm4708-buffalo-wzr-1750dhp.dtb \
|
||||
bcm4708-netgear-r6250.dtb \
|
||||
- bcm4708-netgear-r6300-v2.dtb
|
||||
+ bcm4708-netgear-r6300-v2.dtb \
|
||||
+ bcm47081-asus-rt-n18u.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
|
||||
bcm21664-garnet.dtb
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
|
||||
@@ -0,0 +1,88 @@
|
||||
+/*
|
||||
+ * Broadcom BCM470X / BCM5301X arm platform code.
|
||||
+ * DTS for Asus RT-N18U
|
||||
+ *
|
||||
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "bcm47081.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "asus,rt-n18u", "brcm,bcm47081";
|
||||
+ model = "Asus RT-N18U (BCM47081)";
|
||||
+
|
||||
+ chosen {
|
||||
+ bootargs = "console=ttyS0,115200";
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x00000000 0x08000000>;
|
||||
+ };
|
||||
+
|
||||
+ chipcommonA {
|
||||
+ uart0: serial@0300 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ uart1: serial@0400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ power {
|
||||
+ label = "bcm53xx:blue:power";
|
||||
+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ usb2 {
|
||||
+ label = "bcm53xx:blue:usb2";
|
||||
+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+
|
||||
+ wan {
|
||||
+ label = "bcm53xx:blue:wan";
|
||||
+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ lan {
|
||||
+ label = "bcm53xx:blue:lan";
|
||||
+ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
+ };
|
||||
+
|
||||
+ usb3 {
|
||||
+ label = "bcm53xx:blue:usb3";
|
||||
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
|
||||
+ linux,default-trigger = "default-off";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <200>;
|
||||
+
|
||||
+ restart {
|
||||
+ label = "Reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ wps {
|
||||
+ label = "WPS";
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/bcm47081.dtsi
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * Broadcom BCM470X / BCM5301X ARM platform code.
|
||||
+ * DTS for BCM47081 SoC.
|
||||
+ *
|
||||
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include "bcm5301x.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "brcm,bcm47081";
|
||||
+
|
||||
+ cpus {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ cpu@0 {
|
||||
+ device_type = "cpu";
|
||||
+ compatible = "arm,cortex-a9";
|
||||
+ next-level-cache = <&L2>;
|
||||
+ reg = <0x0>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
--- a/arch/arm/mach-bcm/bcm_5301x.c
|
||||
+++ b/arch/arm/mach-bcm/bcm_5301x.c
|
||||
@@ -75,6 +75,7 @@ static void bcm5301x_restart(enum reboot
|
||||
|
||||
static const char __initconst *bcm5301x_dt_compat[] = {
|
||||
"brcm,bcm4708",
|
||||
+ "brcm,bcm47081",
|
||||
NULL,
|
||||
};
|
||||
|
@ -0,0 +1,97 @@
|
||||
From 4812cd75bc85a9f7050e2b58c1cf17e3bd4dc7f8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 15 Oct 2014 09:01:50 +0200
|
||||
Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WZR-600DHP2
|
||||
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/boot/dts/Makefile | 3 +-
|
||||
arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 67 ++++++++++++++++++++++
|
||||
2 files changed, 69 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -58,7 +58,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
|
||||
bcm4708-buffalo-wzr-1750dhp.dtb \
|
||||
bcm4708-netgear-r6250.dtb \
|
||||
bcm4708-netgear-r6300-v2.dtb \
|
||||
- bcm47081-asus-rt-n18u.dtb
|
||||
+ bcm47081-asus-rt-n18u.dtb \
|
||||
+ bcm47081-buffalo-wzr-600dhp2.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb
|
||||
dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
|
||||
bcm21664-garnet.dtb
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
|
||||
@@ -0,0 +1,67 @@
|
||||
+/*
|
||||
+ * Broadcom BCM470X / BCM5301X arm platform code.
|
||||
+ * DTS for Buffalo WZR-600DHP2
|
||||
+ *
|
||||
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "bcm47081.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ compatible = "buffalo,wzr-600dhp2", "brcm,bcm47081";
|
||||
+ model = "Buffalo WZR-600DHP2 (BCM47081)";
|
||||
+
|
||||
+ chosen {
|
||||
+ bootargs = "console=ttyS0,115200";
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x00000000 0x08000000>;
|
||||
+ };
|
||||
+
|
||||
+ chipcommonA {
|
||||
+ uart0: serial@0300 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ uart1: serial@0400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys-polled";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ poll-interval = <200>;
|
||||
+
|
||||
+ aoss {
|
||||
+ label = "AOSS";
|
||||
+ linux,code = <KEY_WPS_BUTTON>;
|
||||
+ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ restart {
|
||||
+ label = "Reset";
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ /* Switch device mode? */
|
||||
+ mode {
|
||||
+ label = "Mode";
|
||||
+ linux,code = <KEY_SETUP>;
|
||||
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ eject {
|
||||
+ label = "USB eject";
|
||||
+ linux,code = <KEY_EJECTCD>;
|
||||
+ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
@ -0,0 +1,46 @@
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -926,29 +926,23 @@ int spi_nor_scan(struct spi_nor *nor, co
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- info = (void *)id->driver_data;
|
||||
-
|
||||
- if (info->jedec_id) {
|
||||
- const struct spi_device_id *jid;
|
||||
-
|
||||
- jid = nor->read_id(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;
|
||||
+ if (id) {
|
||||
+ info = (void *)id->driver_data;
|
||||
+ if (info->jedec_id) {
|
||||
+ dev_warn(dev,
|
||||
+ "passed SPI device ID (%s) contains JEDEC, ignoring it, driver should be fixed!\n",
|
||||
+ id->name);
|
||||
+ id = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+ if (!id) {
|
||||
+ id = nor->read_id(nor);
|
||||
+ if (IS_ERR(id))
|
||||
+ return PTR_ERR(id);
|
||||
+ }
|
||||
+ info = (void *)id->driver_data;
|
||||
+
|
||||
mutex_init(&nor->lock);
|
||||
|
||||
/*
|
@ -0,0 +1,374 @@
|
||||
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
@@ -719,16 +719,10 @@ static int fsl_qspi_read(struct spi_nor
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -744,16 +738,6 @@ static int fsl_qspi_erase(struct spi_nor
|
||||
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;
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -163,81 +163,69 @@ static inline int set_4byte(struct spi_n
|
||||
return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0);
|
||||
}
|
||||
}
|
||||
-
|
||||
-static int spi_nor_wait_till_ready(struct spi_nor *nor)
|
||||
+static inline int spi_nor_sr_ready(struct spi_nor *nor)
|
||||
{
|
||||
- unsigned long deadline;
|
||||
- int sr;
|
||||
-
|
||||
- deadline = jiffies + MAX_READY_WAIT_JIFFIES;
|
||||
-
|
||||
- do {
|
||||
- cond_resched();
|
||||
+ int sr = read_sr(nor);
|
||||
+ if (sr < 0)
|
||||
+ return sr;
|
||||
+ else
|
||||
+ return !(sr & SR_WIP);
|
||||
+}
|
||||
|
||||
- sr = read_sr(nor);
|
||||
- if (sr < 0)
|
||||
- break;
|
||||
- else if (!(sr & SR_WIP))
|
||||
- return 0;
|
||||
- } while (!time_after_eq(jiffies, deadline));
|
||||
+static inline int spi_nor_fsr_ready(struct spi_nor *nor)
|
||||
+{
|
||||
+ int fsr = read_fsr(nor);
|
||||
+ if (fsr < 0)
|
||||
+ return fsr;
|
||||
+ else
|
||||
+ return fsr & FSR_READY;
|
||||
+}
|
||||
|
||||
- return -ETIMEDOUT;
|
||||
+static int spi_nor_ready(struct spi_nor *nor)
|
||||
+{
|
||||
+ int sr, fsr;
|
||||
+ sr = spi_nor_sr_ready(nor);
|
||||
+ if (sr < 0)
|
||||
+ return sr;
|
||||
+ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1;
|
||||
+ if (fsr < 0)
|
||||
+ return sr;
|
||||
+ return sr && fsr;
|
||||
}
|
||||
|
||||
-static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor)
|
||||
+/*
|
||||
+ * Service routine to read status register until ready, or timeout occurs.
|
||||
+ * Returns non-zero if error.
|
||||
+ */
|
||||
+static int spi_nor_wait_till_ready(struct spi_nor *nor)
|
||||
{
|
||||
unsigned long deadline;
|
||||
- int sr;
|
||||
- int fsr;
|
||||
+ int ret;
|
||||
|
||||
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;
|
||||
- }
|
||||
+ ret = spi_nor_ready(nor);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (ret)
|
||||
+ 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);
|
||||
}
|
||||
|
||||
@@ -290,6 +278,8 @@ static int spi_nor_erase(struct mtd_info
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ write_enable(nor);
|
||||
+
|
||||
/* whole-chip erase? */
|
||||
if (len == mtd->size) {
|
||||
if (erase_chip(nor)) {
|
||||
@@ -297,6 +287,10 @@ static int spi_nor_erase(struct mtd_info
|
||||
goto erase_err;
|
||||
}
|
||||
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
+ if (ret)
|
||||
+ 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.
|
||||
@@ -312,9 +306,15 @@ static int spi_nor_erase(struct mtd_info
|
||||
|
||||
addr += mtd->erasesize;
|
||||
len -= mtd->erasesize;
|
||||
+
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
+ if (ret)
|
||||
+ goto erase_err;
|
||||
}
|
||||
}
|
||||
|
||||
+ write_disable(nor);
|
||||
+
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
|
||||
|
||||
instr->state = MTD_ERASE_DONE;
|
||||
@@ -339,11 +339,6 @@ static int spi_nor_lock(struct mtd_info
|
||||
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))
|
||||
@@ -386,11 +381,6 @@ static int spi_nor_unlock(struct mtd_inf
|
||||
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))
|
||||
@@ -703,11 +693,6 @@ static int sst_write(struct mtd_info *mt
|
||||
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;
|
||||
@@ -719,7 +704,7 @@ static int sst_write(struct mtd_info *mt
|
||||
|
||||
/* write one byte. */
|
||||
nor->write(nor, to, 1, retlen, buf);
|
||||
- ret = wait_till_ready(nor);
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
goto time_out;
|
||||
}
|
||||
@@ -731,7 +716,7 @@ static int sst_write(struct mtd_info *mt
|
||||
|
||||
/* write two bytes. */
|
||||
nor->write(nor, to, 2, retlen, buf + actual);
|
||||
- ret = wait_till_ready(nor);
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
goto time_out;
|
||||
to += 2;
|
||||
@@ -740,7 +725,7 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->sst_write_second = false;
|
||||
|
||||
write_disable(nor);
|
||||
- ret = wait_till_ready(nor);
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
goto time_out;
|
||||
|
||||
@@ -751,7 +736,7 @@ static int sst_write(struct mtd_info *mt
|
||||
nor->program_opcode = SPINOR_OP_BP;
|
||||
nor->write(nor, to, 1, retlen, buf + actual);
|
||||
|
||||
- ret = wait_till_ready(nor);
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
goto time_out;
|
||||
write_disable(nor);
|
||||
@@ -779,11 +764,6 @@ static int spi_nor_write(struct mtd_info
|
||||
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);
|
||||
@@ -802,16 +782,20 @@ static int spi_nor_write(struct mtd_info
|
||||
if (page_size > nor->page_size)
|
||||
page_size = nor->page_size;
|
||||
|
||||
- wait_till_ready(nor);
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
+ if (ret)
|
||||
+ goto write_err;
|
||||
+
|
||||
write_enable(nor);
|
||||
|
||||
nor->write(nor, to + i, page_size, retlen, buf + i);
|
||||
}
|
||||
}
|
||||
|
||||
+ ret = spi_nor_wait_till_ready(nor);
|
||||
write_err:
|
||||
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int macronix_quad_enable(struct spi_nor *nor)
|
||||
@@ -824,7 +808,7 @@ static int macronix_quad_enable(struct s
|
||||
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))
|
||||
+ if (spi_nor_wait_till_ready(nor))
|
||||
return 1;
|
||||
|
||||
ret = read_sr(nor);
|
||||
@@ -906,8 +890,6 @@ static int spi_nor_check(struct spi_nor
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -978,9 +960,8 @@ int spi_nor_scan(struct spi_nor *nor, co
|
||||
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;
|
||||
+ if (info->flags & USE_FSR)
|
||||
+ nor->flags |= SNOR_F_USE_FSR;
|
||||
|
||||
#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
|
||||
/* prefer "small sector" erase if possible */
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -116,6 +116,10 @@ enum spi_nor_ops {
|
||||
SPI_NOR_OPS_UNLOCK,
|
||||
};
|
||||
|
||||
+enum spi_nor_option_flags {
|
||||
+ SNOR_F_USE_FSR = BIT(0),
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct spi_nor - Structure for defining a the SPI NOR layer
|
||||
* @mtd: point to a mtd_info structure
|
||||
@@ -129,6 +133,7 @@ enum spi_nor_ops {
|
||||
* @program_opcode: the program opcode
|
||||
* @flash_read: the mode of the read
|
||||
* @sst_write_second: used by the SST write operation
|
||||
+ * @flags: flag options for the current SPI-NOR (SNOR_F_*)
|
||||
* @cfg: used by the read_xfer/write_xfer
|
||||
* @cmd_buf: used by the write_reg
|
||||
* @prepare: [OPTIONAL] do some preparations for the
|
||||
@@ -141,7 +146,6 @@ enum spi_nor_ops {
|
||||
* @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
|
||||
@@ -160,6 +164,7 @@ struct spi_nor {
|
||||
u8 program_opcode;
|
||||
enum read_mode flash_read;
|
||||
bool sst_write_second;
|
||||
+ u32 flags;
|
||||
struct spi_nor_xfer_cfg cfg;
|
||||
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
|
||||
|
||||
@@ -173,7 +178,6 @@ struct spi_nor {
|
||||
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);
|
@ -0,0 +1,263 @@
|
||||
--- a/drivers/mtd/spi-nor/Kconfig
|
||||
+++ b/drivers/mtd/spi-nor/Kconfig
|
||||
@@ -28,4 +28,10 @@ config SPI_FSL_QUADSPI
|
||||
This enables support for the Quad SPI controller in master mode.
|
||||
We only connect the NOR to this controller now.
|
||||
|
||||
+config MTD_SPI_BCM53XXSPIFLASH
|
||||
+ tristate "SPI-NOR flashes connected to the Broadcom ARM SoC"
|
||||
+ depends on MTD_SPI_NOR
|
||||
+ help
|
||||
+ SPI driver for flashes used on Broadcom ARM SoCs.
|
||||
+
|
||||
endif # MTD_SPI_NOR
|
||||
--- a/drivers/mtd/spi-nor/Makefile
|
||||
+++ b/drivers/mtd/spi-nor/Makefile
|
||||
@@ -1,2 +1,3 @@
|
||||
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
|
||||
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
|
||||
+obj-$(CONFIG_MTD_SPI_BCM53XXSPIFLASH) += bcm53xxspiflash.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/spi-nor/bcm53xxspiflash.c
|
||||
@@ -0,0 +1,241 @@
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/mtd/spi-nor.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/cfi.h>
|
||||
+
|
||||
+static const char * const probes[] = { "bcm47xxpart", NULL };
|
||||
+
|
||||
+struct bcm53xxsf {
|
||||
+ struct spi_device *spi;
|
||||
+ struct mtd_info mtd;
|
||||
+ struct spi_nor nor;
|
||||
+};
|
||||
+
|
||||
+/**************************************************
|
||||
+ * spi-nor API
|
||||
+ **************************************************/
|
||||
+
|
||||
+static int bcm53xxspiflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
|
||||
+ int len)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+
|
||||
+ return spi_write_then_read(b53sf->spi, &opcode, 1, buf, len);
|
||||
+}
|
||||
+
|
||||
+static int bcm53xxspiflash_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
|
||||
+ int len, int write_enable)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+ u8 *cmd = kzalloc(len + 1, GFP_KERNEL);
|
||||
+ int err;
|
||||
+
|
||||
+ if (!cmd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cmd[0] = opcode;
|
||||
+ memcpy(&cmd[1], buf, len);
|
||||
+ err = spi_write(b53sf->spi, cmd, len + 1);
|
||||
+
|
||||
+ kfree(cmd);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int bcm53xxspiflash_read(struct spi_nor *nor, loff_t from, size_t len,
|
||||
+ size_t *retlen, u_char *buf)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+ struct spi_message m;
|
||||
+ struct spi_transfer t[2] = { { 0 }, { 0 } };
|
||||
+ unsigned char cmd[5];
|
||||
+ int cmd_len = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ spi_message_init(&m);
|
||||
+
|
||||
+ cmd[cmd_len++] = SPINOR_OP_READ;
|
||||
+ if (b53sf->mtd.size > 0x1000000)
|
||||
+ cmd[cmd_len++] = (from & 0xFF000000) >> 24;
|
||||
+ cmd[cmd_len++] = (from & 0x00FF0000) >> 16;
|
||||
+ cmd[cmd_len++] = (from & 0x0000FF00) >> 8;
|
||||
+ cmd[cmd_len++] = (from & 0x000000FF) >> 0;
|
||||
+
|
||||
+ t[0].tx_buf = cmd;
|
||||
+ t[0].len = cmd_len;
|
||||
+ spi_message_add_tail(&t[0], &m);
|
||||
+
|
||||
+ t[1].rx_buf = buf;
|
||||
+ t[1].len = len;
|
||||
+ spi_message_add_tail(&t[1], &m);
|
||||
+
|
||||
+ err = spi_sync(b53sf->spi, &m);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (retlen && m.actual_length > cmd_len)
|
||||
+ *retlen = m.actual_length - cmd_len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void bcm53xxspiflash_write(struct spi_nor *nor, loff_t to, size_t len,
|
||||
+ size_t *retlen, const u_char *buf)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+ struct spi_message m;
|
||||
+ struct spi_transfer t = { 0 };
|
||||
+ u8 *cmd = kzalloc(len + 5, GFP_KERNEL);
|
||||
+ int cmd_len = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!cmd)
|
||||
+ return;
|
||||
+
|
||||
+ spi_message_init(&m);
|
||||
+
|
||||
+ cmd[cmd_len++] = nor->program_opcode;
|
||||
+ if (b53sf->mtd.size > 0x1000000)
|
||||
+ cmd[cmd_len++] = (to & 0xFF000000) >> 24;
|
||||
+ cmd[cmd_len++] = (to & 0x00FF0000) >> 16;
|
||||
+ cmd[cmd_len++] = (to & 0x0000FF00) >> 8;
|
||||
+ cmd[cmd_len++] = (to & 0x000000FF) >> 0;
|
||||
+ memcpy(&cmd[cmd_len], buf, len);
|
||||
+
|
||||
+ t.tx_buf = cmd;
|
||||
+ t.len = cmd_len + len;
|
||||
+ spi_message_add_tail(&t, &m);
|
||||
+
|
||||
+ err = spi_sync(b53sf->spi, &m);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (retlen && m.actual_length > cmd_len)
|
||||
+ *retlen += m.actual_length - cmd_len;
|
||||
+
|
||||
+out:
|
||||
+ kfree(cmd);
|
||||
+}
|
||||
+
|
||||
+static int bcm53xxspiflash_erase(struct spi_nor *nor, loff_t offs)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+ unsigned char cmd[5];
|
||||
+ int i;
|
||||
+
|
||||
+ i = 0;
|
||||
+ cmd[i++] = nor->erase_opcode;
|
||||
+ if (b53sf->mtd.size > 0x1000000)
|
||||
+ cmd[i++] = (offs & 0xFF000000) >> 24;
|
||||
+ cmd[i++] = ((offs & 0x00FF0000) >> 16);
|
||||
+ cmd[i++] = ((offs & 0x0000FF00) >> 8);
|
||||
+ cmd[i++] = ((offs & 0x000000FF) >> 0);
|
||||
+
|
||||
+ return spi_write(b53sf->spi, cmd, i);
|
||||
+}
|
||||
+
|
||||
+static const struct spi_device_id *bcm53xxspiflash_read_id(struct spi_nor *nor)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf = nor->priv;
|
||||
+ struct device *dev = &b53sf->spi->dev;
|
||||
+ const struct spi_device_id *id;
|
||||
+ unsigned char cmd[4];
|
||||
+ unsigned char resp[2];
|
||||
+ char *name = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ /* SST and Winbond/NexFlash specific command */
|
||||
+ cmd[0] = 0x90; /* Read Manufacturer / Device ID */
|
||||
+ cmd[1] = 0;
|
||||
+ cmd[2] = 0;
|
||||
+ cmd[3] = 0;
|
||||
+ err = spi_write_then_read(b53sf->spi, cmd, 4, resp, 2);
|
||||
+ if (err < 0) {
|
||||
+ dev_err(dev, "error reading SPI flash id\n");
|
||||
+ return ERR_PTR(-EBUSY);
|
||||
+ }
|
||||
+ switch (resp[0]) {
|
||||
+ case 0xef: /* Winbond/NexFlash */
|
||||
+ switch (resp[1]) {
|
||||
+ case 0x17:
|
||||
+ name = "w25q128";
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!name) {
|
||||
+ dev_err(dev, "Unknown Winbond/NexFlash flash: %02X %02X\n",
|
||||
+ resp[0], resp[1]);
|
||||
+ return ERR_PTR(-ENOTSUPP);
|
||||
+ }
|
||||
+ goto found_name;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO: Try more ID commands */
|
||||
+
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
+
|
||||
+found_name:
|
||||
+ id = spi_nor_match_id(name);
|
||||
+ if (!id) {
|
||||
+ dev_err(dev, "No matching entry for %s flash\n", name);
|
||||
+ return ERR_PTR(-ENOENT);
|
||||
+ }
|
||||
+
|
||||
+ return id;
|
||||
+}
|
||||
+
|
||||
+/**************************************************
|
||||
+ * SPI driver
|
||||
+ **************************************************/
|
||||
+
|
||||
+static int bcm53xxspiflash_probe(struct spi_device *spi)
|
||||
+{
|
||||
+ struct bcm53xxsf *b53sf;
|
||||
+ int err;
|
||||
+
|
||||
+ b53sf = devm_kzalloc(&spi->dev, sizeof(*b53sf), GFP_KERNEL);
|
||||
+ if (!b53sf)
|
||||
+ return -ENOMEM;
|
||||
+ spi_set_drvdata(spi, b53sf);
|
||||
+
|
||||
+ b53sf->spi = spi;
|
||||
+
|
||||
+ b53sf->mtd.priv = &b53sf->nor;
|
||||
+
|
||||
+ b53sf->nor.mtd = &b53sf->mtd;
|
||||
+ b53sf->nor.dev = &spi->dev;
|
||||
+ b53sf->nor.read_reg = bcm53xxspiflash_read_reg;
|
||||
+ b53sf->nor.write_reg = bcm53xxspiflash_write_reg;
|
||||
+ b53sf->nor.read = bcm53xxspiflash_read;
|
||||
+ b53sf->nor.write = bcm53xxspiflash_write;
|
||||
+ b53sf->nor.erase = bcm53xxspiflash_erase;
|
||||
+ b53sf->nor.read_id = bcm53xxspiflash_read_id;
|
||||
+ b53sf->nor.priv = b53sf;
|
||||
+
|
||||
+ err = spi_nor_scan(&b53sf->nor, NULL, SPI_NOR_NORMAL);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = mtd_device_parse_register(&b53sf->mtd, probes, NULL, NULL, 0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bcm53xxspiflash_remove(struct spi_device *spi)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct spi_driver bcm53xxspiflash_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "bcm53xxspiflash",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+ .probe = bcm53xxspiflash_probe,
|
||||
+ .remove = bcm53xxspiflash_remove,
|
||||
+};
|
||||
+
|
||||
+module_spi_driver(bcm53xxspiflash_driver);
|
@ -0,0 +1,42 @@
|
||||
--- a/drivers/mtd/spi-nor/bcm53xxspiflash.c
|
||||
+++ b/drivers/mtd/spi-nor/bcm53xxspiflash.c
|
||||
@@ -173,7 +173,8 @@ static const struct spi_device_id *bcm53
|
||||
|
||||
/* TODO: Try more ID commands */
|
||||
|
||||
- return ERR_PTR(-ENODEV);
|
||||
+ /* Some chips used by Broadcom may actually support JEDEC */
|
||||
+ return spi_nor_read_id(nor);
|
||||
|
||||
found_name:
|
||||
id = spi_nor_match_id(name);
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -630,7 +630,7 @@ const struct spi_device_id spi_nor_ids[]
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(spi_nor_ids);
|
||||
|
||||
-static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor)
|
||||
+const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor)
|
||||
{
|
||||
int tmp;
|
||||
u8 id[5];
|
||||
@@ -661,6 +661,7 @@ static const struct spi_device_id *spi_n
|
||||
dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(spi_nor_read_id);
|
||||
|
||||
static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
--- a/include/linux/mtd/spi-nor.h
|
||||
+++ b/include/linux/mtd/spi-nor.h
|
||||
@@ -188,6 +188,8 @@ struct spi_nor {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
+const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor);
|
||||
+
|
||||
/**
|
||||
* spi_nor_scan() - scan the SPI NOR
|
||||
* @nor: the spi_nor structure
|
@ -0,0 +1,32 @@
|
||||
From 6b833541d73894b5afd40d69949f8f6099db2abf Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 2 Oct 2014 11:33:40 +0200
|
||||
Subject: [PATCH] mtd: bcm47xxpart: alloc memory for more partitions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is needed for some new Netgear devices (e.g. R6250).
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/mtd/bcm47xxpart.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -15,8 +15,12 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
-/* 10 parts were found on sflash on Netgear WNDR4500 */
|
||||
-#define BCM47XXPART_MAX_PARTS 12
|
||||
+/*
|
||||
+ * NAND flash on Netgear R6250 was verified to contain 15 partitions.
|
||||
+ * This will result in allocating too big array for some old devices, but the
|
||||
+ * memory will be freed soon anyway (see mtd_device_parse_register).
|
||||
+ */
|
||||
+#define BCM47XXPART_MAX_PARTS 20
|
||||
|
||||
/*
|
||||
* Amount of bytes we read when analyzing each block of flash memory.
|
1616
target/linux/bcm53xx/patches-3.18/420-mtd-bcm5301x_nand.patch
Normal file
1616
target/linux/bcm53xx/patches-3.18/420-mtd-bcm5301x_nand.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
From f41f8b42db092e505382f7120994de21590dff48 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 16 Oct 2014 20:52:16 +0200
|
||||
Subject: [PATCH] UBI: Detect EOF mark and erase all remaining blocks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/mtd/ubi/io.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/ubi/io.c
|
||||
+++ b/drivers/mtd/ubi/io.c
|
||||
@@ -727,6 +727,7 @@ bad:
|
||||
* o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
|
||||
* o a negative error code in case of failure.
|
||||
*/
|
||||
+static bool erase_all_next = false;
|
||||
int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_ec_hdr *ec_hdr, int verbose)
|
||||
{
|
||||
@@ -753,6 +754,10 @@ int ubi_io_read_ec_hdr(struct ubi_device
|
||||
}
|
||||
|
||||
magic = be32_to_cpu(ec_hdr->magic);
|
||||
+ if (magic == 0xdeadc0de)
|
||||
+ erase_all_next = true;
|
||||
+ if (erase_all_next)
|
||||
+ return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF;
|
||||
if (magic != UBI_EC_HDR_MAGIC) {
|
||||
if (mtd_is_eccerr(read_err))
|
||||
return UBI_IO_BAD_HDR_EBADMSG;
|
@ -0,0 +1,33 @@
|
||||
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
|
||||
@@ -143,7 +143,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
|
||||
@@ -931,7 +931,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;
|
||||
|
@ -0,0 +1,42 @@
|
||||
From fee1501c494954f6e889563ca44aadfe4a83a643 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 14 Oct 2014 00:05:42 +0200
|
||||
Subject: [PATCH] bcma: register SoC later (as a module)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is temporary workaround required for easier debugging.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/bcma/host_soc.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/host_soc.c
|
||||
+++ b/drivers/bcma/host_soc.c
|
||||
@@ -265,14 +265,22 @@ static struct platform_driver bcma_host_
|
||||
.probe = bcma_host_soc_probe,
|
||||
.remove = bcma_host_soc_remove,
|
||||
};
|
||||
+/* FIXME: Using module_platform_driver is a temp hack to get bcma SoC
|
||||
+ * initialzed *after* serial console. This way we get some logs in case of hang
|
||||
+ * inside bcma or related driver. We need that for debugging problems and it's
|
||||
+ * also useful for development. Otherwise any hang (in flash driver, PCIe
|
||||
+ * driver, USB driver, etc.) would result in not getting logs at all.
|
||||
+ */
|
||||
+module_platform_driver(bcma_host_soc_driver);
|
||||
|
||||
int __init bcma_host_soc_register_driver(void)
|
||||
{
|
||||
- return platform_driver_register(&bcma_host_soc_driver);
|
||||
+ /* return platform_driver_register(&bcma_host_soc_driver); */
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
void __exit bcma_host_soc_unregister_driver(void)
|
||||
{
|
||||
- platform_driver_unregister(&bcma_host_soc_driver);
|
||||
+ /* platform_driver_unregister(&bcma_host_soc_driver); */
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
Loading…
Reference in New Issue
Block a user