linux/mpc83xx: add preliminary 2.6.36 kernel support

SVN-Revision: 23633
lede-17.01
Alexandros C. Couloumbis 2010-10-25 17:59:14 +00:00
parent 0ee31ca22e
commit e8e1084654
34 changed files with 5063 additions and 226 deletions

View File

@ -1,226 +0,0 @@
GCC 4.4.x looks to be adding support for generating out-of-line register
saves/restores based on:
http://gcc.gnu.org/ml/gcc-patches/2008-04/msg01678.html
This breaks the kernel build as we'd have to link with libgcc to get the
implementation of the register save/restores.
To workaround this issue, we just stole the save/restore code from gcc
and simplified it down for our needs (integer only). We only do this if
PPC32 as gcc makes believe the linker on ppc64 will deal with this and
only if CONFIG_CC_OPTIMIZE_FOR_SIZE is set (thus -Os).
Signed-off-by: Kumar Gala <[EMAIL PROTECTED]>
---
If someone using cutting edge toolchains for ppc64 could test and make
sure if we enable CONFIG_CC_OPTIMIZE_FOR_SIZE things work that would be
nice.
- k
arch/powerpc/kernel/misc_32.S | 77 +++++++++++++++++++++++++++
arch/powerpc/kernel/ppc_ksyms.c | 111 +++++++++++++++++++++++++++++++++++++++
2 files changed, 188 insertions(+), 0 deletions(-)
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -825,3 +825,80 @@ relocate_new_kernel_end:
relocate_new_kernel_size:
.long relocate_new_kernel_end - relocate_new_kernel
#endif
+
+#if defined(CONFIG_PPC32) && defined(CONFIG_CC_OPTIMIZE_FOR_SIZE)
+/* Routines for saving integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer save area. */
+
+_GLOBAL(_savegpr_14) stw 14,-72(11) /* save gp registers */
+_GLOBAL(_savegpr_15) stw 15,-68(11)
+_GLOBAL(_savegpr_16) stw 16,-64(11)
+_GLOBAL(_savegpr_17) stw 17,-60(11)
+_GLOBAL(_savegpr_18) stw 18,-56(11)
+_GLOBAL(_savegpr_19) stw 19,-52(11)
+_GLOBAL(_savegpr_20) stw 20,-48(11)
+_GLOBAL(_savegpr_21) stw 21,-44(11)
+_GLOBAL(_savegpr_22) stw 22,-40(11)
+_GLOBAL(_savegpr_23) stw 23,-36(11)
+_GLOBAL(_savegpr_24) stw 24,-32(11)
+_GLOBAL(_savegpr_25) stw 25,-28(11)
+_GLOBAL(_savegpr_26) stw 26,-24(11)
+_GLOBAL(_savegpr_27) stw 27,-20(11)
+_GLOBAL(_savegpr_28) stw 28,-16(11)
+_GLOBAL(_savegpr_29) stw 29,-12(11)
+_GLOBAL(_savegpr_30) stw 30,-8(11)
+_GLOBAL(_savegpr_31) stw 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14) lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15) lwz 15,-68(11)
+_GLOBAL(_restgpr_16) lwz 16,-64(11)
+_GLOBAL(_restgpr_17) lwz 17,-60(11)
+_GLOBAL(_restgpr_18) lwz 18,-56(11)
+_GLOBAL(_restgpr_19) lwz 19,-52(11)
+_GLOBAL(_restgpr_20) lwz 20,-48(11)
+_GLOBAL(_restgpr_21) lwz 21,-44(11)
+_GLOBAL(_restgpr_22) lwz 22,-40(11)
+_GLOBAL(_restgpr_23) lwz 23,-36(11)
+_GLOBAL(_restgpr_24) lwz 24,-32(11)
+_GLOBAL(_restgpr_25) lwz 25,-28(11)
+_GLOBAL(_restgpr_26) lwz 26,-24(11)
+_GLOBAL(_restgpr_27) lwz 27,-20(11)
+_GLOBAL(_restgpr_28) lwz 28,-16(11)
+_GLOBAL(_restgpr_29) lwz 29,-12(11)
+_GLOBAL(_restgpr_30) lwz 30,-8(11)
+_GLOBAL(_restgpr_31) lwz 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15_x) lwz 15,-68(11)
+_GLOBAL(_restgpr_16_x) lwz 16,-64(11)
+_GLOBAL(_restgpr_17_x) lwz 17,-60(11)
+_GLOBAL(_restgpr_18_x) lwz 18,-56(11)
+_GLOBAL(_restgpr_19_x) lwz 19,-52(11)
+_GLOBAL(_restgpr_20_x) lwz 20,-48(11)
+_GLOBAL(_restgpr_21_x) lwz 21,-44(11)
+_GLOBAL(_restgpr_22_x) lwz 22,-40(11)
+_GLOBAL(_restgpr_23_x) lwz 23,-36(11)
+_GLOBAL(_restgpr_24_x) lwz 24,-32(11)
+_GLOBAL(_restgpr_25_x) lwz 25,-28(11)
+_GLOBAL(_restgpr_26_x) lwz 26,-24(11)
+_GLOBAL(_restgpr_27_x) lwz 27,-20(11)
+_GLOBAL(_restgpr_28_x) lwz 28,-16(11)
+_GLOBAL(_restgpr_29_x) lwz 29,-12(11)
+_GLOBAL(_restgpr_30_x) lwz 30,-8(11)
+_GLOBAL(_restgpr_31_x) lwz 0,4(11)
+ lwz 31,-4(11)
+ mtlr 0
+ mr 1,11
+ blr
+#endif
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -186,3 +186,114 @@ EXPORT_SYMBOL(__mtdcr);
EXPORT_SYMBOL(__mfdcr);
#endif
EXPORT_SYMBOL(empty_zero_page);
+
+#if defined(CONFIG_PPC32) && defined(CONFIG_CC_OPTIMIZE_FOR_SIZE)
+void _savegpr_14(void);
+void _savegpr_15(void);
+void _savegpr_16(void);
+void _savegpr_17(void);
+void _savegpr_18(void);
+void _savegpr_19(void);
+void _savegpr_20(void);
+void _savegpr_21(void);
+void _savegpr_22(void);
+void _savegpr_23(void);
+void _savegpr_24(void);
+void _savegpr_25(void);
+void _savegpr_26(void);
+void _savegpr_27(void);
+void _savegpr_28(void);
+void _savegpr_29(void);
+void _savegpr_30(void);
+void _savegpr_31(void);
+void _restgpr_14(void);
+void _restgpr_15(void);
+void _restgpr_16(void);
+void _restgpr_17(void);
+void _restgpr_18(void);
+void _restgpr_19(void);
+void _restgpr_20(void);
+void _restgpr_21(void);
+void _restgpr_22(void);
+void _restgpr_23(void);
+void _restgpr_24(void);
+void _restgpr_25(void);
+void _restgpr_26(void);
+void _restgpr_27(void);
+void _restgpr_28(void);
+void _restgpr_29(void);
+void _restgpr_30(void);
+void _restgpr_31(void);
+void _restgpr_14_x(void);
+void _restgpr_15_x(void);
+void _restgpr_16_x(void);
+void _restgpr_17_x(void);
+void _restgpr_18_x(void);
+void _restgpr_19_x(void);
+void _restgpr_20_x(void);
+void _restgpr_21_x(void);
+void _restgpr_22_x(void);
+void _restgpr_23_x(void);
+void _restgpr_24_x(void);
+void _restgpr_25_x(void);
+void _restgpr_26_x(void);
+void _restgpr_27_x(void);
+void _restgpr_28_x(void);
+void _restgpr_29_x(void);
+void _restgpr_30_x(void);
+void _restgpr_31_x(void);
+EXPORT_SYMBOL(_savegpr_14);
+EXPORT_SYMBOL(_savegpr_15);
+EXPORT_SYMBOL(_savegpr_16);
+EXPORT_SYMBOL(_savegpr_17);
+EXPORT_SYMBOL(_savegpr_18);
+EXPORT_SYMBOL(_savegpr_19);
+EXPORT_SYMBOL(_savegpr_20);
+EXPORT_SYMBOL(_savegpr_21);
+EXPORT_SYMBOL(_savegpr_22);
+EXPORT_SYMBOL(_savegpr_23);
+EXPORT_SYMBOL(_savegpr_24);
+EXPORT_SYMBOL(_savegpr_25);
+EXPORT_SYMBOL(_savegpr_26);
+EXPORT_SYMBOL(_savegpr_27);
+EXPORT_SYMBOL(_savegpr_28);
+EXPORT_SYMBOL(_savegpr_29);
+EXPORT_SYMBOL(_savegpr_30);
+EXPORT_SYMBOL(_savegpr_31);
+EXPORT_SYMBOL(_restgpr_14);
+EXPORT_SYMBOL(_restgpr_15);
+EXPORT_SYMBOL(_restgpr_16);
+EXPORT_SYMBOL(_restgpr_17);
+EXPORT_SYMBOL(_restgpr_18);
+EXPORT_SYMBOL(_restgpr_19);
+EXPORT_SYMBOL(_restgpr_20);
+EXPORT_SYMBOL(_restgpr_21);
+EXPORT_SYMBOL(_restgpr_22);
+EXPORT_SYMBOL(_restgpr_23);
+EXPORT_SYMBOL(_restgpr_24);
+EXPORT_SYMBOL(_restgpr_25);
+EXPORT_SYMBOL(_restgpr_26);
+EXPORT_SYMBOL(_restgpr_27);
+EXPORT_SYMBOL(_restgpr_28);
+EXPORT_SYMBOL(_restgpr_29);
+EXPORT_SYMBOL(_restgpr_30);
+EXPORT_SYMBOL(_restgpr_31);
+EXPORT_SYMBOL(_restgpr_14_x);
+EXPORT_SYMBOL(_restgpr_15_x);
+EXPORT_SYMBOL(_restgpr_16_x);
+EXPORT_SYMBOL(_restgpr_17_x);
+EXPORT_SYMBOL(_restgpr_18_x);
+EXPORT_SYMBOL(_restgpr_19_x);
+EXPORT_SYMBOL(_restgpr_20_x);
+EXPORT_SYMBOL(_restgpr_21_x);
+EXPORT_SYMBOL(_restgpr_22_x);
+EXPORT_SYMBOL(_restgpr_23_x);
+EXPORT_SYMBOL(_restgpr_24_x);
+EXPORT_SYMBOL(_restgpr_25_x);
+EXPORT_SYMBOL(_restgpr_26_x);
+EXPORT_SYMBOL(_restgpr_27_x);
+EXPORT_SYMBOL(_restgpr_28_x);
+EXPORT_SYMBOL(_restgpr_29_x);
+EXPORT_SYMBOL(_restgpr_30_x);
+EXPORT_SYMBOL(_restgpr_31_x);
+#endif /* CONFIG_PPC32 && CONFIG_CC_OPTIMIZE_FOR_SIZE */

View File

@ -0,0 +1,402 @@
# CONFIG_40x is not set
# CONFIG_44x is not set
CONFIG_6xx=y
CONFIG_8xxx_WDT=y
# CONFIG_ADVANCED_OPTIONS is not set
# CONFIG_ALTIVEC is not set
# CONFIG_AMIGAONE is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_ARPD is not set
# CONFIG_ASP834x is not set
CONFIG_ATA=y
CONFIG_AUDIT_ARCH=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_BLK_DEV_SD=y
# CONFIG_BOOTX_TEXT is not set
CONFIG_BOUNCE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_BUG is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,yaffs2,jffs2"
CONFIG_CMDLINE_BOOL=y
CONFIG_COMPAT_BRK=y
CONFIG_CONFIGFS_FS=m
CONFIG_CRC16=m
CONFIG_CRC7=m
CONFIG_CRC_CCITT=y
CONFIG_CRC_ITU_T=m
CONFIG_CRC_T10DIF=m
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_DEV_TALITOS=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_HMAC=m
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_MD5=m
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_ZLIB is not set
CONFIG_DEFAULT_CFQ=y
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_DEFAULT_UIMAGE=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
CONFIG_DMADEVICES=y
# CONFIG_DMADEVICES_DEBUG is not set
CONFIG_DMA_ENGINE=y
CONFIG_DTC=y
# CONFIG_E200 is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_EMBEDDED6xx is not set
# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_FIXED_PHY=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_FSL_DMA=y
CONFIG_FSL_EMB_PERFMON=y
CONFIG_FSL_GTM=y
CONFIG_FSL_LBC=y
CONFIG_FSL_PCI=y
CONFIG_FSL_PQ_MDIO=y
CONFIG_FSL_SOC=y
# CONFIG_FSL_ULI1575 is not set
# CONFIG_FSNOTIFY is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_GENERIC_ACL=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
# CONFIG_GENERIC_IOMAP is not set
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_NVRAM=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
CONFIG_GIANFAR=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVICE=y
# CONFIG_HAMRADIO is not set
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAS_RAPIDIO is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=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 is not set
CONFIG_HAVE_IDE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_HW_RANDOM=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
CONFIG_IFB=y
CONFIG_INET_AH=m
CONFIG_INET_DIAG=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_LRO=y
CONFIG_INET_TCP_DIAG=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INPUT=y
# CONFIG_INPUT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_IOSCHED_CFQ=y
CONFIG_IPIC=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_IP_SCTP=m
CONFIG_IRQ_PER_CPU=y
CONFIG_ISA_DMA_API=y
# CONFIG_ISDN is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
# CONFIG_JFFS2_LZMA is not set
# CONFIG_JFFS2_SUMMARY is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_KERNEL_START=0xc0000000
# CONFIG_KMETER1 is not set
# CONFIG_LBDAF is not set
CONFIG_LIBCRC32C=y
CONFIG_LOG_BUF_SHIFT=15
CONFIG_LOWMEM_SIZE=0x30000000
# CONFIG_MATH_EMULATION is not set
CONFIG_MAX_ACTIVE_REGIONS=32
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_GPIO=y
# CONFIG_MMIO_NVRAM is not set
CONFIG_MPC830x_RDB=y
CONFIG_MPC831x_RDB=y
CONFIG_MPC832x_MDS=y
CONFIG_MPC832x_RDB=y
CONFIG_MPC834x_ITX=y
CONFIG_MPC834x_MDS=y
CONFIG_MPC836x_MDS=y
CONFIG_MPC836x_RDK=y
CONFIG_MPC837x_MDS=y
CONFIG_MPC837x_RDB=y
CONFIG_MPC8xxx_GPIO=y
# CONFIG_MPIC is not set
# CONFIG_MPIC_U3_HT_IRQS is not set
# CONFIG_MPIC_WEIRD is not set
CONFIG_MTD_BLOCK2MTD=y
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_NAND_FSL_UPM=y
CONFIG_MTD_NAND_RB_PPC=y
CONFIG_MTD_OF_PARTS=y
# CONFIG_MTD_SM_COMMON is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_RESERVE=1
# CONFIG_MTD_UBI_DEBUG is not set
# CONFIG_MTD_UBI_GLUEBI is not set
CONFIG_MTD_UBI_WL_THRESHOLD=4096
# CONFIG_NEED_DMA_MAP_STATE is not set
# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
CONFIG_NEED_SG_DMA_LENGTH=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NET_ACT_GACT=m
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_ACT_POLICE=m
CONFIG_NET_ACT_SIMP=m
# CONFIG_NET_ACT_SKBEDIT is not set
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_U32=m
# CONFIG_NET_DMA is not set
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=m
CONFIG_NET_EMATCH_META=m
CONFIG_NET_EMATCH_NBYTE=m
CONFIG_NET_EMATCH_TEXT=m
CONFIG_NET_EMATCH_U32=m
CONFIG_NET_IPGRE=m
CONFIG_NET_IPIP=m
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_SCH_NETEM=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_TEQL=m
# CONFIG_NEW_LEDS is not set
CONFIG_NO_HZ=y
CONFIG_NR_IRQS=512
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DEVICE=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_SPI=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PAGE_OFFSET=0xc0000000
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_PATA_RB_PPC=y
CONFIG_PCI=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_MSI=y
CONFIG_PHYLIB=y
CONFIG_PHYSICAL_START=0x00000000
CONFIG_PPC=y
CONFIG_PPC32=y
# CONFIG_PPC64 is not set
# CONFIG_PPC_82xx is not set
CONFIG_PPC_83xx=y
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_PPC_8xx is not set
# CONFIG_PPC_970_NAP is not set
CONFIG_PPC_BOOK3S=y
CONFIG_PPC_BOOK3S_32=y
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_CHRP is not set
# CONFIG_PPC_CLOCK is not set
# CONFIG_PPC_DCR_MMIO is not set
# CONFIG_PPC_DCR_NATIVE is not set
CONFIG_PPC_DISABLE_WERROR=y
# CONFIG_PPC_EARLY_DEBUG is not set
CONFIG_PPC_FPU=y
CONFIG_PPC_HAVE_PMU_SUPPORT=y
# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_IO is not set
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_PPC_LIB_RHEAP=y
# CONFIG_PPC_MM_SLICES is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_MPC512x is not set
# CONFIG_PPC_MPC52xx is not set
CONFIG_PPC_MPC831x=y
CONFIG_PPC_MPC832x=y
CONFIG_PPC_MPC834x=y
CONFIG_PPC_MPC837x=y
CONFIG_PPC_MSI_BITMAP=y
CONFIG_PPC_OF=y
CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_RTAS is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_PQ2ADS is not set
CONFIG_PRINT_STACK_DEPTH=64
CONFIG_PROC_DEVICETREE=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_QE_GPIO=y
CONFIG_QUICC_ENGINE=y
CONFIG_RB_IOMAP=y
CONFIG_RB_PPC=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_SATA_FSL is not set
# CONFIG_SBC834x is not set
CONFIG_SCHED_HRTICK=y
CONFIG_SCSI=y
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_PROC_FS is not set
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
CONFIG_SCTP_HMAC_MD5=y
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not set
CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_SERIAL_QE=y
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
# CONFIG_SERIO_LIBPS2 is not set
CONFIG_SERIO_PCIPS2=y
CONFIG_SERIO_RAW=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_XILINX_XPS_PS2 is not set
CONFIG_SIMPLE_GPIO=y
# CONFIG_SLAB is not set
CONFIG_SLOB=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_GPIO is not set
CONFIG_SPI_MASTER=y
CONFIG_SPI_MPC8xxx=y
# CONFIG_SQUASHFS is not set
# CONFIG_SWAP is not set
# CONFIG_SWIOTLB is not set
CONFIG_TASK_SIZE=0xc0000000
# CONFIG_TAU is not set
CONFIG_TCP_CONG_BIC=m
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_HSTCP=m
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HYBLA=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_TEXTSEARCH_KMP=m
# CONFIG_TIMB_DMA is not set
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_UBIFS_FS is not set
CONFIG_UCC=y
CONFIG_UCC_FAST=y
CONFIG_UCC_GETH=y
CONFIG_UCC_SLOW=y
# CONFIG_UCC_TDM is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
CONFIG_VIA_VELOCITY=y
CONFIG_VITESSE_PHY=y
CONFIG_VITESSE_PHY_8601_SKEW=y
CONFIG_WAN_ROUTER=m
CONFIG_WORD_SIZE=32
CONFIG_XFRM_IPCOMP=m
CONFIG_YAFFS_9BYTE_TAGS=y
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
CONFIG_YAFFS_XATTR=y
CONFIG_YAFFS_YAFFS1=y
CONFIG_YAFFS_YAFFS2=y

View File

@ -0,0 +1,19 @@
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -74,7 +74,7 @@ src-plat := of.c cuboot-52xx.c cuboot-82
cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
- cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
+ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c rb600.c \
cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
@@ -235,6 +235,7 @@ image-$(CONFIG_MPC834x_ITX) += cuImage.
image-$(CONFIG_MPC834x_MDS) += cuImage.mpc834x_mds
image-$(CONFIG_MPC836x_MDS) += cuImage.mpc836x_mds
image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot
+image-$(CONFIG_RB_PPC) += dtbImage.rb600
# Board ports in arch/powerpc/platform/85xx/Kconfig
image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads

View File

@ -0,0 +1,245 @@
--- /dev/null
+++ b/arch/powerpc/boot/dts/rb600.dts
@@ -0,0 +1,242 @@
+/*
+ * RouterBOARD 600 series Device Tree Source
+ *
+ * Copyright 2009 Michael Guntsche <mike@it-loops.com>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "RB600";
+ compatible = "MPC83xx";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ };
+
+ chosen {
+ linux,stdout-path = "/soc8343@e0000000/serial@4500";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8343E@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ d-cache-line-size = <0x20>;
+ i-cache-line-size = <0x20>;
+ d-cache-size = <0x8000>;
+ i-cache-size = <0x8000>;
+ timebase-frequency = <0x0000000>; // filled by the bootwrapper from the firmware blob
+ clock-frequency = <0x00000000>; // filled by the bootwrapper from the firmware blob
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0000000>; // filled by the bootwrapper from the firmware blob
+ };
+
+ cf@f9200000 {
+ lb-timings = <0x5dc 0x3e8 0x1194 0x5dc 0x2af8>;
+ interrupt-at-level = <0x0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <0x16 0x8>;
+ lbc_extra_divider = <0x1>;
+ reg = <0xf9200000 0x200000>;
+ device_type = "rb,cf";
+ };
+
+ cf@f9000000 {
+ lb-timings = <0x5dc 0x3e8 0x1194 0x5dc 0x2af8>;
+ interrupt-at-level = <0x0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <0x14 0x8>;
+ lbc_extra_divider = <0x1>;
+ reg = <0xf9000000 0x200000>;
+ device_type = "rb,cf";
+ };
+
+ flash {
+ reg = <0xff800000 0x20000>;
+ };
+
+ nnand {
+ reg = <0xf0000000 0x1000>;
+ };
+
+ nand {
+ ale = <&gpio 0x6>;
+ cle = <&gpio 0x5>;
+ nce = <&gpio 0x4>;
+ rdy = <&gpio 0x3>;
+ reg = <0xf8000000 0x1000>;
+ device_type = "rb,nand";
+ };
+
+ fancon {
+ interrupt-parent = <&ipic>;
+ interrupts = <0x17 0x8>;
+ sense = <&gpio 0x7>;
+ fan_on = <&gpio 0x9>;
+ };
+
+ pci0: pci@e0008500 {
+ device_type = "pci";
+ compatible = "fsl,mpc8349-pci";
+ reg = <0xe0008500 0x100 0xe0008300 0x8>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x1000000 0x0 0x0 0xd0000000 0x0 0x4000000>;
+ bus-range = <0x0 0x0>;
+ interrupt-map = <
+ 0x5800 0x0 0x0 0x1 &ipic 0x15 0x8
+ 0x6000 0x0 0x0 0x1 &ipic 0x30 0x8
+ 0x6000 0x0 0x0 0x2 &ipic 0x11 0x8
+ 0x6800 0x0 0x0 0x1 &ipic 0x11 0x8
+ 0x6800 0x0 0x0 0x2 &ipic 0x12 0x8
+ 0x7000 0x0 0x0 0x1 &ipic 0x12 0x8
+ 0x7000 0x0 0x0 0x2 &ipic 0x13 0x8
+ 0x7800 0x0 0x0 0x1 &ipic 0x13 0x8
+ 0x7800 0x0 0x0 0x2 &ipic 0x30 0x8
+ 0x8000 0x0 0x0 0x1 &ipic 0x30 0x8
+ 0x8000 0x0 0x0 0x2 &ipic 0x12 0x8
+ 0x8000 0x0 0x0 0x3 &ipic 0x11 0x8
+ 0x8000 0x0 0x0 0x4 &ipic 0x13 0x8
+ 0xa000 0x0 0x0 0x1 &ipic 0x30 0x8
+ 0xa000 0x0 0x0 0x2 &ipic 0x11 0x8
+ 0xa000 0x0 0x0 0x3 &ipic 0x12 0x8
+ 0xa000 0x0 0x0 0x4 &ipic 0x13 0x8
+ 0xa800 0x0 0x0 0x1 &ipic 0x11 0x8
+ 0xa800 0x0 0x0 0x2 &ipic 0x12 0x8
+ 0xa800 0x0 0x0 0x3 &ipic 0x13 0x8
+ 0xa800 0x0 0x0 0x4 &ipic 0x30 0x8>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-parent = <&ipic>;
+ };
+
+ soc8343@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ ranges = <0x0 0xe0000000 0x100000>;
+ reg = <0xe0000000 0x200>;
+ bus-frequency = <0x1>;
+
+ led {
+ user_led = <0x400 0x8>;
+ };
+
+ beeper {
+ reg = <0x500 0x100>;
+ };
+
+ gpio: gpio@0 {
+ reg = <0xc08 0x4>;
+ device-id = <0x0>;
+ compatible = "gpio";
+ device_type = "gpio";
+ };
+
+ enet0: ethernet@25000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <0>;
+ phy-handle = <&phy0>;
+ tbi-handle = <&tbi0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <0x23 0x8 0x24 0x8 0x25 0x8>;
+ local-mac-address = [00 00 00 00 00 00];
+ reg = <0x25000 0x1000>;
+ ranges = <0x0 0x25000 0x1000>;
+ compatible = "gianfar";
+ model = "TSEC";
+ device_type = "network";
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet1: ethernet@24000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <1>;
+ phy-handle = <&phy1>;
+ tbi-handle = <&tbi1>;
+ interrupt-parent = <&ipic>;
+ interrupts = <0x20 0x8 0x21 0x8 0x22 0x8>;
+ local-mac-address = [00 00 00 00 00 00];
+ reg = <0x24000 0x1000>;
+ ranges = <0x0 0x24000 0x1000>;
+ compatible = "gianfar";
+ model = "TSEC";
+ device_type = "network";
+
+ mdio@520 {
+ #size-cells = <0x0>;
+ #address-cells = <0x1>;
+ reg = <0x520 0x20>;
+ compatible = "fsl,gianfar-mdio";
+
+ phy0: ethernet-phy@0 {
+ device_type = "ethernet-phy";
+ reg = <0x0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ device_type = "ethernet-phy";
+ reg = <0x1>;
+ };
+
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ ipic: pic@700 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x700 0x100>;
+ device_type = "ipic";
+ };
+
+ serial@4500 {
+ interrupt-parent = <&ipic>;
+ interrupts = <0x9 0x8>;
+ clock-frequency = <0xfe4f840>;
+ reg = <0x4500 0x100>;
+ compatible = "ns16550";
+ device_type = "serial";
+ };
+
+ wdt@200 {
+ reg = <0x200 0x100>;
+ compatible = "mpc83xx_wdt";
+ device_type = "watchdog";
+ };
+ };
+};

View File

@ -0,0 +1,83 @@
--- /dev/null
+++ b/arch/powerpc/boot/rb600.c
@@ -0,0 +1,80 @@
+/*
+ * The RouterBOARD platform -- for booting RB600(A) RouterBOARDs.
+ *
+ * Author: Michael Guntsche <mike@it-loops.com>
+ *
+ * Copyright (c) 2009 Michael Guntsche
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "types.h"
+#include "io.h"
+#include "stdio.h"
+#include <libfdt.h>
+
+BSS_STACK(4*1024);
+
+u64 memsize64;
+const void *fw_dtb;
+
+static void rb600_fixups(void)
+{
+ const u32 *reg, *timebase, *clock;
+ int node, size;
+ void *chosen;
+ const char* bootargs;
+
+ dt_fixup_memory(0, memsize64);
+
+ /* Set the MAC addresses. */
+ node = fdt_path_offset(fw_dtb, "/soc8343@e0000000/ethernet@24000");
+ reg = fdt_getprop(fw_dtb, node, "mac-address", &size);
+ dt_fixup_mac_address_by_alias("ethernet1", (const u8 *)reg);
+
+ node = fdt_path_offset(fw_dtb, "/soc8343@e0000000/ethernet@25000");
+ reg = fdt_getprop(fw_dtb, node, "mac-address", &size);
+ dt_fixup_mac_address_by_alias("ethernet0", (const u8 *)reg);
+
+ /* Find the CPU timebase and clock frequencies. */
+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "cpu", sizeof("cpu"));
+ timebase = fdt_getprop(fw_dtb, node, "timebase-frequency", &size);
+ clock = fdt_getprop(fw_dtb, node, "clock-frequency", &size);
+ dt_fixup_cpu_clocks(*clock, *timebase, 0);
+
+ /* Fixup chosen
+ * The bootloader reads the kernelparm segment and adds the content to
+ * bootargs. This is needed to specify root and other boot flags.
+ */
+ chosen = finddevice("/chosen");
+ node = fdt_path_offset(fw_dtb, "/chosen");
+ bootargs = fdt_getprop(fw_dtb, node, "bootargs", &size);
+ setprop_str(chosen, "bootargs", bootargs);
+}
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ const u32 *reg;
+ int node, size;
+
+ fw_dtb = (const void *)r3;
+
+ /* Find the memory range. */
+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "memory", sizeof("memory"));
+ reg = fdt_getprop(fw_dtb, node, "reg", &size);
+ memsize64 = reg[1];
+
+ /* Now we have the memory size; initialize the heap. */
+ simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
+
+ /* Prepare the device tree and find the console. */
+ fdt_init(_dtb_start);
+ serial_console_init();
+
+ /* Remaining fixups... */
+ platform_ops.fixups = rb600_fixups;
+}

View File

@ -0,0 +1,11 @@
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -209,7 +209,7 @@ ps3)
isection=.kernel:initrd
link_address=''
;;
-ep88xc|ep405|ep8248e)
+ep88xc|ep405|ep8248e|rb600)
platformo="$object/fixed-head.o $object/$platform.o"
binary=y
;;

View File

@ -0,0 +1,14 @@
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -116,9 +116,11 @@ obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) +=
obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
+ifneq ($(CONFIG_RB_IOMAP),y)
ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
obj-y += iomap.o
endif
+endif
obj-$(CONFIG_PPC64) += $(obj64-y)
obj-$(CONFIG_PPC32) += $(obj32-y)

View File

@ -0,0 +1,18 @@
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -38,6 +38,15 @@ config MPC832x_RDB
help
This option enables support for the MPC8323 RDB board.
+config RB_PPC
+ bool "MikroTik RouterBOARD 600 series"
+ select DEFAULT_UIMAGE
+ select QUICC_ENGINE
+ select PPC_MPC834x
+ select RB_IOMAP
+ help
+ This option enables support for MikroTik RouterBOARD 600 series boards.
+
config MPC834x_MDS
bool "Freescale MPC834x MDS"
select DEFAULT_UIMAGE

View File

@ -0,0 +1,10 @@
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mp
obj-$(CONFIG_MPC830x_RDB) += mpc830x_rdb.o
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
+obj-$(CONFIG_RB_PPC) += rbppc.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o

View File

@ -0,0 +1,13 @@
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -146,6 +146,10 @@ config GENERIC_IOMAP
bool
default n
+config RB_IOMAP
+ bool
+ default y if RB_PPC
+
source "drivers/cpufreq/Kconfig"
menu "CPU Frequency drivers"

View File

@ -0,0 +1,8 @@
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -57,3 +57,5 @@ obj-$(CONFIG_PPC_MPC52xx) += mpc5xxx_clo
ifeq ($(CONFIG_SUSPEND),y)
obj-$(CONFIG_6xx) += 6xx-suspend.o
endif
+
+obj-$(CONFIG_RB_IOMAP) += rb_iomap.o

View File

@ -0,0 +1,226 @@
--- /dev/null
+++ b/arch/powerpc/sysdev/rb_iomap.c
@@ -0,0 +1,223 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+
+#define LOCALBUS_START 0x40000000
+#define LOCALBUS_MASK 0x007fffff
+#define LOCALBUS_REGMASK 0x001fffff
+
+static void __iomem *localbus_base;
+
+static inline int is_localbus(void __iomem *addr)
+{
+ return ((unsigned) addr & ~LOCALBUS_MASK) == LOCALBUS_START;
+}
+
+static inline unsigned localbus_regoff(unsigned reg) {
+ return (reg << 16) | (((reg ^ 8) & 8) << 17);
+}
+
+static inline void __iomem *localbus_addr(void __iomem *addr)
+{
+ return localbus_base
+ + ((unsigned) addr & LOCALBUS_MASK & ~LOCALBUS_REGMASK)
+ + localbus_regoff((unsigned) addr & LOCALBUS_REGMASK);
+}
+
+unsigned int ioread8(void __iomem *addr)
+{
+ if (is_localbus(addr))
+ return in_be16(localbus_addr(addr)) >> 8;
+ return readb(addr);
+}
+EXPORT_SYMBOL(ioread8);
+
+unsigned int ioread16(void __iomem *addr)
+{
+ if (is_localbus(addr))
+ return le16_to_cpu(in_be16(localbus_addr(addr)));
+ return readw(addr);
+}
+EXPORT_SYMBOL(ioread16);
+
+unsigned int ioread16be(void __iomem *addr)
+{
+ return in_be16(addr);
+}
+EXPORT_SYMBOL(ioread16be);
+
+unsigned int ioread32(void __iomem *addr)
+{
+ return readl(addr);
+}
+EXPORT_SYMBOL(ioread32);
+
+unsigned int ioread32be(void __iomem *addr)
+{
+ return in_be32(addr);
+}
+EXPORT_SYMBOL(ioread32be);
+
+void iowrite8(u8 val, void __iomem *addr)
+{
+ if (is_localbus(addr))
+ out_be16(localbus_addr(addr), ((u16) val) << 8);
+ else
+ writeb(val, addr);
+}
+EXPORT_SYMBOL(iowrite8);
+
+void iowrite16(u16 val, void __iomem *addr)
+{
+ if (is_localbus(addr))
+ out_be16(localbus_addr(addr), cpu_to_le16(val));
+ else
+ writew(val, addr);
+}
+EXPORT_SYMBOL(iowrite16);
+
+void iowrite16be(u16 val, void __iomem *addr)
+{
+ out_be16(addr, val);
+}
+EXPORT_SYMBOL(iowrite16be);
+
+void iowrite32(u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+}
+EXPORT_SYMBOL(iowrite32);
+
+void iowrite32be(u32 val, void __iomem *addr)
+{
+ out_be32(addr, val);
+}
+EXPORT_SYMBOL(iowrite32be);
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ if (is_localbus(addr)) {
+ unsigned i;
+ void *laddr = localbus_addr(addr);
+ u8 *buf = dst;
+
+ for (i = 0; i < count; ++i) {
+ *buf++ = in_be16(laddr) >> 8;
+ }
+ } else {
+ _insb((u8 __iomem *) addr, dst, count);
+ }
+}
+EXPORT_SYMBOL(ioread8_rep);
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ if (is_localbus(addr)) {
+ unsigned i;
+ void *laddr = localbus_addr(addr);
+ u16 *buf = dst;
+
+ for (i = 0; i < count; ++i) {
+ *buf++ = in_be16(laddr);
+ }
+ } else {
+ _insw_ns((u16 __iomem *) addr, dst, count);
+ }
+}
+EXPORT_SYMBOL(ioread16_rep);
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+ _insl_ns((u32 __iomem *) addr, dst, count);
+}
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ if (is_localbus(addr)) {
+ unsigned i;
+ void *laddr = localbus_addr(addr);
+ const u8 *buf = src;
+
+ for (i = 0; i < count; ++i) {
+ out_be16(laddr, ((u16) *buf++) << 8);
+ }
+ } else {
+ _outsb((u8 __iomem *) addr, src, count);
+ }
+}
+EXPORT_SYMBOL(iowrite8_rep);
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ if (is_localbus(addr)) {
+ unsigned i;
+ void *laddr = localbus_addr(addr);
+ const u16 *buf = src;
+
+ for (i = 0; i < count; ++i) {
+ out_be16(laddr, *buf++);
+ }
+ } else {
+ _outsw_ns((u16 __iomem *) addr, src, count);
+ }
+}
+EXPORT_SYMBOL(iowrite16_rep);
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+ _outsl_ns((u32 __iomem *) addr, src, count);
+}
+EXPORT_SYMBOL(iowrite32_rep);
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+ return (void __iomem *) (port + _IO_BASE);
+}
+EXPORT_SYMBOL(ioport_unmap);
+
+void ioport_unmap(void __iomem *addr)
+{
+ /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len)
+ return NULL;
+ if (max && len > max)
+ len = max;
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM)
+ return ioremap(start, len);
+ /* What? */
+ return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ /* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iounmap);
+
+void __iomem *localbus_map(unsigned long addr, unsigned int len)
+{
+ if (!localbus_base)
+ localbus_base = ioremap(addr & ~LOCALBUS_MASK,
+ LOCALBUS_MASK + 1);
+ return (void *) (LOCALBUS_START + (addr & LOCALBUS_MASK));
+}
+EXPORT_SYMBOL(localbus_map);
+
+void localbus_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(localbus_unmap);

View File

@ -0,0 +1,15 @@
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -862,5 +862,12 @@ config PATA_LEGACY
If unsure, say N.
+config PATA_RB_PPC
+ tristate "MikroTik RB600 PATA support"
+ depends on RB_PPC
+ help
+ This option enables support for PATA devices on MikroTik RouterBOARD
+ 600 series boards.
+
endif # ATA_SFF
endif # ATA

View File

@ -0,0 +1,10 @@
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_PATA_PLATFORM) += pata_plat
obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
+obj-$(CONFIG_PATA_RB_PPC) += pata_rbppc_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o

View File

@ -0,0 +1,704 @@
--- /dev/null
+++ b/drivers/ata/pata_rbppc_cf.c
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
+ * Copyright (C) Mikrotik 2007
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <linux/of_platform.h>
+#include <linux/ata_platform.h>
+
+#define DEBUG_UPM 0
+
+#define DRV_NAME "pata_rbppc_cf"
+#define DRV_VERSION "0.0.2"
+
+#define DEV2SEL_OFFSET 0x00100000
+
+#define IMMR_LBCFG_OFFSET 0x00005000
+#define IMMR_LBCFG_SIZE 0x00001000
+
+#define LOCAL_BUS_MCMR 0x00000078
+#define MxMR_OP_MASK 0x30000000
+#define MxMR_OP_NORMAL 0x00000000
+#define MxMR_OP_WRITE 0x10000000
+#define MxMR_OP_READ 0x20000000
+#define MxMR_OP_RUN 0x30000000
+#define MxMR_LUPWAIT_LOW 0x08000000
+#define MxMR_LUPWAIT_HIGH 0x00000000
+#define MxMR_LUPWAIT_ENABLE 0x00040000
+#define MxMR_RLF_MASK 0x0003c000
+#define MxMR_RLF_SHIFT 14
+#define MxMR_WLF_MASK 0x00003c00
+#define MxMR_WLF_SHIFT 10
+#define MxMR_MAD_MASK 0x0000003f
+#define LOCAL_BUS_MDR 0x00000088
+#define LOCAL_BUS_LCRR 0x000000D4
+#define LCRR_CLKDIV_MASK 0x0000000f
+
+#define LOOP_SIZE 4
+
+#define UPM_READ_SINGLE_OFFSET 0x00
+#define UPM_WRITE_SINGLE_OFFSET 0x18
+#define UPM_DATA_SIZE 0x40
+
+#define LBT_CPUIN_MIN 0
+#define LBT_CPUOUT_MIN 1
+#define LBT_CPUOUT_MAX 2
+#define LBT_EXTDEL_MIN 3
+#define LBT_EXTDEL_MAX 4
+#define LBT_SIZE 5
+
+/* UPM machine configuration bits */
+#define N_BASE 0x00f00000
+#define N_CS 0xf0000000
+#define N_CS_H1 0xc0000000
+#define N_CS_H2 0x30000000
+#define N_WE 0x0f000000
+#define N_WE_H1 0x0c000000
+#define N_WE_H2 0x03000000
+#define N_OE 0x00030000
+#define N_OE_H1 0x00020000
+#define N_OE_H2 0x00010000
+#define WAEN 0x00001000
+#define REDO_2 0x00000100
+#define REDO_3 0x00000200
+#define REDO_4 0x00000300
+#define LOOP 0x00000080
+#define NA 0x00000008
+#define UTA 0x00000004
+#define LAST 0x00000001
+
+#define REDO_VAL(mult) (REDO_2 * ((mult) - 1))
+#define REDO_MAX_MULT 4
+
+#define READ_BASE (N_BASE | N_WE)
+#define WRITE_BASE (N_BASE | N_OE)
+#define EMPTY (N_BASE | N_CS | N_OE | N_WE | LAST)
+
+#define EOF_UPM_SETTINGS 0
+#define ANOTHER_TIMING 1
+
+#define OA_CPUIN_MIN 0x01
+#define OA_CPUOUT_MAX 0x02
+#define OD_CPUOUT_MIN 0x04
+#define OA_CPUOUT_DELTA 0x06
+#define OA_EXTDEL_MAX 0x08
+#define OD_EXTDEL_MIN 0x10
+#define OA_EXTDEL_DELTA 0x18
+#define O_MIN_CYCLE_TIME 0x20
+#define O_MINUS_PREV 0x40
+#define O_HALF_CYCLE 0x80
+
+extern void __iomem *localbus_map(unsigned long addr, unsigned int len);
+extern void localbus_unmap(void __iomem *addr);
+
+struct rbppc_cf_info {
+ unsigned lbcfg_addr;
+ unsigned clk_time_ps;
+ int cur_mode;
+ u32 lb_timings[LBT_SIZE];
+};
+static struct rbppc_cf_info *rbinfo = NULL;
+
+struct upm_setting {
+ unsigned value;
+ unsigned ns[7];
+ unsigned clk_minus;
+ unsigned group_size;
+ unsigned options;
+};
+
+static const struct upm_setting cfUpmReadSingle[] = {
+ { READ_BASE | N_OE,
+ /* t1 - ADDR setup time */
+ { 70, 50, 30, 30, 25, 15, 10 }, 0, 0, (OA_CPUOUT_DELTA |
+ OA_EXTDEL_MAX) },
+ { READ_BASE | N_OE_H1,
+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
+ { READ_BASE,
+ /* t2 - OE0 time */
+ { 290, 290, 290, 80, 70, 65, 55 }, 0, 2, (OA_CPUOUT_MAX |
+ OA_CPUIN_MIN) },
+ { READ_BASE | WAEN,
+ { 1, 1, 1, 1, 1, 0, 0 }, 0, 0, 0 },
+ { READ_BASE | UTA,
+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
+ { READ_BASE | N_OE,
+ /* t9 - ADDR hold time */
+ { 20, 15, 10, 10, 10, 10, 10 }, 0, 0, (OA_CPUOUT_DELTA |
+ OD_EXTDEL_MIN) },
+ { READ_BASE | N_OE | N_CS_H2,
+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
+ { READ_BASE | N_OE | N_CS,
+ /* t6Z -IORD data tristate */
+ { 30, 30, 30, 30, 30, 20, 20 }, 1, 1, O_MINUS_PREV },
+ { ANOTHER_TIMING,
+ /* t2i -IORD recovery time */
+ { 0, 0, 0, 70, 25, 25, 20 }, 2, 0, 0 },
+ { ANOTHER_TIMING,
+ /* CS 0 -> 1 MAX */
+ { 0, 0, 0, 0, 0, 0, 0 }, 1, 0, (OA_CPUOUT_DELTA |
+ OA_EXTDEL_MAX) },
+ { READ_BASE | N_OE | N_CS | LAST,
+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
+ { EOF_UPM_SETTINGS,
+ /* min total cycle time - includes turnaround and ALE cycle */
+ { 600, 383, 240, 180, 120, 100, 80 }, 2, 0, O_MIN_CYCLE_TIME },
+};
+
+static const struct upm_setting cfUpmWriteSingle[] = {
+ { WRITE_BASE | N_WE,
+ /* t1 - ADDR setup time */
+ { 70, 50, 30, 30, 25, 15, 10 }, 0, 0, (OA_CPUOUT_DELTA |
+ OA_EXTDEL_MAX) },
+ { WRITE_BASE | N_WE_H1,
+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
+ { WRITE_BASE,
+ /* t2 - WE0 time */
+ { 290, 290, 290, 80, 70, 65, 55 }, 0, 1, OA_CPUOUT_DELTA },
+ { WRITE_BASE | WAEN,
+ { 1, 1, 1, 1, 1, 0, 0 }, 0, 0, 0 },
+ { WRITE_BASE | N_WE,
+ /* t9 - ADDR hold time */
+ { 20, 15, 10, 10, 10, 10, 10 }, 0, 0, (OA_CPUOUT_DELTA |
+ OD_EXTDEL_MIN) },
+ { WRITE_BASE | N_WE | N_CS_H2,
+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, O_HALF_CYCLE },
+ { WRITE_BASE | N_WE | N_CS,
+ /* t4 - DATA hold time */
+ { 30, 20, 15, 10, 10, 10, 10 }, 0, 1, O_MINUS_PREV },
+ { ANOTHER_TIMING,
+ /* t2i -IOWR recovery time */
+ { 0, 0, 0, 70, 25, 25, 20 }, 1, 0, 0 },
+ { ANOTHER_TIMING,
+ /* CS 0 -> 1 MAX */
+ { 0, 0, 0, 0, 0, 0, 0 }, 0, 0, (OA_CPUOUT_DELTA |
+ OA_EXTDEL_MAX) },
+ { WRITE_BASE | N_WE | N_CS | UTA | LAST,
+ { 1, 1, 1, 1, 1, 1, 1 }, 0, 0, 0 },
+ /* min total cycle time - includes ALE cycle */
+ { EOF_UPM_SETTINGS,
+ { 600, 383, 240, 180, 120, 100, 80 }, 1, 0, O_MIN_CYCLE_TIME },
+};
+
+static u8 rbppc_cf_check_status(struct ata_port *ap) {
+ u8 val = ioread8(ap->ioaddr.status_addr);
+ if (val == 0xF9)
+ val = 0x7F;
+ return val;
+}
+
+static u8 rbppc_cf_check_altstatus(struct ata_port *ap) {
+ u8 val = ioread8(ap->ioaddr.altstatus_addr);
+ if (val == 0xF9)
+ val = 0x7F;
+ return val;
+}
+
+static void rbppc_cf_dummy_noret(struct ata_port *ap) { }
+static int rbppc_cf_dummy_ret0(struct ata_port *ap) { return 0; }
+
+static int ps2clk(int ps, unsigned clk_time_ps) {
+ int psMaxOver;
+ if (ps <= 0) return 0;
+
+ /* round down if <= 2% over clk border, but no more than 1/4 clk cycle */
+ psMaxOver = ps * 2 / 100;
+ if (4 * psMaxOver > clk_time_ps) {
+ psMaxOver = clk_time_ps / 4;
+ }
+ return (ps + clk_time_ps - 1 - psMaxOver) / clk_time_ps;
+}
+
+static int upm_gen_ps_table(const struct upm_setting *upm,
+ int mode, struct rbppc_cf_info *info,
+ int *psFinal) {
+ int uidx;
+ int lastUpmValIdx = 0;
+ int group_start_idx = -1;
+ int group_left_num = -1;
+ int clk_time_ps = info->clk_time_ps;
+
+ for (uidx = 0; upm[uidx].value != EOF_UPM_SETTINGS; ++uidx) {
+ const struct upm_setting *us = upm + uidx;
+ unsigned opt = us->options;
+ int ps = us->ns[mode] * 1000 - us->clk_minus * clk_time_ps;
+
+ if (opt & OA_CPUIN_MIN) ps += info->lb_timings[LBT_CPUIN_MIN];
+ if (opt & OD_CPUOUT_MIN) ps -= info->lb_timings[LBT_CPUOUT_MIN];
+ if (opt & OA_CPUOUT_MAX) ps += info->lb_timings[LBT_CPUOUT_MAX];
+ if (opt & OD_EXTDEL_MIN) ps -= info->lb_timings[LBT_EXTDEL_MIN];
+ if (opt & OA_EXTDEL_MAX) ps += info->lb_timings[LBT_EXTDEL_MAX];
+
+ if (us->value == ANOTHER_TIMING) {
+ /* use longest timing from alternatives */
+ if (psFinal[lastUpmValIdx] < ps) {
+ psFinal[lastUpmValIdx] = ps;
+ }
+ ps = 0;
+ }
+ else {
+ if (us->group_size) {
+ group_start_idx = uidx;
+ group_left_num = us->group_size;
+ }
+ else if (group_left_num > 0) {
+ /* group time is divided on all group members */
+ int clk = ps2clk(ps, clk_time_ps);
+ psFinal[group_start_idx] -= clk * clk_time_ps;
+ --group_left_num;
+ }
+ if ((opt & O_MINUS_PREV) && lastUpmValIdx > 0) {
+ int clk = ps2clk(psFinal[lastUpmValIdx],
+ clk_time_ps);
+ ps -= clk * clk_time_ps;
+ }
+ lastUpmValIdx = uidx;
+ }
+ psFinal[uidx] = ps;
+ }
+ return uidx;
+}
+
+static int free_half(int ps, int clk, int clk_time_ps) {
+ if (clk < 2) return 0;
+ return (clk * clk_time_ps - ps) * 2 >= clk_time_ps;
+}
+
+static void upm_gen_clk_table(const struct upm_setting *upm,
+ int mode, int clk_time_ps,
+ int max_uidx, const int *psFinal, int *clkFinal) {
+ int clk_cycle_time;
+ int clk_total;
+ int uidx;
+
+ /* convert picoseconds to clocks */
+ clk_total = 0;
+ for (uidx = 0; uidx < max_uidx; ++uidx) {
+ int clk = ps2clk(psFinal[uidx], clk_time_ps);
+ clkFinal[uidx] = clk;
+ clk_total += clk;
+ }
+
+ /* check possibility of half cycle usage */
+ for (uidx = 1; uidx < max_uidx - 1; ++uidx) {
+ if ((upm[uidx].options & O_HALF_CYCLE) &&
+ free_half(psFinal[uidx - 1], clkFinal[uidx - 1],
+ clk_time_ps) &&
+ free_half(psFinal[uidx + 1], clkFinal[uidx + 1],
+ clk_time_ps)) {
+ ++clkFinal[uidx];
+ --clkFinal[uidx - 1];
+ --clkFinal[uidx + 1];
+ }
+ }
+
+ if ((upm[max_uidx].options & O_MIN_CYCLE_TIME) == 0) return;
+
+ /* check cycle time, adjust timings if needed */
+ clk_cycle_time = (ps2clk(upm[max_uidx].ns[mode] * 1000, clk_time_ps) -
+ upm[max_uidx].clk_minus);
+ uidx = 0;
+ while (clk_total < clk_cycle_time) {
+ /* extend all timings in round-robin to match cycle time */
+ if (clkFinal[uidx]) {
+#if DEBUG_UPM
+ printk(KERN_INFO "extending %u by 1 clk\n", uidx);
+#endif
+ ++clkFinal[uidx];
+ ++clk_total;
+ }
+ ++uidx;
+ if (uidx == max_uidx) uidx = 0;
+ }
+}
+
+static void add_data_val(unsigned val, int *clkLeft, int maxClk,
+ unsigned *data, int *dataIdx) {
+ if (*clkLeft == 0) return;
+
+ if (maxClk == 0 && *clkLeft >= LOOP_SIZE * 2) {
+ int times;
+ int times1;
+ int times2;
+
+ times = *clkLeft / LOOP_SIZE;
+ if (times > REDO_MAX_MULT * 2) times = REDO_MAX_MULT * 2;
+ times1 = times / 2;
+ times2 = times - times1;
+
+ val |= LOOP;
+ data[*dataIdx] = val | REDO_VAL(times1);
+ ++(*dataIdx);
+ data[*dataIdx] = val | REDO_VAL(times2);
+ ++(*dataIdx);
+
+ *clkLeft -= times * LOOP_SIZE;
+ return;
+ }
+
+ if (maxClk < 1 || maxClk > REDO_MAX_MULT) maxClk = REDO_MAX_MULT;
+ if (*clkLeft < maxClk) maxClk = *clkLeft;
+
+ *clkLeft -= maxClk;
+ val |= REDO_VAL(maxClk);
+
+ data[*dataIdx] = val;
+ ++(*dataIdx);
+}
+
+static int upm_gen_final_data(const struct upm_setting *upm,
+ int max_uidx, int *clkFinal, unsigned *data) {
+ int dataIdx;
+ int uidx;
+
+ dataIdx = 0;
+ for (uidx = 0; uidx < max_uidx; ++uidx) {
+ int clk = clkFinal[uidx];
+ while (clk > 0) {
+ add_data_val(upm[uidx].value, &clk, 0,
+ data, &dataIdx);
+ }
+ }
+ return dataIdx;
+}
+
+static int conv_upm_table(const struct upm_setting *upm,
+ int mode, struct rbppc_cf_info *info,
+ unsigned *data) {
+#if DEBUG_UPM
+ int uidx;
+#endif
+ int psFinal[32];
+ int clkFinal[32];
+ int max_uidx;
+ int data_len;
+
+ max_uidx = upm_gen_ps_table(upm, mode, info, psFinal);
+
+ upm_gen_clk_table(upm, mode, info->clk_time_ps, max_uidx,
+ psFinal, clkFinal);
+
+#if DEBUG_UPM
+ /* dump out debug info */
+ for (uidx = 0; uidx < max_uidx; ++uidx) {
+ if (clkFinal[uidx]) {
+ printk(KERN_INFO "idx %d val %08x clk %d ps %d\n",
+ uidx, upm[uidx].value,
+ clkFinal[uidx], psFinal[uidx]);
+ }
+ }
+#endif
+
+ data_len = upm_gen_final_data(upm, max_uidx, clkFinal, data);
+
+#if DEBUG_UPM
+ for (uidx = 0; uidx < data_len; ++uidx) {
+ printk(KERN_INFO "cf UPM x result: idx %d val %08x\n",
+ uidx, data[uidx]);
+ }
+#endif
+ return 0;
+}
+
+static int gen_upm_data(int mode, struct rbppc_cf_info *info, unsigned *data) {
+ int i;
+
+ for (i = 0; i < UPM_DATA_SIZE; ++i) {
+ data[i] = EMPTY;
+ }
+
+ if (conv_upm_table(cfUpmReadSingle, mode, info, data + UPM_READ_SINGLE_OFFSET)) {
+ return -1;
+ }
+ if (conv_upm_table(cfUpmWriteSingle, mode, info, data + UPM_WRITE_SINGLE_OFFSET)) {
+ return -1;
+ }
+ return 0;
+}
+
+static void rbppc_cf_program_upm(void *upmMemAddr, volatile void *lbcfg_mxmr, volatile void *lbcfg_mdr, const unsigned *upmData, unsigned offset, unsigned len) {
+ unsigned i;
+ unsigned mxmr;
+
+ mxmr = in_be32(lbcfg_mxmr);
+ mxmr &= ~(MxMR_OP_MASK | MxMR_MAD_MASK);
+ mxmr |= (MxMR_OP_WRITE | offset);
+ out_be32(lbcfg_mxmr, mxmr);
+ in_be32(lbcfg_mxmr); /* flush MxMR write */
+
+ for (i = 0; i < len; ++i) {
+ int to;
+ unsigned data = upmData[i + offset];
+ out_be32(lbcfg_mdr, data);
+ in_be32(lbcfg_mdr); /* flush MDR write */
+
+ iowrite8(1, upmMemAddr); /* dummy write to any CF addr */
+
+ /* wait for dummy write to complete */
+ for (to = 10000; to >= 0; --to) {
+ mxmr = in_be32(lbcfg_mxmr);
+ if (((mxmr ^ (i + 1)) & MxMR_MAD_MASK) == 0) {
+ break;
+ }
+ if (to == 0) {
+ printk(KERN_ERR "rbppc_cf_program_upm: UPMx program error at 0x%x: Timeout\n", i);
+ }
+ }
+ }
+ mxmr &= ~(MxMR_OP_MASK | MxMR_RLF_MASK | MxMR_WLF_MASK);
+ mxmr |= (MxMR_OP_NORMAL | (LOOP_SIZE << MxMR_RLF_SHIFT) | (LOOP_SIZE << MxMR_WLF_SHIFT));
+ out_be32(lbcfg_mxmr, mxmr);
+}
+
+static int rbppc_cf_update_piomode(struct ata_port *ap, int mode) {
+ struct rbppc_cf_info *info = (struct rbppc_cf_info *)ap->host->private_data;
+ void *lbcfgBase;
+ unsigned upmData[UPM_DATA_SIZE];
+
+ if (gen_upm_data(mode, info, upmData)) {
+ return -1;
+ }
+
+ lbcfgBase = ioremap_nocache(info->lbcfg_addr, IMMR_LBCFG_SIZE);
+
+ rbppc_cf_program_upm(ap->ioaddr.cmd_addr, ((char *)lbcfgBase) + LOCAL_BUS_MCMR, ((char *)lbcfgBase) + LOCAL_BUS_MDR, upmData, 0, UPM_DATA_SIZE);
+ iounmap(lbcfgBase);
+ return 0;
+}
+
+static void rbppc_cf_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct rbppc_cf_info *info = (struct rbppc_cf_info *)ap->host->private_data;
+ int mode = adev->pio_mode - XFER_PIO_0;
+
+ DPRINTK("rbppc_cf_set_piomode: PIO %d\n", mode);
+ if (mode < 0) mode = 0;
+ if (mode > 6) mode = 6;
+
+ if (info->cur_mode < 0 || info->cur_mode > mode) {
+ if (rbppc_cf_update_piomode(ap, mode) == 0) {
+ printk(KERN_INFO "rbppc_cf_set_piomode: PIO mode changed to %d\n", mode);
+ info->cur_mode = mode;
+ }
+ }
+}
+
+static struct scsi_host_template rbppc_cf_sht = {
+ ATA_BASE_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations rbppc_cf_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .sff_check_status = rbppc_cf_check_status,
+ .sff_check_altstatus = rbppc_cf_check_altstatus,
+
+ .set_piomode = rbppc_cf_set_piomode,
+
+ .port_start = rbppc_cf_dummy_ret0,
+
+ .sff_irq_clear = rbppc_cf_dummy_noret,
+};
+
+static int rbppc_cf_init_info(struct of_device *pdev, struct rbppc_cf_info *info) {
+ struct device_node *np;
+ struct resource res;
+ const u32 *u32ptr;
+ void *lbcfgBase;
+ void *lbcfg_lcrr;
+ unsigned lbc_clk_khz;
+ unsigned lbc_extra_divider = 1;
+ unsigned ccb_freq_hz;
+ unsigned lb_div;
+
+ u32ptr = of_get_property(pdev->node, "lbc_extra_divider", NULL);
+ if (u32ptr && *u32ptr) {
+ lbc_extra_divider = *u32ptr;
+#if DEBUG_UPM
+ printk(KERN_INFO "rbppc_cf_init_info: LBC extra divider %u\n",
+ lbc_extra_divider);
+#endif
+ }
+
+ np = of_find_node_by_type(NULL, "serial");
+ if (!np) {
+ printk(KERN_ERR "rbppc_cf_init_info: No serial node found\n");
+ return -1;
+ }
+ u32ptr = of_get_property(np, "clock-frequency", NULL);
+ if (u32ptr == 0 || *u32ptr == 0) {
+ printk(KERN_ERR "rbppc_cf_init_info: Serial does not have clock-frequency\n");
+ of_node_put(np);
+ return -1;
+ }
+ ccb_freq_hz = *u32ptr;
+ of_node_put(np);
+
+ np = of_find_node_by_type(NULL, "soc");
+ if (!np) {
+ printk(KERN_ERR "rbppc_cf_init_info: No soc node found\n");
+ return -1;
+ }
+ if (of_address_to_resource(np, 0, &res)) {
+ printk(KERN_ERR "rbppc_cf_init_info: soc does not have resource\n");
+ of_node_put(np);
+ return -1;
+ }
+ info->lbcfg_addr = res.start + IMMR_LBCFG_OFFSET;
+ of_node_put(np);
+
+ lbcfgBase = ioremap_nocache(info->lbcfg_addr, IMMR_LBCFG_SIZE);
+ lbcfg_lcrr = ((char*)lbcfgBase) + LOCAL_BUS_LCRR;
+ lb_div = (in_be32(lbcfg_lcrr) & LCRR_CLKDIV_MASK) * lbc_extra_divider;
+ iounmap(lbcfgBase);
+
+ lbc_clk_khz = ccb_freq_hz / (1000 * lb_div);
+ info->clk_time_ps = 1000000000 / lbc_clk_khz;
+ printk(KERN_INFO "rbppc_cf_init_info: Using Local-Bus clock %u kHz %u ps\n",
+ lbc_clk_khz, info->clk_time_ps);
+
+ u32ptr = of_get_property(pdev->node, "lb-timings", NULL);
+ if (u32ptr) {
+ memcpy(info->lb_timings, u32ptr, LBT_SIZE * sizeof(*u32ptr));
+#if DEBUG_UPM
+ printk(KERN_INFO "rbppc_cf_init_info: Got LB timings <%u %u %u %u %u>\n",
+ u32ptr[0], u32ptr[1], u32ptr[2], u32ptr[3], u32ptr[4]);
+#endif
+ }
+ info->cur_mode = -1;
+ return 0;
+}
+
+static int rbppc_cf_probe(struct of_device *pdev,
+ const struct of_device_id *match)
+{
+ struct ata_host *host;
+ struct ata_port *ap;
+ struct rbppc_cf_info *info = NULL;
+ struct resource res;
+ void *baddr;
+ const u32 *u32ptr;
+ int irq_level = 0;
+ int err = -ENOMEM;
+
+ printk(KERN_INFO "rbppc_cf_probe: MikroTik RouterBOARD 600 series Compact Flash PATA driver, version " DRV_VERSION "\n");
+
+ if (rbinfo == NULL) {
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL) {
+ printk(KERN_ERR "rbppc_cf_probe: Out of memory\n");
+ goto err_info;
+ }
+ memset(info, 0, sizeof(*info));
+
+ if (rbppc_cf_init_info(pdev, info)) {
+ goto err_info;
+ }
+ rbinfo = info;
+ }
+
+ u32ptr = of_get_property(pdev->node, "interrupt-at-level", NULL);
+ if (u32ptr) {
+ irq_level = *u32ptr;
+ printk(KERN_INFO "rbppc_cf_probe: IRQ level %u\n", irq_level);
+ }
+
+ if (of_address_to_resource(pdev->node, 0, &res)) {
+ printk(KERN_ERR "rbppc_cf_probe: No reg property found\n");
+ goto err_info;
+ }
+
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto err_info;
+
+ baddr = localbus_map(res.start, res.end - res.start + 1);
+ host->iomap = baddr;
+ host->private_data = rbinfo;
+
+ ap = host->ports[0];
+ ap->ops = &rbppc_cf_port_ops;
+ ap->pio_mask = 0x7F; /* PIO modes 0-6 */
+ ap->flags = ATA_FLAG_NO_LEGACY;
+ ap->mwdma_mask = 0;
+
+ ap->ioaddr.cmd_addr = baddr;
+ ata_sff_std_ports(&ap->ioaddr);
+ ap->ioaddr.ctl_addr = ap->ioaddr.cmd_addr + 14;
+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
+ ap->ioaddr.bmdma_addr = 0;
+
+ err = ata_host_activate(
+ host,
+ irq_of_parse_and_map(pdev->node, 0), ata_sff_interrupt,
+ irq_level ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW,
+ &rbppc_cf_sht);
+ if (!err) return 0;
+
+ localbus_unmap(baddr);
+err_info:
+ if (info) {
+ kfree(info);
+ rbinfo = NULL;
+ }
+ return err;
+}
+
+static int rbppc_cf_remove(struct of_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ata_host *host = dev_get_drvdata(dev);
+
+ if (host == NULL) return -1;
+
+ ata_host_detach(host);
+ return 0;
+}
+
+static struct of_device_id rbppc_cf_ids[] = {
+ { .name = "cf", },
+ { },
+};
+
+static struct of_platform_driver rbppc_cf_driver = {
+ .name = "cf",
+ .probe = rbppc_cf_probe,
+ .remove = rbppc_cf_remove,
+ .match_table = rbppc_cf_ids,
+ .driver = {
+ .name = "rbppc-cf",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init rbppc_init(void)
+{
+ return of_register_platform_driver(&rbppc_cf_driver);
+}
+
+static void __exit rbppc_exit(void)
+{
+ of_unregister_platform_driver(&rbppc_cf_driver);
+}
+
+MODULE_AUTHOR("Mikrotikls SIA");
+MODULE_AUTHOR("Noah Fontes");
+MODULE_DESCRIPTION("MikroTik RouterBOARD 600 series Compact Flash PATA driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(rbppc_init);
+module_exit(rbppc_exit);

View File

@ -0,0 +1,16 @@
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -439,6 +439,13 @@ config MTD_NAND_PLATFORM
devices. You will need to provide platform-specific functions
via platform_data.
+config MTD_NAND_RB_PPC
+ tristate "MikroTik RB600 NAND support"
+ depends on MTD_NAND && MTD_PARTITIONS && RB_PPC
+ help
+ This option enables support for the NAND device on MikroTik
+ RouterBOARD 600 series boards.
+
config MTD_ALAUDA
tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
depends on USB

View File

@ -0,0 +1,10 @@
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx27
obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
+obj-$(CONFIG_MTD_NAND_RB_PPC) += rbppc_nand.o
obj-$(CONFIG_MTD_ALAUDA) += alauda.o
obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o

View File

@ -0,0 +1,255 @@
--- /dev/null
+++ b/drivers/mtd/nand/rbppc_nand.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
+ * Copyright (C) Mikrotik 2007
+ *
+ * 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/init.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
+#include <asm/of_platform.h>
+#include <asm/of_device.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#define DRV_NAME "rbppc_nand"
+#define DRV_VERSION "0.0.2"
+
+static struct mtd_info rmtd;
+static struct nand_chip rnand;
+
+struct rbppc_nand_info {
+ void *gpi;
+ void *gpo;
+ void *localbus;
+
+ unsigned gpio_rdy;
+ unsigned gpio_nce;
+ unsigned gpio_cle;
+ unsigned gpio_ale;
+ unsigned gpio_ctrls;
+};
+
+/* We must use the OOB layout from yaffs 1 if we want this to be recognized
+ * properly. Borrowed from the OpenWRT patches for the RB532.
+ *
+ * See <https://dev.openwrt.org/browser/trunk/target/linux/rb532/
+ * patches-2.6.28/025-rb532_nand_fixup.patch> for more details.
+ */
+static struct nand_ecclayout rbppc_nand_oob_16 = {
+ .eccbytes = 6,
+ .eccpos = { 8, 9, 10, 13, 14, 15 },
+ .oobavail = 9,
+ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
+};
+
+static struct mtd_partition rbppc_nand_partition_info[] = {
+ {
+ name: "kernel",
+ offset: 0,
+ size: 4 * 1024 * 1024,
+ },
+ {
+ name: "rootfs",
+ offset: MTDPART_OFS_NXTBLK,
+ size: MTDPART_SIZ_FULL,
+ },
+};
+
+static int rbppc_nand_dev_ready(struct mtd_info *mtd) {
+ struct nand_chip *chip = mtd->priv;
+ struct rbppc_nand_info *priv = chip->priv;
+
+ return in_be32(priv->gpi) & priv->gpio_rdy;
+}
+
+static void rbppc_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) {
+ struct nand_chip *chip = mtd->priv;
+ struct rbppc_nand_info *priv = chip->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned val = in_be32(priv->gpo);
+ if (!(val & priv->gpio_nce)) {
+ /* make sure Local Bus has done NAND operations */
+ readb(priv->localbus);
+ }
+
+ if (ctrl & NAND_CLE) {
+ val |= priv->gpio_cle;
+ } else {
+ val &= ~priv->gpio_cle;
+ }
+ if (ctrl & NAND_ALE) {
+ val |= priv->gpio_ale;
+ } else {
+ val &= ~priv->gpio_ale;
+ }
+ if (!(ctrl & NAND_NCE)) {
+ val |= priv->gpio_nce;
+ } else {
+ val &= ~priv->gpio_nce;
+ }
+ out_be32(priv->gpo, val);
+
+ /* make sure GPIO output has changed */
+ val ^= in_be32(priv->gpo);
+ if (val & priv->gpio_ctrls) {
+ printk(KERN_ERR "rbppc_nand_hwcontrol: NAND GPO change failed 0x%08x\n", val);
+ }
+ }
+
+ if (cmd != NAND_CMD_NONE) writeb(cmd, chip->IO_ADDR_W);
+}
+
+static void rbppc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ memcpy(buf, chip->IO_ADDR_R, len);
+}
+
+static unsigned init_ok = 0;
+
+static int rbppc_nand_probe(struct of_device *pdev,
+ const struct of_device_id *match)
+{
+ struct device_node *gpio;
+ struct device_node *nnand;
+ struct resource res;
+ struct rbppc_nand_info *info;
+ void *baddr;
+ const unsigned *rdy, *nce, *cle, *ale;
+
+ printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 600 series NAND driver, version " DRV_VERSION "\n");
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+
+ rdy = of_get_property(pdev->node, "rdy", NULL);
+ nce = of_get_property(pdev->node, "nce", NULL);
+ cle = of_get_property(pdev->node, "cle", NULL);
+ ale = of_get_property(pdev->node, "ale", NULL);
+
+ if (!rdy || !nce || !cle || !ale) {
+ printk(KERN_ERR "rbppc_nand_probe: GPIO properties are missing\n");
+ goto err;
+ }
+ if (rdy[0] != nce[0] || rdy[0] != cle[0] || rdy[0] != ale[0]) {
+ printk(KERN_ERR "rbppc_nand_probe: Different GPIOs are not supported\n");
+ goto err;
+ }
+
+ gpio = of_find_node_by_phandle(rdy[0]);
+ if (!gpio) {
+ printk(KERN_ERR "rbppc_nand_probe: No GPIO<%x> node found\n", *rdy);
+ goto err;
+ }
+ if (of_address_to_resource(gpio, 0, &res)) {
+ printk(KERN_ERR "rbppc_nand_probe: No reg property in GPIO found\n");
+ goto err;
+ }
+ info->gpo = ioremap_nocache(res.start, res.end - res.start + 1);
+
+ if (!of_address_to_resource(gpio, 1, &res)) {
+ info->gpi = ioremap_nocache(res.start, res.end - res.start + 1);
+ } else {
+ info->gpi = info->gpo;
+ }
+ of_node_put(gpio);
+
+ info->gpio_rdy = 1 << (31 - rdy[1]);
+ info->gpio_nce = 1 << (31 - nce[1]);
+ info->gpio_cle = 1 << (31 - cle[1]);
+ info->gpio_ale = 1 << (31 - ale[1]);
+ info->gpio_ctrls = info->gpio_nce | info->gpio_cle | info->gpio_ale;
+
+ nnand = of_find_node_by_name(NULL, "nnand");
+ if (!nnand) {
+ printk("rbppc_nand_probe: No nNAND found\n");
+ goto err;
+ }
+ if (of_address_to_resource(nnand, 0, &res)) {
+ printk("rbppc_nand_probe: No reg property in nNAND found\n");
+ goto err;
+ }
+ of_node_put(nnand);
+ info->localbus = ioremap_nocache(res.start, res.end - res.start + 1);
+
+ if (of_address_to_resource(pdev->node, 0, &res)) {
+ printk("rbppc_nand_probe: No reg property found\n");
+ goto err;
+ }
+ baddr = ioremap_nocache(res.start, res.end - res.start + 1);
+
+ memset(&rnand, 0, sizeof(rnand));
+ rnand.cmd_ctrl = rbppc_nand_cmd_ctrl;
+ rnand.dev_ready = rbppc_nand_dev_ready;
+ rnand.read_buf = rbppc_nand_read_buf;
+ rnand.IO_ADDR_W = baddr;
+ rnand.IO_ADDR_R = baddr;
+ rnand.priv = info;
+
+ memset(&rmtd, 0, sizeof(rmtd));
+ rnand.ecc.mode = NAND_ECC_SOFT;
+ rnand.ecc.layout = &rbppc_nand_oob_16;
+ rnand.chip_delay = 25;
+ rnand.options |= NAND_NO_AUTOINCR;
+ rmtd.priv = &rnand;
+ rmtd.owner = THIS_MODULE;
+
+ if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) {
+ printk(KERN_ERR "rbppc_nand_probe: RouterBOARD NAND device not found\n");
+ return -ENXIO;
+ }
+
+ add_mtd_partitions(&rmtd, rbppc_nand_partition_info, 2);
+ init_ok = 1;
+ return 0;
+
+err:
+ kfree(info);
+ return -1;
+}
+
+static struct of_device_id rbppc_nand_ids[] = {
+ { .name = "nand", },
+ { },
+};
+
+static struct of_platform_driver rbppc_nand_driver = {
+ .name = "nand",
+ .probe = rbppc_nand_probe,
+ .match_table = rbppc_nand_ids,
+ .driver = {
+ .name = "rbppc-nand",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init rbppc_nand_init(void)
+{
+ return of_register_platform_driver(&rbppc_nand_driver);
+}
+
+static void __exit rbppc_nand_exit(void)
+{
+ of_unregister_platform_driver(&rbppc_nand_driver);
+}
+
+MODULE_AUTHOR("Mikrotikls SIA");
+MODULE_AUTHOR("Noah Fontes");
+MODULE_AUTHOR("Michael Guntsche");
+MODULE_DESCRIPTION("MikroTik RouterBOARD 600 series NAND driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(rbppc_nand_init);
+module_exit(rbppc_nand_exit);

View File

@ -0,0 +1,319 @@
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/rbppc.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
+ * Copyright (C) Mikrotik 2007
+ *
+ * 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/delay.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include "mpc83xx.h"
+
+#define SYSCTL 0x100
+#define SICRL 0x014
+
+#define GTCFR2 0x04
+#define GTMDR4 0x22
+#define GTRFR4 0x26
+#define GTCNR4 0x2e
+#define GTVER4 0x36
+#define GTPSR4 0x3e
+
+#define GTCFR_BCM 0x40
+#define GTCFR_STP4 0x20
+#define GTCFR_RST4 0x10
+#define GTCFR_STP3 0x02
+#define GTCFR_RST3 0x01
+
+#define GTMDR_ORI 0x10
+#define GTMDR_FRR 0x08
+#define GTMDR_ICLK16 0x04
+
+extern int par_io_data_set(u8 port, u8 pin, u8 val);
+extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq);
+
+static unsigned timer_freq;
+static void *gtm;
+
+static int beeper_irq;
+static unsigned beeper_gpio_pin[2];
+
+irqreturn_t rbppc_timer_irq(int irq, void *ptr)
+{
+ static int toggle = 0;
+
+ par_io_data_set(beeper_gpio_pin[0], beeper_gpio_pin[1], toggle);
+ toggle = !toggle;
+
+ /* ack interrupt */
+ out_be16(gtm + GTVER4, 3);
+
+ return IRQ_HANDLED;
+}
+
+void rbppc_beep(unsigned freq)
+{
+ unsigned gtmdr;
+
+ if (freq > 5000) freq = 5000;
+
+ if (!gtm)
+ return;
+ if (!freq) {
+ out_8(gtm + GTCFR2, GTCFR_STP4 | GTCFR_STP3);
+ return;
+ }
+
+ out_8(gtm + GTCFR2, GTCFR_RST4 | GTCFR_STP3);
+ out_be16(gtm + GTPSR4, 255);
+ gtmdr = GTMDR_FRR | GTMDR_ICLK16;
+ if (beeper_irq != NO_IRQ) gtmdr |= GTMDR_ORI;
+ out_be16(gtm + GTMDR4, gtmdr);
+ out_be16(gtm + GTVER4, 3);
+
+ out_be16(gtm + GTRFR4, timer_freq / 16 / 256 / freq / 2);
+ out_be16(gtm + GTCNR4, 0);
+}
+EXPORT_SYMBOL(rbppc_beep);
+
+static void __init rbppc_setup_arch(void)
+{
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np) {
+ const unsigned *fp = of_get_property(np, "clock-frequency", NULL);
+ loops_per_jiffy = fp ? *fp / HZ : 0;
+
+ of_node_put(np);
+ }
+
+ np = of_find_node_by_name(NULL, "serial");
+ if (np) {
+ timer_freq =
+ *(unsigned *) of_get_property(np, "clock-frequency", NULL);
+ of_node_put(np);
+ }
+
+#ifdef CONFIG_PCI
+ np = of_find_node_by_type(NULL, "pci");
+ if (np) {
+ mpc83xx_add_bridge(np);
+ }
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_node_by_name(np, "par_io");
+ if (np) {
+ qe_reset();
+ par_io_init(np);
+ of_node_put(np);
+
+ np = NULL;
+ while (1) {
+ np = of_find_node_by_name(np, "ucc");
+ if (!np) break;
+
+ par_io_of_config(np);
+ }
+ }
+#endif
+
+}
+
+void __init rbppc_init_IRQ(void)
+{
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (np) {
+ ipic_init(np, 0);
+ ipic_set_default_priority();
+ of_node_put(np);
+ }
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_node_by_type(NULL, "qeic");
+ if (np) {
+ qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
+ of_node_put(np);
+ }
+#endif
+}
+
+static int __init rbppc_probe(void)
+{
+ char *model;
+
+ model = of_get_flat_dt_prop(of_get_flat_dt_root(), "model", NULL);
+
+ if (!model)
+ return 0;
+
+ if (strcmp(model, "RB600") == 0)
+ return 1;
+
+ return 0;
+}
+
+static void __init rbppc_beeper_init(struct device_node *beeper)
+{
+ struct resource res;
+ struct device_node *gpio;
+ const unsigned *pin;
+ const unsigned *gpio_id;
+
+ if (of_address_to_resource(beeper, 0, &res)) {
+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No region specified\n", beeper->full_name);
+ return;
+ }
+
+ pin = of_get_property(beeper, "gpio", NULL);
+ if (pin) {
+ gpio = of_find_node_by_phandle(pin[0]);
+
+ if (!gpio) {
+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: GPIO handle %x not found\n", beeper->full_name, pin[0]);
+ return;
+ }
+
+ gpio_id = of_get_property(gpio, "device-id", NULL);
+ if (!gpio_id) {
+ printk(KERN_ERR "rbppc_beeper_init(%s): Beeper error: No device-id specified in GPIO\n", beeper->full_name);
+ return;
+ }
+
+ beeper_gpio_pin[0] = *gpio_id;
+ beeper_gpio_pin[1] = pin[1];
+
+ par_io_config_pin(*gpio_id, pin[1], 1, 0, 0, 0);
+ } else {
+ void *sysctl;
+
+ sysctl = ioremap_nocache(get_immrbase() + SYSCTL, 0x100);
+ out_be32(sysctl + SICRL,
+ in_be32(sysctl + SICRL) | (1 << (31 - 19)));
+ iounmap(sysctl);
+ }
+
+ gtm = ioremap_nocache(res.start, res.end - res.start + 1);
+
+ beeper_irq = irq_of_parse_and_map(beeper, 0);
+ if (beeper_irq != NO_IRQ) {
+ int e = request_irq(beeper_irq, rbppc_timer_irq, 0, "beeper", NULL);
+ if (e) {
+ printk(KERN_ERR "rbppc_beeper_init(%s): Request of beeper irq failed!\n", beeper->full_name);
+ }
+ }
+}
+
+#define SBIT(x) (0x80000000 >> (x))
+#define DBIT(x, y) ((y) << (32 - (((x % 16) + 1) * 2)))
+
+#define SICRL_RB600(x) ((x) + (0x114 >> 2))
+#define GPIO_DIR_RB600(x) ((x) + (0xc00 >> 2))
+#define GPIO_DATA_RB600(x) ((x) + (0xc08 >> 2))
+
+static void rbppc_restart(char *cmd)
+{
+ __be32 __iomem *reg;
+
+ reg = ioremap(get_immrbase(), 0x1000);
+ local_irq_disable();
+ out_be32(SICRL_RB600(reg), in_be32(SICRL_RB600(reg)) & ~0x00800000);
+ out_be32(GPIO_DIR_RB600(reg), in_be32(GPIO_DIR_RB600(reg)) | SBIT(2));
+ out_be32(GPIO_DATA_RB600(reg), in_be32(GPIO_DATA_RB600(reg)) & ~SBIT(2));
+
+ while (1);
+}
+
+static void rbppc_halt(void)
+{
+ while (1);
+}
+
+static struct of_device_id rbppc_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .compatible = "simple-bus", },
+ { .compatible = "gianfar", },
+ { },
+};
+
+static int __init rbppc_declare_of_platform_devices(void)
+{
+ struct device_node *np;
+ unsigned idx;
+
+ of_platform_bus_probe(NULL, rbppc_ids, NULL);
+
+ np = of_find_node_by_type(NULL, "mdio");
+ if (np) {
+ unsigned len;
+ unsigned *res;
+ const unsigned *eres;
+ struct device_node *ep;
+
+ ep = of_find_compatible_node(NULL, "network", "ucc_geth");
+ if (ep) {
+ eres = of_get_property(ep, "reg", &len);
+ res = (unsigned *) of_get_property(np, "reg", &len);
+ if (res && eres) {
+ res[0] = eres[0] + 0x120;
+ }
+ }
+ }
+
+ np = of_find_node_by_name(NULL, "nand");
+ if (np) {
+ of_platform_device_create(np, "nand", NULL);
+ }
+
+ idx = 0;
+ for_each_node_by_type(np, "rb,cf") {
+ char dev_name[12];
+ snprintf(dev_name, sizeof(dev_name), "cf.%u", idx);
+ of_platform_device_create(np, dev_name, NULL);
+ ++idx;
+ }
+
+ np = of_find_node_by_name(NULL, "beeper");
+ if (np) {
+ rbppc_beeper_init(np);
+ }
+
+ return 0;
+}
+device_initcall(rbppc_declare_of_platform_devices);
+
+define_machine(rb600) {
+ .name = "MikroTik RouterBOARD 600 series",
+ .probe = rbppc_probe,
+ .setup_arch = rbppc_setup_arch,
+ .init_IRQ = rbppc_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = rbppc_restart,
+ .halt = rbppc_halt,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+};

View File

@ -0,0 +1,94 @@
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -166,7 +166,8 @@ all: zImage
# With make 3.82 we cannot mix normal and wildcard targets
BOOT_TARGETS1 := zImage zImage.initrd uImage
-BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
+BOOT_TARGETS2 := uImage.fit.% zImage% dtbImage% treeImage.% cuImage.% \
+ simpleImage.%
PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
@@ -199,6 +200,7 @@ define archhelp
@echo '* zImage - Build default images selected by kernel config'
@echo ' zImage.* - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
@echo ' uImage - U-Boot native image format'
+ @echo ' uImage.fit.<dt> - U-Boot Flattened Image Tree image format'
@echo ' cuImage.<dt> - Backwards compatible U-Boot image for older'
@echo ' versions which do not support device trees'
@echo ' dtbImage.<dt> - zImage with an embedded device tree blob'
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -19,6 +19,7 @@ kernel-vmlinux.strip.c
kernel-vmlinux.strip.gz
mktree
uImage
+uImage.fit.*
cuImage.*
dtbImage.*
treeImage.*
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -314,6 +314,9 @@ $(obj)/zImage.iseries: vmlinux
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
+$(obj)/uImage.fit.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+ $(call if_changed,wrap,uboot.fit,,$(obj)/$*.dtb)
+
$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
@@ -353,7 +356,7 @@ install: $(CONFIGURE) $(addprefix $(obj)
# anything not in $(targets)
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
- zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
+ uImage.* zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
zImage.iseries zImage.miboot zImage.pmac zImage.pseries \
zImage.maple simpleImage.* otheros.bld *.dtb
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -46,6 +46,9 @@ CROSS=
# mkimage wrapper script
MKIMAGE=$srctree/scripts/mkuboot.sh
+# script to generate an .its file for uImage.fit.* images
+MKITS=$srctree/scripts/mkits.sh
+
# directory for object and other files used by this script
object=arch/powerpc/boot
objbin=$object
@@ -161,7 +164,7 @@ coff)
lds=$object/zImage.coff.lds
link_address='0x500000'
;;
-miboot|uboot)
+miboot|uboot|uboot.fit)
# miboot and U-boot want just the bare bits, not an ELF binary
ext=bin
objflags="-O binary"
@@ -282,6 +285,21 @@ uboot)
if [ -z "$cacheit" ]; then
rm -f "$vmz"
fi
+ exit 0
+ ;;
+uboot.fit)
+ rm -f "$ofile"
+ ${MKITS} -A ppc -C gzip -a $membase -e $membase -v $version \
+ -d "$srctree/$dtb" -k "$srctree/$vmz" -o "$object/uImage.its"
+
+ # mkimage calls dtc for FIT images so use kernel dtc if necessary
+ export PATH=$PATH:$srctree/scripts/dtc
+
+ ${MKIMAGE} -f "$object/uImage.its" "$ofile"
+ rm "$object/uImage.its"
+ if [ -z "$cacheit" ]; then
+ rm -f "$vmz"
+ fi
exit 0
;;
esac

View File

@ -0,0 +1,207 @@
--- a/arch/powerpc/platforms/83xx/rbppc.c
+++ b/arch/powerpc/platforms/83xx/rbppc.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Alexandros C. Couloumbis <alex@ozo.com>
* Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
* Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
* Copyright (C) Mikrotik 2007
@@ -167,6 +168,9 @@ static int __init rbppc_probe(void)
if (!model)
return 0;
+ if (strcmp(model, "RB333") == 0)
+ return 1;
+
if (strcmp(model, "RB600") == 0)
return 1;
@@ -227,6 +231,9 @@ static void __init rbppc_beeper_init(str
#define SBIT(x) (0x80000000 >> (x))
#define DBIT(x, y) ((y) << (32 - (((x % 16) + 1) * 2)))
+#define GPIO_DIR_RB333(x) ((x) + (0x1408 >> 2))
+#define GPIO_DATA_RB333(x) ((x) + (0x1404 >> 2))
+
#define SICRL_RB600(x) ((x) + (0x114 >> 2))
#define GPIO_DIR_RB600(x) ((x) + (0xc00 >> 2))
#define GPIO_DATA_RB600(x) ((x) + (0xc08 >> 2))
@@ -234,14 +241,38 @@ static void __init rbppc_beeper_init(str
static void rbppc_restart(char *cmd)
{
__be32 __iomem *reg;
-
- reg = ioremap(get_immrbase(), 0x1000);
- local_irq_disable();
- out_be32(SICRL_RB600(reg), in_be32(SICRL_RB600(reg)) & ~0x00800000);
- out_be32(GPIO_DIR_RB600(reg), in_be32(GPIO_DIR_RB600(reg)) | SBIT(2));
- out_be32(GPIO_DATA_RB600(reg), in_be32(GPIO_DATA_RB600(reg)) & ~SBIT(2));
-
- while (1);
+ unsigned rb_model;
+ struct device_node *root;
+ unsigned int size;
+
+ root = of_find_node_by_path("/");
+ if (root) {
+ const char *prop = (char *) of_get_property(root, "model", &size);
+ rb_model = prop[sizeof("RB") - 1] - '0';
+ of_node_put(root);
+ switch (rb_model) {
+ case 3:
+ reg = ioremap(get_immrbase(), 0x2000);
+ local_irq_disable();
+ out_be32(GPIO_DIR_RB333(reg),
+ (in_be32(GPIO_DIR_RB333(reg)) & ~DBIT(4, 3)) | DBIT(4, 1));
+ out_be32(GPIO_DATA_RB333(reg), in_be32(GPIO_DATA_RB333(reg)) & ~SBIT(4));
+ break;
+ case 6:
+ reg = ioremap(get_immrbase(), 0x1000);
+ local_irq_disable();
+ out_be32(SICRL_RB600(reg), in_be32(SICRL_RB600(reg)) & ~0x00800000);
+ out_be32(GPIO_DIR_RB600(reg), in_be32(GPIO_DIR_RB600(reg)) | SBIT(2));
+ out_be32(GPIO_DATA_RB600(reg), in_be32(GPIO_DATA_RB600(reg)) & ~SBIT(2));
+ break;
+ default:
+ mpc83xx_restart(cmd);
+ break;
+ }
+ }
+ else mpc83xx_restart(cmd);
+
+ for (;;) ;
}
static void rbppc_halt(void)
@@ -301,10 +332,10 @@ static int __init rbppc_declare_of_platf
return 0;
}
-device_initcall(rbppc_declare_of_platform_devices);
+machine_device_initcall(rb600, rbppc_declare_of_platform_devices);
define_machine(rb600) {
- .name = "MikroTik RouterBOARD 600 series",
+ .name = "MikroTik RouterBOARD 333/600 series",
.probe = rbppc_probe,
.setup_arch = rbppc_setup_arch,
.init_IRQ = rbppc_init_IRQ,
@@ -314,3 +345,31 @@ define_machine(rb600) {
.time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
};
+
+static void fixup_pcibridge(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+ /* let the kernel itself set right memory windows */
+ pci_write_config_word(dev, PCI_MEMORY_BASE, 0);
+ pci_write_config_word(dev, PCI_MEMORY_LIMIT, 0);
+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, 0);
+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, 0);
+ pci_write_config_byte(dev, PCI_IO_BASE, 0);
+ pci_write_config_byte(dev, PCI_IO_LIMIT, 4 << 4);
+
+ pci_write_config_byte(
+ dev, PCI_COMMAND,
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+ }
+}
+
+
+static void fixup_rb604(struct pci_dev *dev)
+{
+ pci_write_config_byte(dev, 0xC0, 0x01);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_pcibridge)
+DECLARE_PCI_FIXUP_HEADER(0x3388, 0x0021, fixup_rb604)
+
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -440,11 +440,11 @@ config MTD_NAND_PLATFORM
via platform_data.
config MTD_NAND_RB_PPC
- tristate "MikroTik RB600 NAND support"
+ tristate "MikroTik RB 333/600 NAND support"
depends on MTD_NAND && MTD_PARTITIONS && RB_PPC
help
This option enables support for the NAND device on MikroTik
- RouterBOARD 600 series boards.
+ RouterBOARD 333/600 series boards.
config MTD_ALAUDA
tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
--- a/drivers/mtd/nand/rbppc_nand.c
+++ b/drivers/mtd/nand/rbppc_nand.c
@@ -126,7 +126,7 @@ static int rbppc_nand_probe(struct of_de
void *baddr;
const unsigned *rdy, *nce, *cle, *ale;
- printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 600 series NAND driver, version " DRV_VERSION "\n");
+ printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 333/600 series NAND driver, version " DRV_VERSION "\n");
info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -244,7 +244,7 @@ static void __exit rbppc_nand_exit(void)
MODULE_AUTHOR("Mikrotikls SIA");
MODULE_AUTHOR("Noah Fontes");
MODULE_AUTHOR("Michael Guntsche");
-MODULE_DESCRIPTION("MikroTik RouterBOARD 600 series NAND driver");
+MODULE_DESCRIPTION("MikroTik RouterBOARD 333/600 series NAND driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -39,13 +39,14 @@ config MPC832x_RDB
This option enables support for the MPC8323 RDB board.
config RB_PPC
- bool "MikroTik RouterBOARD 600 series"
+ bool "MikroTik RouterBOARD 333/600 series"
select DEFAULT_UIMAGE
select QUICC_ENGINE
+ select PPC_MPC832x
select PPC_MPC834x
select RB_IOMAP
help
- This option enables support for MikroTik RouterBOARD 600 series boards.
+ This option enables support for MikroTik RouterBOARD 333/600 series boards.
config MPC834x_MDS
bool "Freescale MPC834x MDS"
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -74,7 +74,7 @@ src-plat := of.c cuboot-52xx.c cuboot-82
cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
- cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c rb600.c \
+ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c rb600.c rb333.c \
cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
@@ -235,7 +235,8 @@ image-$(CONFIG_MPC834x_ITX) += cuImage.
image-$(CONFIG_MPC834x_MDS) += cuImage.mpc834x_mds
image-$(CONFIG_MPC836x_MDS) += cuImage.mpc836x_mds
image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot
-image-$(CONFIG_RB_PPC) += dtbImage.rb600
+image-$(CONFIG_RB_PPC) += dtbImage.rb600 \
+ dtbImage.rb333
# Board ports in arch/powerpc/platform/85xx/Kconfig
image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -212,7 +212,7 @@ ps3)
isection=.kernel:initrd
link_address=''
;;
-ep88xc|ep405|ep8248e|rb600)
+ep88xc|ep405|ep8248e|rb600|rb333)
platformo="$object/fixed-head.o $object/$platform.o"
binary=y
;;

View File

@ -0,0 +1,435 @@
--- /dev/null
+++ b/arch/powerpc/boot/dts/rb333.dts
@@ -0,0 +1,432 @@
+
+/*
+ * RouterBOARD 333 series Device Tree Source
+ *
+ * Copyright 2010 Alexandros C. Couloumbis <alex@ozo.com>
+ * Copyright 2009 Michael Guntsche <mike@it-loops.com>
+ *
+ * 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.
+ *
+ * Warning (reg_format): "reg" property in /qe@e0100000/muram@10000/data-only@0 has invalid length (8 bytes) (#address-cells == 2, #size-cells == 1)
+ * Warning (ranges_format): "ranges" property in /qe@e0100000/muram@10000 has invalid length (12 bytes) (parent #address-cells == 1, child #address-cells == 2, #size-cells == 1)
+ * Warning (avoid_default_addr_size): Relying on default #address-cells value for /qe@e0100000/muram@10000/data-only@0
+ * Warning (avoid_default_addr_size): Relying on default #size-cells value for /qe@e0100000/muram@10000/data-only@0
+ * Warning (obsolete_chosen_interrupt_controller): /chosen has obsolete "interrupt-controller" property
+ *
+ */
+
+
+/dts-v1/;
+
+/ {
+ model = "RB333";
+ compatible = "MPC83xx";
+ #size-cells = <1>;
+ #address-cells = <1>;
+
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ pci0 = &pci0;
+ };
+
+
+ chosen {
+ bootargs = "console=ttyS0,115200 board=mpc8323 rootfstype=squashfs,yaffs2,jffs2 root=/dev/mtdblock1 boot=1";
+ // linux,platform = <0x8062>;
+ // linux,initrd = <0x488000 0x0>;
+ linux,stdout-path = "/soc8323@e0000000/serial@4500";
+ // interrupt-controller = <&ipic>;
+ };
+
+ cpus {
+ #cpus = <1>;
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ PowerPC,8323E@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ i-cache-size = <0x4000>;
+ d-cache-size = <0x4000>;
+ i-cache-line-size = <0x20>;
+ d-cache-line-size = <0x20>;
+ // clock-frequency = <0x13de3650>;
+ // timebase-frequency = <0x1fc9f08>;
+ timebase-frequency = <0x0000000>; // filled by the bootwrapper from the firmware blob
+ clock-frequency = <0x00000000>; // filled by the bootwrapper from the firmware blob
+ 32-bit;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x4000000>;
+ // reg = <0x0 0x0000000>; // filled by the bootwrapper from the firmware blob
+ };
+
+ flash {
+ reg = <0xfe000000 0x20000>;
+ };
+
+ nand {
+ ale = <&gpio2 0x3>;
+ cle = <&gpio2 0x2>;
+ nce = <&gpio2 0x1>;
+ rdy = <&gpio2 0x0>;
+ reg = <0xf8000000 0x1000>;
+ device_type = "rb,nand";
+ };
+
+ nnand {
+ reg = <0xf0000000 0x1000>;
+ };
+
+ voltage {
+ voltage_gpio = <&gpio3 0x11>;
+ };
+
+ fancon {
+ interrupt-parent = <&ipic>;
+ interrupts = <0x14 0x8>;
+ fan_on = <&gpio0 0x10>;
+ };
+
+ pci0: pci@e0008500 {
+ device_type = "pci";
+ // compatible = "83xx";
+ compatible = "fsl,mpc8349-pci";
+ reg = <0xe0008500 0x100 0xe0008300 0x8>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ // clock-frequency = <0>;
+ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 0x1000000 0x0 0x0 0xd0000000 0x0 0x4000000>;
+ bus-range = <0x0 0x0>;
+ interrupt-map = <
+ /* IDSEL 0x10 AD16 miniPCI slot 0 */
+ 0x8000 0x0 0x0 0x1 &ipic 0x11 0x8
+ 0x8000 0x0 0x0 0x2 &ipic 0x12 0x8
+
+ /* IDSEL 0x11 AD17 miniPCI slot 1 */
+ 0x8800 0x0 0x0 0x1 &ipic 0x12 0x8
+ 0x8800 0x0 0x0 0x2 &ipic 0x13 0x8
+
+ /* IDSEL 0x12 AD18 miniPCI slot 2 */
+ 0x9000 0x0 0x0 0x1 &ipic 0x13 0x8
+ 0x9000 0x0 0x0 0x2 &ipic 0x11 0x8>;
+
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-parent = <&ipic>;
+ // interrupts = <66 0x8>;
+ };
+
+
+ qe@e0100000 {
+ reg = <0xe0100000 0x480>;
+ ranges = <0x0 0xe0100000 0x100000>;
+ model = "QE";
+ device_type = "qe";
+ compatible = "fsl,qe";
+ #size-cells = <1>;
+ #address-cells = <1>;
+ brg-frequency = <0>;
+ bus-frequency = <0>;
+ // bus-frequency = <198000000>;
+ fsl,qe-num-riscs = <1>;
+ fsl,qe-num-snums = <28>;
+
+ qeic: qeic@80 {
+ interrupt-controller;
+ compatible = "fsl,qe-ic";
+ big-endian;
+ built-in;
+ reg = <0x80 0x80>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ device_type = "qeic";
+ interrupts = <0x20 0x8 0x21 0x8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ mdio@2120 {
+ compatible = "ucc_geth_phy";
+ device_type = "mdio";
+ reg = <0x3120 0x18>;
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ phy3: ethernet-phy@03 {
+ // interface = <0x3>;
+ device_type = "ethernet-phy";
+ reg = <0x3>;
+ };
+
+ phy2: ethernet-phy@02 {
+ // interface = <0x3>;
+ device_type = "ethernet-phy";
+ reg = <0x2>;
+ };
+
+ phy1: ethernet-phy@01 {
+ // interface = <0x3>;
+ device_type = "ethernet-phy";
+ reg = <0x1>;
+ };
+ };
+
+ enet0: ucc@2200 {
+ tx-clock = <0x1a>;
+ rx-clock = <0x1f>;
+ mac-address = [00 0c 42 1c 29 d2];
+ interrupt-parent = <&qeic>;
+ interrupts = <0x22>;
+ reg = <0x2200 0x200>;
+ device-id = <0x3>;
+ model = "UCC";
+ compatible = "ucc_geth";
+ device_type = "network";
+ phy-handle = <&phy2>;
+ pio-handle = <&pio3>;
+ };
+
+ enet1: ucc@3200 {
+ tx-clock = <0x22>;
+ rx-clock = <0x20>;
+ mac-address = [00 0c 42 1c 29 d1];
+ interrupt-parent = <&qeic>;
+ interrupts = <0x23>;
+ reg = <0x3200 0x200>;
+ device-id = <0x4>;
+ model = "UCC";
+ compatible = "ucc_geth";
+ device_type = "network";
+ phy-handle = <&phy3>;
+ pio-handle = <&pio4>;
+ };
+
+ enet2: ucc@3000 {
+ tx-clock = <0x18>;
+ rx-clock = <0x17>;
+ mac-address = [00 0c 42 1c 29 d0];
+ interrupt-parent = <&qeic>;
+ interrupts = <0x21>;
+ reg = <0x3000 0x200>;
+ device-id = <0x2>;
+ model = "UCC";
+ compatible = "ucc_geth";
+ device_type = "network";
+ phy-handle = <&phy1>;
+ pio-handle = <&pio2>;
+ };
+
+ spi@500 {
+ mode = "cpu";
+ interrupt-parent = <&qeic>;
+ interrupts = <0x1>;
+ reg = <0x500 0x40>;
+ compatible = "fsl,spi";
+ device_type = "spi";
+ };
+
+ spi@4c0 {
+ mode = "cpu";
+ interrupt-parent = <&qeic>;
+ interrupts = <0x2>;
+ reg = <0x4c0 0x40>;
+ compatible = "fsl,spi";
+ device_type = "spi";
+ };
+
+ muram@10000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,qe-muram", "fsl,cpm-muram";
+ ranges = <0x0 0x10000 0x4000>;
+ device_type = "muram";
+
+ data-only@0 {
+ compatible = "fsl,qe-muram-data",
+ "fsl,cpm-muram-data";
+ reg = <0x0 0x4000>;
+ };
+ };
+ };
+
+
+ soc8323@e0000000 {
+ bus-frequency = <0x1>;
+ reg = <0xe0000000 0x200>;
+ ranges = <0x0 0xe0000000 0x100000>;
+ device_type = "soc";
+ compatible = "simple-bus";
+ #interrupt-cells = <0x2>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+
+ beeper {
+ gpio = <&gpio3 0x12>;
+ reg = <0x500 0x100>;
+ interrupt-parent = <&ipic>;
+ interrupts = <0x48 0x8>;
+ };
+
+ gpio3: gpio@3 {
+ reg = <0x144c 0x4>;
+ device-id = <0x3>;
+ compatible = "qe_gpio";
+ device_type = "gpio";
+ };
+
+ gpio2: gpio@2 {
+ reg = <0x1434 0x4>;
+ device-id = <0x2>;
+ compatible = "qe_gpio";
+ device_type = "gpio";
+ };
+
+ gpio0: gpio@0 {
+ reg = <0x1404 0x4>;
+ device-id = <0x0>;
+ compatible = "qe_gpio";
+ device_type = "gpio";
+ };
+
+ par_io@1400 {
+ num-ports = <4>;
+ device_type = "par_io";
+ reg = <0x1400 0x100>;
+
+ pio4: ucc_pin@04 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 1 18 1 0 1 0
+ 1 19 1 0 1 0
+ 1 20 1 0 1 0
+ 1 21 1 0 1 0
+ 1 30 1 0 1 0
+ 3 20 2 0 1 0
+ 1 30 2 0 1 0
+ 1 31 2 0 1 0
+ 1 22 2 0 1 0
+ 1 23 2 0 1 0
+ 1 24 2 0 1 0
+ 1 25 2 0 1 0
+ 1 28 2 0 1 0
+ 1 26 2 0 1 0
+ 3 21 2 0 1 0>;
+ };
+
+ pio3: ucc_pin@03 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 1 0 1 0 1 0
+ 1 1 1 0 1 0
+ 1 2 1 0 1 0
+ 1 3 1 0 1 0
+ 1 12 1 0 1 0
+ 3 24 2 0 1 0
+ 1 11 2 0 1 0
+ 1 13 2 0 1 0
+ 1 4 2 0 1 0
+ 1 5 2 0 1 0
+ 1 6 2 0 1 0
+ 1 7 2 0 1 0
+ 1 10 2 0 1 0
+ 1 8 2 0 1 0
+ 3 29 2 0 1 0>;
+ };
+
+ pio2: ucc_pin@02 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 3 4 3 0 2 0
+ 3 5 1 0 2 0
+ 0 18 1 0 1 0
+ 0 19 1 0 1 0
+ 0 20 1 0 1 0
+ 0 21 1 0 1 0
+ 0 30 1 0 1 0
+ 3 6 2 0 1 0
+ 0 29 2 0 1 0
+ 0 31 2 0 1 0
+ 0 22 2 0 1 0
+ 0 23 2 0 1 0
+ 0 24 2 0 1 0
+ 0 25 2 0 1 0
+ 0 28 2 0 1 0
+ 0 26 2 0 1 0
+ 3 31 2 0 1 0>;
+ };
+ };
+
+ ipic: pic@700 {
+ device_type = "ipic";
+ built-in;
+ reg = <0x700 0x100>;
+ #interrupt-cells = <0x2>;
+ #address-cells = <0x0>;
+ interrupt-controller;
+ };
+
+
+ serial@4500 {
+ interrupt-parent = <&ipic>;
+ interrupts = <0x9 0x8>;
+ clock-frequency = <0x7f27c20>;
+ reg = <0x4500 0x100>;
+ compatible = "ns16550";
+ device_type = "serial";
+ };
+
+ dma@82a8 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8323-dma", "fsl,elo-dma";
+ reg = <0x82a8 4>;
+ ranges = <0 0x8100 0x1a8>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
+ reg = <0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x180 0x28>;
+ cell-index = <3>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ };
+
+ wdt@200 {
+ reg = <0x200 0x100>;
+ compatible = "mpc83xx_wdt";
+ device_type = "watchdog";
+ };
+ };
+};

View File

@ -0,0 +1,76 @@
--- /dev/null
+++ b/arch/powerpc/boot/rb333.c
@@ -0,0 +1,73 @@
+/*
+ * The RouterBOARD platform -- for booting RB333 RouterBOARDs.
+ *
+ * Author: Alexandros C. Couloumbis <alex@ozo.com>
+ * Author: Michael Guntsche <mike@it-loops.com>
+ *
+ * Copyright (c) 2010 Alexandros C. Couloumbis
+ * Copyright (c) 2009 Michael Guntsche
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "types.h"
+#include "io.h"
+#include "stdio.h"
+#include <libfdt.h>
+
+BSS_STACK(4*1024);
+
+u64 memsize64;
+const void *fw_dtb;
+
+static void rb333_fixups(void)
+{
+ const u32 *reg, *timebase, *clock;
+ int node, size;
+ void *chosen;
+ const char* bootargs;
+
+ dt_fixup_memory(0, memsize64);
+
+ /* Find the CPU timebase and clock frequencies. */
+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "cpu", sizeof("cpu"));
+ timebase = fdt_getprop(fw_dtb, node, "timebase-frequency", &size);
+ clock = fdt_getprop(fw_dtb, node, "clock-frequency", &size);
+ dt_fixup_cpu_clocks(*clock, *timebase, 0);
+
+ /* Fixup chosen
+ * The bootloader reads the kernelparm segment and adds the content to
+ * bootargs. This is needed to specify root and other boot flags.
+ */
+ chosen = finddevice("/chosen");
+ node = fdt_path_offset(fw_dtb, "/chosen");
+ bootargs = fdt_getprop(fw_dtb, node, "bootargs", &size);
+ setprop_str(chosen, "bootargs", bootargs);
+}
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ const u32 *reg;
+ int node, size;
+
+ fw_dtb = (const void *)r3;
+
+ /* Find the memory range. */
+ node = fdt_node_offset_by_prop_value(fw_dtb, -1, "device_type", "memory", sizeof("memory"));
+ reg = fdt_getprop(fw_dtb, node, "reg", &size);
+ memsize64 = reg[1];
+
+ /* Now we have the memory size; initialize the heap. */
+ simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
+
+ /* Prepare the device tree and find the console. */
+ fdt_init(_dtb_start);
+ serial_console_init();
+
+ /* Remaining fixups... */
+ platform_ops.fixups = rb333_fixups;
+}

View File

@ -0,0 +1,11 @@
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -145,7 +145,7 @@ objflags=-S
tmp=$tmpdir/zImage.$$.o
ksection=.kernel:vmlinux.strip
isection=.kernel:initrd
-link_address='0x400000'
+link_address='0x490000'
case "$platform" in
pseries)

View File

@ -0,0 +1,71 @@
--- a/arch/powerpc/platforms/83xx/rbppc.c
+++ b/arch/powerpc/platforms/83xx/rbppc.c
@@ -121,21 +121,16 @@ static void __init rbppc_setup_arch(void
#endif
#ifdef CONFIG_QUICC_ENGINE
- np = of_find_node_by_name(np, "par_io");
- if (np) {
- qe_reset();
- par_io_init(np);
- of_node_put(np);
-
- np = NULL;
- while (1) {
- np = of_find_node_by_name(np, "ucc");
- if (!np) break;
+ qe_reset();
- par_io_of_config(np);
- }
- }
-#endif
+ if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
+ par_io_init(np);
+ of_node_put(np);
+
+ for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+ par_io_of_config(np);
+ }
+#endif
}
@@ -151,12 +146,16 @@ void __init rbppc_init_IRQ(void)
}
#ifdef CONFIG_QUICC_ENGINE
- np = of_find_node_by_type(NULL, "qeic");
- if (np) {
- qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
- of_node_put(np);
- }
-#endif
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+ if (!np) {
+ np = of_find_node_by_type(NULL, "qeic");
+ if (!np)
+ return;
+ }
+ qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
+ of_node_put(np);
+#endif /* CONFIG_QUICC_ENGINE */
+
}
static int __init rbppc_probe(void)
@@ -284,6 +283,8 @@ static struct of_device_id rbppc_ids[] =
{ .type = "soc", },
{ .compatible = "soc", },
{ .compatible = "simple-bus", },
+ { .type = "qe", },
+ { .compatible = "fsl,qe", },
{ .compatible = "gianfar", },
{ },
};
@@ -372,4 +373,3 @@ static void fixup_rb604(struct pci_dev *
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_pcibridge)
DECLARE_PCI_FIXUP_HEADER(0x3388, 0x0021, fixup_rb604)
-

View File

@ -0,0 +1,136 @@
--- a/arch/powerpc/boot/dts/rb600.dts
+++ b/arch/powerpc/boot/dts/rb600.dts
@@ -20,9 +20,11 @@
aliases {
ethernet0 = &enet0;
ethernet1 = &enet1;
+ pci0 = &pci0;
};
chosen {
+ bootargs = "console=ttyS0,115200 board=mpc8323 rootfstype=squashfs,yaffs2,jffs2 root=/dev/mtdblock1 boot=1";
linux,stdout-path = "/soc8343@e0000000/serial@4500";
};
@@ -150,6 +152,45 @@
device_type = "gpio";
};
+ dma@82a8 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
+ reg = <0x82a8 4>;
+ ranges = <0 0x8100 0x1a8>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <0>;
+ dma-channel@0 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <0 0x80>;
+ cell-index = <0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@80 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@100 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ dma-channel@180 {
+ compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
+ reg = <0x180 0x28>;
+ cell-index = <3>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ };
+ };
+
enet0: ethernet@25000 {
#address-cells = <1>;
#size-cells = <1>;
--- a/arch/powerpc/boot/rb600.c
+++ b/arch/powerpc/boot/rb600.c
@@ -45,14 +45,6 @@ static void rb600_fixups(void)
clock = fdt_getprop(fw_dtb, node, "clock-frequency", &size);
dt_fixup_cpu_clocks(*clock, *timebase, 0);
- /* Fixup chosen
- * The bootloader reads the kernelparm segment and adds the content to
- * bootargs. This is needed to specify root and other boot flags.
- */
- chosen = finddevice("/chosen");
- node = fdt_path_offset(fw_dtb, "/chosen");
- bootargs = fdt_getprop(fw_dtb, node, "bootargs", &size);
- setprop_str(chosen, "bootargs", bootargs);
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
--- a/arch/powerpc/platforms/83xx/rbppc.c
+++ b/arch/powerpc/platforms/83xx/rbppc.c
@@ -56,6 +56,8 @@ static void *gtm;
static int beeper_irq;
static unsigned beeper_gpio_pin[2];
+int rb333model = 0;
+
irqreturn_t rbppc_timer_irq(int irq, void *ptr)
{
static int toggle = 0;
@@ -120,6 +122,8 @@ static void __init rbppc_setup_arch(void
}
#endif
+if (rb333model) {
+
#ifdef CONFIG_QUICC_ENGINE
qe_reset();
@@ -132,6 +136,8 @@ static void __init rbppc_setup_arch(void
}
#endif
+} /* RB333 */
+
}
void __init rbppc_init_IRQ(void)
@@ -145,6 +151,8 @@ void __init rbppc_init_IRQ(void)
of_node_put(np);
}
+if (rb333model) {
+
#ifdef CONFIG_QUICC_ENGINE
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
if (!np) {
@@ -156,6 +164,8 @@ void __init rbppc_init_IRQ(void)
of_node_put(np);
#endif /* CONFIG_QUICC_ENGINE */
+} /* RB333 */
+
}
static int __init rbppc_probe(void)
@@ -167,8 +177,10 @@ static int __init rbppc_probe(void)
if (!model)
return 0;
- if (strcmp(model, "RB333") == 0)
+ if (strcmp(model, "RB333") == 0) {
+ rb333model = 1;
return 1;
+ }
if (strcmp(model, "RB600") == 0)
return 1;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
--- a/Makefile
+++ b/Makefile
@@ -358,6 +358,7 @@ KBUILD_AFLAGS := -D__ASSEMBLY__
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
+KBUILD_LDFLAGS_MODULE_PREREQ :=
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
@@ -367,7 +368,7 @@ export VERSION PATCHLEVEL SUBLEVEL KERNE
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP
export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
-export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE KBUILD_LDFLAGS_MODULE_PREREQ CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -94,7 +94,7 @@ else
endif
endif
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
+KBUILD_LDFLAGS_MODULE_PREREQ += arch/powerpc/lib/crtsavres.o
ifeq ($(CONFIG_TUNE_CELL),y)
KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -110,7 +110,14 @@ quiet_cmd_cc_o_c = CC $@
cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \
-c -o $@ $<
-$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
+quiet_cmd_as_o_S = AS $(quiet_modtag) $@
+cmd_as_o_S = $(CC) $(a_flags) $(AFLAGS_MODULE) -c -o $@ $<
+
+$(KBUILD_LDFLAGS_MODULE_PREREQ): %.o: %.S FORCE
+ $(Q)mkdir -p $(dir $@)
+ $(call if_changed_dep,as_o_S)
+
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c $(KBUILD_LDFLAGS_MODULE_PREREQ) FORCE
$(call if_changed_dep,cc_o_c)
targets += $(modules:.ko=.mod.o)
@@ -119,6 +126,7 @@ targets += $(modules:.ko=.mod.o)
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ $(KBUILD_LDFLAGS_MODULE_PREREQ) \
-o $@ $(filter-out FORCE,$^)
$(modules): %.ko :%.o %.mod.o FORCE

View File

@ -0,0 +1,37 @@
--- a/drivers/ata/pata_rbppc_cf.c
+++ b/drivers/ata/pata_rbppc_cf.c
@@ -15,6 +15,7 @@
#include <linux/libata.h>
#include <linux/of_platform.h>
#include <linux/ata_platform.h>
+#include <linux/slab.h>
#define DEBUG_UPM 0
@@ -510,7 +511,7 @@ static struct ata_port_operations rbppc_
.sff_irq_clear = rbppc_cf_dummy_noret,
};
-static int rbppc_cf_init_info(struct of_device *pdev, struct rbppc_cf_info *info) {
+static int rbppc_cf_init_info(struct platform_device *pdev, struct rbppc_cf_info *info) {
struct device_node *np;
struct resource res;
const u32 *u32ptr;
@@ -579,7 +580,7 @@ static int rbppc_cf_init_info(struct of_
return 0;
}
-static int rbppc_cf_probe(struct of_device *pdev,
+static int rbppc_cf_probe(struct platform_device *pdev,
const struct of_device_id *match)
{
struct ata_host *host;
@@ -654,7 +655,7 @@ err_info:
return err;
}
-static int rbppc_cf_remove(struct of_device *pdev)
+static int rbppc_cf_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ata_host *host = dev_get_drvdata(dev);

View File

@ -0,0 +1,22 @@
--- a/drivers/mtd/nand/rbppc_nand.c
+++ b/drivers/mtd/nand/rbppc_nand.c
@@ -14,8 +14,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/of_platform.h>
-#include <asm/of_platform.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -116,7 +116,7 @@ static void rbppc_nand_read_buf(struct m
static unsigned init_ok = 0;
-static int rbppc_nand_probe(struct of_device *pdev,
+static int rbppc_nand_probe(struct platform_device *pdev,
const struct of_device_id *match)
{
struct device_node *gpio;

View File

@ -0,0 +1,40 @@
--- a/drivers/mtd/nand/rbppc_nand.c
+++ b/drivers/mtd/nand/rbppc_nand.c
@@ -130,10 +130,10 @@ static int rbppc_nand_probe(struct platf
info = kmalloc(sizeof(*info), GFP_KERNEL);
- rdy = of_get_property(pdev->node, "rdy", NULL);
- nce = of_get_property(pdev->node, "nce", NULL);
- cle = of_get_property(pdev->node, "cle", NULL);
- ale = of_get_property(pdev->node, "ale", NULL);
+ rdy = of_get_property(pdev->dev.of_node, "rdy", NULL);
+ nce = of_get_property(pdev->dev.of_node, "nce", NULL);
+ cle = of_get_property(pdev->dev.of_node, "cle", NULL);
+ ale = of_get_property(pdev->dev.of_node, "ale", NULL);
if (!rdy || !nce || !cle || !ale) {
printk(KERN_ERR "rbppc_nand_probe: GPIO properties are missing\n");
@@ -180,7 +180,7 @@ static int rbppc_nand_probe(struct platf
of_node_put(nnand);
info->localbus = ioremap_nocache(res.start, res.end - res.start + 1);
- if (of_address_to_resource(pdev->node, 0, &res)) {
+ if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
printk("rbppc_nand_probe: No reg property found\n");
goto err;
}
@@ -222,12 +222,11 @@ static struct of_device_id rbppc_nand_id
};
static struct of_platform_driver rbppc_nand_driver = {
- .name = "nand",
.probe = rbppc_nand_probe,
- .match_table = rbppc_nand_ids,
.driver = {
.name = "rbppc-nand",
.owner = THIS_MODULE,
+ .of_match_table = rbppc_nand_ids,
},
};

View File

@ -0,0 +1,60 @@
--- a/drivers/ata/pata_rbppc_cf.c
+++ b/drivers/ata/pata_rbppc_cf.c
@@ -522,7 +522,7 @@ static int rbppc_cf_init_info(struct pla
unsigned ccb_freq_hz;
unsigned lb_div;
- u32ptr = of_get_property(pdev->node, "lbc_extra_divider", NULL);
+ u32ptr = of_get_property(pdev->dev.of_node, "lbc_extra_divider", NULL);
if (u32ptr && *u32ptr) {
lbc_extra_divider = *u32ptr;
#if DEBUG_UPM
@@ -568,7 +568,7 @@ static int rbppc_cf_init_info(struct pla
printk(KERN_INFO "rbppc_cf_init_info: Using Local-Bus clock %u kHz %u ps\n",
lbc_clk_khz, info->clk_time_ps);
- u32ptr = of_get_property(pdev->node, "lb-timings", NULL);
+ u32ptr = of_get_property(pdev->dev.of_node, "lb-timings", NULL);
if (u32ptr) {
memcpy(info->lb_timings, u32ptr, LBT_SIZE * sizeof(*u32ptr));
#if DEBUG_UPM
@@ -608,13 +608,13 @@ static int rbppc_cf_probe(struct platfor
rbinfo = info;
}
- u32ptr = of_get_property(pdev->node, "interrupt-at-level", NULL);
+ u32ptr = of_get_property(pdev->dev.of_node, "interrupt-at-level", NULL);
if (u32ptr) {
irq_level = *u32ptr;
printk(KERN_INFO "rbppc_cf_probe: IRQ level %u\n", irq_level);
}
- if (of_address_to_resource(pdev->node, 0, &res)) {
+ if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
printk(KERN_ERR "rbppc_cf_probe: No reg property found\n");
goto err_info;
}
@@ -641,7 +641,7 @@ static int rbppc_cf_probe(struct platfor
err = ata_host_activate(
host,
- irq_of_parse_and_map(pdev->node, 0), ata_sff_interrupt,
+ irq_of_parse_and_map(pdev->dev.of_node, 0), ata_sff_interrupt,
irq_level ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW,
&rbppc_cf_sht);
if (!err) return 0;
@@ -672,13 +672,12 @@ static struct of_device_id rbppc_cf_ids[
};
static struct of_platform_driver rbppc_cf_driver = {
- .name = "cf",
.probe = rbppc_cf_probe,
.remove = rbppc_cf_remove,
- .match_table = rbppc_cf_ids,
.driver = {
.name = "rbppc-cf",
.owner = THIS_MODULE,
+ .of_match_table = rbppc_cf_ids,
},
};

View File

@ -0,0 +1,116 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -51,6 +51,12 @@ config VITESSE_PHY
---help---
Currently supports the vsc8244
+config VITESSE_PHY_8601_SKEW
+ bool "Enable skew timing to vsc8601"
+ depends on VITESSE_PHY
+ ---help---
+ Apply clock timing adjustments for vsc8601
+
config SMSC_PHY
tristate "Drivers for SMSC PHYs"
---help---
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -26,6 +26,11 @@
#define MII_VSC8244_EXTCON1_TX_SKEW 0x0800
#define MII_VSC8244_EXTCON1_RX_SKEW 0x0200
+/* EXT_CON1 Register values for VSC8601 */
+#define MII_VSC8601_EXTCON1_INIT 0x0000
+#define MII_VSC8601_EXTCON1_SKEW 0x0100
+#define MII_VSC8601_EXTCON1_ACTIPHY 0x0020
+
/* Vitesse Interrupt Mask Register */
#define MII_VSC8244_IMASK 0x19
#define MII_VSC8244_IMASK_IEN 0x8000
@@ -88,6 +93,30 @@ static int vsc824x_config_init(struct ph
return err;
}
+static int vsc8601_config_init(struct phy_device *phydev)
+{
+ int err;
+ int extcon;
+
+ err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+ MII_VSC8244_AUXCONSTAT_INIT);
+
+ if (err < 0)
+ return err;
+
+#ifdef CONFIG_VITESSE_PHY_8601_SKEW
+ extcon = phy_read(phydev, MII_VSC8244_EXT_CON1);
+ if (err < 0)
+ return err;
+
+ extcon |= MII_VSC8601_EXTCON1_SKEW;
+
+ err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon);
+#endif
+
+ return err;
+}
+
static int vsc824x_ack_interrupt(struct phy_device *phydev)
{
int err = 0;
@@ -143,6 +172,21 @@ static struct phy_driver vsc8244_driver
.driver = { .owner = THIS_MODULE,},
};
+/* Vitesse 8601 */
+static struct phy_driver vsc8601_driver = {
+ .phy_id = 0x00070420,
+ .name = "Vitesse VSC8601",
+ .phy_id_mask = 0x000ffff8,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc8601_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
static int vsc8221_config_init(struct phy_device *phydev)
{
int err;
@@ -176,10 +220,23 @@ static int __init vsc82xx_init(void)
err = phy_driver_register(&vsc8244_driver);
if (err < 0)
- return err;
+ goto err;
+
err = phy_driver_register(&vsc8221_driver);
if (err < 0)
- phy_driver_unregister(&vsc8244_driver);
+ goto err1;
+
+ err = phy_driver_register(&vsc8601_driver);
+ if (err < 0)
+ goto err2;
+
+ return 0;
+
+err2:
+ phy_driver_unregister(&vsc8221_driver);
+err1:
+ phy_driver_unregister(&vsc8244_driver);
+err:
return err;
}
@@ -187,6 +244,7 @@ static void __exit vsc82xx_exit(void)
{
phy_driver_unregister(&vsc8244_driver);
phy_driver_unregister(&vsc8221_driver);
+ phy_driver_unregister(&vsc8601_driver);
}
module_init(vsc82xx_init);

View File

@ -0,0 +1,17 @@
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1002,6 +1002,14 @@ static int gfar_probe(struct platform_de
udelay(2);
tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
+ /*
+ * Do not enable flow control on chips earlier than rev 1.1,
+ * because of the eTSEC27 erratum
+ */
+ tempval = 0;
+ if (mfspr(SPRN_SVR) & 0xffff >= 0x0011)
+ tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
+
gfar_write(&regs->maccfg1, tempval);
/* Initialize MACCFG2. */