cns3xxx: add support for 3.3
Compile tested only. SVN-Revision: 31809
This commit is contained in:
parent
1fd4bf270b
commit
c2a2d59db5
204
target/linux/cns3xxx/config-3.3
Normal file
204
target/linux/cns3xxx/config-3.3
Normal file
@ -0,0 +1,204 @@
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
|
||||
CONFIG_ARCH_CNS3XXX=y
|
||||
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
|
||||
CONFIG_ARCH_NR_GPIO=0
|
||||
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
|
||||
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
|
||||
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
|
||||
CONFIG_ARM=y
|
||||
# CONFIG_ARM_CPU_SUSPEND is not set
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=5
|
||||
CONFIG_ARM_NR_BANKS=8
|
||||
CONFIG_ARM_PATCH_PHYS_VIRT=y
|
||||
CONFIG_ARM_THUMB=y
|
||||
CONFIG_ATA=y
|
||||
# CONFIG_ATA_SFF is not set
|
||||
CONFIG_ATA_VERBOSE_ERROR=y
|
||||
CONFIG_BCMA_POSSIBLE=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=2
|
||||
CONFIG_BLK_DEV_RAM_SIZE=32768
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CACHE_L2X0=y
|
||||
CONFIG_CLKDEV_LOOKUP=y
|
||||
CONFIG_CNS3XXX_ETH=y
|
||||
CONFIG_CPU_32v6=y
|
||||
CONFIG_CPU_32v6K=y
|
||||
CONFIG_CPU_ABRT_EV6=y
|
||||
# CONFIG_CPU_BPREDICT_DISABLE is not set
|
||||
CONFIG_CPU_CACHE_V6=y
|
||||
CONFIG_CPU_CACHE_VIPT=y
|
||||
CONFIG_CPU_COPY_V6=y
|
||||
CONFIG_CPU_CP15=y
|
||||
CONFIG_CPU_CP15_MMU=y
|
||||
CONFIG_CPU_HAS_ASID=y
|
||||
CONFIG_CPU_HAS_PMU=y
|
||||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||
CONFIG_CPU_PABRT_V6=y
|
||||
CONFIG_CPU_RMAP=y
|
||||
CONFIG_CPU_TLB_V6=y
|
||||
CONFIG_CPU_V6K=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_USER is not set
|
||||
CONFIG_DECOMPRESS_LZMA=y
|
||||
CONFIG_DMA_CACHE_RWFO=y
|
||||
# CONFIG_DWC_DEBUG is not set
|
||||
# CONFIG_DWC_DEVICE_ONLY is not set
|
||||
# CONFIG_DWC_HOST_ONLY is not set
|
||||
CONFIG_DWC_OTG_MODE=y
|
||||
CONFIG_EEPROM_AT24=y
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_GENERIC_BUG=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
CONFIG_GENERIC_GPIO=y
|
||||
CONFIG_GENERIC_IRQ_SHOW=y
|
||||
CONFIG_GENERIC_PCI_IOMAP=y
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_PCA953X=y
|
||||
CONFIG_GPIO_PCA953X_IRQ=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAVE_AOUT=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_ARCH_PFN_VALID=y
|
||||
CONFIG_HAVE_ARM_SCU=y
|
||||
CONFIG_HAVE_ARM_TWD=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
CONFIG_HAVE_GENERIC_HARDIRQS=y
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_IRQ_WORK=y
|
||||
CONFIG_HAVE_KERNEL_GZIP=y
|
||||
CONFIG_HAVE_KERNEL_LZMA=y
|
||||
CONFIG_HAVE_KERNEL_LZO=y
|
||||
CONFIG_HAVE_KERNEL_XZ=y
|
||||
CONFIG_HAVE_MEMBLOCK=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_HAVE_PROC_CPU=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_SMP=y
|
||||
CONFIG_HAVE_SPARSE_IRQ=y
|
||||
CONFIG_HWMON=y
|
||||
CONFIG_HW_RANDOM=m
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_BOARDINFO=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_CNS3XXX=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_KTIME_SCALAR=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
# CONFIG_LEDS_TRIGGER_NETDEV is not set
|
||||
CONFIG_LOCAL_TIMERS=y
|
||||
CONFIG_M25PXX_USE_FAST_READ=y
|
||||
CONFIG_MACH_CNS3420VB=y
|
||||
CONFIG_MACH_GW2388=y
|
||||
CONFIG_MDIO_BOARDINFO=y
|
||||
# CONFIG_MFD_T7L66XB is not set
|
||||
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
|
||||
CONFIG_MIGHT_HAVE_PCI=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_BLOCK=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_CNS3XXX=y
|
||||
# CONFIG_MMC_SDHCI_PCI is not set
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
# CONFIG_MMC_TIFM_SD is not set
|
||||
CONFIG_MPCORE_WATCHDOG=y
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_MULTI_IRQ_HANDLER=y
|
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NET_VENDOR_CAVIUM=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_OUTER_CACHE=y
|
||||
CONFIG_OUTER_CACHE_SYNC=y
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_PAGE_OFFSET=0xC0000000
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PL310_ERRATA_588369=y
|
||||
CONFIG_PL310_ERRATA_727915=y
|
||||
CONFIG_PL310_ERRATA_769419=y
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
CONFIG_RAID_ATTRS=y
|
||||
CONFIG_RFS_ACCEL=y
|
||||
CONFIG_RPS=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_DS1672=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_SCSI=y
|
||||
# CONFIG_SCSI_MULTI_LUN is not set
|
||||
CONFIG_SENSORS_AD7418=y
|
||||
CONFIG_SENSORS_GSP=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=3
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=3
|
||||
CONFIG_SMP=y
|
||||
CONFIG_SMP_ON_UP=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_BITBANG=y
|
||||
CONFIG_SPI_CNS3XXX=y
|
||||
CONFIG_SPI_MASTER=y
|
||||
# CONFIG_STAGING is not set
|
||||
CONFIG_STOP_MACHINE=y
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_UID16=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
|
||||
CONFIG_USB_ARCH_HAS_XHCI=y
|
||||
# CONFIG_USB_CDC_COMPOSITE is not set
|
||||
CONFIG_USB_CNS3XXX_EHCI=y
|
||||
CONFIG_USB_CNS3XXX_OHCI=y
|
||||
CONFIG_USB_COMMON=y
|
||||
CONFIG_USB_DWC_OTG=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
# CONFIG_USB_ETH is not set
|
||||
# CONFIG_USB_FILE_STORAGE is not set
|
||||
# CONFIG_USB_FUNCTIONFS is not set
|
||||
CONFIG_USB_GADGET=y
|
||||
# CONFIG_USB_GADGETFS is not set
|
||||
# CONFIG_USB_GADGET_DEBUG_FILES is not set
|
||||
# CONFIG_USB_GADGET_DEBUG_FS is not set
|
||||
CONFIG_USB_GADGET_VBUS_DRAW=2
|
||||
# CONFIG_USB_G_DBGP is not set
|
||||
# CONFIG_USB_G_HID is not set
|
||||
# CONFIG_USB_G_NCM is not set
|
||||
# CONFIG_USB_G_PRINTER is not set
|
||||
# CONFIG_USB_G_SERIAL is not set
|
||||
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
|
||||
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
# CONFIG_USB_UHCI_HCD is not set
|
||||
# CONFIG_USB_ZERO is not set
|
||||
CONFIG_USE_GENERIC_SMP_HELPERS=y
|
||||
CONFIG_VECTORS_BASE=0xffff0000
|
||||
CONFIG_VFP=y
|
||||
CONFIG_WATCHDOG_NOWAYOUT=y
|
||||
CONFIG_XPS=y
|
||||
CONFIG_XZ_DEC=y
|
||||
CONFIG_ZBOOT_ROM_BSS=0
|
||||
CONFIG_ZBOOT_ROM_TEXT=0
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
@ -0,0 +1,69 @@
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -368,6 +368,7 @@ config ARCH_CNS3XXX
|
||||
select CPU_V6K
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARM_GIC
|
||||
+ select CLKDEV_LOOKUP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
select MIGHT_HAVE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
--- a/arch/arm/mach-cns3xxx/core.c
|
||||
+++ b/arch/arm/mach-cns3xxx/core.c
|
||||
@@ -9,8 +9,11 @@
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
+#include <linux/export.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clockchips.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clkdev.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
@@ -20,6 +23,10 @@
|
||||
#include <mach/cns3xxx.h>
|
||||
#include "core.h"
|
||||
|
||||
+struct clk {
|
||||
+ unsigned long rate;
|
||||
+};
|
||||
+
|
||||
static struct map_desc cns3xxx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT,
|
||||
@@ -287,3 +294,33 @@ void __init cns3xxx_l2x0_init(void)
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CACHE_L2X0 */
|
||||
+
|
||||
+int clk_enable(struct clk *clk)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(clk_enable);
|
||||
+
|
||||
+void clk_disable(struct clk *clk)
|
||||
+{
|
||||
+}
|
||||
+EXPORT_SYMBOL(clk_disable);
|
||||
+
|
||||
+unsigned long clk_get_rate(struct clk *clk)
|
||||
+{
|
||||
+ return clk->rate;
|
||||
+}
|
||||
+EXPORT_SYMBOL(clk_get_rate);
|
||||
+
|
||||
+static struct clk_lookup cns3xxx_clocks[] = {
|
||||
+ {
|
||||
+ /* TODO */
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns3xxx_clocks_init(void)
|
||||
+{
|
||||
+ clkdev_add_table(cns3xxx_clocks, ARRAY_SIZE(cns3xxx_clocks));
|
||||
+ return 0;
|
||||
+}
|
||||
+postcore_initcall(cns3xxx_clocks_init);
|
69
target/linux/cns3xxx/patches-3.3/002-cns3xxx_wdt.patch
Normal file
69
target/linux/cns3xxx/patches-3.3/002-cns3xxx_wdt.patch
Normal file
@ -0,0 +1,69 @@
|
||||
1. Made the connection between CNS3xxx SOCs(ARCH_CNS3xxx) and MPcore watchdog
|
||||
since the CNS3xxx SOCs have ARM11 MPcore CPU.
|
||||
2. Enable mpcore_watchdog option as module to default configuration at
|
||||
arch/arm/configs/cns3420vb_defconfig.
|
||||
|
||||
Signed-off-by: Tommy Lin <tommy.lin@caviumnetworks.com>
|
||||
|
||||
---
|
||||
arch/arm/Kconfig | 1 +
|
||||
arch/arm/configs/cns3420vb_defconfig | 2 ++
|
||||
arch/arm/mach-cns3xxx/cns3420vb.c | 22 ++++++++++++++++++++++
|
||||
3 files changed, 25 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -372,6 +372,7 @@ config ARCH_CNS3XXX
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
select MIGHT_HAVE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
+ select HAVE_ARM_TWD
|
||||
help
|
||||
Support for Cavium Networks CNS3XXX platform.
|
||||
|
||||
--- a/arch/arm/configs/cns3420vb_defconfig
|
||||
+++ b/arch/arm/configs/cns3420vb_defconfig
|
||||
@@ -53,6 +53,8 @@ CONFIG_LEGACY_PTY_COUNT=16
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
+CONFIG_WATCHDOG=y
|
||||
+CONFIG_MPCORE_WATCHDOG=m
|
||||
# CONFIG_HID_SUPPORT is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_MMC=y
|
||||
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
@@ -159,10 +159,32 @@ static struct platform_device cns3xxx_us
|
||||
},
|
||||
};
|
||||
|
||||
+/* Watchdog */
|
||||
+static struct resource cns3xxx_watchdog_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS3XXX_TC11MP_TWD_BASE,
|
||||
+ .end = CNS3XXX_TC11MP_TWD_BASE + PAGE_SIZE - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = IRQ_LOCALWDOG,
|
||||
+ .end = IRQ_LOCALWDOG,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns3xxx_watchdog_device = {
|
||||
+ .name = "mpcore_wdt",
|
||||
+ .id = -1,
|
||||
+ .num_resources = ARRAY_SIZE(cns3xxx_watchdog_resources),
|
||||
+ .resource = cns3xxx_watchdog_resources,
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
static struct platform_device *cns3420_pdevs[] __initdata = {
|
||||
+ &cns3xxx_watchdog_device,
|
||||
&cns3420_nor_pdev,
|
||||
&cns3xxx_usb_ehci_device,
|
||||
&cns3xxx_usb_ohci_device,
|
414
target/linux/cns3xxx/patches-3.3/049-cns3xxx_smp_support.patch
Normal file
414
target/linux/cns3xxx/patches-3.3/049-cns3xxx_smp_support.patch
Normal file
@ -0,0 +1,414 @@
|
||||
--- a/arch/arm/mach-cns3xxx/Makefile
|
||||
+++ b/arch/arm/mach-cns3xxx/Makefile
|
||||
@@ -1,3 +1,6 @@
|
||||
obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o devices.o
|
||||
obj-$(CONFIG_PCI) += pcie.o
|
||||
obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o
|
||||
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/headsmp.S
|
||||
@@ -0,0 +1,42 @@
|
||||
+/*
|
||||
+ * linux/arch/arm/mach-cns3xxx/headsmp.S
|
||||
+ *
|
||||
+ * Cloned from linux/arch/arm/plat-versatile/headsmp.S
|
||||
+ *
|
||||
+ * Copyright (c) 2003 ARM Limited
|
||||
+ * All Rights Reserved
|
||||
+ *
|
||||
+ * 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 <linux/linkage.h>
|
||||
+#include <linux/init.h>
|
||||
+
|
||||
+ __INIT
|
||||
+
|
||||
+/*
|
||||
+ * CNS3XXX specific entry point for secondary CPUs. This provides
|
||||
+ * a "holding pen" into which all secondary cores are held until we're
|
||||
+ * ready for them to initialise.
|
||||
+ */
|
||||
+ENTRY(cns3xxx_secondary_startup)
|
||||
+ mrc p15, 0, r0, c0, c0, 5
|
||||
+ and r0, r0, #15
|
||||
+ adr r4, 1f
|
||||
+ ldmia r4, {r5, r6}
|
||||
+ sub r4, r4, r5
|
||||
+ add r6, r6, r4
|
||||
+pen: ldr r7, [r6]
|
||||
+ cmp r7, r0
|
||||
+ bne pen
|
||||
+
|
||||
+ /*
|
||||
+ * we've been released from the holding pen: secondary_stack
|
||||
+ * should now contain the SVC stack for this core
|
||||
+ */
|
||||
+ b secondary_startup
|
||||
+
|
||||
+ .align
|
||||
+1: .long .
|
||||
+ .long pen_release
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/hotplug.c
|
||||
@@ -0,0 +1,130 @@
|
||||
+/* linux arch/arm/mach-cns3xxx/hotplug.c
|
||||
+ *
|
||||
+ * Cloned from linux/arch/arm/mach-realview/hotplug.c
|
||||
+ *
|
||||
+ * Copyright (C) 2002 ARM Ltd.
|
||||
+ * All Rights Reserved
|
||||
+ *
|
||||
+ * 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 <linux/kernel.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/smp.h>
|
||||
+
|
||||
+#include <asm/cacheflush.h>
|
||||
+
|
||||
+extern volatile int pen_release;
|
||||
+
|
||||
+static inline void cpu_enter_lowpower(void)
|
||||
+{
|
||||
+ unsigned int v;
|
||||
+
|
||||
+ flush_cache_all();
|
||||
+ asm volatile(
|
||||
+ " mcr p15, 0, %1, c7, c5, 0\n"
|
||||
+ " mcr p15, 0, %1, c7, c10, 4\n"
|
||||
+ /*
|
||||
+ * Turn off coherency
|
||||
+ */
|
||||
+ " mrc p15, 0, %0, c1, c0, 1\n"
|
||||
+ " bic %0, %0, %3\n"
|
||||
+ " mcr p15, 0, %0, c1, c0, 1\n"
|
||||
+ " mrc p15, 0, %0, c1, c0, 0\n"
|
||||
+ " bic %0, %0, %2\n"
|
||||
+ " mcr p15, 0, %0, c1, c0, 0\n"
|
||||
+ : "=&r" (v)
|
||||
+ : "r" (0), "Ir" (CR_C), "Ir" (0x40)
|
||||
+ : "cc");
|
||||
+}
|
||||
+
|
||||
+static inline void cpu_leave_lowpower(void)
|
||||
+{
|
||||
+ unsigned int v;
|
||||
+
|
||||
+ asm volatile(
|
||||
+ "mrc p15, 0, %0, c1, c0, 0\n"
|
||||
+ " orr %0, %0, %1\n"
|
||||
+ " mcr p15, 0, %0, c1, c0, 0\n"
|
||||
+ " mrc p15, 0, %0, c1, c0, 1\n"
|
||||
+ " orr %0, %0, %2\n"
|
||||
+ " mcr p15, 0, %0, c1, c0, 1\n"
|
||||
+ : "=&r" (v)
|
||||
+ : "Ir" (CR_C), "Ir" (0x40)
|
||||
+ : "cc");
|
||||
+}
|
||||
+
|
||||
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
+{
|
||||
+ /*
|
||||
+ * there is no power-control hardware on this platform, so all
|
||||
+ * we can do is put the core into WFI; this is safe as the calling
|
||||
+ * code will have already disabled interrupts
|
||||
+ */
|
||||
+ for (;;) {
|
||||
+ /*
|
||||
+ * here's the WFI
|
||||
+ */
|
||||
+ asm(".word 0xe320f003\n"
|
||||
+ :
|
||||
+ :
|
||||
+ : "memory", "cc");
|
||||
+
|
||||
+ if (pen_release == cpu) {
|
||||
+ /*
|
||||
+ * OK, proper wakeup, we're done
|
||||
+ */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Getting here, means that we have come out of WFI without
|
||||
+ * having been woken up - this shouldn't happen
|
||||
+ *
|
||||
+ * Just note it happening - when we're woken, we can report
|
||||
+ * its occurrence.
|
||||
+ */
|
||||
+ (*spurious)++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int platform_cpu_kill(unsigned int cpu)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * platform-specific code to shutdown a CPU
|
||||
+ *
|
||||
+ * Called with IRQs disabled
|
||||
+ */
|
||||
+void platform_cpu_die(unsigned int cpu)
|
||||
+{
|
||||
+ int spurious = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * we're ready for shutdown now, so do it
|
||||
+ */
|
||||
+ cpu_enter_lowpower();
|
||||
+ platform_do_lowpower(cpu, &spurious);
|
||||
+
|
||||
+ /*
|
||||
+ * bring this CPU back into the world of cache
|
||||
+ * coherency, and then restore interrupts
|
||||
+ */
|
||||
+ cpu_leave_lowpower();
|
||||
+
|
||||
+ if (spurious)
|
||||
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
+}
|
||||
+
|
||||
+int platform_cpu_disable(unsigned int cpu)
|
||||
+{
|
||||
+ /*
|
||||
+ * we don't allow CPU 0 to be shutdown (it is still too special
|
||||
+ * e.g. clock tick interrupts)
|
||||
+ */
|
||||
+ return cpu == 0 ? -EPERM : 0;
|
||||
+}
|
||||
--- a/arch/arm/mach-cns3xxx/Kconfig
|
||||
+++ b/arch/arm/mach-cns3xxx/Kconfig
|
||||
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
|
||||
|
||||
config MACH_CNS3420VB
|
||||
bool "Support for CNS3420 Validation Board"
|
||||
+ select HAVE_ARM_SCU if SMP
|
||||
select MIGHT_HAVE_PCI
|
||||
help
|
||||
Include support for the Cavium Networks CNS3420 MPCore Platform
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/localtimer.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* linux/arch/arm/mach-cns3xxx/localtimer.c
|
||||
+ *
|
||||
+ * Cloned from linux/arch/arm/mach-realview/localtimer.c
|
||||
+ *
|
||||
+ * Copyright (C) 2002 ARM Ltd.
|
||||
+ * All Rights Reserved
|
||||
+ *
|
||||
+ * 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 <linux/clockchips.h>
|
||||
+
|
||||
+#include <asm/irq.h>
|
||||
+#include <asm/localtimer.h>
|
||||
+
|
||||
+/*
|
||||
+ * Setup the local clock events for a CPU.
|
||||
+ */
|
||||
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
+{
|
||||
+ evt->irq = IRQ_LOCALTIMER;
|
||||
+ twd_timer_setup(evt);
|
||||
+ return 0;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/platsmp.c
|
||||
@@ -0,0 +1,175 @@
|
||||
+/* linux/arch/arm/mach-cns3xxx/platsmp.c
|
||||
+ *
|
||||
+ * Copyright 2011 Gateworks Corporation
|
||||
+ * Chris Lang <clang@gateworks.com>
|
||||
+ *
|
||||
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
|
||||
+ *
|
||||
+ * Copyright (C) 2002 ARM Ltd.
|
||||
+ * All Rights Reserved
|
||||
+ *
|
||||
+ * 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 <linux/init.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/smp.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+#include <asm/cacheflush.h>
|
||||
+#include <asm/hardware/gic.h>
|
||||
+#include <asm/smp_scu.h>
|
||||
+#include <asm/unified.h>
|
||||
+
|
||||
+#include <mach/cns3xxx.h>
|
||||
+
|
||||
+extern void cns3xxx_secondary_startup(void);
|
||||
+
|
||||
+/*
|
||||
+ * control for which core is the next to come out of the secondary
|
||||
+ * boot "holding pen"
|
||||
+ */
|
||||
+
|
||||
+volatile int __cpuinitdata pen_release = -1;
|
||||
+
|
||||
+/*
|
||||
+ * Write pen_release in a way that is guaranteed to be visible to all
|
||||
+ * observers, irrespective of whether they're taking part in coherency
|
||||
+ * or not. This is necessary for the hotplug code to work reliably.
|
||||
+ */
|
||||
+static void write_pen_release(int val)
|
||||
+{
|
||||
+ pen_release = val;
|
||||
+ smp_wmb();
|
||||
+ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
+ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
|
||||
+}
|
||||
+
|
||||
+static void __iomem *scu_base_addr(void)
|
||||
+{
|
||||
+ return (void __iomem *)(CNS3XXX_TC11MP_SCU_BASE_VIRT);
|
||||
+}
|
||||
+
|
||||
+static DEFINE_SPINLOCK(boot_lock);
|
||||
+
|
||||
+void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
+{
|
||||
+ /*
|
||||
+ * if any interrupts are already enabled for the primary
|
||||
+ * core (e.g. timer irq), then they will not have been enabled
|
||||
+ * for us: do so
|
||||
+ */
|
||||
+ gic_secondary_init(0);
|
||||
+
|
||||
+ /*
|
||||
+ * let the primary processor know we're out of the
|
||||
+ * pen, then head off into the C entry point
|
||||
+ */
|
||||
+ write_pen_release(-1);
|
||||
+
|
||||
+ /*
|
||||
+ * Synchronise with the boot thread.
|
||||
+ */
|
||||
+ spin_lock(&boot_lock);
|
||||
+ spin_unlock(&boot_lock);
|
||||
+}
|
||||
+
|
||||
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
+{
|
||||
+ unsigned long timeout;
|
||||
+
|
||||
+ /*
|
||||
+ * Set synchronisation state between this boot processor
|
||||
+ * and the secondary one
|
||||
+ */
|
||||
+ spin_lock(&boot_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * The secondary processor is waiting to be released from
|
||||
+ * the holding pen - release it, then wait for it to flag
|
||||
+ * that it has been released by resetting pen_release.
|
||||
+ *
|
||||
+ * Note that "pen_release" is the hardware CPU ID, whereas
|
||||
+ * "cpu" is Linux's internal ID.
|
||||
+ */
|
||||
+ write_pen_release(cpu);
|
||||
+
|
||||
+ /*
|
||||
+ * Send the secondary CPU a soft interrupt, thereby causing
|
||||
+ * the boot monitor to read the system wide flags register,
|
||||
+ * and branch to the address found there.
|
||||
+ */
|
||||
+ gic_raise_softirq(cpumask_of(cpu), 1);
|
||||
+
|
||||
+ timeout = jiffies + (1 * HZ);
|
||||
+ while (time_before(jiffies, timeout)) {
|
||||
+ smp_rmb();
|
||||
+ if (pen_release == -1)
|
||||
+ break;
|
||||
+
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * now the secondary core is starting up let it run its
|
||||
+ * calibrations, then wait for it to finish
|
||||
+ */
|
||||
+ spin_unlock(&boot_lock);
|
||||
+
|
||||
+ return pen_release != -1 ? -ENOSYS : 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Initialise the CPU possible map early - this describes the CPUs
|
||||
+ * which may be present or become present in the system.
|
||||
+ */
|
||||
+
|
||||
+void __init smp_init_cpus(void)
|
||||
+{
|
||||
+ void __iomem *scu_base = scu_base_addr();
|
||||
+ unsigned int i, ncores;
|
||||
+
|
||||
+ ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
+
|
||||
+ /* sanity check */
|
||||
+ if (ncores > NR_CPUS) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "cns3xxx: no. of cores (%d) greater than configured "
|
||||
+ "maximum of %d - clipping\n",
|
||||
+ ncores, NR_CPUS);
|
||||
+ ncores = NR_CPUS;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < ncores; i++)
|
||||
+ set_cpu_possible(i, true);
|
||||
+
|
||||
+ set_smp_cross_call(gic_raise_softirq);
|
||||
+}
|
||||
+
|
||||
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ /*
|
||||
+ * Initialise the present map, which describes the set of CPUs
|
||||
+ * actually populated at the present time.
|
||||
+ */
|
||||
+ for (i = 0; i < max_cpus; i++)
|
||||
+ set_cpu_present(i, true);
|
||||
+
|
||||
+ scu_enable(scu_base_addr());
|
||||
+
|
||||
+ /*
|
||||
+ * Write the address of secondary startup into the
|
||||
+ * system-wide flags register. The boot monitor waits
|
||||
+ * until it receives a soft interrupt, and then the
|
||||
+ * secondary CPU branches to this address.
|
||||
+ */
|
||||
+ __raw_writel(virt_to_phys(cns3xxx_secondary_startup),
|
||||
+ (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0600));
|
||||
+}
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -373,6 +373,7 @@ config ARCH_CNS3XXX
|
||||
select MIGHT_HAVE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
select HAVE_ARM_TWD
|
||||
+ select HAVE_SMP
|
||||
help
|
||||
Support for Cavium Networks CNS3XXX platform.
|
||||
|
@ -0,0 +1,421 @@
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -326,6 +326,18 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
|
||||
help
|
||||
The unit of the TWI clock is kHz.
|
||||
|
||||
+config I2C_CNS3XXX
|
||||
+ tristate "Cavium CNS3xxx I2C driver"
|
||||
+ depends on ARCH_CNS3XXX
|
||||
+ help
|
||||
+ Support for Cavium CNS3xxx I2C controller driver.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module
|
||||
+ will be called i2c-cns3xxx.
|
||||
+
|
||||
+ Please note that this driver might be needed to bring up other
|
||||
+ devices such as Cavium CNS3xxx Ethernet.
|
||||
+
|
||||
config I2C_CPM
|
||||
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
|
||||
depends on (CPM1 || CPM2) && OF_I2C
|
||||
--- a/drivers/i2c/busses/Makefile
|
||||
+++ b/drivers/i2c/busses/Makefile
|
||||
@@ -83,6 +83,7 @@ obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
|
||||
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
|
||||
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
||||
+obj-$(CONFIG_I2C_CNS3XXX) += i2c-cns3xxx.o
|
||||
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
|
||||
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/i2c/busses/i2c-cns3xxx.c
|
||||
@@ -0,0 +1,387 @@
|
||||
+/*
|
||||
+ * Cavium CNS3xxx I2C Host Controller
|
||||
+ *
|
||||
+ * Copyright 2010 Cavium Network
|
||||
+ * Copyright 2011 Gateworks Corporation
|
||||
+ * Chris Lang <clang@gateworks.com>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <linux/wait.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <mach/pm.h>
|
||||
+#include <mach/cns3xxx.h>
|
||||
+
|
||||
+/*
|
||||
+ * We need the memory map
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+#define MISC_MEM_MAP_VALUE(reg_offset) (*((uint32_t volatile *)(CNS3XXX_MISC_BASE_VIRT + reg_offset)))
|
||||
+#define MISC_IOCDB_CTRL MISC_MEM_MAP_VALUE(0x020)
|
||||
+
|
||||
+#define I2C_MEM_MAP_ADDR(x) (CNS3XXX_SSP_BASE_VIRT + x)
|
||||
+#define I2C_MEM_MAP_VALUE(x) (*((unsigned int volatile*)I2C_MEM_MAP_ADDR(x)))
|
||||
+
|
||||
+#define I2C_CONTROLLER_REG I2C_MEM_MAP_VALUE(0x20)
|
||||
+#define I2C_TIME_OUT_REG I2C_MEM_MAP_VALUE(0x24)
|
||||
+#define I2C_SLAVE_ADDRESS_REG I2C_MEM_MAP_VALUE(0x28)
|
||||
+#define I2C_WRITE_DATA_REG I2C_MEM_MAP_VALUE(0x2C)
|
||||
+#define I2C_READ_DATA_REG I2C_MEM_MAP_VALUE(0x30)
|
||||
+#define I2C_INTERRUPT_STATUS_REG I2C_MEM_MAP_VALUE(0x34)
|
||||
+#define I2C_INTERRUPT_ENABLE_REG I2C_MEM_MAP_VALUE(0x38)
|
||||
+#define I2C_TWI_OUT_DLY_REG I2C_MEM_MAP_VALUE(0x3C)
|
||||
+
|
||||
+#define I2C_BUS_ERROR_FLAG (0x1)
|
||||
+#define I2C_ACTION_DONE_FLAG (0x2)
|
||||
+
|
||||
+#define CNS3xxx_I2C_ENABLE() (I2C_CONTROLLER_REG) |= ((unsigned int)0x1 << 31)
|
||||
+#define CNS3xxx_I2C_DISABLE() (I2C_CONTROLLER_REG) &= ~((unsigned int)0x1 << 31)
|
||||
+#define CNS3xxx_I2C_ENABLE_INTR() (I2C_INTERRUPT_ENABLE_REG) |= 0x03
|
||||
+#define CNS3xxx_I2C_DISABLE_INTR() (I2C_INTERRUPT_ENABLE_REG) &= 0xfc
|
||||
+
|
||||
+#define TWI_TIMEOUT (10*HZ)
|
||||
+#define I2C_100KHZ 100000
|
||||
+#define I2C_200KHZ 200000
|
||||
+#define I2C_300KHZ 300000
|
||||
+#define I2C_400KHZ 400000
|
||||
+
|
||||
+#define CNS3xxx_I2C_CLK I2C_100KHZ
|
||||
+
|
||||
+#define STATE_DONE 1
|
||||
+#define STATE_ERROR 2
|
||||
+
|
||||
+struct cns3xxx_i2c {
|
||||
+ void __iomem *base;
|
||||
+ wait_queue_head_t wait;
|
||||
+ struct i2c_adapter adap;
|
||||
+ struct i2c_msg *msg;
|
||||
+ int state; /* see STATE_ */
|
||||
+ int rd_wr_len;
|
||||
+ u8 *buf;
|
||||
+};
|
||||
+
|
||||
+static u32 cns3xxx_i2c_func(struct i2c_adapter *adap)
|
||||
+{
|
||||
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+cns3xxx_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg)
|
||||
+{
|
||||
+ struct cns3xxx_i2c *i2c = i2c_get_adapdata(adap);
|
||||
+ int i, j;
|
||||
+ u8 buf[1] = { 0 };
|
||||
+
|
||||
+ if (msg->len == 0) {
|
||||
+ /*
|
||||
+ * We are probably doing a probe for a device here,
|
||||
+ * so set the length to one, and data to 0
|
||||
+ */
|
||||
+ msg->len = 1;
|
||||
+ i2c->buf = buf;
|
||||
+ } else {
|
||||
+ i2c->buf = msg->buf;
|
||||
+ }
|
||||
+
|
||||
+ if (msg->flags & I2C_M_TEN) {
|
||||
+ printk
|
||||
+ ("%s:%d: Presently the driver does not handle extended addressing\n",
|
||||
+ __FUNCTION__, __LINE__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ i2c->msg = msg;
|
||||
+
|
||||
+ for (i = 0; i < msg->len; i++) {
|
||||
+ if (msg->len - i >= 4)
|
||||
+ i2c->rd_wr_len = 3;
|
||||
+ else
|
||||
+ i2c->rd_wr_len = msg->len - i - 1;
|
||||
+
|
||||
+ // Set Data Width and TWI_EN
|
||||
+ I2C_CONTROLLER_REG = 0x80000000 | (i2c->rd_wr_len << 2) | (i2c->rd_wr_len);
|
||||
+
|
||||
+ // Clear Write Reg
|
||||
+ I2C_WRITE_DATA_REG = 0;
|
||||
+
|
||||
+ // Set the slave address
|
||||
+ I2C_SLAVE_ADDRESS_REG = (msg->addr << 1);
|
||||
+
|
||||
+ // Are we Writing
|
||||
+ if (!(msg->flags & I2C_M_RD)) {
|
||||
+ I2C_CONTROLLER_REG |= (1 << 4);
|
||||
+ if (i != 0) {
|
||||
+ /*
|
||||
+ * We need to set the address in the first byte.
|
||||
+ * The base address is going to be in buf[0] and then
|
||||
+ * it needs to be incremented by i - 1.
|
||||
+ */
|
||||
+ i2c->buf--;
|
||||
+ *i2c->buf = buf[0] + i - 1;
|
||||
+
|
||||
+ if (i2c->rd_wr_len < 3) {
|
||||
+ i += i2c->rd_wr_len;
|
||||
+ i2c->rd_wr_len++;
|
||||
+ I2C_CONTROLLER_REG = 0x80000000 | (1 << 4) | (i2c->rd_wr_len << 2) | (i2c->rd_wr_len);
|
||||
+ } else {
|
||||
+ i += i2c->rd_wr_len - 1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ i += i2c->rd_wr_len;
|
||||
+ buf[0] = *i2c->buf;
|
||||
+ }
|
||||
+ for (j = 0; j <= i2c->rd_wr_len; j++) {
|
||||
+ I2C_WRITE_DATA_REG |= ((*i2c->buf++) << (8 * j));
|
||||
+ }
|
||||
+ } else {
|
||||
+ i += i2c->rd_wr_len;
|
||||
+ }
|
||||
+
|
||||
+ // Start the Transfer
|
||||
+ i2c->state = 0; // Clear out the State
|
||||
+ I2C_CONTROLLER_REG |= (1 << 6);
|
||||
+
|
||||
+ if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
|
||||
+ (i2c->state == STATE_DONE), TWI_TIMEOUT)) {
|
||||
+ if (i2c->state == STATE_ERROR) {
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return -ETIMEDOUT;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+cns3xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
+{
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+ for (i = 0; i < num; i++)
|
||||
+ {
|
||||
+ ret = cns3xxx_i2c_xfer_msg(adap, &msgs[i]);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ return num;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static struct i2c_algorithm cns3xxx_i2c_algo = {
|
||||
+ .master_xfer = cns3xxx_i2c_xfer,
|
||||
+ .functionality = cns3xxx_i2c_func,
|
||||
+};
|
||||
+
|
||||
+static struct i2c_adapter cns3xxx_i2c_adapter = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .algo = &cns3xxx_i2c_algo,
|
||||
+ .algo_data = NULL,
|
||||
+ .nr = 0,
|
||||
+ .name = "CNS3xxx I2C 0",
|
||||
+ .retries = 5,
|
||||
+};
|
||||
+
|
||||
+static void cns3xxx_i2c_adapter_init(struct cns3xxx_i2c *i2c)
|
||||
+{
|
||||
+ cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
|
||||
+ cns3xxx_pwr_power_up(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
|
||||
+ cns3xxx_pwr_soft_rst(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
|
||||
+
|
||||
+ /* Disable the I2C */
|
||||
+ I2C_CONTROLLER_REG = 0; /* Disabled the I2C */
|
||||
+
|
||||
+ //enable SCL and SDA which share pin with GPIOB_PIN_EN(0x18)
|
||||
+ //GPIOB[12]: SCL
|
||||
+ //GPIOB[13]: SDA
|
||||
+ (*(u32*)(CNS3XXX_MISC_BASE_VIRT+0x18)) |= ((1<<12)|(1<<13));
|
||||
+
|
||||
+ MISC_IOCDB_CTRL &= ~0x300;
|
||||
+ MISC_IOCDB_CTRL |= 0x300; //21mA...
|
||||
+
|
||||
+ /* Check the Reg Dump when testing */
|
||||
+ I2C_TIME_OUT_REG =
|
||||
+ ((((((cns3xxx_cpu_clock()*(1000000/8)) / (2 * CNS3xxx_I2C_CLK)) -
|
||||
+ 1) & 0x3FF) << 8) | (1 << 7) | 0x7F);
|
||||
+ I2C_TWI_OUT_DLY_REG |= 0x3;
|
||||
+
|
||||
+ /* Enable The Interrupt */
|
||||
+ CNS3xxx_I2C_ENABLE_INTR();
|
||||
+
|
||||
+ /* Clear Interrupt Status (0x2 | 0x1) */
|
||||
+ I2C_INTERRUPT_STATUS_REG |= (I2C_ACTION_DONE_FLAG | I2C_BUS_ERROR_FLAG);
|
||||
+
|
||||
+ /* Enable the I2C Controller */
|
||||
+ CNS3xxx_I2C_ENABLE();
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t cns3xxx_i2c_isr(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct cns3xxx_i2c *i2c = dev_id;
|
||||
+ int i;
|
||||
+ uint32_t stat = I2C_INTERRUPT_STATUS_REG;
|
||||
+
|
||||
+ /* Clear Interrupt */
|
||||
+ I2C_INTERRUPT_STATUS_REG |= 0x1;
|
||||
+
|
||||
+ if (stat & I2C_BUS_ERROR_FLAG) {
|
||||
+ i2c->state = STATE_ERROR;
|
||||
+ } else {
|
||||
+ if (i2c->msg->flags & I2C_M_RD) {
|
||||
+ for (i = 0; i <= i2c->rd_wr_len; i++)
|
||||
+ {
|
||||
+ *i2c->buf++ = ((I2C_READ_DATA_REG >> (8 * i)) & 0xff);
|
||||
+ }
|
||||
+ }
|
||||
+ i2c->state = STATE_DONE;
|
||||
+ }
|
||||
+ wake_up(&i2c->wait);
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int __devinit cns3xxx_i2c_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns3xxx_i2c *i2c;
|
||||
+ struct resource *res, *res2;
|
||||
+ int ret;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ printk("%s: IORESOURCE_MEM not defined \n", __FUNCTION__);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (!res2) {
|
||||
+ printk("%s: IORESOURCE_IRQ not defined \n", __FUNCTION__);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
|
||||
+ if (!i2c)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (!request_mem_region(res->start, res->end - res->start + 1,
|
||||
+ pdev->name)) {
|
||||
+ dev_err(&pdev->dev, "Memory region busy\n");
|
||||
+ ret = -EBUSY;
|
||||
+ goto request_mem_failed;
|
||||
+ }
|
||||
+
|
||||
+ i2c->base = ioremap(res->start, res->end - res->start + 1);
|
||||
+ if (!i2c->base) {
|
||||
+ dev_err(&pdev->dev, "Unable to map registers\n");
|
||||
+ ret = -EIO;
|
||||
+ goto map_failed;
|
||||
+ }
|
||||
+
|
||||
+ cns3xxx_i2c_adapter_init(i2c);
|
||||
+
|
||||
+ init_waitqueue_head(&i2c->wait);
|
||||
+ ret = request_irq(res2->start, cns3xxx_i2c_isr, 0, pdev->name, i2c);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
|
||||
+ goto request_irq_failed;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, i2c);
|
||||
+ i2c->adap = cns3xxx_i2c_adapter;
|
||||
+ i2c_set_adapdata(&i2c->adap, i2c);
|
||||
+ i2c->adap.dev.parent = &pdev->dev;
|
||||
+
|
||||
+ /* add i2c adapter to i2c tree */
|
||||
+ ret = i2c_add_numbered_adapter(&i2c->adap);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "Failed to add adapter\n");
|
||||
+ goto add_adapter_failed;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ add_adapter_failed:
|
||||
+ free_irq(res2->start, i2c);
|
||||
+ request_irq_failed:
|
||||
+ iounmap(i2c->base);
|
||||
+ map_failed:
|
||||
+ release_mem_region(res->start, res->end - res->start + 1);
|
||||
+ request_mem_failed:
|
||||
+ kfree(i2c);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit cns3xxx_i2c_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns3xxx_i2c *i2c = platform_get_drvdata(pdev);
|
||||
+ struct resource *res;
|
||||
+
|
||||
+ /* disable i2c logic */
|
||||
+ CNS3xxx_I2C_DISABLE_INTR();
|
||||
+ CNS3xxx_I2C_DISABLE();
|
||||
+ /* remove adapter & data */
|
||||
+ i2c_del_adapter(&i2c->adap);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (res)
|
||||
+ free_irq(res->start, i2c);
|
||||
+
|
||||
+ iounmap(i2c->base);
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (res)
|
||||
+ release_mem_region(res->start, res->end - res->start + 1);
|
||||
+
|
||||
+ kfree(i2c);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+#warning "CONFIG_PM defined: suspend and resume not implemented"
|
||||
+#define cns3xxx_i2c_suspend NULL
|
||||
+#define cns3xxx_i2c_resume NULL
|
||||
+#else
|
||||
+#define cns3xxx_i2c_suspend NULL
|
||||
+#define cns3xxx_i2c_resume NULL
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver cns3xxx_i2c_driver = {
|
||||
+ .probe = cns3xxx_i2c_probe,
|
||||
+ .remove = cns3xxx_i2c_remove,
|
||||
+ .suspend = cns3xxx_i2c_suspend,
|
||||
+ .resume = cns3xxx_i2c_resume,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "cns3xxx-i2c",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns3xxx_i2c_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&cns3xxx_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit cns3xxx_i2c_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&cns3xxx_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(cns3xxx_i2c_init);
|
||||
+module_exit(cns3xxx_i2c_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Cavium Networks");
|
||||
+MODULE_DESCRIPTION("Cavium CNS3XXX I2C Controller");
|
||||
+MODULE_LICENSE("GPL");
|
1357
target/linux/cns3xxx/patches-3.3/051-cns3xxx_gigabit.patch
Normal file
1357
target/linux/cns3xxx/patches-3.3/051-cns3xxx_gigabit.patch
Normal file
File diff suppressed because it is too large
Load Diff
509
target/linux/cns3xxx/patches-3.3/052-cns3xxx_spi.patch
Normal file
509
target/linux/cns3xxx/patches-3.3/052-cns3xxx_spi.patch
Normal file
@ -0,0 +1,509 @@
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -117,6 +117,13 @@ config SPI_BUTTERFLY
|
||||
inexpensive battery powered microcontroller evaluation board.
|
||||
This same cable can be used to flash new firmware.
|
||||
|
||||
+config SPI_CNS3XXX
|
||||
+ tristate "CNS3XXX SPI controller"
|
||||
+ depends on ARCH_CNS3XXX && SPI_MASTER
|
||||
+ select SPI_BITBANG
|
||||
+ help
|
||||
+ This enables using the CNS3XXX SPI controller in master mode.
|
||||
+
|
||||
config SPI_COLDFIRE_QSPI
|
||||
tristate "Freescale Coldfire QSPI controller"
|
||||
depends on (M520x || M523x || M5249 || M527x || M528x || M532x)
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.
|
||||
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
|
||||
+obj-$(CONFIG_SPI_CNS3XXX) += spi_cns3xxx.o
|
||||
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
|
||||
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
|
||||
obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi_cns3xxx.c
|
||||
@@ -0,0 +1,449 @@
|
||||
+/*******************************************************************************
|
||||
+ *
|
||||
+ * CNS3XXX SPI controller driver (master mode only)
|
||||
+ *
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright 2011 Gateworks Corporation
|
||||
+ * Chris Lang <clang@gateworks.com>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This file is distributed in the hope that it will be useful,
|
||||
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
|
||||
+ * NONINFRINGEMENT. See the GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this file; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
|
||||
+ * visit http://www.gnu.org/licenses/.
|
||||
+ *
|
||||
+ * This file may also be available under a different license from Cavium.
|
||||
+ * Contact Cavium Networks for more information
|
||||
+ *
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/spi_bitbang.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/memory.h>
|
||||
+#include <asm/dma.h>
|
||||
+#include <asm/delay.h>
|
||||
+#include <mach/cns3xxx.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <mach/pm.h>
|
||||
+
|
||||
+/*
|
||||
+ * define access macros
|
||||
+ */
|
||||
+#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(CNS3XXX_SSP_BASE_VIRT + reg_offset)))
|
||||
+
|
||||
+#define SPI_CONFIGURATION_REG SPI_MEM_MAP_VALUE(0x40)
|
||||
+#define SPI_SERVICE_STATUS_REG SPI_MEM_MAP_VALUE(0x44)
|
||||
+#define SPI_BIT_RATE_CONTROL_REG SPI_MEM_MAP_VALUE(0x48)
|
||||
+#define SPI_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x4C)
|
||||
+#define SPI_TRANSMIT_BUFFER_REG SPI_MEM_MAP_VALUE(0x50)
|
||||
+#define SPI_RECEIVE_CONTROL_REG SPI_MEM_MAP_VALUE(0x54)
|
||||
+#define SPI_RECEIVE_BUFFER_REG SPI_MEM_MAP_VALUE(0x58)
|
||||
+#define SPI_FIFO_TRANSMIT_CONFIG_REG SPI_MEM_MAP_VALUE(0x5C)
|
||||
+#define SPI_FIFO_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x60)
|
||||
+#define SPI_FIFO_RECEIVE_CONFIG_REG SPI_MEM_MAP_VALUE(0x64)
|
||||
+#define SPI_INTERRUPT_STATUS_REG SPI_MEM_MAP_VALUE(0x68)
|
||||
+#define SPI_INTERRUPT_ENABLE_REG SPI_MEM_MAP_VALUE(0x6C)
|
||||
+
|
||||
+#define SPI_TRANSMIT_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x50)
|
||||
+#define SPI_RECEIVE_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x58)
|
||||
+
|
||||
+/* Structure for SPI controller of CNS3XXX SOCs */
|
||||
+struct cns3xxx_spi {
|
||||
+ /* bitbang has to be first */
|
||||
+ struct spi_bitbang bitbang;
|
||||
+ struct completion done;
|
||||
+ wait_queue_head_t wait;
|
||||
+
|
||||
+ int len;
|
||||
+ int count;
|
||||
+ int last_in_message_list;
|
||||
+
|
||||
+ /* data buffers */
|
||||
+ const unsigned char *tx;
|
||||
+ unsigned char *rx;
|
||||
+
|
||||
+ struct spi_master *master;
|
||||
+ struct platform_device *pdev;
|
||||
+ struct device *dev;
|
||||
+};
|
||||
+
|
||||
+static inline u8 cns3xxx_spi_bus_idle(void)
|
||||
+{
|
||||
+ return ((SPI_SERVICE_STATUS_REG & 0x1) ? 0 : 1);
|
||||
+}
|
||||
+
|
||||
+static inline u8 cns3xxx_spi_tx_buffer_empty(void)
|
||||
+{
|
||||
+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 3)) ? 1 : 0);
|
||||
+}
|
||||
+
|
||||
+static inline u8 cns3xxx_spi_rx_buffer_full(void)
|
||||
+{
|
||||
+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 2)) ? 1 : 0);
|
||||
+}
|
||||
+
|
||||
+u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data,
|
||||
+ u32 * rx_data)
|
||||
+{
|
||||
+ u8 rx_channel;
|
||||
+ u8 rx_eof;
|
||||
+
|
||||
+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
|
||||
+
|
||||
+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
|
||||
+
|
||||
+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
|
||||
+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
|
||||
+
|
||||
+ SPI_TRANSMIT_BUFFER_REG = tx_data;
|
||||
+
|
||||
+ while (!cns3xxx_spi_rx_buffer_full()) ; // do nothing
|
||||
+
|
||||
+ rx_channel = SPI_RECEIVE_CONTROL_REG & 0x3;
|
||||
+ rx_eof = (SPI_RECEIVE_CONTROL_REG & (0x1 << 2)) ? 1 : 0;
|
||||
+
|
||||
+ *rx_data = SPI_RECEIVE_BUFFER_REG;
|
||||
+
|
||||
+ if ((tx_channel != rx_channel) || (tx_eof != rx_eof)) {
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+u8 cns3xxx_spi_tx(u8 tx_channel, u8 tx_eof, u32 tx_data)
|
||||
+{
|
||||
+
|
||||
+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
|
||||
+
|
||||
+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
|
||||
+
|
||||
+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
|
||||
+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
|
||||
+
|
||||
+ SPI_TRANSMIT_BUFFER_REG = tx_data;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static inline struct cns3xxx_spi *to_hw(struct spi_device *sdev)
|
||||
+{
|
||||
+ return spi_master_get_devdata(sdev->master);
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_spi_setup_transfer(struct spi_device *spi,
|
||||
+ struct spi_transfer *t)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void cns3xxx_spi_chipselect(struct spi_device *spi, int value)
|
||||
+{
|
||||
+ unsigned int spi_config;
|
||||
+
|
||||
+ switch (value) {
|
||||
+ case BITBANG_CS_INACTIVE:
|
||||
+ break;
|
||||
+
|
||||
+ case BITBANG_CS_ACTIVE:
|
||||
+ spi_config = SPI_CONFIGURATION_REG;
|
||||
+
|
||||
+ if (spi->mode & SPI_CPHA)
|
||||
+ spi_config |= (0x1 << 13);
|
||||
+ else
|
||||
+ spi_config &= ~(0x1 << 13);
|
||||
+
|
||||
+ if (spi->mode & SPI_CPOL)
|
||||
+ spi_config |= (0x1 << 14);
|
||||
+ else
|
||||
+ spi_config &= ~(0x1 << 14);
|
||||
+
|
||||
+ /* write new configration */
|
||||
+ SPI_CONFIGURATION_REG = spi_config;
|
||||
+
|
||||
+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
|
||||
+ SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3);
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_spi_setup(struct spi_device *spi)
|
||||
+{
|
||||
+ if (!spi->bits_per_word)
|
||||
+ spi->bits_per_word = 8;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
+{
|
||||
+ struct cns3xxx_spi *hw = to_hw(spi);
|
||||
+
|
||||
+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf,
|
||||
+ t->len);
|
||||
+
|
||||
+ hw->tx = t->tx_buf;
|
||||
+ hw->rx = t->rx_buf;
|
||||
+ hw->len = t->len;
|
||||
+ hw->count = 0;
|
||||
+ hw->last_in_message_list = t->last_in_message_list;
|
||||
+
|
||||
+ init_completion(&hw->done);
|
||||
+
|
||||
+ if (hw->tx) {
|
||||
+ int i;
|
||||
+ u32 rx_data;
|
||||
+ for (i = 0; i < (hw->len - 1); i++) {
|
||||
+ dev_dbg(&spi->dev,
|
||||
+ "[SPI_CNS3XXX_DEBUG] hw->tx[%02d]: 0x%02x\n", i,
|
||||
+ hw->tx[i]);
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
|
||||
+ &rx_data);
|
||||
+ if (hw->rx) {
|
||||
+ hw->rx[i] = rx_data;
|
||||
+ dev_dbg(&spi->dev,
|
||||
+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
|
||||
+ i, hw->rx[i]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (t->last_in_message_list) {
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 1, hw->tx[i],
|
||||
+ &rx_data);
|
||||
+ if (hw->rx) {
|
||||
+ hw->rx[i] = rx_data;
|
||||
+ dev_dbg(&spi->dev,
|
||||
+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
|
||||
+ i, hw->rx[i]);
|
||||
+ }
|
||||
+ } else {
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
|
||||
+ &rx_data);
|
||||
+ }
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (hw->rx) {
|
||||
+ int i;
|
||||
+ u32 rx_data;
|
||||
+ for (i = 0; i < (hw->len - 1); i++) {
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
|
||||
+ hw->rx[i] = rx_data;
|
||||
+ dev_dbg(&spi->dev,
|
||||
+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n", i,
|
||||
+ hw->rx[i]);
|
||||
+ }
|
||||
+
|
||||
+ if (t->last_in_message_list) {
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 1, 0xff, &rx_data);
|
||||
+ } else {
|
||||
+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
|
||||
+ }
|
||||
+ hw->rx[i] = rx_data;
|
||||
+ dev_dbg(&spi->dev, "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
|
||||
+ i, hw->rx[i]);
|
||||
+ }
|
||||
+done:
|
||||
+ return hw->len;
|
||||
+}
|
||||
+
|
||||
+static void __init cns3xxx_spi_initial(void)
|
||||
+{
|
||||
+ u32 __iomem *gpiob = __io(CNS3XXX_MISC_BASE_VIRT + 0x0018);
|
||||
+ u32 gpiob_pins = __raw_readl(gpiob);
|
||||
+
|
||||
+ /* MMC/SD pins share with GPIOA */
|
||||
+ gpiob_pins |= 0xf80;
|
||||
+ __raw_writel(gpiob_pins, gpiob);
|
||||
+
|
||||
+ /* share pin config. */
|
||||
+ //PM_PLL_HM_PD_CTRL_REG &= ~(0x1 << 5);
|
||||
+ //HAL_MISC_ENABLE_SPI_PINS();
|
||||
+ cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SPI_PCM_I2C));
|
||||
+ cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SPI_PCM_I2C));
|
||||
+
|
||||
+ SPI_CONFIGURATION_REG = (((0x0 & 0x3) << 0) | /* 8bits shift length */
|
||||
+ (0x0 << 9) | /* SPI mode */
|
||||
+ (0x0 << 10) | /* disable FIFO */
|
||||
+ (0x1 << 11) | /* SPI master mode */
|
||||
+ (0x0 << 12) | /* disable SPI loopback mode */
|
||||
+ (0x1 << 13) | /* clock phase */
|
||||
+ (0x1 << 14) | /* clock polarity */
|
||||
+ (0x0 << 24) | /* disable - SPI data swap */
|
||||
+ (0x1 << 29) | /* enable - 2IO Read mode */
|
||||
+ (0x0 << 30) | /* disable - SPI high speed read for system boot up */
|
||||
+ (0x0 << 31)); /* disable - SPI */
|
||||
+
|
||||
+ /* Set SPI bit rate PCLK/2 */
|
||||
+ SPI_BIT_RATE_CONTROL_REG = 0x1;
|
||||
+
|
||||
+ /* Set SPI Tx channel 0 */
|
||||
+ SPI_TRANSMIT_CONTROL_REG = 0x0;
|
||||
+
|
||||
+ /* Set Tx FIFO Threshold, Tx FIFO has 2 words */
|
||||
+ SPI_FIFO_TRANSMIT_CONFIG_REG &= ~(0x03 << 4);
|
||||
+ SPI_FIFO_TRANSMIT_CONFIG_REG |= ((0x0 & 0x03) << 4);
|
||||
+
|
||||
+ /* Set Rx FIFO Threshold, Rx FIFO has 2 words */
|
||||
+ SPI_FIFO_RECEIVE_CONFIG_REG &= ~(0x03 << 4);
|
||||
+ SPI_FIFO_RECEIVE_CONFIG_REG |= ((0x0 & 0x03) << 4);
|
||||
+
|
||||
+ /* Disable all interrupt */
|
||||
+ SPI_INTERRUPT_ENABLE_REG = 0x0;
|
||||
+
|
||||
+ /* Clear spurious interrupt sources */
|
||||
+ SPI_INTERRUPT_STATUS_REG = (0x0F << 4);
|
||||
+
|
||||
+ /* Enable SPI */
|
||||
+ SPI_CONFIGURATION_REG |= (0x1 << 31);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static int __devinit cns3xxx_spi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct spi_master *master;
|
||||
+ struct cns3xxx_spi *hw;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ printk("%s: setup CNS3XXX SPI Controller\n", __FUNCTION__);
|
||||
+
|
||||
+ /* Allocate master with space for cns3xxx_spi */
|
||||
+ master = spi_alloc_master(&pdev->dev, sizeof(struct cns3xxx_spi));
|
||||
+ if (master == NULL) {
|
||||
+ dev_err(&pdev->dev, "No memory for spi_master\n");
|
||||
+ err = -ENOMEM;
|
||||
+ goto err_nomem;
|
||||
+ }
|
||||
+
|
||||
+ hw = spi_master_get_devdata(master);
|
||||
+ memset(hw, 0, sizeof(struct cns3xxx_spi));
|
||||
+
|
||||
+ hw->master = spi_master_get(master);
|
||||
+ hw->dev = &pdev->dev;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hw);
|
||||
+ init_completion(&hw->done);
|
||||
+
|
||||
+ /* setup the master state. */
|
||||
+
|
||||
+ master->num_chipselect = 4;
|
||||
+ master->bus_num = 1;
|
||||
+
|
||||
+ /* setup the state for the bitbang driver */
|
||||
+
|
||||
+ hw->bitbang.master = hw->master;
|
||||
+ hw->bitbang.setup_transfer = cns3xxx_spi_setup_transfer;
|
||||
+ hw->bitbang.chipselect = cns3xxx_spi_chipselect;
|
||||
+ hw->bitbang.txrx_bufs = cns3xxx_spi_txrx;
|
||||
+ hw->bitbang.master->setup = cns3xxx_spi_setup;
|
||||
+
|
||||
+ dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
|
||||
+
|
||||
+ /* SPI controller initializations */
|
||||
+ cns3xxx_spi_initial();
|
||||
+
|
||||
+ /* register SPI controller */
|
||||
+
|
||||
+ err = spi_bitbang_start(&hw->bitbang);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Failed to register SPI master\n");
|
||||
+ goto err_register;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_register:
|
||||
+ spi_master_put(hw->master);;
|
||||
+
|
||||
+err_nomem:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int __devexit cns3xxx_spi_remove(struct platform_device *dev)
|
||||
+{
|
||||
+ struct cns3xxx_spi *hw = platform_get_drvdata(dev);
|
||||
+
|
||||
+ platform_set_drvdata(dev, NULL);
|
||||
+
|
||||
+ spi_unregister_master(hw->master);
|
||||
+
|
||||
+ spi_master_put(hw->master);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+
|
||||
+static int cns3xxx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
|
||||
+{
|
||||
+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_spi_resume(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+#define cns3xxx_spi_suspend NULL
|
||||
+#define cns3xxx_spi_resume NULL
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver cns3xxx_spi_driver = {
|
||||
+ .probe = cns3xxx_spi_probe,
|
||||
+ .remove = __devexit_p(cns3xxx_spi_remove),
|
||||
+ .suspend = cns3xxx_spi_suspend,
|
||||
+ .resume = cns3xxx_spi_resume,
|
||||
+ .driver = {
|
||||
+ .name = "cns3xxx_spi",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns3xxx_spi_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&cns3xxx_spi_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit cns3xxx_spi_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&cns3xxx_spi_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(cns3xxx_spi_init);
|
||||
+module_exit(cns3xxx_spi_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Cavium Networks");
|
||||
+MODULE_DESCRIPTION("CNS3XXX SPI Controller Driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("platform:cns3xxx_spi");
|
||||
+
|
||||
+EXPORT_SYMBOL_GPL(cns3xxx_spi_tx_rx);
|
||||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -457,6 +457,13 @@ struct spi_transfer {
|
||||
u32 speed_hz;
|
||||
|
||||
struct list_head transfer_list;
|
||||
+
|
||||
+#ifdef CONFIG_ARCH_CNS3XXX
|
||||
+ unsigned last_in_message_list;
|
||||
+#ifdef CONFIG_SPI_CNS3XXX_2IOREAD
|
||||
+ u8 dio_read;
|
||||
+#endif
|
||||
+#endif
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/drivers/spi/spi-bitbang.c
|
||||
+++ b/drivers/spi/spi-bitbang.c
|
||||
@@ -330,6 +330,12 @@ static void bitbang_work(struct work_str
|
||||
*/
|
||||
if (!m->is_dma_mapped)
|
||||
t->rx_dma = t->tx_dma = 0;
|
||||
+
|
||||
+ if (t->transfer_list.next == &m->transfers)
|
||||
+ t->last_in_message_list = 1;
|
||||
+ else
|
||||
+ t->last_in_message_list = 0;
|
||||
+
|
||||
status = bitbang->txrx_bufs(spi, t);
|
||||
}
|
||||
if (status > 0)
|
@ -0,0 +1,11 @@
|
||||
--- a/arch/arm/mach-cns3xxx/pcie.c
|
||||
+++ b/arch/arm/mach-cns3xxx/pcie.c
|
||||
@@ -378,8 +378,6 @@ static int __init cns3xxx_pcie_init(void
|
||||
for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
|
||||
iotable_init(cns3xxx_pcie[i].cfg_bases,
|
||||
ARRAY_SIZE(cns3xxx_pcie[i].cfg_bases));
|
||||
- cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i));
|
||||
- cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i));
|
||||
cns3xxx_pcie_check_link(&cns3xxx_pcie[i]);
|
||||
cns3xxx_pcie_hw_init(&cns3xxx_pcie[i]);
|
||||
pci_common_init(&cns3xxx_pcie[i].hw_pci);
|
992
target/linux/cns3xxx/patches-3.3/100-laguna_support.patch
Normal file
992
target/linux/cns3xxx/patches-3.3/100-laguna_support.patch
Normal file
@ -0,0 +1,992 @@
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/laguna.c
|
||||
@@ -0,0 +1,761 @@
|
||||
+/*
|
||||
+ * Gateworks Corporation Laguna Platform
|
||||
+ *
|
||||
+ * Copyright 2000 Deep Blue Solutions Ltd
|
||||
+ * Copyright 2008 ARM Limited
|
||||
+ * Copyright 2008 Cavium Networks
|
||||
+ * Scott Shu
|
||||
+ * Copyright 2010 MontaVista Software, LLC.
|
||||
+ * Anton Vorontsov <avorontsov@mvista.com>
|
||||
+ * Copyright 2011 Gateworks Corporation
|
||||
+ * Chris Lang <clang@gateworks.com>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/serial_core.h>
|
||||
+#include <linux/serial_8250.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/physmap.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/i2c/at24.h>
|
||||
+#include <linux/i2c/pca953x.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/if_ether.h>
|
||||
+#include <asm/setup.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <asm/mach/map.h>
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <mach/cns3xxx.h>
|
||||
+#include <mach/irqs.h>
|
||||
+#include <mach/platform.h>
|
||||
+#include <mach/pm.h>
|
||||
+#include "core.h"
|
||||
+#include "devices.h"
|
||||
+
|
||||
+// Config 1 Bitmap
|
||||
+#define ETH0_LOAD BIT(0)
|
||||
+#define ETH1_LOAD BIT(1)
|
||||
+#define ETH2_LOAD BIT(2)
|
||||
+#define SATA0_LOAD BIT(3)
|
||||
+#define SATA1_LOAD BIT(4)
|
||||
+#define PCM_LOAD BIT(5)
|
||||
+#define I2S_LOAD BIT(6)
|
||||
+#define SPI0_LOAD BIT(7)
|
||||
+#define SPI1_LOAD BIT(8)
|
||||
+#define PCIE0_LOAD BIT(9)
|
||||
+#define PCIE1_LOAD BIT(10)
|
||||
+#define USB0_LOAD BIT(11)
|
||||
+#define USB1_LOAD BIT(12)
|
||||
+#define USB1_ROUTE BIT(13)
|
||||
+#define SD_LOAD BIT(14)
|
||||
+#define UART0_LOAD BIT(15)
|
||||
+#define UART1_LOAD BIT(16)
|
||||
+#define UART2_LOAD BIT(17)
|
||||
+#define MPCI0_LOAD BIT(18)
|
||||
+#define MPCI1_LOAD BIT(19)
|
||||
+#define MPCI2_LOAD BIT(20)
|
||||
+#define MPCI3_LOAD BIT(21)
|
||||
+#define FP_BUT_LOAD BIT(22)
|
||||
+#define FP_BUT_HEADER_LOAD BIT(23)
|
||||
+#define FP_LED_LOAD BIT(24)
|
||||
+#define FP_LED_HEADER_LOAD BIT(25)
|
||||
+#define FP_TAMPER_LOAD BIT(26)
|
||||
+#define HEADER_33V_LOAD BIT(27)
|
||||
+#define SATA_POWER_LOAD BIT(28)
|
||||
+#define FP_POWER_LOAD BIT(29)
|
||||
+#define GPIO_HEADER_LOAD BIT(30)
|
||||
+#define GSP_BAT_LOAD BIT(31)
|
||||
+
|
||||
+// Config 2 Bitmap
|
||||
+#define FAN_LOAD BIT(0)
|
||||
+#define SPI_FLASH_LOAD BIT(1)
|
||||
+#define NOR_FLASH_LOAD BIT(2)
|
||||
+#define GPS_LOAD BIT(3)
|
||||
+#define SUPPLY_5V_LOAD BIT(6)
|
||||
+#define SUPPLY_33V_LOAD BIT(7)
|
||||
+
|
||||
+struct laguna_board_info {
|
||||
+ char model[16];
|
||||
+ u32 config_bitmap;
|
||||
+ u32 config2_bitmap;
|
||||
+ u8 nor_flash_size;
|
||||
+ u8 spi_flash_size;
|
||||
+};
|
||||
+
|
||||
+static struct laguna_board_info laguna_info;
|
||||
+
|
||||
+/*
|
||||
+ * NOR Flash
|
||||
+ */
|
||||
+static struct mtd_partition laguna_nor_partitions[] = {
|
||||
+ {
|
||||
+ .name = "uboot",
|
||||
+ .size = SZ_256K,
|
||||
+ .offset = 0,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "params",
|
||||
+ .size = SZ_128K,
|
||||
+ .offset = SZ_256K,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .size = SZ_2M,
|
||||
+ .offset = SZ_256K + SZ_128K,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .size = SZ_16M - SZ_256K - SZ_128K - SZ_2M,
|
||||
+ .offset = SZ_256K + SZ_128K + SZ_2M,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct physmap_flash_data laguna_nor_pdata = {
|
||||
+ .width = 2,
|
||||
+ .parts = laguna_nor_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(laguna_nor_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct resource laguna_nor_res = {
|
||||
+ .start = CNS3XXX_FLASH_BASE,
|
||||
+ .end = CNS3XXX_FLASH_BASE + SZ_128M - 1,
|
||||
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_nor_pdev = {
|
||||
+ .name = "physmap-flash",
|
||||
+ .id = 0,
|
||||
+ .resource = &laguna_nor_res,
|
||||
+ .num_resources = 1,
|
||||
+ .dev = {
|
||||
+ .platform_data = &laguna_nor_pdata,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * SPI
|
||||
+ */
|
||||
+static struct mtd_partition laguna_spi_partitions[] = {
|
||||
+ {
|
||||
+ .name = "uboot",
|
||||
+ .size = SZ_256K,
|
||||
+ .offset = 0,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "params",
|
||||
+ .size = SZ_256K,
|
||||
+ .offset = SZ_256K,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .size = SZ_1M + SZ_512K,
|
||||
+ .offset = SZ_512K,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .size = SZ_16M - SZ_2M,
|
||||
+ .offset = SZ_2M,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct flash_platform_data laguna_spi_pdata = {
|
||||
+ .parts = laguna_spi_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(laguna_spi_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info __initdata laguna_spi_devices[] = {
|
||||
+ {
|
||||
+ .modalias = "m25p80",
|
||||
+ .platform_data = &laguna_spi_pdata,
|
||||
+ .max_speed_hz = 50000000,
|
||||
+ .bus_num = 1,
|
||||
+ .chip_select = 0,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_spi_controller = {
|
||||
+ .name = "cns3xxx_spi",
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * LED's
|
||||
+ */
|
||||
+static struct gpio_led laguna_gpio_leds[] = {
|
||||
+ {
|
||||
+ .name = "user1", /* Green Led */
|
||||
+ .gpio = 115,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "user2", /* Red Led */
|
||||
+ .gpio = 114,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "pwr1", /* Green Led */
|
||||
+ .gpio = 116,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "pwr2", /* Yellow Led */
|
||||
+ .gpio = 117,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "txd1", /* Green Led */
|
||||
+ .gpio = 118,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "txd2", /* Yellow Led */
|
||||
+ .gpio = 119,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "rxd1", /* Green Led */
|
||||
+ .gpio = 120,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "rxd2", /* Yellow Led */
|
||||
+ .gpio = 121,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "ser1", /* Green Led */
|
||||
+ .gpio = 122,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "ser2", /* Yellow Led */
|
||||
+ .gpio = 123,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "enet1", /* Green Led */
|
||||
+ .gpio = 124,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "enet2", /* Yellow Led */
|
||||
+ .gpio = 125,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig1_1", /* Green Led */
|
||||
+ .gpio = 126,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig1_2", /* Yellow Led */
|
||||
+ .gpio = 127,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig2_1", /* Green Led */
|
||||
+ .gpio = 128,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig2_2", /* Yellow Led */
|
||||
+ .gpio = 129,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig3_1", /* Green Led */
|
||||
+ .gpio = 130,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "sig3_2", /* Yellow Led */
|
||||
+ .gpio = 131,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "net1", /*Green Led */
|
||||
+ .gpio = 109,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "net2", /* Red Led */
|
||||
+ .gpio = 110,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "mod1", /* Green Led */
|
||||
+ .gpio = 111,
|
||||
+ .active_low = 1,
|
||||
+ },{
|
||||
+ .name = "mod2", /* Red Led */
|
||||
+ .gpio = 112,
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data laguna_gpio_leds_data = {
|
||||
+ .num_leds = 22,
|
||||
+ .leds = laguna_gpio_leds,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_gpio_leds_device = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &laguna_gpio_leds_data,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Ethernet
|
||||
+ */
|
||||
+static struct cns3xxx_plat_info laguna_net_data = {
|
||||
+ .ports = 0,
|
||||
+ .phy = {
|
||||
+ 0,
|
||||
+ 1,
|
||||
+ 2,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_net_device = {
|
||||
+ .name = "cns3xxx_eth",
|
||||
+ .id = 0,
|
||||
+ .dev.platform_data = &laguna_net_data,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * UART
|
||||
+ */
|
||||
+static void __init laguna_early_serial_setup(void)
|
||||
+{
|
||||
+#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
+ static struct uart_port laguna_serial_port = {
|
||||
+ .membase = (void __iomem *)CNS3XXX_UART0_BASE_VIRT,
|
||||
+ .mapbase = CNS3XXX_UART0_BASE,
|
||||
+ .irq = IRQ_CNS3XXX_UART0,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
|
||||
+ .regshift = 2,
|
||||
+ .uartclk = 24000000,
|
||||
+ .line = 0,
|
||||
+ .type = PORT_16550A,
|
||||
+ .fifosize = 16,
|
||||
+ };
|
||||
+
|
||||
+ early_serial_setup(&laguna_serial_port);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct resource laguna_uart_resources[] = {
|
||||
+ {
|
||||
+ .start = CNS3XXX_UART0_BASE,
|
||||
+ .end = CNS3XXX_UART0_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM
|
||||
+ },{
|
||||
+ .start = CNS3XXX_UART2_BASE,
|
||||
+ .end = CNS3XXX_UART2_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM
|
||||
+ },{
|
||||
+ .start = CNS3XXX_UART2_BASE,
|
||||
+ .end = CNS3XXX_UART2_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct plat_serial8250_port laguna_uart_data[] = {
|
||||
+ {
|
||||
+ .membase = (char*) (CNS3XXX_UART0_BASE_VIRT),
|
||||
+ .mapbase = (CNS3XXX_UART0_BASE),
|
||||
+ .irq = IRQ_CNS3XXX_UART0,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
|
||||
+ .regshift = 2,
|
||||
+ .uartclk = 24000000,
|
||||
+ .type = PORT_16550A,
|
||||
+ },{
|
||||
+ .membase = (char*) (CNS3XXX_UART1_BASE_VIRT),
|
||||
+ .mapbase = (CNS3XXX_UART1_BASE),
|
||||
+ .irq = IRQ_CNS3XXX_UART1,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
|
||||
+ .regshift = 2,
|
||||
+ .uartclk = 24000000,
|
||||
+ .type = PORT_16550A,
|
||||
+ },{
|
||||
+ .membase = (char*) (CNS3XXX_UART2_BASE_VIRT),
|
||||
+ .mapbase = (CNS3XXX_UART2_BASE),
|
||||
+ .irq = IRQ_CNS3XXX_UART2,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST,
|
||||
+ .regshift = 2,
|
||||
+ .uartclk = 24000000,
|
||||
+ .type = PORT_16550A,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_uart = {
|
||||
+ .name = "serial8250",
|
||||
+ .id = PLAT8250_DEV_PLATFORM,
|
||||
+ .dev.platform_data = laguna_uart_data,
|
||||
+ .num_resources = 3,
|
||||
+ .resource = laguna_uart_resources
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * USB
|
||||
+ */
|
||||
+static struct resource cns3xxx_usb_ehci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS3XXX_USB_BASE,
|
||||
+ .end = CNS3XXX_USB_BASE + SZ_16M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = IRQ_CNS3XXX_USB_EHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct platform_device cns3xxx_usb_ehci_device = {
|
||||
+ .name = "cns3xxx-ehci",
|
||||
+ .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
|
||||
+ .resource = cns3xxx_usb_ehci_resources,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns3xxx_usb_ehci_dma_mask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct resource cns3xxx_usb_ohci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS3XXX_USB_OHCI_BASE,
|
||||
+ .end = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = IRQ_CNS3XXX_USB_OHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct platform_device cns3xxx_usb_ohci_device = {
|
||||
+ .name = "cns3xxx-ohci",
|
||||
+ .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
|
||||
+ .resource = cns3xxx_usb_ohci_resources,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns3xxx_usb_ohci_dma_mask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct resource cns3xxx_usb_otg_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS3XXX_USBOTG_BASE,
|
||||
+ .end = CNS3XXX_USBOTG_BASE + SZ_16M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = IRQ_CNS3XXX_USB_OTG,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static u64 cns3xxx_usb_otg_dma_mask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct platform_device cns3xxx_usb_otg_device = {
|
||||
+ .name = "dwc_otg",
|
||||
+ .num_resources = ARRAY_SIZE(cns3xxx_usb_otg_resources),
|
||||
+ .resource = cns3xxx_usb_otg_resources,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns3xxx_usb_otg_dma_mask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * I2C
|
||||
+ */
|
||||
+static struct resource laguna_i2c_resource[] = {
|
||||
+ {
|
||||
+ .start = CNS3XXX_SSP_BASE + 0x20,
|
||||
+ .end = 0x7100003f,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },{
|
||||
+ .start = IRQ_CNS3XXX_I2C,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_i2c_controller = {
|
||||
+ .name = "cns3xxx-i2c",
|
||||
+ .num_resources = 2,
|
||||
+ .resource = laguna_i2c_resource,
|
||||
+};
|
||||
+
|
||||
+static struct memory_accessor *at24_mem_acc;
|
||||
+
|
||||
+static void at24_setup(struct memory_accessor *mem_acc, void *context)
|
||||
+{
|
||||
+ char buf[8];
|
||||
+
|
||||
+ at24_mem_acc = mem_acc;
|
||||
+
|
||||
+ /* Read MAC addresses */
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x100, 6) == 6)
|
||||
+ memcpy(&laguna_net_data.hwaddr[0], buf, ETH_ALEN);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x106, 6) == 6)
|
||||
+ memcpy(&laguna_net_data.hwaddr[1], buf, ETH_ALEN);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x10C, 6) == 6)
|
||||
+ memcpy(&laguna_net_data.hwaddr[2], buf, ETH_ALEN);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x112, 6) == 6)
|
||||
+ memcpy(&laguna_net_data.hwaddr[3], buf, ETH_ALEN);
|
||||
+
|
||||
+ /* Read out Model Information */
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x130, 16) == 16)
|
||||
+ memcpy(&laguna_info.model, buf, 16);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x140, 1) == 1)
|
||||
+ memcpy(&laguna_info.nor_flash_size, buf, 1);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x141, 1) == 1)
|
||||
+ memcpy(&laguna_info.spi_flash_size, buf, 1);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x142, 4) == 4)
|
||||
+ memcpy(&laguna_info.config_bitmap, buf, 4);
|
||||
+ if (at24_mem_acc->read(at24_mem_acc, buf, 0x146, 4) == 4)
|
||||
+ memcpy(&laguna_info.config2_bitmap, buf, 4);
|
||||
+};
|
||||
+
|
||||
+static struct at24_platform_data laguna_eeprom_info = {
|
||||
+ .byte_len = 1024,
|
||||
+ .page_size = 16,
|
||||
+ .flags = AT24_FLAG_READONLY,
|
||||
+ .setup = at24_setup,
|
||||
+};
|
||||
+
|
||||
+static struct pca953x_platform_data laguna_pca_data = {
|
||||
+ .gpio_base = 100,
|
||||
+ .irq_base = -1,
|
||||
+};
|
||||
+
|
||||
+static struct pca953x_platform_data laguna_pca2_data = {
|
||||
+ .gpio_base = 116,
|
||||
+ .irq_base = -1,
|
||||
+};
|
||||
+
|
||||
+static struct i2c_board_info __initdata laguna_i2c_devices[] = {
|
||||
+ {
|
||||
+ I2C_BOARD_INFO("pca9555", 0x23),
|
||||
+ .platform_data = &laguna_pca_data,
|
||||
+ },{
|
||||
+ I2C_BOARD_INFO("pca9555", 0x27),
|
||||
+ .platform_data = &laguna_pca2_data,
|
||||
+ },{
|
||||
+ I2C_BOARD_INFO("gsp", 0x29),
|
||||
+ },{
|
||||
+ I2C_BOARD_INFO ("24c08",0x50),
|
||||
+ .platform_data = &laguna_eeprom_info,
|
||||
+ },{
|
||||
+ I2C_BOARD_INFO("ds1672", 0x68),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Watchdog
|
||||
+ */
|
||||
+
|
||||
+static struct resource laguna_watchdog_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS3XXX_TC11MP_TWD_BASE,
|
||||
+ .end = CNS3XXX_TC11MP_TWD_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = IRQ_LOCALWDOG,
|
||||
+ .end = IRQ_LOCALWDOG,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct platform_device laguna_watchdog = {
|
||||
+ .name = "mpcore_wdt",
|
||||
+ .id = -1,
|
||||
+ .num_resources = ARRAY_SIZE(laguna_watchdog_resources),
|
||||
+ .resource = laguna_watchdog_resources,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Initialization
|
||||
+ */
|
||||
+
|
||||
+static void __init laguna_init(void)
|
||||
+{
|
||||
+ cns3xxx_l2x0_init();
|
||||
+
|
||||
+ platform_device_register(&laguna_watchdog);
|
||||
+
|
||||
+ platform_device_register(&laguna_i2c_controller);
|
||||
+
|
||||
+ i2c_register_board_info(0, laguna_i2c_devices,
|
||||
+ ARRAY_SIZE(laguna_i2c_devices));
|
||||
+
|
||||
+ pm_power_off = cns3xxx_power_off;
|
||||
+}
|
||||
+
|
||||
+static struct map_desc laguna_io_desc[] __initdata = {
|
||||
+ {
|
||||
+ .virtual = CNS3XXX_UART0_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_UART0_BASE),
|
||||
+ .length = SZ_4K,
|
||||
+ .type = MT_DEVICE,
|
||||
+ },{
|
||||
+ .virtual = CNS3XXX_UART1_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_UART1_BASE),
|
||||
+ .length = SZ_4K,
|
||||
+ .type = MT_DEVICE,
|
||||
+ },{
|
||||
+ .virtual = CNS3XXX_UART2_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_UART2_BASE),
|
||||
+ .length = SZ_4K,
|
||||
+ .type = MT_DEVICE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init laguna_map_io(void)
|
||||
+{
|
||||
+ cns3xxx_map_io();
|
||||
+ iotable_init(laguna_io_desc, ARRAY_SIZE(laguna_io_desc));
|
||||
+ laguna_early_serial_setup();
|
||||
+}
|
||||
+
|
||||
+static int __init laguna_model_setup(void)
|
||||
+{
|
||||
+ u32 __iomem *mem;
|
||||
+ u32 reg;
|
||||
+ u8 pcie_bitmap = 0;
|
||||
+
|
||||
+ printk("Running on Gateworks Laguna %s\n", laguna_info.model);
|
||||
+
|
||||
+ if (strncmp(laguna_info.model, "GW", 2) == 0) {
|
||||
+ if (laguna_info.config_bitmap & ETH0_LOAD)
|
||||
+ laguna_net_data.ports |= BIT(0);
|
||||
+ if (laguna_info.config_bitmap & ETH1_LOAD)
|
||||
+ laguna_net_data.ports |= BIT(1);
|
||||
+ if (laguna_info.config_bitmap & ETH2_LOAD)
|
||||
+ laguna_net_data.ports |= BIT(2);
|
||||
+ if (laguna_net_data.ports)
|
||||
+ platform_device_register(&laguna_net_device);
|
||||
+
|
||||
+ if ((laguna_info.config_bitmap & SATA0_LOAD) ||
|
||||
+ (laguna_info.config_bitmap & SATA1_LOAD))
|
||||
+ cns3xxx_ahci_init();
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (PCIE0_LOAD))
|
||||
+ pcie_bitmap |= 0x1;
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (PCIE1_LOAD))
|
||||
+ pcie_bitmap |= 0x2;
|
||||
+
|
||||
+ cns3xxx_pcie_init(pcie_bitmap);
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (USB0_LOAD)) {
|
||||
+ cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
|
||||
+
|
||||
+ /* DRVVBUS pins share with GPIOA */
|
||||
+ mem = (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0014);
|
||||
+ reg = __raw_readl(mem);
|
||||
+ reg |= 0x8;
|
||||
+ __raw_writel(reg, mem);
|
||||
+
|
||||
+ /* Enable OTG */
|
||||
+ mem = (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0808);
|
||||
+ reg = __raw_readl(mem);
|
||||
+ reg &= ~(1 << 10);
|
||||
+ __raw_writel(reg, mem);
|
||||
+
|
||||
+ platform_device_register(&cns3xxx_usb_otg_device);
|
||||
+ }
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (USB1_LOAD)) {
|
||||
+ platform_device_register(&cns3xxx_usb_ehci_device);
|
||||
+ platform_device_register(&cns3xxx_usb_ohci_device);
|
||||
+ }
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (SD_LOAD))
|
||||
+ cns3xxx_sdhci_init();
|
||||
+
|
||||
+ if (laguna_info.config_bitmap & (UART0_LOAD))
|
||||
+ laguna_uart.num_resources = 1;
|
||||
+ if (laguna_info.config_bitmap & (UART1_LOAD))
|
||||
+ laguna_uart.num_resources = 2;
|
||||
+ if (laguna_info.config_bitmap & (UART2_LOAD))
|
||||
+ laguna_uart.num_resources = 3;
|
||||
+ platform_device_register(&laguna_uart);
|
||||
+
|
||||
+ if (laguna_info.config2_bitmap & (NOR_FLASH_LOAD)) {
|
||||
+ switch (laguna_info.nor_flash_size) {
|
||||
+ case 1:
|
||||
+ laguna_nor_partitions[3].size = SZ_8M - SZ_256K - SZ_128K - SZ_2M;
|
||||
+ laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_8M - 1;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ laguna_nor_partitions[3].size = SZ_16M - SZ_256K - SZ_128K - SZ_2M;
|
||||
+ laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_16M - 1;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ laguna_nor_partitions[3].size = SZ_32M - SZ_256K - SZ_128K - SZ_2M;
|
||||
+ laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_32M - 1;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ laguna_nor_partitions[3].size = SZ_64M - SZ_256K - SZ_128K - SZ_2M;
|
||||
+ laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_64M - 1;
|
||||
+ break;
|
||||
+ case 5:
|
||||
+ laguna_nor_partitions[3].size = SZ_128M - SZ_256K - SZ_128K - SZ_2M;
|
||||
+ laguna_nor_res.end = CNS3XXX_FLASH_BASE + SZ_128M - 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ platform_device_register(&laguna_nor_pdev);
|
||||
+ }
|
||||
+
|
||||
+ if (laguna_info.config2_bitmap & (SPI_FLASH_LOAD)) {
|
||||
+ switch (laguna_info.spi_flash_size) {
|
||||
+ case 1:
|
||||
+ laguna_spi_partitions[3].size = SZ_4M - SZ_2M;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ laguna_spi_partitions[3].size = SZ_8M - SZ_2M;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ laguna_spi_partitions[3].size = SZ_16M - SZ_2M;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ laguna_spi_partitions[3].size = SZ_32M - SZ_2M;
|
||||
+ break;
|
||||
+ case 5:
|
||||
+ laguna_spi_partitions[3].size = SZ_64M - SZ_2M;
|
||||
+ break;
|
||||
+ }
|
||||
+ spi_register_board_info(laguna_spi_devices, ARRAY_SIZE(laguna_spi_devices));
|
||||
+ }
|
||||
+
|
||||
+ if ((laguna_info.config_bitmap & SPI0_LOAD) ||
|
||||
+ (laguna_info.config_bitmap & SPI1_LOAD))
|
||||
+ platform_device_register(&laguna_spi_controller);
|
||||
+
|
||||
+ /*
|
||||
+ * Do any model specific setup not known by the bitmap by matching
|
||||
+ * the first 6 characters of the model name
|
||||
+ */
|
||||
+
|
||||
+ if (strncmp(laguna_info.model, "GW2388", 6) == 0) {
|
||||
+ laguna_gpio_leds_data.num_leds = 2;
|
||||
+ } else if (strncmp(laguna_info.model, "GW2380", 6) == 0) {
|
||||
+ laguna_gpio_leds[0].gpio = 107;
|
||||
+ laguna_gpio_leds[1].gpio = 106;
|
||||
+ laguna_gpio_leds_data.num_leds = 2;
|
||||
+ }
|
||||
+ platform_device_register(&laguna_gpio_leds_device);
|
||||
+ } else {
|
||||
+ // Do some defaults here, not sure what yet
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+late_initcall(laguna_model_setup);
|
||||
+
|
||||
+MACHINE_START(GW2388, "Gateworks Corporation Laguna Platform")
|
||||
+ .atag_offset = 0x100,
|
||||
+ .map_io = laguna_map_io,
|
||||
+ .init_irq = cns3xxx_init_irq,
|
||||
+ .timer = &cns3xxx_timer,
|
||||
+ .init_machine = laguna_init,
|
||||
+MACHINE_END
|
||||
--- a/arch/arm/mach-cns3xxx/Kconfig
|
||||
+++ b/arch/arm/mach-cns3xxx/Kconfig
|
||||
@@ -11,4 +11,14 @@ config MACH_CNS3420VB
|
||||
This is a platform with an on-board ARM11 MPCore and has support
|
||||
for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, etc.
|
||||
|
||||
+config MACH_GW2388
|
||||
+ bool "Support for Gateworks Laguna Platform"
|
||||
+ select HAVE_ARM_SCU if SMP
|
||||
+ select MIGHT_HAVE_PCI
|
||||
+ help
|
||||
+ Include support for the Gateworks Laguna Platform
|
||||
+
|
||||
+ This is a platform with an on-board ARM11 MPCore and has support
|
||||
+ for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, I2C, GIG, etc.
|
||||
+
|
||||
endmenu
|
||||
--- a/arch/arm/mach-cns3xxx/core.c
|
||||
+++ b/arch/arm/mach-cns3xxx/core.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
+#include <asm/smp_twd.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <mach/cns3xxx.h>
|
||||
#include "core.h"
|
||||
@@ -68,11 +69,24 @@ static struct map_desc cns3xxx_io_desc[]
|
||||
.pfn = __phys_to_pfn(CNS3XXX_PM_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
+ }, {
|
||||
+ .virtual = CNS3XXX_SWITCH_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_SWITCH_BASE),
|
||||
+ .length = SZ_4K,
|
||||
+ .type = MT_DEVICE,
|
||||
+ }, {
|
||||
+ .virtual = CNS3XXX_SSP_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_SSP_BASE),
|
||||
+ .length = SZ_4K,
|
||||
+ .type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
void __init cns3xxx_map_io(void)
|
||||
{
|
||||
+#ifdef CONFIG_LOCAL_TIMERS
|
||||
+ twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
|
||||
+#endif
|
||||
iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
|
||||
}
|
||||
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -366,6 +366,7 @@ config ARCH_CLPS711X
|
||||
config ARCH_CNS3XXX
|
||||
bool "Cavium Networks CNS3XXX family"
|
||||
select CPU_V6K
|
||||
+ select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARM_GIC
|
||||
select CLKDEV_LOOKUP
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ * arch/arm/mach-cns3xxx/include/mach/gpio.h
|
||||
+ *
|
||||
+ * CNS3xxx GPIO wrappers for arch-neutral GPIO calls
|
||||
+ *
|
||||
+ * Copyright 2011 Gateworks Corporation
|
||||
+ * Chris Lang <clang@gateworks.com>
|
||||
+ *
|
||||
+ * Based on IXP implementation by Milan Svoboda <msvoboda@ra.rockwell.com>
|
||||
+ * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.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.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __ASM_ARCH_CNS3XXX_GPIO_H
|
||||
+#define __ASM_ARCH_CNS3XXX_GPIO_H
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <mach/platform.h>
|
||||
+#include <asm-generic/gpio.h> /* cansleep wrappers */
|
||||
+
|
||||
+#define NR_BUILTIN_GPIO 64
|
||||
+
|
||||
+#define CNS3XXX_GPIO_IN 0x0
|
||||
+#define CNS3XXX_GPIO_OUT 0x1
|
||||
+
|
||||
+#define CNS3XXX_GPIO_LO 0
|
||||
+#define CNS3XXX_GPIO_HI 1
|
||||
+
|
||||
+#define CNS3XXX_GPIO_OUTPUT 0x00
|
||||
+#define CNS3XXX_GPIO_INPUT 0x04
|
||||
+#define CNS3XXX_GPIO_DIR 0x08
|
||||
+#define CNS3XXX_GPIO_SET 0x10
|
||||
+#define CNS3XXX_GPIO_CLEAR 0x14
|
||||
+
|
||||
+static inline void gpio_line_get(u8 line, int *value)
|
||||
+{
|
||||
+ if (line < 32)
|
||||
+ *value = ((__raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> line) & 0x1);
|
||||
+ else
|
||||
+ *value = ((__raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> (line - 32)) & 0x1);
|
||||
+}
|
||||
+
|
||||
+static inline void gpio_line_set(u8 line, int value)
|
||||
+{
|
||||
+ if (line < 32) {
|
||||
+ if (value)
|
||||
+ __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_SET);
|
||||
+ else
|
||||
+ __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
|
||||
+ } else {
|
||||
+ if (value)
|
||||
+ __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_SET);
|
||||
+ else
|
||||
+ __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline int gpio_get_value(unsigned gpio)
|
||||
+{
|
||||
+ if (gpio < NR_BUILTIN_GPIO)
|
||||
+ {
|
||||
+ int value;
|
||||
+ gpio_line_get(gpio, &value);
|
||||
+ return value;
|
||||
+ }
|
||||
+ else
|
||||
+ return __gpio_get_value(gpio);
|
||||
+}
|
||||
+
|
||||
+static inline void gpio_set_value(unsigned gpio, int value)
|
||||
+{
|
||||
+ if (gpio < NR_BUILTIN_GPIO)
|
||||
+ gpio_line_set(gpio, value);
|
||||
+ else
|
||||
+ __gpio_set_value(gpio, value);
|
||||
+}
|
||||
+
|
||||
+#define gpio_cansleep __gpio_cansleep
|
||||
+
|
||||
+extern int gpio_to_irq(int gpio);
|
||||
+extern int irq_to_gpio(int gpio);
|
||||
+
|
||||
+#endif
|
||||
--- a/arch/arm/mach-cns3xxx/Makefile
|
||||
+++ b/arch/arm/mach-cns3xxx/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o devices.o
|
||||
obj-$(CONFIG_PCI) += pcie.o
|
||||
obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o
|
||||
+obj-$(CONFIG_MACH_GW2388) += laguna.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
--- a/arch/arm/mach-cns3xxx/pcie.c
|
||||
+++ b/arch/arm/mach-cns3xxx/pcie.c
|
||||
@@ -365,7 +365,7 @@ static int cns3xxx_pcie_abort_handler(un
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int __init cns3xxx_pcie_init(void)
|
||||
+int cns3xxx_pcie_init(u8 bitmap)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -376,6 +376,9 @@ static int __init cns3xxx_pcie_init(void
|
||||
"imprecise external abort");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
|
||||
+ if (!(bitmap & (1 << i)))
|
||||
+ continue;
|
||||
+
|
||||
iotable_init(cns3xxx_pcie[i].cfg_bases,
|
||||
ARRAY_SIZE(cns3xxx_pcie[i].cfg_bases));
|
||||
cns3xxx_pcie_check_link(&cns3xxx_pcie[i]);
|
||||
@@ -387,4 +390,3 @@ static int __init cns3xxx_pcie_init(void
|
||||
|
||||
return 0;
|
||||
}
|
||||
-device_initcall(cns3xxx_pcie_init);
|
||||
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <asm/mach/time.h>
|
||||
#include <mach/cns3xxx.h>
|
||||
#include <mach/irqs.h>
|
||||
+#include <mach/platform.h>
|
||||
#include "core.h"
|
||||
#include "devices.h"
|
||||
|
||||
@@ -199,6 +200,8 @@ static void __init cns3420_init(void)
|
||||
cns3xxx_ahci_init();
|
||||
cns3xxx_sdhci_init();
|
||||
|
||||
+ cns3xxx_pcie_init(0x3);
|
||||
+
|
||||
pm_power_off = cns3xxx_power_off;
|
||||
}
|
||||
|
||||
--- a/arch/arm/mach-cns3xxx/core.h
|
||||
+++ b/arch/arm/mach-cns3xxx/core.h
|
||||
@@ -12,6 +12,7 @@
|
||||
#define __CNS3XXX_CORE_H
|
||||
|
||||
extern struct sys_timer cns3xxx_timer;
|
||||
+extern int cns3xxx_pcie_init(u8 bitmap);
|
||||
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
void __init cns3xxx_l2x0_init(void);
|
@ -0,0 +1,16 @@
|
||||
--- a/drivers/mmc/host/sdhci-cns3xxx.c
|
||||
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
|
||||
@@ -89,10 +89,11 @@ static struct sdhci_pltfm_data sdhci_cns
|
||||
.ops = &sdhci_cns3xxx_ops,
|
||||
.quirks = SDHCI_QUIRK_BROKEN_DMA |
|
||||
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
|
||||
- SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
|
||||
+ //SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
|
||||
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
||||
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
|
||||
- SDHCI_QUIRK_NONSTANDARD_CLOCK,
|
||||
+ SDHCI_QUIRK_NONSTANDARD_CLOCK |
|
||||
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION,
|
||||
};
|
||||
|
||||
static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
|
109
target/linux/cns3xxx/patches-3.3/102-cns3xxx_timers.patch
Normal file
109
target/linux/cns3xxx/patches-3.3/102-cns3xxx_timers.patch
Normal file
@ -0,0 +1,109 @@
|
||||
--- a/arch/arm/mach-cns3xxx/core.c
|
||||
+++ b/arch/arm/mach-cns3xxx/core.c
|
||||
@@ -125,12 +125,13 @@ static void cns3xxx_timer_set_mode(enum
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
- reload = pclk * 20 / (3 * HZ) * 0x25000;
|
||||
+ reload = pclk * 1000000 / HZ;
|
||||
writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
|
||||
ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set, and timer enabled in 'next_event' hook */
|
||||
+ writel(0, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
|
||||
ctrl |= (1 << 2) | (1 << 9);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
@@ -155,11 +156,11 @@ static int cns3xxx_timer_set_next_event(
|
||||
|
||||
static struct clock_event_device cns3xxx_tmr1_clockevent = {
|
||||
.name = "cns3xxx timer1",
|
||||
- .shift = 8,
|
||||
+ .shift = 32,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = cns3xxx_timer_set_mode,
|
||||
.set_next_event = cns3xxx_timer_set_next_event,
|
||||
- .rating = 350,
|
||||
+ .rating = 300,
|
||||
.cpumask = cpu_all_mask,
|
||||
};
|
||||
|
||||
@@ -201,6 +202,35 @@ static struct irqaction cns3xxx_timer_ir
|
||||
.handler = cns3xxx_timer_interrupt,
|
||||
};
|
||||
|
||||
+static cycle_t cns3xxx_get_cycles(struct clocksource *cs)
|
||||
+{
|
||||
+ u64 val;
|
||||
+
|
||||
+ val = readl(cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
|
||||
+ val &= 0xffff;
|
||||
+
|
||||
+ return ((val << 32) | readl(cns3xxx_tmr1 + TIMER_FREERUN_OFFSET));
|
||||
+}
|
||||
+
|
||||
+static struct clocksource clocksource_cns3xxx = {
|
||||
+ .name = "freerun",
|
||||
+ .rating = 200,
|
||||
+ .read = cns3xxx_get_cycles,
|
||||
+ .mask = CLOCKSOURCE_MASK(48),
|
||||
+ .shift = 16,
|
||||
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
+};
|
||||
+
|
||||
+static void __init cns3xxx_clocksource_init(void)
|
||||
+{
|
||||
+ /* Reset the FreeRunning counter */
|
||||
+ writel((1 << 16), cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
|
||||
+
|
||||
+ clocksource_cns3xxx.mult =
|
||||
+ clocksource_khz2mult(100, clocksource_cns3xxx.shift);
|
||||
+ clocksource_register(&clocksource_cns3xxx);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Set up the clock source and clock events devices
|
||||
*/
|
||||
@@ -218,13 +248,12 @@ static void __init __cns3xxx_timer_init(
|
||||
/* stop free running timer3 */
|
||||
writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET);
|
||||
|
||||
- /* timer1 */
|
||||
- writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
|
||||
- writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
|
||||
-
|
||||
writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET);
|
||||
writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET);
|
||||
|
||||
+ val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ;
|
||||
+ writel(val, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET);
|
||||
+
|
||||
/* mask irq, non-mask timer1 overflow */
|
||||
irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
|
||||
irq_mask &= ~(1 << 2);
|
||||
@@ -236,23 +265,9 @@ static void __init __cns3xxx_timer_init(
|
||||
val |= (1 << 9);
|
||||
writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
|
||||
|
||||
- /* timer2 */
|
||||
- writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET);
|
||||
- writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET);
|
||||
-
|
||||
- /* mask irq */
|
||||
- irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
|
||||
- irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5));
|
||||
- writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET);
|
||||
-
|
||||
- /* down counter */
|
||||
- val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
|
||||
- val |= (1 << 10);
|
||||
- writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
|
||||
-
|
||||
- /* Make irqs happen for the system timer */
|
||||
setup_irq(timer_irq, &cns3xxx_timer_irq);
|
||||
|
||||
+ cns3xxx_clocksource_init();
|
||||
cns3xxx_clockevents_init(timer_irq);
|
||||
}
|
||||
|
118
target/linux/cns3xxx/patches-3.3/104-cns3xxx_gpio.patch
Normal file
118
target/linux/cns3xxx/patches-3.3/104-cns3xxx_gpio.patch
Normal file
@ -0,0 +1,118 @@
|
||||
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
|
||||
@@ -216,7 +216,7 @@ static struct map_desc cns3420_io_desc[]
|
||||
|
||||
static void __init cns3420_map_io(void)
|
||||
{
|
||||
- cns3xxx_map_io();
|
||||
+ cns3xxx_common_init();
|
||||
iotable_init(cns3420_io_desc, ARRAY_SIZE(cns3420_io_desc));
|
||||
|
||||
cns3420_early_serial_setup();
|
||||
--- a/arch/arm/mach-cns3xxx/core.c
|
||||
+++ b/arch/arm/mach-cns3xxx/core.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
+#include <asm/gpio.h>
|
||||
#include <mach/cns3xxx.h>
|
||||
#include "core.h"
|
||||
|
||||
@@ -82,12 +83,73 @@ static struct map_desc cns3xxx_io_desc[]
|
||||
},
|
||||
};
|
||||
|
||||
-void __init cns3xxx_map_io(void)
|
||||
+static inline void gpio_line_config(u8 line, u32 direction)
|
||||
+{
|
||||
+ u32 reg;
|
||||
+ if (direction) {
|
||||
+ if (line < 32) {
|
||||
+ reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ reg |= (1 << line);
|
||||
+ __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ } else {
|
||||
+ reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ reg |= (1 << (line - 32));
|
||||
+ __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (line < 32) {
|
||||
+ reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ reg &= ~(1 << line);
|
||||
+ __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ } else {
|
||||
+ reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ reg &= ~(1 << (line - 32));
|
||||
+ __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
+{
|
||||
+ gpio_line_config(gpio, CNS3XXX_GPIO_IN);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
|
||||
+{
|
||||
+ gpio_line_set(gpio, level);
|
||||
+ gpio_line_config(gpio, CNS3XXX_GPIO_OUT);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns3xxx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
|
||||
+{
|
||||
+ return gpio_get_value(gpio);
|
||||
+}
|
||||
+
|
||||
+static void cns3xxx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
+{
|
||||
+ gpio_set_value(gpio, value);
|
||||
+}
|
||||
+
|
||||
+static struct gpio_chip cns3xxx_gpio_chip = {
|
||||
+ .label = "CNS3XXX_GPIO_CHIP",
|
||||
+ .direction_input = cns3xxx_gpio_direction_input,
|
||||
+ .direction_output = cns3xxx_gpio_direction_output,
|
||||
+ .get = cns3xxx_gpio_get_value,
|
||||
+ .set = cns3xxx_gpio_set_value,
|
||||
+ .base = 0,
|
||||
+ .ngpio = 64,
|
||||
+};
|
||||
+
|
||||
+void __init cns3xxx_common_init(void)
|
||||
{
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
|
||||
#endif
|
||||
iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
|
||||
+
|
||||
+ gpiochip_add(&cns3xxx_gpio_chip);
|
||||
}
|
||||
|
||||
/* used by entry-macro.S */
|
||||
--- a/arch/arm/mach-cns3xxx/core.h
|
||||
+++ b/arch/arm/mach-cns3xxx/core.h
|
||||
@@ -20,7 +20,7 @@ void __init cns3xxx_l2x0_init(void);
|
||||
static inline void cns3xxx_l2x0_init(void) {}
|
||||
#endif /* CONFIG_CACHE_L2X0 */
|
||||
|
||||
-void __init cns3xxx_map_io(void);
|
||||
+void __init cns3xxx_common_init(void);
|
||||
void __init cns3xxx_init_irq(void);
|
||||
void cns3xxx_power_off(void);
|
||||
void cns3xxx_restart(char, const char *);
|
||||
--- a/arch/arm/mach-cns3xxx/laguna.c
|
||||
+++ b/arch/arm/mach-cns3xxx/laguna.c
|
||||
@@ -611,7 +611,7 @@ static struct map_desc laguna_io_desc[]
|
||||
|
||||
static void __init laguna_map_io(void)
|
||||
{
|
||||
- cns3xxx_map_io();
|
||||
+ cns3xxx_common_init();
|
||||
iotable_init(laguna_io_desc, ARRAY_SIZE(laguna_io_desc));
|
||||
laguna_early_serial_setup();
|
||||
}
|
88
target/linux/cns3xxx/patches-3.3/105-cns3xxx_pcie_io.patch
Normal file
88
target/linux/cns3xxx/patches-3.3/105-cns3xxx_pcie_io.patch
Normal file
@ -0,0 +1,88 @@
|
||||
--- a/arch/arm/mach-cns3xxx/core.c
|
||||
+++ b/arch/arm/mach-cns3xxx/core.c
|
||||
@@ -80,6 +80,16 @@ static struct map_desc cns3xxx_io_desc[]
|
||||
.pfn = __phys_to_pfn(CNS3XXX_SSP_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
+ }, {
|
||||
+ .virtual = CNS3XXX_PCIE0_IO_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_PCIE0_IO_BASE),
|
||||
+ .length = SZ_16M,
|
||||
+ .type = MT_DEVICE,
|
||||
+ }, {
|
||||
+ .virtual = CNS3XXX_PCIE1_IO_BASE_VIRT,
|
||||
+ .pfn = __phys_to_pfn(CNS3XXX_PCIE1_IO_BASE),
|
||||
+ .length = SZ_16M,
|
||||
+ .type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -155,13 +165,13 @@ void __init cns3xxx_common_init(void)
|
||||
/* used by entry-macro.S */
|
||||
void __init cns3xxx_init_irq(void)
|
||||
{
|
||||
- gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
|
||||
- __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
|
||||
+ gic_init(0, 29, (void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
|
||||
+ (void __iomem *) CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
|
||||
}
|
||||
|
||||
void cns3xxx_power_off(void)
|
||||
{
|
||||
- u32 __iomem *pm_base = __io(CNS3XXX_PM_BASE_VIRT);
|
||||
+ u32 __iomem *pm_base = (void __iomem *) CNS3XXX_PM_BASE_VIRT;
|
||||
u32 clkctrl;
|
||||
|
||||
printk(KERN_INFO "powering system down...\n");
|
||||
@@ -335,7 +345,7 @@ static void __init __cns3xxx_timer_init(
|
||||
|
||||
static void __init cns3xxx_timer_init(void)
|
||||
{
|
||||
- cns3xxx_tmr1 = __io(CNS3XXX_TIMER1_2_3_BASE_VIRT);
|
||||
+ cns3xxx_tmr1 = (void __iomem *) CNS3XXX_TIMER1_2_3_BASE_VIRT;
|
||||
|
||||
__cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
|
||||
}
|
||||
--- a/arch/arm/mach-cns3xxx/devices.c
|
||||
+++ b/arch/arm/mach-cns3xxx/devices.c
|
||||
@@ -98,7 +98,7 @@ static struct platform_device cns3xxx_sd
|
||||
|
||||
void __init cns3xxx_sdhci_init(void)
|
||||
{
|
||||
- u32 __iomem *gpioa = __io(CNS3XXX_MISC_BASE_VIRT + 0x0014);
|
||||
+ u32 __iomem *gpioa = (void __iomem *) (CNS3XXX_MISC_BASE_VIRT + 0x0014);
|
||||
u32 gpioa_pins = __raw_readl(gpioa);
|
||||
|
||||
/* MMC/SD pins share with GPIOA */
|
||||
--- a/arch/arm/mach-cns3xxx/include/mach/io.h
|
||||
+++ b/arch/arm/mach-cns3xxx/include/mach/io.h
|
||||
@@ -9,9 +9,17 @@
|
||||
#ifndef __MACH_IO_H
|
||||
#define __MACH_IO_H
|
||||
|
||||
+#include "cns3xxx.h"
|
||||
+
|
||||
#define IO_SPACE_LIMIT 0xffffffff
|
||||
|
||||
-#define __io(a) __typesafe_io(a)
|
||||
+static inline void __iomem *__io(unsigned long addr)
|
||||
+{
|
||||
+ return (void __iomem *)((addr - CNS3XXX_PCIE0_IO_BASE)
|
||||
+ + CNS3XXX_PCIE0_IO_BASE_VIRT);
|
||||
+}
|
||||
+
|
||||
+#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#endif
|
||||
--- a/drivers/spi/spi_cns3xxx.c
|
||||
+++ b/drivers/spi/spi_cns3xxx.c
|
||||
@@ -273,7 +273,7 @@ done:
|
||||
|
||||
static void __init cns3xxx_spi_initial(void)
|
||||
{
|
||||
- u32 __iomem *gpiob = __io(CNS3XXX_MISC_BASE_VIRT + 0x0018);
|
||||
+ u32 __iomem *gpiob = (void __iomem *) (CNS3XXX_MISC_BASE_VIRT + 0x0018);
|
||||
u32 gpiob_pins = __raw_readl(gpiob);
|
||||
|
||||
/* MMC/SD pins share with GPIOA */
|
@ -0,0 +1,97 @@
|
||||
--- a/arch/arm/mach-cns3xxx/devices.c
|
||||
+++ b/arch/arm/mach-cns3xxx/devices.c
|
||||
@@ -41,7 +41,7 @@ static struct resource cns3xxx_ahci_reso
|
||||
static u64 cns3xxx_ahci_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device cns3xxx_ahci_pdev = {
|
||||
- .name = "ahci",
|
||||
+ .name = "ahci-cns3xxx",
|
||||
.id = 0,
|
||||
.resource = cns3xxx_ahci_resource,
|
||||
.num_resources = ARRAY_SIZE(cns3xxx_ahci_resource),
|
||||
--- a/drivers/ata/ahci_platform.c
|
||||
+++ b/drivers/ata/ahci_platform.c
|
||||
@@ -27,6 +27,7 @@ enum ahci_type {
|
||||
AHCI, /* standard platform ahci */
|
||||
IMX53_AHCI, /* ahci on i.mx53 */
|
||||
STRICT_AHCI, /* delayed DMA engine start */
|
||||
+ CNS3XXX_AHCI, /* AHCI on cns3xxx */
|
||||
};
|
||||
|
||||
static struct platform_device_id ahci_devtype[] = {
|
||||
@@ -40,11 +41,32 @@ static struct platform_device_id ahci_de
|
||||
.name = "strict-ahci",
|
||||
.driver_data = STRICT_AHCI,
|
||||
}, {
|
||||
+ .name = "ahci-cns3xxx",
|
||||
+ .driver_data = CNS3XXX_AHCI,
|
||||
+ }, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, ahci_devtype);
|
||||
|
||||
+static int
|
||||
+cns3xxx_ahci_softreset(struct ata_link *link, unsigned int *class,
|
||||
+ unsigned long deadline)
|
||||
+{
|
||||
+ int pmp = sata_srst_pmp(link);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
|
||||
+ if (pmp && ret)
|
||||
+ return ahci_do_softreset(link, class, 0, deadline,
|
||||
+ ahci_check_ready);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static struct ata_port_operations cns3xxx_ahci_ops = {
|
||||
+ .inherits = &ahci_ops,
|
||||
+ .softreset = cns3xxx_ahci_softreset,
|
||||
+};
|
||||
|
||||
static const struct ata_port_info ahci_port_info[] = {
|
||||
/* by features */
|
||||
@@ -67,13 +89,19 @@ static const struct ata_port_info ahci_p
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
+ [CNS3XXX_AHCI] = {
|
||||
+ .flags = AHCI_FLAG_COMMON,
|
||||
+ .pio_mask = ATA_PIO4,
|
||||
+ .udma_mask = ATA_UDMA6,
|
||||
+ .port_ops = &cns3xxx_ahci_ops,
|
||||
+ }
|
||||
};
|
||||
|
||||
static struct scsi_host_template ahci_platform_sht = {
|
||||
AHCI_SHT("ahci_platform"),
|
||||
};
|
||||
|
||||
-static int __init ahci_probe(struct platform_device *pdev)
|
||||
+static int __devinit ahci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ahci_platform_data *pdata = dev_get_platdata(dev);
|
||||
@@ -285,6 +313,7 @@ static const struct of_device_id ahci_of
|
||||
MODULE_DEVICE_TABLE(of, ahci_of_match);
|
||||
|
||||
static struct platform_driver ahci_driver = {
|
||||
+ .probe = ahci_probe,
|
||||
.remove = __devexit_p(ahci_remove),
|
||||
.driver = {
|
||||
.name = "ahci",
|
||||
@@ -299,7 +328,7 @@ static struct platform_driver ahci_drive
|
||||
|
||||
static int __init ahci_init(void)
|
||||
{
|
||||
- return platform_driver_probe(&ahci_driver, ahci_probe);
|
||||
+ return platform_driver_register(&ahci_driver);
|
||||
}
|
||||
module_init(ahci_init);
|
||||
|
||||
@@ -312,4 +341,3 @@ module_exit(ahci_exit);
|
||||
MODULE_DESCRIPTION("AHCI SATA platform driver");
|
||||
MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
-MODULE_ALIAS("platform:ahci");
|
@ -0,0 +1,26 @@
|
||||
--- a/arch/arm/mach-cns3xxx/pcie.c
|
||||
+++ b/arch/arm/mach-cns3xxx/pcie.c
|
||||
@@ -161,12 +161,12 @@ static int cns3xxx_pci_setup(int nr, str
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static struct pci_ops cns3xxx_pcie_ops = {
|
||||
+struct pci_ops cns3xxx_pcie_ops = {
|
||||
.read = cns3xxx_pci_read_config,
|
||||
.write = cns3xxx_pci_write_config,
|
||||
};
|
||||
|
||||
-static struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
+struct pci_bus * __devinit cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
return pci_scan_root_bus(NULL, sys->busnr, &cns3xxx_pcie_ops, sys,
|
||||
&sys->resources);
|
||||
@@ -365,7 +365,7 @@ static int cns3xxx_pcie_abort_handler(un
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int cns3xxx_pcie_init(u8 bitmap)
|
||||
+int __init cns3xxx_pcie_init(u8 bitmap)
|
||||
{
|
||||
int i;
|
||||
|
339
target/linux/cns3xxx/patches-3.3/110-gateworks_gsp_support.patch
Normal file
339
target/linux/cns3xxx/patches-3.3/110-gateworks_gsp_support.patch
Normal file
@ -0,0 +1,339 @@
|
||||
--- a/drivers/hwmon/Kconfig
|
||||
+++ b/drivers/hwmon/Kconfig
|
||||
@@ -423,6 +423,15 @@ config SENSORS_GL520SM
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called gl520sm.
|
||||
|
||||
+config SENSORS_GSP
|
||||
+ tristate "Gateworks System Peripheral"
|
||||
+ depends on I2C && EXPERIMENTAL
|
||||
+ help
|
||||
+ If you say yes here you get support for the Gateworks System Peripherals.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module
|
||||
+ will be called gsp.
|
||||
+
|
||||
config SENSORS_GPIO_FAN
|
||||
tristate "GPIO fan"
|
||||
depends on GENERIC_GPIO
|
||||
--- a/drivers/hwmon/Makefile
|
||||
+++ b/drivers/hwmon/Makefile
|
||||
@@ -125,6 +125,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l7
|
||||
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
|
||||
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
|
||||
+obj-$(CONFIG_SENSORS_GSP) += gsp.o
|
||||
|
||||
obj-$(CONFIG_PMBUS) += pmbus/
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/hwmon/gsp.c
|
||||
@@ -0,0 +1,308 @@
|
||||
+/*
|
||||
+ * A hwmon driver for the Gateworks System Peripheral
|
||||
+ * Copyright (C) 2009 Gateworks Corporation
|
||||
+ *
|
||||
+ * Author: Chris Lang <clang@gateworks.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 - version 2.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/hwmon.h>
|
||||
+#include <linux/hwmon-sysfs.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define DRV_VERSION "0.2"
|
||||
+
|
||||
+enum chips { gsp };
|
||||
+
|
||||
+/* AD7418 registers */
|
||||
+#define GSP_REG_TEMP_IN 0x00
|
||||
+#define GSP_REG_VIN 0x02
|
||||
+#define GSP_REG_3P3 0x05
|
||||
+#define GSP_REG_BAT 0x08
|
||||
+#define GSP_REG_5P0 0x0b
|
||||
+#define GSP_REG_CORE 0x0e
|
||||
+#define GSP_REG_CPU1 0x11
|
||||
+#define GSP_REG_CPU2 0x14
|
||||
+#define GSP_REG_DRAM 0x17
|
||||
+#define GSP_REG_EXT_BAT 0x1a
|
||||
+#define GSP_REG_IO1 0x1d
|
||||
+#define GSP_REG_IO2 0x20
|
||||
+#define GSP_REG_PCIE 0x23
|
||||
+#define GSP_REG_CURRENT 0x26
|
||||
+#define GSP_FAN_0 0x2C
|
||||
+#define GSP_FAN_1 0x2E
|
||||
+#define GSP_FAN_2 0x30
|
||||
+#define GSP_FAN_3 0x32
|
||||
+#define GSP_FAN_4 0x34
|
||||
+#define GSP_FAN_5 0x36
|
||||
+
|
||||
+struct gsp_sensor_info {
|
||||
+ const char* name;
|
||||
+ int reg;
|
||||
+};
|
||||
+
|
||||
+static const struct gsp_sensor_info gsp_sensors[] = {
|
||||
+ {"temp", GSP_REG_TEMP_IN},
|
||||
+ {"vin", GSP_REG_VIN},
|
||||
+ {"3p3", GSP_REG_3P3},
|
||||
+ {"bat", GSP_REG_BAT},
|
||||
+ {"5p0", GSP_REG_5P0},
|
||||
+ {"core", GSP_REG_CORE},
|
||||
+ {"cpu1", GSP_REG_CPU1},
|
||||
+ {"cpu2", GSP_REG_CPU2},
|
||||
+ {"dram", GSP_REG_DRAM},
|
||||
+ {"ext_bat", GSP_REG_EXT_BAT},
|
||||
+ {"io1", GSP_REG_IO1},
|
||||
+ {"io2", GSP_REG_IO2},
|
||||
+ {"pci2", GSP_REG_PCIE},
|
||||
+ {"current", GSP_REG_CURRENT},
|
||||
+ {"fan_point0", GSP_FAN_0},
|
||||
+ {"fan_point1", GSP_FAN_1},
|
||||
+ {"fan_point2", GSP_FAN_2},
|
||||
+ {"fan_point3", GSP_FAN_3},
|
||||
+ {"fan_point4", GSP_FAN_4},
|
||||
+ {"fan_point5", GSP_FAN_5},
|
||||
+};
|
||||
+
|
||||
+struct gsp_data {
|
||||
+ struct device *hwmon_dev;
|
||||
+ struct attribute_group attrs;
|
||||
+ enum chips type;
|
||||
+};
|
||||
+
|
||||
+static int gsp_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id);
|
||||
+static int gsp_remove(struct i2c_client *client);
|
||||
+
|
||||
+static const struct i2c_device_id gsp_id[] = {
|
||||
+ { "gsp", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, gsp_id);
|
||||
+
|
||||
+static struct i2c_driver gsp_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "gsp",
|
||||
+ },
|
||||
+ .probe = gsp_probe,
|
||||
+ .remove = gsp_remove,
|
||||
+ .id_table = gsp_id,
|
||||
+};
|
||||
+
|
||||
+/* All registers are word-sized, except for the configuration registers.
|
||||
+ * AD7418 uses a high-byte first convention. Do NOT use those functions to
|
||||
+ * access the configuration registers CONF and CONF2, as they are byte-sized.
|
||||
+ */
|
||||
+static inline int gsp_read(struct i2c_client *client, u8 reg)
|
||||
+{
|
||||
+ unsigned int adc = 0;
|
||||
+ if (reg == GSP_REG_TEMP_IN || reg > GSP_REG_CURRENT)
|
||||
+ {
|
||||
+ adc |= i2c_smbus_read_byte_data(client, reg);
|
||||
+ adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
|
||||
+ return adc;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ adc |= i2c_smbus_read_byte_data(client, reg);
|
||||
+ adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
|
||||
+ adc |= i2c_smbus_read_byte_data(client, reg + 2) << 16;
|
||||
+ return adc;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline int gsp_write(struct i2c_client *client, u8 reg, u16 value)
|
||||
+{
|
||||
+ i2c_smbus_write_byte_data(client, reg, value & 0xff);
|
||||
+ i2c_smbus_write_byte_data(client, reg + 1, ((value >> 8) & 0xff));
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static ssize_t show_adc(struct device *dev, struct device_attribute *devattr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
+ struct i2c_client *client = to_i2c_client(dev);
|
||||
+ return sprintf(buf, "%d\n", gsp_read(client, gsp_sensors[attr->index].reg));
|
||||
+}
|
||||
+
|
||||
+static ssize_t show_label(struct device *dev,
|
||||
+ struct device_attribute *devattr, char *buf)
|
||||
+{
|
||||
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
+
|
||||
+ return sprintf(buf, "%s\n", gsp_sensors[attr->index].name);
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_fan(struct device *dev,
|
||||
+ struct device_attribute *devattr, const char *buf, size_t count)
|
||||
+{
|
||||
+ u16 val;
|
||||
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
+ struct i2c_client *client = to_i2c_client(dev);
|
||||
+ val = simple_strtoul(buf, NULL, 10);
|
||||
+ gsp_write(client, gsp_sensors[attr->index].reg, val);
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static SENSOR_DEVICE_ATTR(temp0_input, S_IRUGO, show_adc, NULL, 0);
|
||||
+static SENSOR_DEVICE_ATTR(temp0_label, S_IRUGO, show_label, NULL, 0);
|
||||
+
|
||||
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_adc, NULL, 1);
|
||||
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL, 1);
|
||||
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 2);
|
||||
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL, 2);
|
||||
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 3);
|
||||
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL, 3);
|
||||
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 4);
|
||||
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 4);
|
||||
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 5);
|
||||
+static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_label, NULL, 5);
|
||||
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_adc, NULL, 6);
|
||||
+static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_label, NULL, 6);
|
||||
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_adc, NULL, 7);
|
||||
+static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_label, NULL, 7);
|
||||
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_adc, NULL, 8);
|
||||
+static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 8);
|
||||
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_adc, NULL, 9);
|
||||
+static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 9);
|
||||
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_adc, NULL, 10);
|
||||
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 10);
|
||||
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_adc, NULL, 11);
|
||||
+static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_label, NULL, 11);
|
||||
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_adc, NULL, 12);
|
||||
+static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_label, NULL, 12);
|
||||
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_adc, NULL, 13);
|
||||
+static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_label, NULL, 13);
|
||||
+
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point0, S_IRUGO | S_IWUSR, show_adc, store_fan, 14);
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point1, S_IRUGO | S_IWUSR, show_adc, store_fan, 15);
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point2, S_IRUGO | S_IWUSR, show_adc, store_fan, 16);
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point3, S_IRUGO | S_IWUSR, show_adc, store_fan, 17);
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point4, S_IRUGO | S_IWUSR, show_adc, store_fan, 18);
|
||||
+static SENSOR_DEVICE_ATTR(fan0_point5, S_IRUGO | S_IWUSR, show_adc, store_fan, 19);
|
||||
+
|
||||
+static struct attribute *gsp_attributes[] = {
|
||||
+ &sensor_dev_attr_temp0_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in8_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in9_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in10_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in11_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in12_input.dev_attr.attr,
|
||||
+
|
||||
+ &sensor_dev_attr_temp0_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in0_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in1_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in2_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in3_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in4_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in5_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in6_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in7_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in8_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in9_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in10_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in11_label.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in12_label.dev_attr.attr,
|
||||
+
|
||||
+ &sensor_dev_attr_fan0_point0.dev_attr.attr,
|
||||
+ &sensor_dev_attr_fan0_point1.dev_attr.attr,
|
||||
+ &sensor_dev_attr_fan0_point2.dev_attr.attr,
|
||||
+ &sensor_dev_attr_fan0_point3.dev_attr.attr,
|
||||
+ &sensor_dev_attr_fan0_point4.dev_attr.attr,
|
||||
+ &sensor_dev_attr_fan0_point5.dev_attr.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static int gsp_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ struct i2c_adapter *adapter = client->adapter;
|
||||
+ struct gsp_data *data;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
+ I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
+ err = -EOPNOTSUPP;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ if (!(data = kzalloc(sizeof(struct gsp_data), GFP_KERNEL))) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ i2c_set_clientdata(client, data);
|
||||
+
|
||||
+ data->type = id->driver_data;
|
||||
+
|
||||
+ switch (data->type) {
|
||||
+ case 0:
|
||||
+ data->attrs.attrs = gsp_attributes;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&client->dev, "%s chip found\n", client->name);
|
||||
+
|
||||
+ /* Register sysfs hooks */
|
||||
+ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
|
||||
+ goto exit_free;
|
||||
+
|
||||
+ data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
+ if (IS_ERR(data->hwmon_dev)) {
|
||||
+ err = PTR_ERR(data->hwmon_dev);
|
||||
+ goto exit_remove;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+exit_remove:
|
||||
+ sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
+exit_free:
|
||||
+ kfree(data);
|
||||
+exit:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int gsp_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct gsp_data *data = i2c_get_clientdata(client);
|
||||
+ hwmon_device_unregister(data->hwmon_dev);
|
||||
+ sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
+ kfree(data);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __init gsp_init(void)
|
||||
+{
|
||||
+ return i2c_add_driver(&gsp_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit gsp_exit(void)
|
||||
+{
|
||||
+ i2c_del_driver(&gsp_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(gsp_init);
|
||||
+module_exit(gsp_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Chris Lang <clang@gateworks.com>");
|
||||
+MODULE_DESCRIPTION("GSP HWMON driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_VERSION(DRV_VERSION);
|
||||
+
|
22702
target/linux/cns3xxx/patches-3.3/200-dwc_otg.patch
Normal file
22702
target/linux/cns3xxx/patches-3.3/200-dwc_otg.patch
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user