--- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -32,6 +32,8 @@ #include #include #include +#include + static DEFINE_SPINLOCK(irq_controller_lock); @@ -90,7 +92,7 @@ static void gic_ack_irq(unsigned int irq spin_unlock(&irq_controller_lock); } -static void gic_mask_irq(unsigned int irq) +void gic_mask_irq(unsigned int irq) { u32 mask = 1 << (irq % 32); @@ -175,6 +177,109 @@ void __init gic_cascade_irq(unsigned int set_irq_chained_handler(irq, gic_handle_cascade_irq); } + +// type: level or edge +// 0 - level high active, 1 - rising edge sensitive +void set_interrupt_type_by_base(void __iomem *base, int id, u32 type) +{ + unsigned char int_type_bit=0; + u32 gic_v=0; + + // judge gic offset + //printk("gic addr: %#x\n", id/16*4 + 0xc00); + //printk("gic addr bits: %#x\n", id%16*2); + int_type_bit=(id%16*2+1); + + gic_v = readl(base + GIC_DIST_CONFIG + id/16*4); + + gic_v &= (~(1 << int_type_bit)); + gic_v |= ( type << int_type_bit); + + writel(gic_v, base + GIC_DIST_CONFIG + id/16*4); +} + +// type: level or edge +// 0 - level high active, 1 - rising edge sensitive +void set_interrupt_type(int id, u32 type) +{ + set_interrupt_type_by_base((void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, id, type); +} + +void get_interrupt_type_by_base(void __iomem *base, u32 id, u32 *type) +{ + unsigned char int_type_bit=0; + u32 gic_v=0; + + // judge gic offset + int_type_bit=(id%16*2+1); + + //gic_v = readl(base + GIC_DIST_CONFIG + 4); + gic_v = readl(base + GIC_DIST_CONFIG + id/16*4); + + *type = ((gic_v >> int_type_bit) & 0x1); + + //writel(0, base + GIC_DIST_CONFIG + id/16*4); +} + +void get_interrupt_type(u32 id, u32 *type) +{ + get_interrupt_type_by_base((void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, id, type); +} + + + +// set interrupt priority +void set_interrupt_pri_by_base(void __iomem *base, u32 id, u32 pri) +{ + unsigned char int_type_bit=0; + u32 gic_v=0; + + + // judge gic offset + int_type_bit=(id%4*8+4); + + gic_v = readl(base + GIC_DIST_PRI + id/4*4); + + gic_v &= (~(0xf << int_type_bit)); + gic_v |= (pri << int_type_bit); + + writel(gic_v, base + GIC_DIST_PRI + id/4*4); + + gic_v = 0; + gic_v = readl(base + GIC_DIST_PRI + id/4*4); + //printk("read gic_v: %x\n", gic_v); +} + +void set_interrupt_pri(u32 id, u32 pri) +{ + set_interrupt_pri_by_base((void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, id, pri); +} + +void get_interrupt_pri_by_base(void __iomem *base, int id, u32 *type) +{ + unsigned char int_type_bit=0; + u32 gic_v=0; + + // judge gic offset + int_type_bit=(id%4*8+4); + + gic_v = readl(base + GIC_DIST_PRI + id/4*4); + + //printk("int_type_bit: %d\n", int_type_bit); + //printk("gic_v: %#x\n", gic_v); + *type = ((gic_v >> int_type_bit) & 0xf); + //gic_v &= (~(1 << int_type_bit)); + //gic_v |= ( type << int_type_bit); + + //writel(0, base + GIC_DIST_CONFIG + id/16*4); +} + +void get_interrupt_pri(int id, u32 *pri) +{ + get_interrupt_pri_by_base((void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, id, pri); +} + + void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start) { @@ -254,6 +359,12 @@ void __cpuinit gic_cpu_init(unsigned int writel(1, base + GIC_CPU_CTRL); } +void cns3xxx_write_pri_mask(u8 pri_mask) +{ + writel(pri_mask, (void __iomem *) CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT + GIC_CPU_PRIMASK); +} + + #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -280,6 +280,35 @@ extern void dmac_flush_range(const void #endif +#ifdef CONFIG_CPU_NO_CACHE_BCAST +enum smp_dma_cache_type { + SMP_DMA_CACHE_INV, + SMP_DMA_CACHE_CLEAN, + SMP_DMA_CACHE_FLUSH, +}; + +extern void smp_dma_cache_op(int type, const void *start, const void *end); + +static inline void smp_dma_inv_range(const void *start, const void *end) +{ + smp_dma_cache_op(SMP_DMA_CACHE_INV, start, end); +} + +static inline void smp_dma_clean_range(const void *start, const void *end) +{ + smp_dma_cache_op(SMP_DMA_CACHE_CLEAN, start, end); +} + +static inline void smp_dma_flush_range(const void *start, const void *end) +{ + smp_dma_cache_op(SMP_DMA_CACHE_FLUSH, start, end); +} +#else +#define smp_dma_inv_range dmac_inv_range +#define smp_dma_clean_range dmac_clean_range +#define smp_dma_flush_range dmac_flush_range +#endif + #ifdef CONFIG_OUTER_CACHE extern struct outer_cache_fns outer_cache; --- /dev/null +++ b/arch/arm/include/asm/hardware/arm_twd.h @@ -0,0 +1,21 @@ +#ifndef __ASM_HARDWARE_TWD_H +#define __ASM_HARDWARE_TWD_H + +#define TWD_TIMER_LOAD 0x00 +#define TWD_TIMER_COUNTER 0x04 +#define TWD_TIMER_CONTROL 0x08 +#define TWD_TIMER_INTSTAT 0x0C + +#define TWD_WDOG_LOAD 0x20 +#define TWD_WDOG_COUNTER 0x24 +#define TWD_WDOG_CONTROL 0x28 +#define TWD_WDOG_INTSTAT 0x2C +#define TWD_WDOG_RESETSTAT 0x30 +#define TWD_WDOG_DISABLE 0x34 + +#define TWD_TIMER_CONTROL_ENABLE (1 << 0) +#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) +#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) +#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) + +#endif --- /dev/null +++ b/arch/arm/include/asm/hardware/cache-l2cc.h @@ -0,0 +1,79 @@ +/******************************************************************************* + * + * arch/arm/include/asm/hardware/cache-l2cc.h + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + * + ******************************************************************************/ + +#ifndef __ASM_ARM_HARDWARE_L2_H +#define __ASM_ARM_HARDWARE_L2_H + +#define L2CC_CACHE_ID 0x000 +#define L2CC_CACHE_TYPE 0x004 +#define L2CC_CTRL 0x100 +#define L2CC_AUX_CTRL 0x104 +#define L2CC_TAG_RAM_LATENCY_CTRL 0x108 +#define L2CC_DATA_RAM_LATENCY_CTRL 0x10C +#define L2CC_EVENT_CNT_CTRL 0x200 +#define L2CC_EVENT_CNT1_CFG 0x204 +#define L2CC_EVENT_CNT0_CFG 0x208 +#define L2CC_EVENT_CNT1_VAL 0x20C +#define L2CC_EVENT_CNT0_VAL 0x210 +#define L2CC_INTR_MASK 0x214 +#define L2CC_MASKED_INTR_STAT 0x218 +#define L2CC_RAW_INTR_STAT 0x21C +#define L2CC_INTR_CLEAR 0x220 +#define L2CC_CACHE_SYNC 0x730 +#define L2CC_INV_LINE_PA 0x770 +#define L2CC_INV_WAY 0x77C +#define L2CC_CLEAN_LINE_PA 0x7B0 +#define L2CC_CLEAN_LINE_IDX 0x7B8 +#define L2CC_CLEAN_WAY 0x7BC +#define L2CC_CLEAN_INV_LINE_PA 0x7F0 +#define L2CC_CLEAN_INV_LINE_IDX 0x7F8 +#define L2CC_CLEAN_INV_WAY 0x7FC +#define L2CC_LOCKDOWN_0_WAY_D 0x900 +#define L2CC_LOCKDOWN_0_WAY_I 0x904 +#define L2CC_LOCKDOWN_1_WAY_D 0x908 +#define L2CC_LOCKDOWN_1_WAY_I 0x90C +#define L2CC_LOCKDOWN_2_WAY_D 0x910 +#define L2CC_LOCKDOWN_2_WAY_I 0x914 +#define L2CC_LOCKDOWN_3_WAY_D 0x918 +#define L2CC_LOCKDOWN_3_WAY_I 0x91C +#define L2CC_LOCKDOWN_4_WAY_D 0x920 +#define L2CC_LOCKDOWN_4_WAY_I 0x924 +#define L2CC_LOCKDOWN_5_WAY_D 0x928 +#define L2CC_LOCKDOWN_5_WAY_I 0x92C +#define L2CC_LOCKDOWN_6_WAY_D 0x930 +#define L2CC_LOCKDOWN_6_WAY_I 0x934 +#define L2CC_LOCKDOWN_7_WAY_D 0x938 +#define L2CC_LOCKDOWN_7_WAY_I 0x93C +#define L2CC_LOCKDOWN_LINE_EN 0x950 +#define L2CC_UNLOCK_ALL_LINE_WAY 0x954 +#define L2CC_ADDR_FILTER_START 0xC00 +#define L2CC_ADDR_FILTER_END 0xC04 +#define L2CC_DEBUG_CTRL 0xF40 + +#ifndef __ASSEMBLY__ +extern void __init l2cc_init(void __iomem *base); +#endif + +#endif --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -37,6 +37,13 @@ void gic_dist_init(unsigned int gic_nr, void gic_cpu_init(unsigned int gic_nr, void __iomem *base); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + +void cns3xxx_write_pri_mask(u8 pri_mask); +void set_interrupt_type(int id, u32 type); +void get_interrupt_type(u32 id, u32 *type); +void set_interrupt_pri(u32 id, u32 pri); +void get_interrupt_pri(int id, u32 *pri); + #endif #endif --- a/arch/arm/include/asm/mach/pci.h +++ b/arch/arm/include/asm/mach/pci.h @@ -20,6 +20,9 @@ struct hw_pci { void (*postinit)(void); u8 (*swizzle)(struct pci_dev *dev, u8 *pin); int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin); +#ifdef CONFIG_PCI_DOMAINS + int nr_domains; +#endif }; /* @@ -37,8 +40,12 @@ struct pci_sys_data { /* IRQ mapping */ int (*map_irq)(struct pci_dev *, u8, u8); struct hw_pci *hw; +#ifdef CONFIG_PCI_DOMAINS + int domain; +#endif }; + /* * This is the standard PCI-PCI bridge swizzling algorithm. */ --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -25,6 +25,11 @@ static inline void pcibios_penalize_isa_ /* We don't do dynamic PCI IRQ allocation */ } +#ifdef CONFIG_PCI_DOMAINS +int pci_domain_nr(struct pci_bus *bus); +int pci_proc_domain(struct pci_bus *bus); +#endif + /* * The PCI address space does equal the physical memory address space. * The networking and block device layers use this boolean for bounce --- a/arch/arm/include/asm/xor.h +++ b/arch/arm/include/asm/xor.h @@ -132,10 +132,43 @@ static struct xor_block_template xor_blo .do_5 = xor_arm4regs_5, }; +#ifdef CONFIG_CNS3XXX_RAID +extern void do_cns_rdma_xorgen(unsigned int src_no, unsigned int bytes, + void **bh_ptr, void *dst_ptr); +/* + * We create these funcs/template just for benchmark reference. + */ +static void xor_cns_raid_2(unsigned long bytes, unsigned long *p1, + unsigned long *p2) +{ + void *src[2]; + + src[0] = p2; + src[1] = p1; + do_cns_rdma_xorgen(2, bytes, src, (void *)p2); +} + +static struct xor_block_template xor_block_cnsraid = { + .name = "CNS-RAID", + .do_2 = xor_cns_raid_2, +}; +#endif /* CONFIG_CNS3XXX_RAID */ + #undef XOR_TRY_TEMPLATES + +#ifdef CONFIG_CNS3XXX_RAID +#define XOR_TRY_TEMPLATES \ + do { \ + xor_speed(&xor_block_arm4regs); \ + xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_32regs); \ + xor_speed(&xor_block_cnsraid); \ + } while (0) +#else #define XOR_TRY_TEMPLATES \ do { \ xor_speed(&xor_block_arm4regs); \ xor_speed(&xor_block_8regs); \ xor_speed(&xor_block_32regs); \ } while (0) +#endif /* CONFIG_CNS3XXX_RAID */ --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -193,7 +193,7 @@ menu "System Type" choice prompt "ARM system type" - default ARCH_VERSATILE + default ARCH_CNS3XXX config ARCH_AAEC2000 bool "Agilent AAEC-2000 based" @@ -235,6 +235,17 @@ config ARCH_VERSATILE help This enables support for ARM Ltd Versatile board. +config ARCH_CNS3XXX + bool "Cavium Networks CNS3XXX family" + select ARM_AMBA + select HAVE_CLK + select COMMON_CLKDEV + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select ARCH_REQUIRE_GPIOLIB + help + This enables support for Cavium Networks CNS3XXX boards. + config ARCH_AT91 bool "Atmel AT91" select GENERIC_GPIO @@ -715,6 +726,8 @@ source "arch/arm/mach-aaec2000/Kconfig" source "arch/arm/mach-realview/Kconfig" +source "arch/arm/mach-cns3xxx/Kconfig" + source "arch/arm/mach-at91/Kconfig" source "arch/arm/plat-mxc/Kconfig" @@ -768,7 +781,7 @@ endif config ARM_ERRATA_411920 bool "ARM errata: Invalidation of the Instruction Cache operation can fail" - depends on CPU_V6 && !SMP + depends on CPU_V6 && !SMP && !ARCH_CNS3XXX help Invalidation of the Instruction Cache operation can fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. @@ -849,13 +862,17 @@ config ISA_DMA_API bool config PCI - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_CNS3XXX || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or VESA. If you have PCI, say Y, otherwise N. +config PCI_DOMAINS + def_bool y + depends on PCI && ARCH_CNS3XXX + config PCI_SYSCALL def_bool PCI @@ -873,6 +890,8 @@ config PCI_HOST_ITE8152 source "drivers/pci/Kconfig" +source "drivers/pci/pcie/Kconfig" + source "drivers/pcmcia/Kconfig" endmenu @@ -884,10 +903,10 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ - MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4) + MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_CNS3XXX || ARCH_OMAP4) depends on GENERIC_CLOCKEVENTS select USE_GENERIC_SMP_HELPERS - select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4) + select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_CNS3XXX || ARCH_OMAP4) help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -944,7 +963,7 @@ config NR_CPUS int "Maximum number of CPUs (2-32)" range 2 32 depends on SMP - default "4" + default "2" config HOTPLUG_CPU bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" @@ -955,10 +974,10 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \ + depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || ARCH_CNS3XXX || \ REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4) default y - select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4) + select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_CNS3XXX || ARCH_OMAP4) help Enable support for local timers on SMP platforms, rather then the legacy IPI broadcast method. Local timers allows the system --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -531,6 +531,7 @@ static void __init pcibios_init_hw(struc sys->busnr = busnr; sys->swizzle = hw->swizzle; sys->map_irq = hw->map_irq; + sys->domain = hw->nr_domains; sys->resource[0] = &ioport_resource; sys->resource[1] = &iomem_resource; @@ -694,3 +695,20 @@ int pci_mmap_page_range(struct pci_dev * return 0; } +#ifdef CONFIG_PCI_DOMAINS +int pci_domain_nr(struct pci_bus *bus) +{ + + //struct pci_sysdata *sd = bus->sysdata; + struct pci_sys_data *sd = bus->sysdata; + return sd->domain; + +} +EXPORT_SYMBOL(pci_domain_nr); + +int pci_proc_domain(struct pci_bus *bus) +{ + return pci_domain_nr(bus); +} +EXPORT_SYMBOL(pci_proc_domain); +#endif --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -38,6 +38,12 @@ bne asm_do_IRQ #ifdef CONFIG_SMP + + test_for_cache_ipi r0, r6, r5, lr + movne r0, sp + adrne lr, 1b + bne do_cache_IPI + /* * XXX * --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -58,12 +58,20 @@ static DEFINE_PER_CPU(struct ipi_data, i .lock = SPIN_LOCK_UNLOCKED, }; +#ifdef CONFIG_CPU_NO_CACHE_BCAST_DEBUG +static DEFINE_PER_CPU(unsigned long,dma_cache_counter) = 0; +unsigned long bcache_bitmap = 0; +#endif + enum ipi_msg_type { IPI_TIMER, IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, +#ifdef CONFIG_CPU_NO_CACHE_BCAST + IPI_DMA_CACHE, +#endif }; int __cpuinit __cpu_up(unsigned int cpu) @@ -349,10 +357,17 @@ static void send_ipi_message(const struc * Call the platform specific cross-CPU call function. */ smp_cross_call(mask); - local_irq_restore(flags); } +static void send_ipi_message_cache(const struct cpumask *mask) +{ + unsigned long flags; + + local_irq_save(flags); + smp_cross_call_cache(mask); + local_irq_restore(flags); +} void arch_send_call_function_ipi_mask(const struct cpumask *mask) { send_ipi_message(mask, IPI_CALL_FUNC); @@ -373,6 +388,13 @@ void show_ipi_list(struct seq_file *p) seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); seq_putc(p, '\n'); + +#ifdef CONFIG_CPU_NO_CACHE_BCAST_DEBUG + seq_puts(p, " dc: "); + for_each_present_cpu(cpu) + seq_printf(p, " %10lu", per_cpu(dma_cache_counter, cpu)); + seq_putc(p, '\n'); +#endif } void show_local_irqs(struct seq_file *p) @@ -472,6 +494,10 @@ static void ipi_cpu_stop(unsigned int cp cpu_relax(); } +#ifdef CONFIG_CPU_NO_CACHE_BCAST +static void ipi_dma_cache_op(unsigned int cpu); +#endif + /* * Main handler for inter-processor interrupts * @@ -531,6 +557,16 @@ asmlinkage void __exception do_IPI(struc ipi_cpu_stop(cpu); break; +#ifdef CONFIG_CPU_NO_CACHE_BCAST + case IPI_DMA_CACHE: +#ifdef CONFIG_CPU_NO_CACHE_BCAST_DEBUG + //get_cpu_var(dma_cache_counter)++; + //put_cpu_var(dma_cache_counter); +#endif + ipi_dma_cache_op(cpu); + break; +#endif + default: printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", cpu, nextmsg); @@ -542,6 +578,19 @@ asmlinkage void __exception do_IPI(struc set_irq_regs(old_regs); } +asmlinkage void __exception do_cache_IPI(struct pt_regs *regs) +{ + unsigned int cpu = smp_processor_id(); + struct ipi_data *ipi = &per_cpu(ipi_data, cpu); + struct pt_regs *old_regs = set_irq_regs(regs); + + ipi->ipi_count++; + + ipi_dma_cache_op(cpu); + + set_irq_regs(old_regs); +} + void smp_send_reschedule(int cpu) { send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); @@ -692,3 +741,115 @@ void flush_tlb_kernel_range(unsigned lon } else local_flush_tlb_kernel_range(start, end); } + +#ifdef CONFIG_CPU_NO_CACHE_BCAST +/* + * DMA cache maintenance operations on SMP if the automatic hardware + * broadcasting is not available + */ +struct smp_dma_cache_struct { + int type; + const void *start; + const void *end; + char unfinished; +}; + +static struct smp_dma_cache_struct smp_dma_cache_data[3]; +static DEFINE_SPINLOCK(smp_dma_cache_lock); + +static void local_dma_cache_op(int type, const void *start, const void *end) +{ + switch (type) { + case SMP_DMA_CACHE_INV: + dmac_inv_range(start, end); + break; + case SMP_DMA_CACHE_CLEAN: + dmac_clean_range(start, end); + break; + case SMP_DMA_CACHE_FLUSH: + dmac_flush_range(start, end); + break; + default: + printk(KERN_CRIT "CPU%u: Unknown SMP DMA cache type %d\n", + smp_processor_id(), type); + } +} + +/* + * This function must be executed with interrupts disabled. + */ +static void ipi_dma_cache_op(unsigned int cpu) +{ + unsigned long flags; + int type; + const void *start; + const void *end; + + /* check for spurious IPI */ + spin_lock_irqsave(&smp_dma_cache_lock, flags); + if (!test_bit(cpu, &bcache_bitmap)) + goto out; + + type = smp_dma_cache_data[cpu].type; + start = smp_dma_cache_data[cpu].start; + end = smp_dma_cache_data[cpu].end; + spin_unlock_irqrestore(&smp_dma_cache_lock, flags); + + + local_dma_cache_op(type, start, end); + + spin_lock_irqsave(&smp_dma_cache_lock, flags); + clear_bit(cpu, &bcache_bitmap); + smp_dma_cache_data[cpu].type = 0; + smp_dma_cache_data[cpu].start = 0; + smp_dma_cache_data[cpu].end = 0; + smp_dma_cache_data[cpu].unfinished = 0; +out: + spin_unlock_irqrestore(&smp_dma_cache_lock, flags); +} + +/* + * Execute the DMA cache operations on all online CPUs. This function + * can be called with interrupts disabled or from interrupt context. + */ +static void __smp_dma_cache_op(int type, const void *start, const void *end) +{ + cpumask_t callmap = cpu_online_map; + unsigned int cpu = get_cpu(); + unsigned long flags; + unsigned long cpu_check; + cpu_clear(cpu, callmap); + cpu_check = *cpus_addr(callmap) >> 1; + + while (test_bit(cpu, &bcache_bitmap)) + ipi_dma_cache_op(cpu); + + while (test_bit(cpu_check, &bcache_bitmap)) + barrier(); + + spin_lock_irqsave(&smp_dma_cache_lock, flags); + smp_dma_cache_data[cpu_check].type = type; + smp_dma_cache_data[cpu_check].start = start; + smp_dma_cache_data[cpu_check].end = end; + smp_dma_cache_data[cpu_check].unfinished = 1; + set_bit(cpu_check, &bcache_bitmap); + send_ipi_message_cache(&callmap); + spin_unlock_irqrestore(&smp_dma_cache_lock, flags); + + /* run the local operation in parallel with the other CPUs */ + local_dma_cache_op(type, start, end); + put_cpu(); +} + +#define DMA_MAX_RANGE SZ_4K + +/* + * Split the cache range in smaller pieces if interrupts are enabled + * to reduce the latency caused by disabling the interrupts during the + * broadcast. + */ +void smp_dma_cache_op(int type, const void *start, const void *end) +{ + __smp_dma_cache_op(type, start, end); +} +#endif --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -41,7 +41,8 @@ /* set up by the platform code */ void __iomem *twd_base; -static unsigned long twd_timer_rate; +unsigned long twd_timer_rate; +EXPORT_SYMBOL(twd_timer_rate); static void twd_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) --- /dev/null +++ b/arch/arm/mach-cns3xxx/core.c @@ -0,0 +1,629 @@ +/* + * linux/arch/arm/mach-cns3xxx/cns3xxx.c + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "core.h" +#include "rdma.h" + +static struct map_desc cns3xxx_io_desc[] __initdata = { + { + .virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_I2S_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_I2S_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TIMER1_2_3_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TC11MP_L220_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_L220_BASE), + .length = SZ_8K, + .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, + }, { + .virtual = CNS3XXX_DMC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_DMC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_SMC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_SMC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_GPIOA_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_GPIOA_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_GPIOB_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_GPIOB_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_RTC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_RTC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_MISC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_MISC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PM_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .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, + }, { + .virtual = CNS3XXX_UART3_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_UART3_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_DMAC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_DMAC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_CRYPTO_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_CRYPTO_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_HCIE_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_HCIE_BASE), + .length = SZ_32K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_RAID_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_RAID_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_AXI_IXC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_AXI_IXC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_CLCD_BASE_VIRT, + .pfn = __phys_to_pfn( CNS3XXX_CLCD_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_USBOTG_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_USBOTG_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_USB_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_USB_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_SATA2_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_SATA2_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_CAMERA_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_CAMERA_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_I2S_TDM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_I2S_TDM_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_2DG_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_2DG_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_USB_OHCI_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_USB_OHCI_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE0_MEM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE0_MEM_BASE), + .length = SZ_16M, // 176MB + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE0_HOST_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE0_HOST_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE0_CFG0_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG0_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE0_CFG1_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE0_CFG1_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE0_MSG_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE0_MSG_BASE), + .length = SZ_16M, + .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_MEM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_MEM_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE1_HOST_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_HOST_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE1_CFG0_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG0_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE1_CFG1_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_CFG1_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE1_MSG_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_MSG_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PCIE1_IO_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PCIE1_IO_BASE), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_L2C_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_L2C_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PPE_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PPE_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_EMBEDDED_SRAM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_EMBEDDED_SRAM_BASE), + .length = SZ_8K, + .type = MT_DEVICE, + }, +}; + +void __init cns3xxx_map_io(void) +{ + iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc)); +} + +/* used by entry-macro.S */ +void __iomem *gic_cpu_base_addr; + +void __init cns3xxx_init_irq(void) +{ + /* ARM11 MPCore test chip GIC */ + gic_cpu_base_addr = (void __iomem *) CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT; + gic_dist_init(0, (void __iomem *) CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, 29); + gic_cpu_init(0, gic_cpu_base_addr); + set_interrupt_pri(1, 0); // Set cache broadcast priority to the highest priority +} + +int gpio_to_irq(int gpio) +{ + if (gpio > 63) + return -EINVAL; + + if (gpio < 32) + return IRQ_CNS3XXX_GPIOA; + else + return IRQ_CNS3XXX_GPIOB; +} + +int irq2gpio(int irq) +{ + if (irq == IRQ_CNS3XXX_GPIOA) + return 0; + else if (irq == IRQ_CNS3XXX_GPIOB) + return 32; + else + return -EINVAL; +} + +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, +}; + +/* Watchdog */ +static struct resource cns3xxx_watchdog_resources[] = { + { + .start = CNS3XXX_TC11MP_TWD_BASE, + .end = CNS3XXX_TC11MP_TWD_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + },{ + .start = IRQ_LOCALWDOG, + .end = IRQ_LOCALWDOG, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device cns3xxx_watchdog_device = { + .name = "cns3xxx-wdt", + .id = -1, + .num_resources = ARRAY_SIZE(cns3xxx_watchdog_resources), + .resource = cns3xxx_watchdog_resources, +}; + +static struct resource cns3xxx_gpio_resources[] = { + { + .name = "gpio", + .start = 0xFFFFFFFF, + .end = 0xFFFFFFFF, + .flags = 0, + }, +}; + +static struct platform_device cns3xxx_gpio = { + .name = "GPIODEV", + .id = -1, + .num_resources = ARRAY_SIZE(cns3xxx_gpio_resources), + .resource = cns3xxx_gpio_resources, +}; + +void __init cns3xxx_sys_init(void) +{ + l2cc_init((void __iomem *) CNS3XXX_L2C_BASE_VIRT); + + dmac_init(); + cns_rdma_init(); + + platform_device_register(&cns3xxx_gpio); + platform_device_register(&cns3xxx_watchdog_device); + gpiochip_add(&cns3xxx_gpio_chip); +} + +void __iomem *timer1_va_base; + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + unsigned long ctrl = readl(timer1_va_base + TIMER1_2_CONTROL_OFFSET); + int reload; + int pclk = (cns3xxx_cpu_clock() >> 3); + + switch(mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* pclk is cpu clock/8 */ + reload=pclk*1000000/HZ; + writel(reload, timer1_va_base + 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, timer1_va_base + TIMER1_AUTO_RELOAD_OFFSET); + ctrl |= (1 << 2) | (1 << 9); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + ctrl = 0; + } + + writel(ctrl, timer1_va_base + TIMER1_2_CONTROL_OFFSET); +} + +static int timer_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long ctrl = readl(timer1_va_base + TIMER1_2_CONTROL_OFFSET); + + writel(evt, timer1_va_base + TIMER1_COUNTER_OFFSET); + writel(ctrl | (1 << 0), timer1_va_base + TIMER1_2_CONTROL_OFFSET); + + return 0; +} + +static struct clock_event_device timer1_clockevent = { + .name = "timer1", + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, + .rating = 300, + .cpumask = cpu_all_mask, +}; + +static void __init cns3xxx_clockevents_init(unsigned int timer_irq) +{ + timer1_clockevent.irq = timer_irq; + timer1_clockevent.mult = + div_sc( (cns3xxx_cpu_clock() >> 3)*1000000, NSEC_PER_SEC, timer1_clockevent.shift); + timer1_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer1_clockevent); + timer1_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer1_clockevent); + + clockevents_register_device(&timer1_clockevent); +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t cns3xxx_timer_interrupt(int irq, void *dev_id) +{ + u32 val; + struct clock_event_device *evt = &timer1_clockevent; + + /* Clear the interrupt */ + val = readl(timer1_va_base + TIMER1_2_INTERRUPT_STATUS_OFFSET); + writel(val & ~(1 << 2), timer1_va_base + TIMER1_2_INTERRUPT_STATUS_OFFSET); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction cns3xxx_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = cns3xxx_timer_interrupt, +}; + +static cycle_t cns3xxx_get_cycles(struct clocksource *cs) +{ + u64 val; + + val = readl(timer1_va_base + TIMER_FREERUN_CONTROL_OFFSET); + val &= 0xffff; + + return ((val << 32) | readl(timer1_va_base + 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), timer1_va_base + 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 + */ +void __init __cns3xxx_timer_init(unsigned int timer_irq) +{ + unsigned long val, irq_mask; + + /* + * Initialise to a known state (all timers off) + */ + writel(0, timer1_va_base + TIMER1_2_CONTROL_OFFSET); /* disable timer1 and timer2 */ + writel(0, timer1_va_base + TIMER_FREERUN_CONTROL_OFFSET); /* stop free running timer3 */ + writel(0, timer1_va_base + TIMER1_MATCH_V1_OFFSET); + writel(0, timer1_va_base + TIMER1_MATCH_V2_OFFSET); + + val = (cns3xxx_cpu_clock() >> 3) * 1000000 / HZ; + writel(val, timer1_va_base + TIMER1_COUNTER_OFFSET); + + /* mask irq, non-mask timer1 overflow */ + irq_mask = readl(timer1_va_base + TIMER1_2_INTERRUPT_MASK_OFFSET); + irq_mask &= ~(1 << 2); + irq_mask |= 0x03; + writel(irq_mask, timer1_va_base + TIMER1_2_INTERRUPT_MASK_OFFSET); + /* down counter */ + val = readl(timer1_va_base + TIMER1_2_CONTROL_OFFSET); + val |= (1 << 9); + writel(val, timer1_va_base + 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); +} + +void __init cns3xxx_timer_init(void) +{ + timer1_va_base = (void __iomem *) CNS3XXX_TIMER1_2_3_BASE_VIRT; + twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT; + __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0); +} + +struct sys_timer cns3xxx_timer = { + .init = cns3xxx_timer_init, +}; + + +void cns3xxx_power_off(void) +{ + __u32 clkctrl; + + printk(KERN_INFO "powering system down...\n"); + + clkctrl = readl(CNS3XXX_PM_BASE_VIRT + PM_SYS_CLK_CTRL_OFFSET); + clkctrl &= 0xfffff1ff; + clkctrl |= (0x5 << 9); /* Hibernate */ + writel(clkctrl, CNS3XXX_PM_BASE_VIRT + PM_SYS_CLK_CTRL_OFFSET); +} --- /dev/null +++ b/arch/arm/mach-cns3xxx/core.h @@ -0,0 +1,34 @@ +/* + * linux/arch/arm/mach-cns3xxx/core.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2004 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 + */ + +#ifndef __ASM_ARCH_CNS3XXX_H +#define __ASM_ARCH_CNS3XXX_H + +void __init cns3xxx_map_io(void); +void cns3xxx_power_off(void); +void __init cns3xxx_init_irq(void); + +extern struct sys_timer cns3xxx_timer; +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/dmac.c @@ -0,0 +1,1464 @@ +/******************************************************************************* + * + * Copyright (c) 2008 Cavium Networks + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +//#define DEBUG_GDMA + +#define DMAC_MEM_MAP_VALUE(reg_offset) (*((uint32_t volatile *)(CNS3XXX_DMAC_BASE_VIRT + reg_offset))) + +#define DMAC_INTEN DMAC_MEM_MAP_VALUE(0x020) +#define DMAC_INTSTATUS DMAC_MEM_MAP_VALUE(0x028) +#define DMAC_INTCLR DMAC_MEM_MAP_VALUE(0x02C) + +/* DMAC Debug registers */ +#define DMAC_DBGSTATUS DMAC_MEM_MAP_VALUE(0xD00) /* Debug Status Register */ +#define DMAC_DBGCMD DMAC_MEM_MAP_VALUE(0xD04) /* Debug Command Register */ +#define DMAC_DBGINST0 DMAC_MEM_MAP_VALUE(0xD08) /* Debug Instrucion-0 Register */ +#define DMAC_DBGINST1 DMAC_MEM_MAP_VALUE(0xD0C) /* Debug Instrucion-1 Register */ + +#define CHANNEL_AND_MANAGER 0x1ff +#define CHANNEL_ONLY 0xff +#define MANAGER_ONLY 0x100 + +#define MAX_MICROCODE_SIZE 2048 + +#if 0 +#define ERROR_INTR 45 +#define DMAC_IRQNO_BASE 46 +#else +#define ERROR_INTR 68 +#define DMAC_IRQNO_BASE 69 +#endif + +#define MAX_INTR_EVENTS 32 + +#define MIN_EVENT_NUM 8 //2 + +/* Debug Status Register */ +#define DMAC_DBG_BUSY_BIT (1<<0) +#define DMAC_DBG_INSTR_0_SHIFT 16 +#define DMAC_DBG_INSTR_2_SHIFT 0 +#define DMAC_DBG_THREAD_BIT (1<<0) +#define DMAC_DBG_CH_NUM_SHIFT 8 +#define DMAC_DBG_CH_NUM_BIT_MASK 0x7 +#define DMAC_CHMGR 8 + +spinlock_t dma_mgr_lock; + +typedef enum { +// DMAC_INSTR_DMAADDH = 0, /* Add Halfword */ /*** No implement ***/ + DMAC_INSTR_DMAEND = 0, /* End */ + DMAC_INSTR_DMAFLUSHP, /* Flash and notify Peripheral */ + DMAC_INSTR_DMAGO, /* Go */ + DMAC_INSTR_DMALD, /* Load */ + DMAC_INSTR_DMALDP, /* Load aPeripheral */ + DMAC_INSTR_DMALP, /* Loop */ + DMAC_INSTR_DMALPEND, /* Loop End */ +// DMAC_INSTR_DMALPFE, /* Loop Forever */ + DMAC_INSTR_DMAKILL, /* kill */ + DMAC_INSTR_DMAMOV, /* Move */ + DMAC_INSTR_DMANOP, /* No operation */ +// DMAC_INSTR_DMARMB, /* Read Memory Barrier */ + DMAC_INSTR_DMASEV, /* Send Event */ + DMAC_INSTR_DMAST, /* Store */ + DMAC_INSTR_DMASTP, /* Store and notify Peripheral */ + DMAC_INSTR_DMASTZ, /* Store Zero */ + DMAC_INSTR_DMAWFE, /* Wait For Event */ + DMAC_INSTR_DMAWFP, /* Wait For Peripheral */ + DMAC_INSTR_DMAWMB /* Wait For Barrier */ +} dmac_instr_t; + +typedef struct { + const char *enc_buf; + int enc_buf_len; + int chan_or_mgr; /* 0xff for DMA manager and DMA channel, + 0x7f for DMA channel, + 0x80 for DMA manager */ +} dmac_instr_encode_t; + +typedef struct { + uint32_t sa:1; /* source address increment: 0 - FIXED / 1 - INCR */ + uint32_t ss:3; /* source burst size in bytes: mapping value TBD with designer */ + uint32_t sb:4; /* source burst length */ + uint32_t sp:3; /* source protection */ + uint32_t sc:3; /* source cache */ + uint32_t da:1; /* destination address increment: 0 - FIXED / 1 - INCR */ + uint32_t ds:3; /* destination burst size in bytes: mapping value TBD with designer */ + uint32_t db:4; /* destination burst length */ + uint32_t dp:3; /* destination protection */ + uint32_t dc:3; /* destination cache */ + uint32_t es:3; /* endian swap size, in bits */ + uint32_t padding:1; +} dmac_ch_ctrl_t; + +typedef struct { + union { + dmac_ch_ctrl_t ccr; + uint32_t val; + } i; +} dmac_cmd_imm32_t; + +typedef struct { + uint16_t bs:1; /* burst/single bit */ + uint16_t x:1; /* x bit */ + uint16_t ns:1; /* not secure bit */ + uint16_t lc:1; /* loop counter bit */ + uint16_t p:1; /* p bit */ + uint16_t nf:1; /* no-finite bit */ + uint16_t i:1; /* invalid bit */ + uint16_t padding:9; +} dmac_cmd_bits_t; + +typedef struct { + uint8_t periph; /* peripheral ID */ + uint8_t cn; /* Channel Number */ + uint8_t iter; /* iteration count */ + uint8_t backwards_jump; /* backwards jump length */ + uint8_t rd; /* destination register, */ + uint8_t event_num; /* event number */ + + union { + dmac_cmd_bits_t b; + uint16_t val; + } bits; + + dmac_cmd_imm32_t imm32; /* immediate 32bit value */ +} dmac_instr_param_t; + +typedef struct { + int in_use; /* Channel in use or not */ + int channel; /* Channel number */ + int microcode_size; /* Microcode size */ + uint8_t *microcode; /* TODO */ + dma_addr_t microcode_dma; + int (*intr_handler) (void *); + void *handler_args; + int notifications_used; /* 32 bits for every interrupt/event */ +} dmac_channel_t; + +/* TODO: Not protected as of now */ +dmac_channel_t *dmac_channels[MAX_DMA_CHANNELS]; + +int dmac_events[MAX_INTR_EVENTS]; + +static int dmac_create_instr(int chan, dmac_instr_t instr, + dmac_instr_param_t * param); +static int dmac_exec_ucode(int ucode_channel, int ch); +void pl330_dump_regs(void); + +/****************************************************************************** + * + * Instruction: DMAEND + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 0 0 0 + * Example: + * DMAEND + * 00 + ******************************************************************************/ +const char dmac_code_DMAEND[] = { 0x00 }; + +int DMAC_DMAEND(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAEND, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAEND); + +/****************************************************************************** + * + * Instruction: DMAFLUSHP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 1 0 1 0 1 + * Example: + * DMAFLUSHP P0 + * 35 00 + ******************************************************************************/ +const char dmac_code_DMAFLUSHP[] = { 0x35, 0x00 }; + +int DMAC_DMAFLUSHP(int ch_num, int periph) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.periph = periph; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAFLUSHP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAFLUSHP); + +/****************************************************************************** + * + * Instruction: DMAGO + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 0 1 0 0 0 ns 0 + * + * | 47 16 | + * < imm[31:0] > + * Example: + * DMAGO C0, 0x40000000 + * A0 00 00 00 00 40 + ******************************************************************************/ +const char dmac_code_DMAGO[] = { 0xA0, 0x00, 0x00, 0x00, 0x00, 0x40 }; + +int DMAC_DMAGO(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + dmac_channel_t *dma_ch = dmac_channels[ch_num]; + + if(!dma_ch->in_use) { + printk("DMAC_DMAGO an unused channel\n"); + return -1; + } + + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.bits.b.ns = 1; + param.cn = ch_num; + param.imm32.i.val = dma_ch->microcode_dma; +#ifdef DEBUG_GDMA + printk("%s:%d: microcode Physical Address *(%x)==[%x]\n", __FUNCTION__, + __LINE__, param.imm32.i.val, + *((uint32_t *) phys_to_virt(dma_ch->microcode_dma))); +#endif + instr_len = dmac_create_instr(DMAC_CHMGR, DMAC_INSTR_DMAGO, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + dmac_exec_ucode(DMAC_CHMGR, DMAC_CHMGR); // DMAC_CHMGR); + if (dmac_channels[DMAC_CHMGR]) + dmac_channels[DMAC_CHMGR]->microcode_size = 0; + else + printk("BUG HERE !! DEBUG .. \n"); + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAGO); + +/****************************************************************************** + * + * Instruction: DMALD + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 bs x + * Example: + * DMALD + * 04 + ******************************************************************************/ +const char dmac_code_DMALD[] = { 0x04 }; + +int DMAC_DMALD(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALD, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALD); + +int DMAC_DMALDB(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + param.bits.b.x = 1; + param.bits.b.bs = 1; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALD, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALDB); + +int DMAC_DMALDS(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + param.bits.b.x = 1; + param.bits.b.bs = 0; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALD, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALDS); + +/****************************************************************************** + * + * Instruction: DMALP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < iter[7:0] > 0 0 1 0 0 0 lc 0 + * Example: + * DMALP 8 + * 20 07 + ******************************************************************************/ +const char dmac_code_DMALP[] = { 0x20, 0x07 }; + +int DMAC_DMALP(int ch_num, int loop_reg_idx, int iter) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.bits.b.lc = loop_reg_idx; + param.iter = (uint8_t) (iter - 1); + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALP); + +/****************************************************************************** + * + * Instruction: DMALPEND + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < backwards_jump[7:0] > 0 0 1 nf 1 lc bs x + * Example: + * DMALPEND + * 38 04 + ******************************************************************************/ +const char dmac_code_DMALPEND[] = { 0x38, 0x04 }; + +int DMAC_DMALPEND(int ch_num, int loop_reg_idx, int jump, int lpfe) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + param.bits.b.lc = loop_reg_idx; + param.bits.b.nf = lpfe; + param.backwards_jump = jump; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALPEND, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALPEND); + +/****************************************************************************** + * + * Instruction: DMAMOV + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 0 1 1 1 1 0 0 + * + * | 47 16 | + * < imm[31:0] > + * + * # CCR Description + * # [30:28] Endian swap size + * # [27:25] AWCACHE[3,1:0] value + * # [24:22] AWPROT value + * # [21:18] AWLEN value + * # [17:15] AWSIZE value + * # [14] AWBURST[0] value + * 0 - FIXED / 1 - INCR + * # [13:11] ARCACHE[2:0] value + * # [10:8] ARPROT value + * # [7:4] ARLEN value + * # [3:1] ARSIZE value + * # [0] ARBURST[0] value + * 0 - FIXED / 1 - INCR + * Example: + * DMAMOV CCR, SB1 SS32 DB1 DS32 + * BC 01 05 40 01 00 + ******************************************************************************/ +const char dmac_code_DMAMOV[] = { 0xBC, 0x01, 0x05, 0x40, 0x01, 0x00 }; + +/* ccr_sar_dar: 0 for SAR, 1, for CCR, 2 for DAR */ +//typedef enum { SAR = 0, CCR = 1, DAR = 2} dmamov_arg_t; +int DMAC_DMAMOV(int ch_num, dmamov_arg_t ccr_sar_dar, uint32_t value) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.rd = ccr_sar_dar; + param.imm32.i.val = value; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAMOV, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAMOV); + +/****************************************************************************** + * + * Instruction: DMAST + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 1 0 bs x + * Example: + * DMAST + * 08 + ******************************************************************************/ +const char dmac_code_DMAST[] = { 0x08 }; + +int DMAC_DMAST(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAST, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAST); + +const char dmac_code_DMAWMB[] = { 0x13 }; + +int DMAC_DMAWMB(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAWMB, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed\n"); + return -1; + } + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAWMB); + +const char dmac_code_DMANOP[] = { 0x18 }; + +int DMAC_DMANOP(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMANOP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed\n"); + return -1; + } + return 0; +} + +EXPORT_SYMBOL(DMAC_DMANOP); + +int DMAC_DMASTB(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.bits.b.x = 1; + param.bits.b.bs = 1; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAST, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMASTB); + +int DMAC_DMASTS(int ch_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.bits.b.x = 1; + param.bits.b.bs = 0; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAST, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMASTS); + +/****************************************************************************** + * + * Instruction: DMASTZ + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 1 1 0 0 + * Example: + * DMASTZ + * 08 + ******************************************************************************/ +const char dmac_code_DMASTZ[] = { 0x0C }; + +/****************************************************************************** + * + * Instruction: DMAWFE + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 i 0 0 0 1 1 0 1 1 0 + * Example: + * DMAWFE E0 + * 36 00 + ******************************************************************************/ +const char dmac_code_DMAWFE[] = { 0x36, 0x00 }; + +int DMAC_WFE(int chan, int event_num) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ +//#warning "to set bits" + param.event_num = event_num; + instr_len = dmac_create_instr(chan, DMAC_INSTR_DMAWFE, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_WFE); + +/****************************************************************************** + * + * Instruction: DMAWFP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 1 0 0 bs p + * Example: + * DMAWFP P0, periph + * 31 00 + ******************************************************************************/ +const char dmac_code_DMAWFP[] = { 0x31, 0x00 }; + +int DMAC_DMAWFP(int ch_num, int periph_id, dmawfp_burst_type s) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + if (s == SINGLE) { + param.bits.b.bs = 0; + param.bits.b.p = 0; + } + if (s == BURST) { + param.bits.b.bs = 1; + param.bits.b.p = 0; + } + if (s == PERIPHERAL) { + param.bits.b.bs = 0; + param.bits.b.p = 1; + } + param.periph = periph_id; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAWFP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMAWFP); + +/****************************************************************************** + * + * Instruction: DMAKILL + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 0 0 1 + * Example: + * DMAKILL + * 01 + ******************************************************************************/ +const char dmac_code_DMAKILL[] = { 0x01 }; + +/****************************************************************************** + * + * Instruction: DMASEV + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 i 0 0 0 1 1 0 1 0 0 + * Example: + * DMASEV E0 + * 34 00 + ******************************************************************************/ +const char dmac_code_DMASEV[] = { 0x34, 0x00 }; + +int DMAC_DMASEV(int ch_num, int event_num) +{ + dmac_instr_param_t param; + int instr_len; + dmac_channel_t *dma_ch = dmac_channels[ch_num]; + if ((event_num >= MIN_EVENT_NUM) + && !(dma_ch->notifications_used & (1 << event_num))) { + printk("DMAC_DMASEV failed event number request not done\n"); + return -1; + } else if ((event_num < MIN_EVENT_NUM) && (event_num != ch_num)) { + printk + ("%s:%d - Presently, we have this hard restriction that each channel can signal irq event == channel_no\n", + __FUNCTION__, __LINE__); + return -1; + } + memset(¶m, 0, sizeof(dmac_instr_param_t)); + param.event_num = event_num; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMASEV, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMASEV); + +/****************************************************************************** + * + * Instruction: DMALDP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 0 0 1 bs 1 + * Example: + * DMALDPS P0 + * 25 00 + ******************************************************************************/ +const char dmac_code_DMALDP[] = { 0x25, 0x00 }; + +int DMAC_DMALDP(int ch_num, int periph_id, int burst) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + param.periph = periph_id; + param.bits.b.bs = burst; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMALDP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMALDP); + +/****************************************************************************** + * + * Instruction: DMASTP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 0 1 0 bs 1 + * Example: + * DMASTPS P0 + * 29 00 + ******************************************************************************/ +const char dmac_code_DMASTP[] = { 0x29, 0x00 }; + +int DMAC_DMASTP(int ch_num, int periph_id, int burst) +{ + dmac_instr_param_t param; + int instr_len; + memset(¶m, 0, sizeof(dmac_instr_param_t)); + /* param.bits.b.x = param.bits.b.bs = 0; */ + param.periph = periph_id; + param.bits.b.bs = burst; + instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMASTP, ¶m); + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + return 0; +} + +EXPORT_SYMBOL(DMAC_DMASTP); + +dmac_instr_encode_t dmac_codes[] = { + {dmac_code_DMAEND, sizeof(dmac_code_DMAEND), CHANNEL_AND_MANAGER} + , + {dmac_code_DMAFLUSHP, sizeof(dmac_code_DMAFLUSHP), CHANNEL_ONLY} + , + {dmac_code_DMAGO, sizeof(dmac_code_DMAGO), MANAGER_ONLY} + , + {dmac_code_DMALD, sizeof(dmac_code_DMALD), CHANNEL_ONLY} + , + {dmac_code_DMALDP, sizeof(dmac_code_DMALDP), CHANNEL_ONLY} + , + {dmac_code_DMALP, sizeof(dmac_code_DMALP), CHANNEL_ONLY} + , + {dmac_code_DMALPEND, sizeof(dmac_code_DMALPEND), CHANNEL_ONLY} + , + {dmac_code_DMAKILL, sizeof(dmac_code_DMAKILL), CHANNEL_AND_MANAGER} + , + {dmac_code_DMAMOV, sizeof(dmac_code_DMAMOV), CHANNEL_ONLY} + , + {dmac_code_DMANOP, sizeof(dmac_code_DMANOP), CHANNEL_AND_MANAGER} + , + {dmac_code_DMASEV, sizeof(dmac_code_DMASEV), CHANNEL_AND_MANAGER} + , + {dmac_code_DMAST, sizeof(dmac_code_DMAST), CHANNEL_ONLY} + , + {dmac_code_DMASTP, sizeof(dmac_code_DMASTP), CHANNEL_ONLY} + , + {dmac_code_DMASTZ, sizeof(dmac_code_DMASTZ), CHANNEL_ONLY} + , + {dmac_code_DMAWFE, sizeof(dmac_code_DMAWFE), CHANNEL_AND_MANAGER} + , + {dmac_code_DMAWFP, sizeof(dmac_code_DMAWFP), CHANNEL_ONLY} + , + {dmac_code_DMAWMB, sizeof(dmac_code_DMAWMB), CHANNEL_ONLY} + , +}; + +static void Dmac_Cmd_Write32(uint8_t * buf, uint32_t val) +{ + buf[0] = (uint8_t) (val); + buf[1] = (uint8_t) (val >> 8); + buf[2] = (uint8_t) (val >> 16); + buf[3] = (uint8_t) (val >> 24); + + return; +} + +static int +dmac_create_instr(int chan, dmac_instr_t instr, dmac_instr_param_t * param) +{ + int len = 0; + dmac_channel_t *dma_ch = dmac_channels[chan]; + uint8_t *buf = NULL; +#ifdef DEBUG_GDMA + printk("%s:%d: In with channel no %d\n", __FUNCTION__, __LINE__, chan); +#endif + + if (!((0x1 << chan) & dmac_codes[instr].chan_or_mgr)) { + printk("Channel %d does not support this instruction %d\n", + chan, instr); + return -1; + } +#ifdef DEBUG_GDMA + if (!dma_ch) + printk("%s:%d: Bug here !!\n", __FUNCTION__, __LINE__); +#endif + + if (dma_ch->microcode == NULL) { + buf = dma_ch->microcode = + dma_alloc_coherent(NULL, MAX_MICROCODE_SIZE, + &dma_ch->microcode_dma, GFP_KERNEL); + printk + ("First time microcode alloc for channel %d done @phy:%x\n", + chan, dma_ch->microcode_dma); + dma_ch->microcode_size = 0; + } else { + if ((dmac_codes[instr].enc_buf_len + dma_ch->microcode_size) > + MAX_MICROCODE_SIZE) { + printk + ("We have a buffer overflow [%d]issue here ... BUG !!\n", + dma_ch->microcode_size); + return -1; + } + buf = dma_ch->microcode + dma_ch->microcode_size; + } +#ifdef DEBUG_GDMA + printk("%s:%d: Microcode alloc for channel %d\n", __FUNCTION__, + __LINE__, chan); +#endif + + if (buf == NULL) { + printk("%s: Unable to allocate memory for microocode space\n", + __FUNCTION__); + return -1; + } +#ifdef DEBUG_GDMA + printk("%s:%d: allocated microcode buffer%p [@phy: %x]\n", __FUNCTION__, + __LINE__, buf, dma_ch->microcode_dma + dma_ch->microcode_size); +#endif + /* TODO: buf_space checking */ + memcpy(buf, dmac_codes[instr].enc_buf, dmac_codes[instr].enc_buf_len); + len += dmac_codes[instr].enc_buf_len; + + /* TODO: Parameter checking */ + switch (instr) { + case DMAC_INSTR_DMAEND: + case DMAC_INSTR_DMASTZ: + case DMAC_INSTR_DMAKILL: + case DMAC_INSTR_DMAWMB: + case DMAC_INSTR_DMANOP: + /* no parameter needed */ + break; + + case DMAC_INSTR_DMAFLUSHP: + /* Fill additional parameters */ + buf[1] |= (param->periph) << 3; // shift to bit 11 + break; + + case DMAC_INSTR_DMAGO: + // Fill additional parameters + if (param->bits.b.ns) + buf[0] |= 0x2; + else + buf[0] &= ~0x2; + buf[1] = param->cn & 0x7; +//#warning "rewrite this" + Dmac_Cmd_Write32(&buf[2], param->imm32.i.val); + //memcpy (&buf[2],&(param->imm32.i.val),4); + break; + + case DMAC_INSTR_DMALD: + case DMAC_INSTR_DMAST: + // Fill additional parameters + buf[0] &= 0xFC; + if (param->bits.b.x) + buf[0] |= 0x1; + else + buf[0] &= ~0x1; + if (param->bits.b.bs) + buf[0] |= 0x2; + else + buf[0] &= ~0x2; + break; + + case DMAC_INSTR_DMALP: + buf[0] &= (~0x2); + if (param->bits.b.lc) + buf[0] |= 0x2; + buf[1] = param->iter; + break; + + case DMAC_INSTR_DMALPEND: + // Fill additional parameters + buf[0] = 0x28; + if (param->bits.b.x) + buf[0] |= 0x1; + if (param->bits.b.bs) + buf[0] |= 0x2; + if (param->bits.b.lc) + buf[0] |= 0x4; + if (param->bits.b.nf) + buf[0] |= 0x10; + buf[1] = param->backwards_jump; + break; + + case DMAC_INSTR_DMAMOV: + // Fill additional parameters + buf[1] = (param->rd) & 0x7; +//#warning "rewrite this" + Dmac_Cmd_Write32(&buf[2], param->imm32.i.val); + //memcpy (&buf[2],&(param->imm32.i.val),4); + break; + + case DMAC_INSTR_DMAWFE: + buf[1] = 0x0; + if (param->bits.b.i) + buf[1] |= 0x2; + buf[1] |= (param->event_num) << 3; // shift to bit 11 + break; + + case DMAC_INSTR_DMASEV: + buf[1] |= (param->event_num) << 3; // shift to bit 11 + break; + + case DMAC_INSTR_DMAWFP: + if (param->bits.b.p) + buf[0] |= 0x1; + else + buf[0] &= ~0x1; + if (param->bits.b.bs) + buf[0] |= 0x2; + else + buf[0] &= ~0x2; + buf[1] |= (param->periph) << 3; // shift to bit 11 + break; + + case DMAC_INSTR_DMALDP: + case DMAC_INSTR_DMASTP: + // Fill additional parameters + if (param->bits.b.bs) + buf[0] |= 0x2; + else + buf[0] &= ~0x2; + buf[1] |= (param->periph) << 3; // shift to bit 11 + break; + + default: + printk("%s: unknown instr (%d)\r\n", __FUNCTION__, instr); + break; + } + dma_ch->microcode_size += len; +#ifdef DEBUG_GDMA + printk("%s:%d: out with length %d\n", __FUNCTION__, __LINE__, + dma_ch->microcode_size); + { + int foo = 0; + uint8_t *foop = dma_ch->microcode; + printk("Dumping the buffer -- "); + for (foo = 0; foo < dma_ch->microcode_size; foo++) + printk("%x ", *(foop + foo)); + printk(" -- done.\n"); + } +#endif + return len; +} + +static int dmac_exec_ucode(int ucode_channel, int ch) +{ + uint8_t i, dbg_instr_0_shift_base, dbg_instr_2_shift_base, dbg_cmd_len, + *dbg_cmd_buf; + uint32_t dbg1_val, dbg2_val; + dmac_channel_t *dma_ch = dmac_channels[ucode_channel]; + + if (!dma_ch->microcode_size) { + printk("%s: No instructions have been created\n", __FUNCTION__); + return -1; + } + + dbg_cmd_buf = dma_ch->microcode; + dbg_cmd_len = dma_ch->microcode_size; +#ifdef DEBUG_GDMA + { + int tmp; + uint8_t *tmpp = dbg_cmd_buf; + printk + ("Executing the code for channel %d, with instrn len %d\n", + ch, dma_ch->microcode_size); + printk("Dumping microcode : "); + for (tmp = 0; tmp < dbg_cmd_len; tmp++) + printk("%x ", *tmpp++); + printk("\n"); + } +#endif + + spin_lock(&dma_mgr_lock); + + /* 3. Poll the Debug Status Register */ + while (DMAC_DBGSTATUS & DMAC_DBG_BUSY_BIT) ; + + /* 4. Write to the Debug Instrution-X Register */ + dbg1_val = 0; + dbg2_val = 0; + + dbg_instr_0_shift_base = DMAC_DBG_INSTR_0_SHIFT; + dbg_instr_2_shift_base = DMAC_DBG_INSTR_2_SHIFT; + for (i = 0; i < dbg_cmd_len; i++) { + uint8_t tmp_val = dbg_cmd_buf[i]; + switch (i) { + case 0: + case 1: + dbg1_val |= (tmp_val << dbg_instr_0_shift_base); + dbg_instr_0_shift_base += 8; + break; + case 2: + case 3: + case 4: + case 5: + tmp_val = dbg_cmd_buf[i]; + dbg2_val |= (tmp_val << dbg_instr_2_shift_base); + dbg_instr_2_shift_base += 8; + break; + default: + printk("BUG here ... DEBUG\n"); + break; + } + } + + // Fill channel field + if (ch == DMAC_CHMGR) { + dbg1_val &= (~DMAC_DBG_THREAD_BIT); + } else { + dbg1_val |= DMAC_DBG_THREAD_BIT; + dbg1_val |= + ((ch & DMAC_DBG_CH_NUM_BIT_MASK) << DMAC_DBG_CH_NUM_SHIFT); + } + +#ifdef DEBUG_GDMA + { + printk("dbg1_val: %x, dbg2_val: %x\n", dbg1_val, dbg2_val); + } +#endif + + DMAC_DBGINST0 = dbg1_val; + DMAC_DBGINST1 = dbg2_val; + + /* 5. Writing zero to the Debug Command Register */ + DMAC_DBGCMD = 0x0; + + spin_unlock(&dma_mgr_lock); + return 0; +} + +#define MAX_SINGLE_INSTR_LEN 8 /* TODO */ + +static int dmac_channel_state_init(int ch_num) +{ + int instr_len = dmac_create_instr(ch_num, DMAC_INSTR_DMAKILL, NULL); + + if (instr_len < 0) { + printk("dmac_create_instr failed \n"); + return -1; + } + + dmac_exec_ucode(ch_num, ch_num); + + if (dmac_channels[ch_num]) + dmac_channels[ch_num]->microcode_size = 0; + else + printk("BUG HERE !! DEBUG .. \n"); + + return 0; +} + +static irqreturn_t dmac_irq_handler(int irq, void *dev_id) +{ + uint32_t irq_status = 0; + uint8_t event_status = 0, channel_no = 0; + dmac_channel_t *chan = NULL; + + irq_status = DMAC_INTSTATUS; /* TODO: Get Interrupt status */ +#ifdef DEBUG_GDMA + printk("Dumping the interrupt status register %x\n", irq_status); +#endif + + if (!irq_status) { +#ifdef DEBUG_GDMA + printk("%s: Probably a DMAC Fault !!%x\n", __FUNCTION__, + irq_status); + pl330_dump_regs(); +#endif + return IRQ_NONE; + } + +// if (irq_status >= MIN_EVENT_NUM) { +// printk(KERN_CRIT +// "Event interrupt handler..(%d) Not implemented\n", +// irq_status); +// return IRQ_NONE; +// } + + event_status = irq_status & 0xff; + /* Clear Interrupt */ + DMAC_INTCLR |= (irq_status & 0xff); + + while (event_status) { + if (event_status & 0x1) { + chan = dmac_channels[channel_no]; + if (chan->intr_handler && chan->in_use) + chan->intr_handler(chan->handler_args); + } + event_status >>= 1; + channel_no++; + } + return IRQ_HANDLED; +} + +static void cns3xxx_dmac_hw_init(void) +{ +#ifdef CONFIG_CNS3XXX_PM_API + /* enable GDMA clock*/ + cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(GDMA)); + /* check clok status and power status */ + #if 0 + PM_PWR_STA_REG & (0x1 << PM_PWR_STA_REG_REG_OFFSET_GDMA) + PM_CACTIVE_STA_REG & (0x1 << PM_CACTIVE_STA_REG_OFFSET_GDMA) + #endif + /* do software reset*/ + cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(GDMA)); +#else +#error "CNS3XXX PM API support should be enabled in Linux kernel" +#endif +} + +/* + * dmac_init + */ +int __init dmac_init(void) +{ + int i, irqno = DMAC_IRQNO_BASE; + + printk(KERN_INFO "Initializing CNS3XXX DMA controller \n"); + + cns3xxx_dmac_hw_init(); + + memset(dmac_channels, 0, sizeof(dmac_channel_t *) * MAX_DMA_CHANNELS); + + spin_lock_init(&dma_mgr_lock); + + for (i = 0; i < MAX_DMA_CHANNELS; i++) { + dmac_channels[i] = kmalloc(sizeof(dmac_channel_t), GFP_KERNEL); + + if (dmac_channels[i] == NULL) { + printk("Unable to allocate memory for channel %d \n", + i); + return -ENOMEM; + } + + memset(dmac_channels[i], 0, sizeof(dmac_channel_t)); + } + + /* Moves all the DMA channels to the Stopped state */ + for (i = 0; i < MAX_DMA_CHANNELS; i++) + dmac_channel_state_init(i); + + for (i = 0; i < MAX_INTR_EVENTS; i++) + dmac_events[i] = -1; + + /* Clear spurious interrupts */ + DMAC_INTCLR = 0xffffffff; + DMAC_INTEN = 0xff; //Enable 8 interrupt 0x03; /* Enabling interrupts IRQ[0], IRQ[1] */ + + /* TODO: error interrupt Right now using the same irq handler, + * and reporting error inside the handler + */ + if (request_irq(ERROR_INTR, dmac_irq_handler, 0, "DMAC-ERR", NULL)) { + printk(KERN_CRIT "failed to request DMAC-ERR interrupt.\n"); + return -ENOENT; + } + + do { + if (request_irq(irqno, dmac_irq_handler, 0, "DMAC", NULL)) { + printk(KERN_CRIT "failed to request DMAC interrupt.\n"); + return -ENOENT; + } + } while (++irqno < (DMAC_IRQNO_BASE + MIN_EVENT_NUM)); + + return 0; +} + +/* + * dmac_get_channel + */ +int dmac_get_channel(int (*handler) (void *), void *handler_args) +{ + int i; + + for (i = 0; i < MAX_DMA_CHANNELS; i++) + if (dmac_channels[i]->in_use == 0) { + dmac_channel_t *dmac_ch = dmac_channels[i]; + + dmac_ch->microcode_size = 0; + dmac_ch->in_use = 1; + dmac_ch->intr_handler = handler; + dmac_ch->handler_args = handler_args; + + /* TODO enable interrupts for that channel */ +// dmac_channel_state_init(i); + return i; + } + + return -1; +} + +int dmac_get_channel_ex(int channel, int (*handler) (void *), void *handler_args) +{ + if((channel >= 0) && (channel < MAX_DMA_CHANNELS) && (dmac_channels[channel]->in_use == 0)) { + dmac_channel_t *dmac_ch = dmac_channels[channel]; + + dmac_ch->microcode_size = 0; + dmac_ch->in_use = 1; + dmac_ch->intr_handler = handler; + dmac_ch->handler_args = handler_args; + + /* TODO enable interrupts for that channel */ +// dmac_channel_state_init(channel); + return channel; + } + + return -1; +} + +EXPORT_SYMBOL(dmac_get_channel); +EXPORT_SYMBOL(dmac_get_channel_ex); + +/* + * dmac_release_channel + */ +int dmac_release_channel(int chan) +{ + dmac_channel_t *dma_ch; + + if (chan < 0 || chan > 7) + return -1; + + dma_ch = dmac_channels[chan]; + if (!dma_ch->in_use) + return -1; + + dma_ch->in_use = 0; + dma_ch->microcode_size = 0; + dma_ch->intr_handler = 0; + dma_ch->handler_args = 0; + + /* TODO enable interrupts for that channel */ + dmac_channel_state_init(chan); + + return 0; +} + +EXPORT_SYMBOL(dmac_release_channel); + +/* + * + */ +int dmac_get_event(int chan, int event_num) +{ + if ((event_num < MIN_EVENT_NUM) || (event_num > MAX_INTR_EVENTS)) { + return -1; + } + + if (dmac_events[event_num] == -1) { + dmac_channel_t *dmac_ch = dmac_channels[chan]; + dmac_events[event_num] = chan; + dmac_ch->notifications_used |= (1 << event_num); + return 0; + } + return -1; +} + +EXPORT_SYMBOL(dmac_get_event); + +/* + * + */ +int dmac_release_event(int chan, int event_num) +{ + if (dmac_events[event_num] != chan) + return -1; + + dmac_events[event_num] = -1; + dmac_channels[chan]->notifications_used ^= (1 << event_num); + return 0; +} + +EXPORT_SYMBOL(dmac_release_event); + +static int get_bpb_val(int bpb) +{ + int i = bpb; + int retval = -1; + while (i) { + retval += 0x1; + i /= 2; + } + return retval; +} + +/* @src_inc - src address auto increment + * @s_bpb - src bytes per burst + * @s_dt - src num of data transfers + * @dst_inc - dst address auto increment + * @d_bpb - dst bytes per burst + * @d_dt - dst data transfers + * @swap - swapping bytes + */ +uint32_t dmac_create_ctrlval(int src_inc, int s_bpb, int s_dt, int dst_inc, + int d_bpb, int d_dt, int swap) +{ + if (! + ((s_bpb == 1) || (s_bpb == 2) || (s_bpb == 4) || (s_bpb == 8) + || (s_bpb == 16) + || (s_bpb == 32) || (s_bpb == 64) || (s_bpb == 128))) { + printk + ("INVALID s_bpb parameter ... setting default and proceeding\n"); + s_bpb = 4; + } + if (! + ((d_bpb == 1) || (d_bpb == 2) || (d_bpb == 4) || (d_bpb == 8) + || (d_bpb == 16) + || (d_bpb == 32) || (d_bpb == 64) || (d_bpb == 128))) { + printk + ("INVALID d_bpb parameter ... setting default and proceeding\n"); + d_bpb = 4; + } + + if ((s_dt < 1) || (s_dt > 16)) { + printk + ("INVALID s_dt parameter ... setting default and proceeding\n"); + s_dt = 1; + } + if ((d_dt < 1) || (d_dt > 16)) { + printk + ("INVALID d_dt parameter ... setting default and proceeding\n"); + d_dt = 1; + } + return (((src_inc & 0x1) << 0) | + ((get_bpb_val(s_bpb) & 0x7) << 1) | + ((s_dt - 1) << 4) | + (0x2 << 8) | + (0x0 << 11) | + ((dst_inc & 0x1) << 14) | + ((get_bpb_val(d_bpb) & 0x7) << 15) | + ((d_dt - 1) << 18) | (0x2 << 22) | (0x0 << 25) | (swap << 28) + ); +} + +EXPORT_SYMBOL(dmac_create_ctrlval); + +void pl330_dump_regs(void) +{ + printk("Read Periph Id 0 for GDMAC is %x\n", DMAC_MEM_MAP_VALUE(0xFE0)); + printk("DS Register: %x\n", DMAC_MEM_MAP_VALUE(0x0)); + printk("Conf Reg 0 : %x\n", DMAC_MEM_MAP_VALUE(0xE00)); + printk("Conf Reg 1 : %x\n", DMAC_MEM_MAP_VALUE(0xE04)); + printk("Conf Reg 2 : %x\n", DMAC_MEM_MAP_VALUE(0xE08)); + printk("Conf Reg 3 : %x\n", DMAC_MEM_MAP_VALUE(0xE0C)); + printk("Conf Reg 4 : %x\n", DMAC_MEM_MAP_VALUE(0xE10)); + printk("Conf Reg d : %x\n", DMAC_MEM_MAP_VALUE(0xE14)); + + printk("Dumping the status registers \n"); + printk("INTEN Register: %x\n", DMAC_MEM_MAP_VALUE(0x20)); + printk("ES Register: %x\n", DMAC_MEM_MAP_VALUE(0x24)); + printk("INTSTAT Register: %x\n", DMAC_MEM_MAP_VALUE(0x28)); + printk("FSDM Register: %x\n", DMAC_MEM_MAP_VALUE(0x30)); + printk("FSC Register: %x\n", DMAC_MEM_MAP_VALUE(0x34)); + printk("FTM Register: %x\n", DMAC_MEM_MAP_VALUE(0x38)); + printk("FTC0 Register: %x\n", DMAC_MEM_MAP_VALUE(0x40)); + printk("FTC1 Register: %x\n", DMAC_MEM_MAP_VALUE(0x44)); + printk("CS0 Register: %x\n", DMAC_MEM_MAP_VALUE(0x100)); + printk("CPC0 Register: %x\n", DMAC_MEM_MAP_VALUE(0x104)); + printk("CS1 Register: %x\n", DMAC_MEM_MAP_VALUE(0x108)); + printk("CPC1 Register: %x\n", DMAC_MEM_MAP_VALUE(0x10C)); + printk("SA0 Register: %x\n", DMAC_MEM_MAP_VALUE(0x400)); + printk("SA1 Register: %x\n", DMAC_MEM_MAP_VALUE(0x420)); + printk("DA0 Register: %x\n", DMAC_MEM_MAP_VALUE(0x404)); + printk("DA1 Register: %x\n", DMAC_MEM_MAP_VALUE(0x424)); + return; +} + +EXPORT_SYMBOL(pl330_dump_regs); + +/* + * + */ +uint32_t DMAC_READ_CHREGS(int chan, chregs_t reg) +{ + int step = 0, base = 0; + + switch (reg) { + case PL330_FTC: + base = 0x40; + step = chan * 0x4; + break; + case PL330_CS: + base = 0x100; + step = chan * 0x8; + break; + case PL330_CPC: + base = 0x104; + step = chan * 0x8; + break; + case PL330_SA: + base = 0x400; + step = chan * 0x20; + break; + case PL330_DA: + base = 0x404; + step = chan * 0x20; + break; + case PL330_CC: + base = 0x408; + step = chan * 0x20; + break; + case PL330_LC0: + base = 0x40C; + step = chan * 0x20; + break; + case PL330_LC1: + base = 0x410; + step = chan * 0x20; + break; + default: + printk("Wrong argument to function %s\n", __FUNCTION__); + } + return DMAC_MEM_MAP_VALUE(base + step); +} + +EXPORT_SYMBOL(DMAC_READ_CHREGS); --- /dev/null +++ b/arch/arm/mach-cns3xxx/headsmp.S @@ -0,0 +1,54 @@ +/* + * linux/arch/arm/mach-cns3xxx/headsmp.S + * + * Copyright (c) 2008 Cavium Networks + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * 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 +#include + + __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 + +1: .long . + .long pen_release --- /dev/null +++ b/arch/arm/mach-cns3xxx/hotplug.c @@ -0,0 +1,155 @@ +/* + * linux/arch/arm/mach-cns3xxx/hotplug.c + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * 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 +#include +#include +#include + +#include + +extern volatile int pen_release; + +static DECLARE_COMPLETION(cpu_killed); + +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, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : + : "cc"); +} + +static inline void platform_do_lowpower(unsigned int cpu) +{ + /* + * 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 + * + * The trouble is, letting people know about this is not really + * possible, since we are currently running incoherently, and + * therefore cannot safely call printk() or anything else + */ +#ifdef DEBUG + printk("CPU%u: spurious wakeup call\n", cpu); +#endif + } +} + +int platform_cpu_kill(unsigned int cpu) +{ + return wait_for_completion_timeout(&cpu_killed, 5000); +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void platform_cpu_die(unsigned int cpu) +{ +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); + + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + complete(&cpu_killed); + + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); +} + +int mach_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; +} --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/board.h @@ -0,0 +1,386 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/board.h + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + */ + +#ifndef __ASM_ARCH_BOARD_CNS3XXXH +#define __ASM_ARCH_BOARD_CNS3XXXH + +/* + * Cavium Networks CNS3XXX Linux Memory Map: + * + * Phy Size Virt Description + * ========================================================================= + * + * 0x00000000 0x10000000(max) PAGE_OFFSET Alien RAM (??) + * + * 0x78000000 0x00400000 0xFFF09000 UART0 + * + */ + +/* + * Peripheral addresses + */ +#define CNS3XXX_FLASH0_BASE 0x10000000 /* Flash/SRAM Memory Bank 0 */ +#define CNS3XXX_FLASH0_SIZE SZ_128M + +#define CNS3XXX_FLASH1_BASE 0x11000000 /* Flash/SRAM Memory Bank 1 */ +#define CNS3XXX_FLASH1_SIZE SZ_16M +#define CNS3XXX_FLASH2_BASE 0x12000000 /* Flash/SRAM Memory Bank 2 */ +#define CNS3XXX_FLASH2_SIZE SZ_16M +#define CNS3XXX_FLASH3_BASE 0x13000000 /* Flash/SRAM Memory Bank 3 */ +#define CNS3XXX_FLASH3_SIZE SZ_16M + +#define CNS3XXX_DDR2SDRAM_BASE 0x20000000 /* DDR2 SDRAM Memory */ + +#define CNS3XXX_SPI_FLASH_BASE 0x60000000 /* SPI Serial Flash Memory */ + +#define CNS3XXX_SWITCH_BASE 0x70000000 /* Switch and HNAT Control */ +#define CNS3XXX_SWITCH_BASE_VIRT 0xFFF00000 + +#define CNS3XXX_PPE_BASE 0x70001000 /* HANT */ +#define CNS3XXX_PPE_BASE_VIRT 0xFFF50000 + +#define CNS3XXX_EMBEDDED_SRAM_BASE 0x70002000 /* HANT Embedded SRAM */ +#define CNS3XXX_EMBEDDED_SRAM_BASE_VIRT 0xFFF60000 + +#define CNS3XXX_SSP_BASE 0x71000000 /* Synchronous Serial Port - SPI/PCM/I2C */ +#define CNS3XXX_SSP_BASE_VIRT 0xFFF01000 + +#define CNS3XXX_DMC_BASE 0x72000000 /* DMC Control (DDR2 SDRAM) */ +#define CNS3XXX_DMC_BASE_VIRT 0xFFF02000 + +#define CNS3XXX_SMC_BASE 0x73000000 /* SMC Control */ +#define CNS3XXX_SMC_BASE_VIRT 0xFFF03000 + +#define SMC_MEMC_STATUS_OFFSET 0x000 +#define SMC_MEMIF_CFG_OFFSET 0x004 +#define SMC_MEMC_CFG_SET_OFFSET 0x008 +#define SMC_MEMC_CFG_CLR_OFFSET 0x00C +#define SMC_DIRECT_CMD_OFFSET 0x010 +#define SMC_SET_CYCLES_OFFSET 0x014 +#define SMC_SET_OPMODE_OFFSET 0x018 +#define SMC_REFRESH_PERIOD_0_OFFSET 0x020 +#define SMC_REFRESH_PERIOD_1_OFFSET 0x024 +#define SMC_SRAM_CYCLES0_0_OFFSET 0x100 +#define SMC_NAND_CYCLES0_0_OFFSET 0x100 +#define SMC_OPMODE0_0_OFFSET 0x104 +#define SMC_SRAM_CYCLES0_1_OFFSET 0x120 +#define SMC_NAND_CYCLES0_1_OFFSET 0x120 +#define SMC_OPMODE0_1_OFFSET 0x124 +#define SMC_USER_STATUS_OFFSET 0x200 +#define SMC_USER_CONFIG_OFFSET 0x204 +#define SMC_ECC_STATUS_OFFSET 0x300 +#define SMC_ECC_MEMCFG_OFFSET 0x304 +#define SMC_ECC_MEMCOMMAND1_OFFSET 0x308 +#define SMC_ECC_MEMCOMMAND2_OFFSET 0x30C +#define SMC_ECC_ADDR0_OFFSET 0x310 +#define SMC_ECC_ADDR1_OFFSET 0x314 +#define SMC_ECC_VALUE0_OFFSET 0x318 +#define SMC_ECC_VALUE1_OFFSET 0x31C +#define SMC_ECC_VALUE2_OFFSET 0x320 +#define SMC_ECC_VALUE3_OFFSET 0x324 +#define SMC_PERIPH_ID_0_OFFSET 0xFE0 +#define SMC_PERIPH_ID_1_OFFSET 0xFE4 +#define SMC_PERIPH_ID_2_OFFSET 0xFE8 +#define SMC_PERIPH_ID_3_OFFSET 0xFEC +#define SMC_PCELL_ID_0_OFFSET 0xFF0 +#define SMC_PCELL_ID_1_OFFSET 0xFF4 +#define SMC_PCELL_ID_2_OFFSET 0xFF8 +#define SMC_PCELL_ID_3_OFFSET 0xFFC + +#define CNS3XXX_GPIOA_BASE 0x74000000 /* GPIO port A */ +#define CNS3XXX_GPIOA_BASE_VIRT 0xFFF04000 + +#define CNS3XXX_GPIOB_BASE 0x74800000 /* GPIO port B */ +#define CNS3XXX_GPIOB_BASE_VIRT 0xFFF05000 + +#define CNS3XXX_RTC_BASE 0x75000000 /* Real Time Clock */ +#define CNS3XXX_RTC_BASE_VIRT 0xFFF06000 + +#define RTC_SEC_OFFSET 0x00 +#define RTC_MIN_OFFSET 0x04 +#define RTC_HOUR_OFFSET 0x08 +#define RTC_DAY_OFFSET 0x0C +#define RTC_SEC_ALM_OFFSET 0x10 +#define RTC_MIN_ALM_OFFSET 0x14 +#define RTC_HOUR_ALM_OFFSET 0x18 +#define RTC_REC_OFFSET 0x1C +#define RTC_CTRL_OFFSET 0x20 +#define RTC_INTR_STS_OFFSET 0x34 + +#define CNS3XXX_MISC_BASE 0x76000000 /* Misc Control */ +#define CNS3XXX_MISC_BASE_VIRT 0xFFF07000 /* Misc Control */ + +#define CNS3XXX_PM_BASE 0x77000000 /* Power Management Control */ +#define CNS3XXX_PM_BASE_VIRT 0xFFF08000 + +#define PM_CLK_GATE_OFFSET 0x00 +#define PM_SOFT_RST_OFFSET 0x04 +#define PM_HS_CFG_OFFSET 0x08 +#define PM_CACTIVE_STA_OFFSET 0x0C +#define PM_PWR_STA_OFFSET 0x10 +#define PM_SYS_CLK_CTRL_OFFSET 0x14 +#define PM_PLL_LCD_I2S_CTRL_OFFSET 0x18 +#define PM_PLL_HM_PD_OFFSET 0x1C + +#define CNS3XXX_UART0_BASE 0x78000000 /* UART 0 */ +#define CNS3XXX_UART0_BASE_VIRT 0xFFF09000 + +#define CNS3XXX_UART1_BASE 0x78400000 /* UART 1 */ +#define CNS3XXX_UART1_BASE_VIRT 0xFFF0A000 + +#define CNS3XXX_UART2_BASE 0x78800000 /* UART 2 */ +#define CNS3XXX_UART2_BASE_VIRT 0xFFF0B000 + +#define CNS3XXX_UART3_BASE 0x78C00000 /* UART 3 */ +#define CNS3XXX_UART3_BASE_VIRT 0xFFF0C000 + +#define CNS3XXX_DMAC_BASE 0x79000000 /* Generic DMA Control */ +#define CNS3XXX_DMAC_BASE_VIRT 0xFFF0D000 + +#define CNS3XXX_CORESIGHT_BASE 0x7A000000 /* CoreSight */ +#define CNS3XXX_CORESIGHT_BASE_VIRT 0xFFF0E000 + +#define CNS3XXX_CRYPTO_BASE 0x7B000000 /* Crypto */ +#define CNS3XXX_CRYPTO_BASE_VIRT 0xFFF0F000 + +#define CNS3XXX_I2S_BASE 0x7C000000 /* I2S */ +#define CNS3XXX_I2S_BASE_VIRT 0xFFF10000 + +#define CNS3XXX_TIMER1_2_3_BASE 0x7C800000 /* Timer */ +#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFFF10800 + +#define TIMER1_COUNTER_OFFSET 0x00 +#define TIMER1_AUTO_RELOAD_OFFSET 0x04 +#define TIMER1_MATCH_V1_OFFSET 0x08 +#define TIMER1_MATCH_V2_OFFSET 0x0C + +#define TIMER2_COUNTER_OFFSET 0x10 +#define TIMER2_AUTO_RELOAD_OFFSET 0x14 +#define TIMER2_MATCH_V1_OFFSET 0x18 +#define TIMER2_MATCH_V2_OFFSET 0x1C + +#define TIMER1_2_CONTROL_OFFSET 0x30 +#define TIMER1_2_INTERRUPT_STATUS_OFFSET 0x34 +#define TIMER1_2_INTERRUPT_MASK_OFFSET 0x38 + +#define TIMER_FREERUN_OFFSET 0x40 +#define TIMER_FREERUN_CONTROL_OFFSET 0x44 + +#define CNS3XXX_HCIE_BASE 0x7D000000 /* HCIE Control */ +#if 0 +#define CNS3XXX_HCIE_BASE_VIRT 0xFFF11000 +#else +#define CNS3XXX_HCIE_BASE_VIRT 0xFFF30000 +#endif + +#define CNS3XXX_RAID_BASE 0x7E000000 /* RAID Control */ +#define CNS3XXX_RAID_BASE_VIRT 0xFFF12000 + +#define CNS3XXX_AXI_IXC_BASE 0x7F000000 /* AXI IXC */ +#define CNS3XXX_AXI_IXC_BASE_VIRT 0xFFF13000 + +#define CNS3XXX_CLCD_BASE 0x80000000 /* LCD Control */ +#define CNS3XXX_CLCD_BASE_VIRT 0xFFF14000 + +#define CNS3XXX_USBOTG_BASE 0x81000000 /* USB OTG Control */ +#define CNS3XXX_USBOTG_BASE_VIRT 0xFFF15000 + +#define CNS3XXX_USB_BASE 0x82000000 /* USB Host Control */ +#define CNS3XXX_USB_BASE_VIRT 0xFFF16000 + +#define CNS3XXX_SATA2_BASE 0x83000000 /* SATA */ +#define CNS3XXX_SATA2_SIZE SZ_16M +#define CNS3XXX_SATA2_BASE_VIRT 0xFFF17000 + +#define CNS3XXX_CAMERA_BASE 0x84000000 /* Camera Interface */ +#define CNS3XXX_CAMERA_BASE_VIRT 0xFFF18000 + +#define CNS3XXX_SDIO_BASE 0x85000000 /* SDIO */ +#define CNS3XXX_SDIO_BASE_VIRT 0xFFF19000 + +#define CNS3XXX_I2S_TDM_BASE 0x86000000 /* I2S TDM */ +#define CNS3XXX_I2S_TDM_BASE_VIRT 0xFFF1A000 + +#define CNS3XXX_2DG_BASE 0x87000000 /* 2D Graphic Control */ +#define CNS3XXX_2DG_BASE_VIRT 0xFFF1B000 + +#define CNS3XXX_USB_OHCI_BASE 0x88000000 /* USB OHCI */ +#define CNS3XXX_USB_OHCI_BASE_VIRT 0xFFF1C000 + +#define CNS3XXX_L2C_BASE 0x92000000 /* L2 Cache Control */ +#define CNS3XXX_L2C_BASE_VIRT 0xFFF27000 + +#define CNS3XXX_PCIE0_MEM_BASE 0xA0000000 /* PCIe Port 0 IO/Memory Space */ +#define CNS3XXX_PCIE0_MEM_BASE_VIRT 0xE0000000 + +#define CNS3XXX_PCIE0_HOST_BASE 0xAB000000 /* PCIe Port 0 RC Base */ +#define CNS3XXX_PCIE0_HOST_BASE_VIRT 0xE1000000 + +#define CNS3XXX_PCIE0_IO_BASE 0xAC000000 /* PCIe Port 0 */ +#define CNS3XXX_PCIE0_IO_BASE_VIRT 0xE2000000 + +#define CNS3XXX_PCIE0_CFG0_BASE 0xAD000000 /* PCIe Port 0 CFG Type 0 */ +#define CNS3XXX_PCIE0_CFG0_BASE_VIRT 0xE3000000 + +#define CNS3XXX_PCIE0_CFG1_BASE 0xAE000000 /* PCIe Port 0 CFG Type 1 */ +#define CNS3XXX_PCIE0_CFG1_BASE_VIRT 0xE4000000 + +#define CNS3XXX_PCIE0_MSG_BASE 0xAF000000 /* PCIe Port 0 Message Space */ +#define CNS3XXX_PCIE0_MSG_BASE_VIRT 0xE5000000 + +#define CNS3XXX_PCIE1_MEM_BASE 0xB0000000 /* PCIe Port 1 IO/Memory Space */ +#define CNS3XXX_PCIE1_MEM_BASE_VIRT 0xE8000000 + +#define CNS3XXX_PCIE1_HOST_BASE 0xBB000000 /* PCIe Port 1 RC Base */ +#define CNS3XXX_PCIE1_HOST_BASE_VIRT 0xE9000000 + +#define CNS3XXX_PCIE1_IO_BASE 0xBC000000 /* PCIe Port 1 */ +#define CNS3XXX_PCIE1_IO_BASE_VIRT 0xEA000000 + +#define CNS3XXX_PCIE1_CFG0_BASE 0xBD000000 /* PCIe Port 1 CFG Type 0 */ +#define CNS3XXX_PCIE1_CFG0_BASE_VIRT 0xEB000000 + +#define CNS3XXX_PCIE1_CFG1_BASE 0xBE000000 /* PCIe Port 1 CFG Type 1 */ +#define CNS3XXX_PCIE1_CFG1_BASE_VIRT 0xEC000000 + +#define CNS3XXX_PCIE1_MSG_BASE 0xBF000000 /* PCIe Port 1 Message Space */ +#define CNS3XXX_PCIE1_MSG_BASE_VIRT 0xED000000 + +/* + * Testchip peripheral and fpga gic regions + */ +//#define CNS3XXX_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */ +#define CNS3XXX_TC11MP_SCU_BASE 0x90000000 /* IRQ, Test chip */ +#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFF000000 + +//#define CNS3XXX_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */ +#define CNS3XXX_TC11MP_GIC_CPU_BASE 0x90000100 /* Test chip interrupt controller CPU interface */ +#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT 0xFF000100 + +//#define CNS3XXX_TC11MP_TWD_BASE 0x1F000600 +#define CNS3XXX_TC11MP_TWD_BASE 0x90000600 +#define CNS3XXX_TC11MP_TWD_BASE_VIRT 0xFF000600 + +//#define CNS3XXX_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */ +#define CNS3XXX_TC11MP_GIC_DIST_BASE 0x90001000 /* Test chip interrupt controller distributor */ +#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT 0xFF001000 + +//#define CNS3XXX_TC11MP_L220_BASE 0x1F002000 /* L220 registers */ +#define CNS3XXX_TC11MP_L220_BASE 0x92002000 /* L220 registers */ +#define CNS3XXX_TC11MP_L220_BASE_VIRT 0xFF002000 + +/* + * Irqs + */ +#define IRQ_TC11MP_GIC_START 32 + +/* + * ARM11 MPCore test chip interrupt sources (primary GIC on the test chip) + */ +#define IRQ_CNS3XXX_PMU (IRQ_TC11MP_GIC_START + 0) +#define IRQ_CNS3XXX_SDIO (IRQ_TC11MP_GIC_START + 1) +#define IRQ_CNS3XXX_L2CC (IRQ_TC11MP_GIC_START + 2) +#define IRQ_CNS3XXX_RTC (IRQ_TC11MP_GIC_START + 3) +#define IRQ_CNS3XXX_I2S (IRQ_TC11MP_GIC_START + 4) +#define IRQ_CNS3XXX_PCM (IRQ_TC11MP_GIC_START + 5) +#define IRQ_CNS3XXX_SPI (IRQ_TC11MP_GIC_START + 6) +#define IRQ_CNS3XXX_I2C (IRQ_TC11MP_GIC_START + 7) +#define IRQ_CNS3XXX_CIM (IRQ_TC11MP_GIC_START + 8) +#define IRQ_CNS3XXX_GPU (IRQ_TC11MP_GIC_START + 9) +#define IRQ_CNS3XXX_LCD (IRQ_TC11MP_GIC_START + 10) +#define IRQ_CNS3XXX_GPIOA (IRQ_TC11MP_GIC_START + 11) +#define IRQ_CNS3XXX_GPIOB (IRQ_TC11MP_GIC_START + 12) +#define IRQ_CNS3XXX_UART0 (IRQ_TC11MP_GIC_START + 13) +#define IRQ_CNS3XXX_UART1 (IRQ_TC11MP_GIC_START + 14) +#define IRQ_CNS3XXX_UART2 (IRQ_TC11MP_GIC_START + 15) +#define IRQ_CNS3XXX_ARM11 (IRQ_TC11MP_GIC_START + 16) + +#define IRQ_CNS3XXX_SW_STATUS (IRQ_TC11MP_GIC_START + 17) +#define IRQ_CNS3XXX_SW_R0TXC (IRQ_TC11MP_GIC_START + 18) +#define IRQ_CNS3XXX_SW_R0RXC (IRQ_TC11MP_GIC_START + 19) +#define IRQ_CNS3XXX_SW_R0QE (IRQ_TC11MP_GIC_START + 20) +#define IRQ_CNS3XXX_SW_R0QF (IRQ_TC11MP_GIC_START + 21) +#define IRQ_CNS3XXX_SW_R1TXC (IRQ_TC11MP_GIC_START + 22) +#define IRQ_CNS3XXX_SW_R1RXC (IRQ_TC11MP_GIC_START + 23) +#define IRQ_CNS3XXX_SW_R1QE (IRQ_TC11MP_GIC_START + 24) +#define IRQ_CNS3XXX_SW_R1QF (IRQ_TC11MP_GIC_START + 25) +#define IRQ_CNS3XXX_SW_PPE (IRQ_TC11MP_GIC_START + 26) + +#define IRQ_CNS3XXX_CRYPTO (IRQ_TC11MP_GIC_START + 27) +#define IRQ_CNS3XXX_HCIE (IRQ_TC11MP_GIC_START + 28) +#define IRQ_CNS3XXX_PCIE0_DEVICE (IRQ_TC11MP_GIC_START + 29) +#define IRQ_CNS3XXX_PCIE1_DEVICE (IRQ_TC11MP_GIC_START + 30) +#define IRQ_CNS3XXX_USB_OTG (IRQ_TC11MP_GIC_START + 31) +#define IRQ_CNS3XXX_USB_EHCI (IRQ_TC11MP_GIC_START + 32) +#define IRQ_CNS3XXX_SATA (IRQ_TC11MP_GIC_START + 33) +#define IRQ_CNS3XXX_RAID (IRQ_TC11MP_GIC_START + 34) +#define IRQ_CNS3XXX_SMC (IRQ_TC11MP_GIC_START + 35) + +#define IRQ_CNS3XXX_DMAC_ABORT (IRQ_TC11MP_GIC_START + 36) +#define IRQ_CNS3XXX_DMAC0 (IRQ_TC11MP_GIC_START + 37) +#define IRQ_CNS3XXX_DMAC1 (IRQ_TC11MP_GIC_START + 38) +#define IRQ_CNS3XXX_DMAC2 (IRQ_TC11MP_GIC_START + 39) +#define IRQ_CNS3XXX_DMAC3 (IRQ_TC11MP_GIC_START + 40) +#define IRQ_CNS3XXX_DMAC4 (IRQ_TC11MP_GIC_START + 41) +#define IRQ_CNS3XXX_DMAC5 (IRQ_TC11MP_GIC_START + 42) +#define IRQ_CNS3XXX_DMAC6 (IRQ_TC11MP_GIC_START + 43) +#define IRQ_CNS3XXX_DMAC7 (IRQ_TC11MP_GIC_START + 44) +#define IRQ_CNS3XXX_DMAC8 (IRQ_TC11MP_GIC_START + 45) +#define IRQ_CNS3XXX_DMAC9 (IRQ_TC11MP_GIC_START + 46) +#define IRQ_CNS3XXX_DMAC10 (IRQ_TC11MP_GIC_START + 47) +#define IRQ_CNS3XXX_DMAC11 (IRQ_TC11MP_GIC_START + 48) +#define IRQ_CNS3XXX_DMAC12 (IRQ_TC11MP_GIC_START + 49) +#define IRQ_CNS3XXX_DMAC13 (IRQ_TC11MP_GIC_START + 50) +#define IRQ_CNS3XXX_DMAC14 (IRQ_TC11MP_GIC_START + 51) +#define IRQ_CNS3XXX_DMAC15 (IRQ_TC11MP_GIC_START + 52) +#define IRQ_CNS3XXX_DMAC16 (IRQ_TC11MP_GIC_START + 53) +#define IRQ_CNS3XXX_DMAC17 (IRQ_TC11MP_GIC_START + 54) + +#define IRQ_CNS3XXX_PCIE0_RC (IRQ_TC11MP_GIC_START + 55) +#define IRQ_CNS3XXX_PCIE1_RC (IRQ_TC11MP_GIC_START + 56) +#define IRQ_CNS3XXX_TIMER0 (IRQ_TC11MP_GIC_START + 57) +#define IRQ_CNS3XXX_TIMER1 (IRQ_TC11MP_GIC_START + 58) +#define IRQ_CNS3XXX_USB_OHCI (IRQ_TC11MP_GIC_START + 59) +#define IRQ_CNS3XXX_TIMER2 (IRQ_TC11MP_GIC_START + 60) +#define IRQ_CNS3XXX_EXTERNAL_PIN0 (IRQ_TC11MP_GIC_START + 61) +#define IRQ_CNS3XXX_EXTERNAL_PIN1 (IRQ_TC11MP_GIC_START + 62) +#define IRQ_CNS3XXX_EXTERNAL_PIN2 (IRQ_TC11MP_GIC_START + 63) + +#define NR_GIC_CNS3XXX 1 + +/* + * Only define NR_IRQS if less than NR_IRQS_CNS3XXX + */ +#define NR_IRQS_CNS3XXX (IRQ_TC11MP_GIC_START + 64) + +#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_CNS3XXX) +#undef NR_IRQS +#define NR_IRQS NR_IRQS_CNS3XXX +#endif + +#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_CNS3XXX) +#undef MAX_GIC_NR +#define MAX_GIC_NR NR_GIC_CNS3XXX +#endif + +#endif /* __ASM_ARCH_BOARD_CNS3XXX_H */ --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/camera.h @@ -0,0 +1,97 @@ +/* + camera.h - CNS3XXX camera driver header file + + Copyright (C) 2003, Intel Corporation + Copyright (C) 2008, Guennadi Liakhovetski + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ASM_ARCH_CAMERA_H_ +#define __ASM_ARCH_CAMERA_H_ + +#define CNS3XXX_CAMERA_MASTER 0x01 +#define CNS3XXX_CAMERA_DATAWIDTH_4 0x02 +#define CNS3XXX_CAMERA_DATAWIDTH_5 0x04 +#define CNS3XXX_CAMERA_DATAWIDTH_8 0x08 +#define CNS3XXX_CAMERA_DATAWIDTH_9 0x10 +#define CNS3XXX_CAMERA_DATAWIDTH_10 0x20 +#define CNS3XXX_CAMERA_PCLK_EN 0x40 +#define CNS3XXX_CAMERA_MCLK_EN 0x80 +#define CNS3XXX_CAMERA_PCP 0x100 +#define CNS3XXX_CAMERA_HSP 0x200 +#define CNS3XXX_CAMERA_VSP 0x400 + +/* Camera Interface */ +#define CIM_GLOBAL_REG 0x00 /* CIM control*/ +#define CIM_TIMING_V_REG 0x04 /* Vertical capture range setting */ +#define CIM_TIMING_H_REG 0x08 /* Horizontal capture range setting */ +#define CIM_CCIR656_0_REG 0x0C /* CCIR656 detect and control setting*/ +#define CIM_CCIR656_1_REG 0x10 /* CCIR656 self test setting */ +#define CIM_SERIAL_SRC_REG 0x14 /* Serial pix capture module control settings */ +#define CIM_INT_MASK_REG 0x28 /* CIM interrupt mask register. */ +#define CIM_INT_STATUS_REG 0x2C /* CIM interrupt status register. */ +#define CIM_INT_CLEAR_REG 0x30 /* CIM interrupt clear register. */ +#define CIM_DATAPATH_CTL_REG 0x34 /* CIM data path options and control settings */ +#define CIM_VIDEO_PORT_REG 0x100 /* CIM¡¦s video port */ +#define CIM_CORRECTION_R_REG 0x200 /* Internal programmable table for R component. */ +#define CIM_CORRECTION_G_REG 0x600 /* Internal programmable table for G component. */ +#define CIM_CORRECTION_B_REG 0xA00 /* Internal programmable table for B component. */ + +#define SRC_DATA_FMT_CCIR656 0x00 +#define SRC_DATA_FMT_YCBCR_A 0x01 +#define SRC_DATA_FMT_YCBCR_B 0x02 +#define SRC_DATA_FMT_RGB565 0x03 +#define SRC_DATA_FMT_RGB555 0x04 +#define SRC_DATA_FMT_BAYER_82 0x05 +#define SRC_DATA_FMT_BAYER_10 0x06 + +#define DST_DATA_FMT_RGB888 0x00 +#define DST_DATA_FMT_RGB565 0x01 +#define DST_DATA_FMT_RGB1555 0x02 +#define DST_DATA_FMT_RGB444 0x03 + +#define CISR_LAST_LINE (1 << 0) /* Last line */ +#define CISR_FIRST_LINE (1 << 1) /* First line */ +#define CISR_LINE_END (1 << 2) /* Line end */ +#define CISR_LINE_START (1 << 3) /* Line start */ +#define CISR_FIELD_CHG (1 << 4) /* Field Change */ +#define CISR_FIFO_OVERRUN (1 << 5) /* FIFO overrun */ + + +#define CIMR_LAST_LINE_M (1 << 0) /* Last line mask*/ +#define CIMR_FIRST_LINE_M (1 << 1) /* First line mask*/ +#define CIMR_LINE_END_M (1 << 2) /* Line end mask*/ +#define CIMR_LINE_START_M (1 << 3) /* Line start mask*/ +#define CIMR_FIELD_CHG_M (1 << 4) /* Field Change mask*/ +#define CIMR_FIFO_OVERRUN_M (1 << 5) /* FIFO overrun mask*/ + + +struct cns3xxx_camera_platform_data { +#if 0 + int (*init)(struct device *); + int (*power)(struct device *, int); + int (*reset)(struct device *, int); +#endif + + unsigned long flags; + unsigned long mclk_10khz; + unsigned long lcd_base; + unsigned long misc_base; +}; + +//extern void cns3xxx_set_camera_info(struct pxacamera_platform_data *); + +#endif /* __ASM_ARCH_CAMERA_H_ */ --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S @@ -0,0 +1,35 @@ +/* arch/arm/mach-cns3xxx/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * 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 + */ + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x10000000 + movne \rx, #0xf0000000 @ virtual base + orr \rx, \rx, #0x00009000 + .endm + +#include --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/dmac.h @@ -0,0 +1,295 @@ +/******************************************************************************* + * + * arch/arm/mach-cns3xxx/dmac.h + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + * + ******************************************************************************/ + +#ifndef _CNS3XXX_DMAC_H_ +#define _CNS3XXX_DMAC_H_ + +#define MAX_DMA_CHANNELS 9 +#define DMAC_PCM1_PERIPH_ID_0 4 +#define DMAC_SPI_PERIPH_ID 8 +#define DMAC_PCM_PERIPH_ID_0 9 +#define CNS3XXX_DMAC_I2STX_PID 12 +#define CNS3XXX_DMAC_I2SRX_PID 13 + +/* APIs */ +int __init dmac_init(void); +extern int dmac_get_channel (int (*handler)(void*), void *handler_args); +extern int dmac_get_channel_ex(int channel, int (*handler) (void *), void *handler_args); +extern int dmac_release_channel(int chan); + +extern int dmac_get_event (int chan, int ev); +extern int dmac_release_event (int chan, int ev); + +extern uint32_t dmac_create_ctrlval (int src_inc, int s_bpb, int s_dt, int dst_inc, int d_bpb, int d_dt, int swap); +/* enum - reg ? 0 => PL330_FTC, 1 => PL330_CS, 2 => PL330_CPC, 3 => PL330_SA, + * 4 => PL330_DA, 5=>PL330_CC, 6 => PL330_LC0, 7 => PL330_LC1 + */ +typedef enum { PL330_FTC =0, + PL330_CS, + PL330_CPC, + PL330_SA, + PL330_DA, + PL330_CC, + PL330_LC0, + PL330_LC1 +} chregs_t; + +extern uint32_t DMAC_READ_CHREGS (int chan, chregs_t reg); + +/* Instruction Set */ + +/****************************************************************************** + * + * Instruction: DMAEND + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 0 0 0 + * Example: + * DMAEND + * 00 + ******************************************************************************/ +int DMAC_DMAEND(int ch_num); + +/****************************************************************************** + * + * Instruction: DMAFLUSHP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 1 0 1 0 1 + * Example: + * DMAFLUSHP P0 + * 35 00 + ******************************************************************************/ +#define DMAFLUSHP_INSTR_SIZE 2 +int DMAC_DMAFLUSHP(int ch_num, int periph); + +/****************************************************************************** + * + * Instruction: DMAGO + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 0 1 0 0 0 ns 0 + * + * | 47 16 | + * < imm[31:0] > + * Example: + * DMAGO C0, 0x40000000 + * A0 00 00 00 00 40 + ******************************************************************************/ +int DMAC_DMAGO(int ch_num); + +/****************************************************************************** + * + * Instruction: DMALD + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 bs x + * Example: + * DMALD + * 04 + ******************************************************************************/ +#define DMALD_INSTR_SIZE 1 +#define DMALDB_INSTR_SIZE 1 +#define DMALDS_INSTR_SIZE 1 +int DMAC_DMALD(int ch_num); + +int DMAC_DMALDB(int ch_num); + +int DMAC_DMALDS(int ch_num); + +/****************************************************************************** + * + * Instruction: DMALP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < iter[7:0] > 0 0 1 0 0 0 lc 0 + * Example: + * DMALP 8 + * 20 07 + ******************************************************************************/ +#define DMALP_INSTR_SIZE 2 +int DMAC_DMALP(int ch_num, int loop_reg_idx, int iter); + +/****************************************************************************** + * + * Instruction: DMALPEND + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < backwards_jump[7:0] > 0 0 1 nf 1 lc bs x + * Example: + * DMALPEND + * 38 04 + ******************************************************************************/ +#define DMALPEND_INSTR_SIZE 2 +int DMAC_DMALPEND(int ch_num, int loop_reg_idx, int jump, int lpfe); + +/****************************************************************************** + * + * Instruction: DMAMOV + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 1 0 1 1 1 1 0 0 + * + * | 47 16 | + * < imm[31:0] > + * + * # CCR Description + * # [30:28] Endian swap size + * # [27:25] AWCACHE[3,1:0] value + * # [24:22] AWPROT value + * # [21:18] AWLEN value + * # [17:15] AWSIZE value + * # [14] AWBURST[0] value + * 0 - FIXED / 1 - INCR + * # [13:11] ARCACHE[2:0] value + * # [10:8] ARPROT value + * # [7:4] ARLEN value + * # [3:1] ARSIZE value + * # [0] ARBURST[0] value + * 0 - FIXED / 1 - INCR + * Example: + * DMAMOV CCR, SB1 SS32 DB1 DS32 + * BC 01 05 40 01 00 + ******************************************************************************/ + +#define DMAMOV_INSTR_SIZE 6 +/* ccr_sar_dar: 0 for SAR, 1, for CCR, 2 for DAR */ +typedef enum { SAR = 0, CCR = 1, DAR = 2 } dmamov_arg_t; +int DMAC_DMAMOV(int ch_num, dmamov_arg_t ccr_sar_dar, uint32_t value); + +#define DMAWMB_INSTR_SIZE 1 +int DMAC_DMAWMB (int ch_num); + +#define DMANOP_INSTR_SIZE 1 +int DMAC_DMANOP (int ch_num); +/****************************************************************************** + * + * Instruction: DMAST + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 1 0 bs x + * Example: + * DMAST + * 08 + ******************************************************************************/ +#define DMAST_INSTR_SIZE 1 /* 1 Byte */ +int DMAC_DMAST(int ch_num); + +#define DMASTB_INSTR_SIZE 1 /* 1 Byte */ +int DMAC_DMASTB(int ch_num); + +#define DMASTS_INSTR_SIZE 1 /* 1 Byte */ +int DMAC_DMASTS(int ch_num); + +/****************************************************************************** + * + * Instruction: DMASTZ + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 1 1 0 0 + * Example: + * DMASTZ + * 08 + ******************************************************************************/ +/* Not done */ + +/****************************************************************************** + * + * Instruction: DMAWFE + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 i 0 0 0 1 1 0 1 1 0 + * Example: + * DMAWFE E0 + * 36 00 + ******************************************************************************/ +int DMAC_WFE(int ch_num, int event); +#define DMAWFE_INSTR_SIZE 2 + +/****************************************************************************** + * + * Instruction: DMAWFP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 1 0 0 bs p + * Example: + * DMAWFP P0, periph + * 31 00 + ******************************************************************************/ +typedef enum { SINGLE = 0, BURST = 1, PERIPHERAL = 2} dmawfp_burst_type; +int DMAC_DMAWFP(int ch_num, int periph_id,dmawfp_burst_type b); +#define DMAWFP_INSTR_SIZE 2 + +/****************************************************************************** + * + * Instruction: DMAKILL + * Description: + * | 7 6 5 4 | 3 2 1 0 | + * 0 0 0 0 0 0 0 1 + * Example: + * DMAKILL + * 01 + ******************************************************************************/ + +/****************************************************************************** + * + * Instruction: DMASEV + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * 0 i 0 0 0 1 1 0 1 0 0 + * Example: + * DMASEV E0 + * 34 00 + ******************************************************************************/ +int DMAC_DMASEV(int ch_num, int event_num); +#define DMASEV_INSTR_SIZE 2 + +/****************************************************************************** + * + * Instruction: DMALDP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 0 0 1 bs 1 + * Example: + * DMALDPS P0 + * 25 00 + ******************************************************************************/ +int DMAC_DMALDP(int ch_num, int periph_id, int burst); +#define DMALDP_INSTR_SIZE 2 + +/****************************************************************************** + * + * Instruction: DMASTP + * Description: + * | 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * < periph[4:0] > 0 0 0 0 0 1 0 1 0 bs 1 + * Example: + * DMASTPS P0 + * 29 00 + ******************************************************************************/ +int DMAC_DMASTP(int ch_num, int periph_id, int burst); +#define DMASTP_INSTR_SIZE 2 + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -0,0 +1,105 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for Cavium Networks platforms + * + * Copyright (c) 2008 Cavium Networks + * + * 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 +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm + + .macro test_for_cache_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #1 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h @@ -0,0 +1,94 @@ +/* + * arch/arm/mach-ixp4xx/include/mach/gpio.h + * + * IXP4XX GPIO wrappers for arch-neutral GPIO calls + * + * Written by Milan Svoboda + * Based on PXA implementation by Philipp Zabel + * + * 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_IXP4XX_GPIO_H +#define __ASM_ARCH_IXP4XX_GPIO_H + +#include +#include +#include /* 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 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/hardware.h @@ -0,0 +1,40 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/hardware.h + * + * This file contains the hardware definitions of the Cavium Networks boards. + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited. + * + * 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 + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* macro to get at IO space when running virtually */ +#define PCIBIOS_MIN_IO 0x00000000 +#define PCIBIOS_MIN_MEM 0x00000000 + +#define pcibios_assign_all_busses() 0 + +#include "board.h" + +#include "platform.h" + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/io.h @@ -0,0 +1,41 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/io.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * + * 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 + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#include "board.h" + +#define IO_SPACE_LIMIT 0xffffffff + +#if 1 +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)((addr - CNS3XXX_PCIE0_IO_BASE) + + CNS3XXX_PCIE0_IO_BASE_VIRT); +} +#endif +#define __io(a) __io(a) +#define __mem_pci(a) (a) + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/irqs.h @@ -0,0 +1,45 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/irqs.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * 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 + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#include + +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + +#define IRQ_GIC_START 32 +#define IRQ_CLCD 44 + +#ifdef CONFIG_CNS_RAID +#define IRQ_CNS_RAID (43) +#endif /* CONFIG_CNS_RAID */ + +#ifndef NR_IRQS +#error "NR_IRQS not defined by the board-specific files" +#endif + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/lm.h @@ -0,0 +1,32 @@ +#include + +struct lm_device { + struct device dev; + struct resource resource; + unsigned int irq; + unsigned int id; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + void *lm_drvdata; +#endif +}; + +struct lm_driver { + struct device_driver drv; + int (*probe)(struct lm_device *); + void (*remove)(struct lm_device *); + int (*suspend)(struct lm_device *, pm_message_t); + int (*resume)(struct lm_device *); +}; + +int lm_driver_register(struct lm_driver *drv); +void lm_driver_unregister(struct lm_driver *drv); + +int lm_device_register(struct lm_device *dev); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +# define lm_get_drvdata(lm) ((lm)->lm_drvdata) +# define lm_set_drvdata(lm,d) do { (lm)->lm_drvdata = (d); } while (0) +#else +# define lm_get_drvdata(lm) dev_get_drvdata(&(lm)->dev) +# define lm_set_drvdata(lm,d) dev_set_drvdata(&(lm)->dev, d) +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/memory.h @@ -0,0 +1,43 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/memory.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * + * 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 + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET UL(0x00000000) + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define __virt_to_bus(x) ((x) - PAGE_OFFSET) +#define __bus_to_virt(x) ((x) + PAGE_OFFSET) + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/misc.h @@ -0,0 +1,670 @@ +/****************************************************************************** + * MODULE NAME: star_misc.h + * PROJECT CODE: Vega + * DESCRIPTION: + * MAINTAINER: Jacky Hou + * DATE: 9 February 2009 + * + * SOURCE CONTROL: + * + * LICENSE: + * This source code is copyright (c) 2008-2009 Cavium Networks Inc. + * All rights reserved. + * + * REVISION HISTORY: + * + * + * SOURCE: + * ISSUES: + * NOTES TO USERS: + ******************************************************************************/ + +#ifndef _CNS3XXX_MISC_H_ +#define _CNS3XXX_MISC_H_ +#include +#define MISC_MEM_MAP_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_MISC_BASE_VIRT + offset))) + + +/* + * define access macros + */ +#define MISC_MEMORY_REMAP_REG MISC_MEM_MAP_VALUE(0x00) +#define MISC_CHIP_CONFIG_REG MISC_MEM_MAP_VALUE(0x04) +#define MISC_DEBUG_PROBE_DATA_REG MISC_MEM_MAP_VALUE(0x08) +#define MISC_DEBUG_PROBE_SELECTION_REG MISC_MEM_MAP_VALUE(0x0C) +#define MISC_IO_PIN_FUNC_SELECTION_REG MISC_MEM_MAP_VALUE(0x10) +#define MISC_GPIOA_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x14) +#define MISC_GPIOB_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x18) +#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_A MISC_MEM_MAP_VALUE(0x1C) +#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_B MISC_MEM_MAP_VALUE(0x20) +#define MISC_GPIOA_15_0_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x24) +#define MISC_GPIOA_16_31_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x28) +#define MISC_GPIOB_15_0_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x2C) +#define MISC_GPIOB_16_31_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x30) +#define MISC_IO_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x34) +#define MISC_E_FUSE_31_0_REG MISC_MEM_MAP_VALUE(0x40) +#define MISC_E_FUSE_63_32_REG MISC_MEM_MAP_VALUE(0x44) +#define MISC_E_FUSE_95_64_REG MISC_MEM_MAP_VALUE(0x48) +#define MISC_E_FUSE_127_96_REG MISC_MEM_MAP_VALUE(0x4C) +#define MISC_SOFTWARE_TEST_1_REG MISC_MEM_MAP_VALUE(0x50) +#define MISC_SOFTWARE_TEST_2_REG MISC_MEM_MAP_VALUE(0x54) + + + +// USB MISC +#define MISC_USB_CFG_REG MISC_MEM_MAP_VALUE(0x800) +#define MISC_USB_STS_REG MISC_MEM_MAP_VALUE(0x804) +#define MISC_USBPHY00_CFG_REG MISC_MEM_MAP_VALUE(0x808) +#define MISC_USBPHY01_CFG_REG MISC_MEM_MAP_VALUE(0x80c) +#define MISC_USBPHY10_CFG_REG MISC_MEM_MAP_VALUE(0x810) +#define MISC_USBPHY11_CFG_REG MISC_MEM_MAP_VALUE(0x814) + +#define MISC_PCIEPHY_CMCTL0_REG MISC_MEM_MAP_VALUE(0x900) +#define MISC_PCIEPHY_CMCTL1_REG MISC_MEM_MAP_VALUE(0x904) + +#define MISC_PCIEPHY0_CTL_REG MISC_MEM_MAP_VALUE(0x940) +#define MISC_PCIE0_AXIS_AWMISC_REG MISC_MEM_MAP_VALUE(0x944) +#define MISC_PCIE0_AXIS_ARMISC_REG MISC_MEM_MAP_VALUE(0x948) +#define MISC_PCIE0_AXIS_RMISC_REG MISC_MEM_MAP_VALUE(0x94C) +#define MISC_PCIE0_AXIS_BMISC_REG MISC_MEM_MAP_VALUE(0x950) +#define MISC_PCIE0_AXIM_RMISC_REG MISC_MEM_MAP_VALUE(0x954) +#define MISC_PCIE0_AXIM_BMISC_REG MISC_MEM_MAP_VALUE(0x958) +#define MISC_PCIE0_CTRL_REG MISC_MEM_MAP_VALUE(0x95C) +#define MISC_PCIE0_PM_DEBUG_REG MISC_MEM_MAP_VALUE(0x960) +#define MISC_PCIE0_RFC_DEBUG_REG MISC_MEM_MAP_VALUE(0x964) +#define MISC_PCIE0_CXPL_DEBUGL_REG MISC_MEM_MAP_VALUE(0x968) +#define MISC_PCIE0_CXPL_DEBUGH_REG MISC_MEM_MAP_VALUE(0x96C) +#define MISC_PCIE0_DIAG_DEBUGH_REG MISC_MEM_MAP_VALUE(0x970) +#define MISC_PCIE0_W1CLR_REG MISC_MEM_MAP_VALUE(0x974) +#define MISC_PCIE0_INT_MASK_REG MISC_MEM_MAP_VALUE(0x978) +#define MISC_PCIE0_INT_STATUS_REG MISC_MEM_MAP_VALUE(0x97C) + +#define MISC_PCIEPHY1_CTL_REG MISC_MEM_MAP_VALUE(0xa40) +#define MISC_PCIE1_AXIS_AWMISC_REG MISC_MEM_MAP_VALUE(0xa44) +#define MISC_PCIE1_AXIS_ARMISC_REG MISC_MEM_MAP_VALUE(0xa48) +#define MISC_PCIE1_AXIS_RMISC_REG MISC_MEM_MAP_VALUE(0xa4C) +#define MISC_PCIE1_AXIS_BMISC_REG MISC_MEM_MAP_VALUE(0xa50) +#define MISC_PCIE1_AXIM_RMISC_REG MISC_MEM_MAP_VALUE(0xa54) +#define MISC_PCIE1_AXIM_BMISC_REG MISC_MEM_MAP_VALUE(0xa58) +#define MISC_PCIE1_CTRL_REG MISC_MEM_MAP_VALUE(0xa5C) +#define MISC_PCIE1_PM_DEBUG_REG MISC_MEM_MAP_VALUE(0xa60) +#define MISC_PCIE1_RFC_DEBUG_REG MISC_MEM_MAP_VALUE(0xa64) +#define MISC_PCIE1_CXPL_DEBUGL_REG MISC_MEM_MAP_VALUE(0xa68) +#define MISC_PCIE1_CXPL_DEBUGH_REG MISC_MEM_MAP_VALUE(0xa6C) +#define MISC_PCIE1_DIAG_DEBUGH_REG MISC_MEM_MAP_VALUE(0xa70) +#define MISC_PCIE1_W1CLR_REG MISC_MEM_MAP_VALUE(0xa74) +#define MISC_PCIE1_INT_MASK_REG MISC_MEM_MAP_VALUE(0xa78) +#define MISC_PCIE1_INT_STATUS_REG MISC_MEM_MAP_VALUE(0xa7C) + + + + + + +/* + * define constants macros + */ +#define MISC_PARALLEL_FLASH_BOOT (0x0) +#define MISC_SPI_SERIAL_FLASH_BOOT (0x1) +#define MISC_NAND_FLASH_BOOT (0x2) + +#define MISC_ALIGN_LITTLE_ENDIAN (0x0) +#define MISC_UNALIGN_LITTLE_ENDIAN (0x2) +#define MISC_UNALIGN_BIG_ENDIAN (0x3) + +#define MISC_CPU_CLOCK_333_MHZ (0) +#define MISC_CPU_CLOCK_366_MHZ (1) +#define MISC_CPU_CLOCK_400_MHZ (2) +#define MISC_CPU_CLOCK_433_MHZ (3) +#define MISC_CPU_CLOCK_466_MHZ (4) +#define MISC_CPU_CLOCK_500_MHZ (5) +#define MISC_CPU_CLOCK_533_MHZ (6) +#define MISC_CPU_CLOCK_566_MHZ (7) +#define MISC_CPU_CLOCK_600_MHZ (8) +#define MISC_CPU_CLOCK_633_MHZ (9) +#define MISC_CPU_CLOCK_666_MHZ (10) +#define MISC_CPU_CLOCK_700_MHZ (11) + +/* + * Macro-defines for shared pins with GPIO_A + */ +#if 0 +#define MISC_LCD_PWR_PIN ((0x1 << 0)) +#define MISC_CIM_OE_PIN ((0x1 << 1)) + +#define MISC_SMC_PINS ((0x1 << 2) | (0x1 << 3) | (0x1 << 4) | (0x1 << 5)| (0x1 << 6)) +#define MISC_SMC_CS3_PIN ((0x1 << 2)) +#define MISC_SMC_CS2_PIN ((0x1 << 3)) +#define MISC_SMC_CLK_PIN ((0x1 << 4)) +#define MISC_SMC_ADV_PIN ((0x1 << 5)) +#define MISC_SMC_CRE_PIN ((0x1 << 6)) + + +#define MISC_NFI_PINS ((0x1 << 7) | (0x1 << 8) | (0x1 << 9) | (0x1 << 10)| (0x1 << 11)) +#define MISC_NFI_BUSY_PIN ((0x1 << 7)) +#define MISC_NFI_CS3_PIN ((0x1 << 8)) +#define MISC_NFI_CS2_PIN ((0x1 << 9)) +#define MISC_NFI_CE1_PIN ((0x1 << 10)) +#define MISC_NFI_CE0_PIN ((0x1 << 11)) + +#define MISC_EXT_INT2_PIN ((0x1 << 12)) +#define MISC_EXT_INT1_PIN ((0x1 << 13)) +#define MISC_EXT_INT0_PIN ((0x1 << 14)) + + +#define MISC_UART0_PINS ((0x1 << 15) | (0x1 << 16) | (0x1 << 17) | (0x1 << 18)) +#define MISC_UART0_RTS_PIN ((0x1 << 15)) +#define MISC_UART0_CTS_PIN ((0x1 << 16)) +#define MISC_UART0_TXD_PIN ((0x1 << 17)) +#define MISC_UART0_RXD_PIN ((0x1 << 18)) + +#define MISC_UART1_PINS ((0x1 << 19) | (0x1 << 20) | (0x1 << 21) | (0x1 << 22)) +#define MISC_UART1_RTS_PIN ((0x1 << 19)) +#define MISC_UART1_CTS_PIN ((0x1 << 20)) +#define MISC_UART1_RXD_PIN ((0x1 << 21)) +#define MISC_UART1_TXD_PIN ((0x1 << 22)) + +#define MISC_UART2_PINS ((0x1 << 23) | (0x1 << 24)) +#define MISC_UART2_RXD_PIN ((0x1 << 23)) +#define MISC_UART2_TXD_PIN ((0x1 << 24)) + +#define MISC_PCM_PINS ((0x1 << 25) | (0x1 << 26) | (0x1 << 27) | (0x1 << 28)) +#define MISC_PCM_CLK_PIN ((0x1 << 25)) +#define MISC_PCM_FS_PIN ((0x1 << 26)) +#define MISC_PCM_DT_PIN ((0x1 << 27)) +#define MISC_PCM_DR_PIN ((0x1 << 28)) + +#define MISC_SPI_CS1_PIN ((0x1 << 29)) +#define MISC_SPI_CS0_PIN ((0x1 << 30)) +#define MISC_SPI_CLK_PIN ((0x1 << 31)) +#else +#define MISC_SD_PWR_ON_PIN ((0x1 << 2)) +#define MISC_OTG_DRVVBUS_PIN ((0x1 << 3)) +#define MISC_CIM_OE_PIN ((0x1 << 8)) +#define MISC_LCD_PWR_PIN ((0x1 << 9)) +#define MISC_SMC_CS3_PIN ((0x1 << 10)) +#define MISC_SMC_CS2_PIN ((0x1 << 11)) +#define MISC_SMC_CLK_PIN ((0x1 << 12)) +#define MISC_SMC_ADV_PIN ((0x1 << 13)) +#define MISC_SMC_CRE_PIN ((0x1 << 14)) +#define MISC_SMC_ADDR_26_PIN ((0x1 << 15)) + +#define MISC_SD_nCD_PIN ((0x1 << 16)) +#define MISC_SD_nWP_PIN ((0x1 << 17)) +#define MISC_SD_CLK_PIN ((0x1 << 18)) +#define MISC_SD_CMD_PIN ((0x1 << 19)) +#define MISC_SD_DT7_PIN ((0x1 << 20)) +#define MISC_SD_DT6_PIN ((0x1 << 21)) +#define MISC_SD_DT5_PIN ((0x1 << 22)) +#define MISC_SD_DT4_PIN ((0x1 << 23)) +#define MISC_SD_DT3_PIN ((0x1 << 24)) +#define MISC_SD_DT2_PIN ((0x1 << 25)) +#define MISC_SD_DT1_PIN ((0x1 << 26)) +#define MISC_SD_DT0_PIN ((0x1 << 27)) +#define MISC_SD_LED_PIN ((0x1 << 28)) + +#define MISC_UR_RXD1_PIN ((0x1 << 29)) +#define MISC_UR_TXD1_PIN ((0x1 << 30)) +#define MISC_UR_RTS2_PIN ((0x1 << 31)) + +#endif + + +/* + * Macro-defines for shared pins with GPIO_B + */ +#if 0 +#define MISC_SPI_DT_PIN ((0x1 << 0)) +#define MISC_SPI_DR_PIN ((0x1 << 1)) + +#define MISC_SD_CD_PIN ((0x1 << 2)) +#define MISC_SD_WP_PIN ((0x1 << 3)) +#define MISC_SD_CLK_PIN ((0x1 << 4)) +#define MISC_SD_CMD_PIN ((0x1 << 5)) +#define MISC_SD_DT7_PIN ((0x1 << 6)) +#define MISC_SD_DT6_PIN ((0x1 << 7)) +#define MISC_SD_DT5_PIN ((0x1 << 8)) +#define MISC_SD_DT4_PIN ((0x1 << 9)) +#define MISC_SD_DT3_PIN ((0x1 << 10)) +#define MISC_SD_DT2_PIN ((0x1 << 11)) +#define MISC_SD_DT1_PIN ((0x1 << 12)) +#define MISC_SD_DT0_PIN ((0x1 << 13)) +#define MISC_SD_LED_PIN ((0x1 << 14)) + + +#define MISC_I2S_CLK_PIN ((0x1 << 15)) +#define MISC_I2S_FS_PIN ((0x1 << 16)) +#define MISC_I2S_DT_PIN ((0x1 << 17)) +#define MISC_I2S_DR_PIN ((0x1 << 18)) + +//Tim.Liao modify +#define MISC_I2C_SCL_PIN ((0x1 << 19)) +#define MISC_I2C_SDA_PIN ((0x1 << 20)) + +#define MISC_GSW_P2_CRS_PIN ((0x1 << 21)) +#define MISC_GSW_P2_COL_PIN ((0x1 << 22)) +#define MISC_GSW_P1_CRS_PIN ((0x1 << 23)) +#define MISC_GSW_P1_COL_PIN ((0x1 << 24)) +#define MISC_GSW_P0_CRS_PIN ((0x1 << 25)) +#define MISC_GSW_P0_COL_PIN ((0x1 << 26)) + +#define MISC_GSW_MDC_PIN ((0x1 << 27)) +#define MISC_GSW_MDIO_PIN ((0x1 << 28)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) +#else +#define MISC_UR_CTS2_PIN ((0x1 << 0)) +#define MISC_UR_RXD2_PIN ((0x1 << 1)) +#define MISC_UR_TXD2_PIN ((0x1 << 2)) +#define MISC_PCMCLK_PIN ((0x1 << 3)) +#define MISC_PCMFS_PIN ((0x1 << 4)) +#define MISC_PCMDT_PIN ((0x1 << 5)) +#define MISC_PCMDR_PIN ((0x1 << 6)) +#define MISC_PCM_PINS (MISC_PCMCLK_PIN|MISC_PCMFS_PIN|MISC_PCMDT_PIN|MISC_PCMDR_PIN) + +#define MISC_SPInCS1_PIN ((0x1 << 7)) +#define MISC_SPInCS0_PIN ((0x1 << 8)) +#define MISC_SPICLK_PIN ((0x1 << 9)) +#define MISC_SPIDT_PIN ((0x1 << 10)) +#define MISC_SPIDR_PIN ((0x1 << 11)) + +#define MISC_I2C_SCL_PIN ((0x1 << 12)) +#define MISC_I2C_SDA_PIN ((0x1 << 13)) + +#define MISC_GSW_P2_CRS_PIN ((0x1 << 14)) +#define MISC_GSW_P2_COL_PIN ((0x1 << 15)) +#define MISC_GSW_P1_CRS_PIN ((0x1 << 16)) +#define MISC_GSW_P1_COL_PIN ((0x1 << 17)) +#define MISC_GSW_P0_CRS_PIN ((0x1 << 18)) +#define MISC_GSW_P0_COL_PIN ((0x1 << 19)) + +#define MISC_GSW_MDC_PIN ((0x1 << 20)) +#define MISC_GSW_MDIO_PIN ((0x1 << 21)) + +#define MISC_I2S_CLK_PIN (0x1 << 22) +#define MISC_I2S_FS_PIN (0x1 << 23) +#define MISC_I2S_DT_PIN (0x1 << 24) +#define MISC_I2S_DR_PIN (0x1 << 25) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#define MISC_CLOCK_OUTPUT_PIN ((0x1 << 26)) + +#define MISC_EXT_INT2_PIN ((0x1 << 27)) +#define MISC_EXT_INT1_PIN ((0x1 << 28)) +#define MISC_EXT_INT0_PIN ((0x1 << 29)) + +#define MISC_SATA_LED1_PIN ((0x1 << 30)) +#define MISC_SATA_LED0_PIN ((0x1 << 31)) + +#endif +/* + * Other defines + */ +#define MISC_GPIOA_PIN_0 (0) +#define MISC_GPIOA_PIN_1 (1) +#define MISC_GPIOA_PIN_2 (2) +#define MISC_GPIOA_PIN_3 (3) +#define MISC_GPIOA_PIN_4 (4) +#define MISC_GPIOA_PIN_5 (5) +#define MISC_GPIOA_PIN_6 (6) +#define MISC_GPIOA_PIN_7 (7) +#define MISC_GPIOA_PIN_8 (8) +#define MISC_GPIOA_PIN_9 (9) +#define MISC_GPIOA_PIN_10 (10) +#define MISC_GPIOA_PIN_11 (11) +#define MISC_GPIOA_PIN_12 (12) +#define MISC_GPIOA_PIN_13 (13) +#define MISC_GPIOA_PIN_14 (14) +#define MISC_GPIOA_PIN_15 (15) + + +#define MISC_GPIOA_RESISTOR_PULL_DOWN (1) +#define MISC_GPIOA_RESISTOR_PULL_UP (1) + + + +/* + * function declarations + */ + + +/* + * macro declarations + */ +#define HAL_MISC_GET_SYSTEM_ALIGN_ENDIAN_MODE(mode) \ +{ \ + (mode) = (MISC_CHIP_CONFIG_REG) & 0x3; \ +} + + +#define HAL_MISC_GET_SYSTEM_CPU_CLOCK(cpu_clock) \ +{ \ + (cpu_clock) = (MISC_CHIP_CONFIG_REG >> 5) & 0xF; \ +} + + +#define HAL_MISC_ENABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \ +{ \ + (MISC_CHIP_CONFIG_REG) |= (0x1 << 16); \ +} + +#define HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \ +{ \ + (MISC_CHIP_CONFIG_REG) &= ~(0x1 << 16); \ +} + + +/* + * Macro defines for GPIOA and GPIOB Pin Enable Register + */ +#define HAL_MISC_ENABLE_EXT_INT0_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_EXT_INT0_PIN); \ +} + +#define HAL_MISC_DISABLE_EXT_INT1_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_EXT_INT1_PIN); \ +} + +#define HAL_MISC_ENABLE_EXT_INT2_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_EXT_INT2_PIN); \ +} + +#define HAL_MISC_DISABLE_EXT_INT2_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_EXT_INT2_PIN); \ +} + +#define HAL_MISC_ENABLE_EXT_INT1_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_EXT_INT1_PIN); \ +} + +#define HAL_MISC_DISABLE_EXT_INT0_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_EXT_INT0_PIN); \ +} + + +#define HAL_MISC_ENABLE_PCM_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_PCM_PINS); \ +} + +#define HAL_MISC_DISABLE_PCM_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_PCM_PINS); \ +} + + +#define HAL_MISC_ENABLE_CIM_OE_PIN() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_CIM_OE_PIN); \ +} + +#define HAL_MISC_DISABLE_CIM_OE_PIN() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_CIM_OE_PIN); \ +} + + +#define HAL_MISC_ENABLE_LCD_PWR_PIN() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LCD_PWR_PIN); \ +} + +#define HAL_MISC_DISABLE_LCD_PWR_PIN() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LCD_PWR_PIN); \ +} + + +#define HAL_MISC_ENABLE_NFI_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_NFI_PINS); \ +} + +#define HAL_MISC_DISABLE_NFI_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_NFI_PINS); \ +} + + + +#define HAL_MISC_ENABLE_SMC_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_SMC_PINS); \ +} + +#define HAL_MISC_DISABLE_SMC_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_SMC_PINS); \ +} + +#define HAL_MISC_ENABLE_UART0_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART0_PINS); \ +} + +#define HAL_MISC_DISABLE_UART0_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART0_PINS); \ +} + +#define HAL_MISC_ENABLE_UART1_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART1_PINS); \ +} + +#define HAL_MISC_DISABLE_UART1_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART1_PINS); \ +} + +#define HAL_MISC_ENABLE_UART2_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART2_PINS); \ +} + +#define HAL_MISC_DISABLE_UART2_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART2_PINS); \ +} + + + + + +/* + * Macro-defines for GPIO_B + */ +#define HAL_MISC_ENABLE_SPI_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= \ + (MISC_SPInCS1_PIN | MISC_SPInCS0_PIN | \ + MISC_SPICLK_PIN | MISC_SPIDT_PIN | MISC_SPIDR_PIN); \ +} + +#define HAL_MISC_DISABLE_SPI_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= \ + ~(MISC_SPInCS1_PIN | MISC_SPInCS0_PIN | \ + MISC_SPICLK_PIN | MISC_SPIDT_PIN | MISC_SPIDR_PIN); \ +} + +#define HAL_MISC_ENABLE_SD_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SD_CD_PIN | MISC_SD_WP_PIN | MISC_SD_CLK_PIN |MISC_SD_CMD_PIN |MISC_SD_DT7_PIN|MISC_SD_DT6_PIN | \ + MISC_SD_DT5_PIN | MISC_SD_DT4_PIN |MISC_SD_DT3_PIN | MISC_SD_DT2_PIN| MISC_SD_DT1_PIN | MISC_SD_DT0_PIN | MISC_SD_LED_PIN); \ +} + +#define HAL_MISC_DISABLE_SD_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SD_CD_PIN | MISC_SD_WP_PIN | MISC_SD_CLK_PIN |MISC_SD_CMD_PIN |MISC_SD_DT7_PIN|MISC_SD_DT6_PIN |\ + MISC_SD_DT5_PIN | MISC_SD_DT4_PIN |MISC_SD_DT3_PIN | MISC_SD_DT2_PIN| MISC_SD_DT1_PIN | MISC_SD_DT0_PIN | MISC_SD_LED_PIN); \ +} + + +#define HAL_MISC_ENABLE_I2S_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_I2S_CLK_PIN | MISC_I2S_FS_PIN | MISC_I2S_DT_PIN |MISC_I2S_DR_PIN |MISC_I2S_DR_PIN); \ +} + +#define HAL_MISC_DISABLE_I2S_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_I2S_CLK_PIN | MISC_I2S_FS_PIN | MISC_I2S_DT_PIN |MISC_I2S_DR_PIN |MISC_I2S_DR_PIN); \ +} + +//Tim.Liao modify I2C pin +#define HAL_MISC_ENABLE_I2C_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_I2C_SCL_PIN | MISC_I2C_SDA_PIN); \ +} + +#define HAL_MISC_DISABLE_I2C_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_I2C_SCL_PIN | MISC_I2C_SDA_PIN); \ +} + +#define HAL_MISC_ENABLE_GSW_P2_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_GSW_P2_CRS_PIN | MISC_GSW_P2_COL_PIN); \ +} + +#define HAL_MISC_DISABLE_GSW_P2_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_GSW_P2_CRS_PIN | MISC_GSW_P2_COL_PIN); \ +} + + +#define HAL_MISC_ENABLE_GSW_P1_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_GSW_P1_CRS_PIN | MISC_GSW_P1_COL_PIN); \ +} + +#define HAL_MISC_DISABLE_GSW_P1_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_GSW_P1_CRS_PIN | MISC_GSW_P1_COL_PIN); \ +} + + + +#define HAL_MISC_ENABLE_GSW_P0_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_GSW_P0_CRS_PIN | MISC_GSW_P0_COL_PIN); \ +} + +#define HAL_MISC_DISABLE_GSW_P0_CRS_COL_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_GSW_P0_CRS_PIN | MISC_GSW_P0_COL_PIN); \ +} + + +#define HAL_MISC_ENABLE_MDC_MDIO_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_GSW_MDC_PIN | MISC_GSW_MDIO_PIN); \ +} + +#define HAL_MISC_DISABLE_MDC_MDIO_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_GSW_MDC_PIN | MISC_GSW_MDIO_PIN); \ +} + + + +#define HAL_MISC_ENABLE_SATA_LED_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SATA_LED1_PIN | MISC_SATA_LED0_PIN); \ +} + +#define HAL_MISC_DISABLE_SATA_LED_PINS() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SATA_LED1_PIN | MISC_SATA_LED0_PIN); \ +} + + + +#define HAL_MISC_ENABLE_CLOCK_OUTPUT_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_CLOCK_OUTPUT_PIN); \ +} + +#define HAL_MISC_DISABLE_CLOCK_OUTPUT_PIN() \ +{ \ + (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_CLOCK_OUTPUT_PIN); \ +} + + +#define HAL_MISC_ENABLE_ALL_SHARED_GPIO_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) = (0x0); \ + (MISC_GPIOB_PIN_ENABLE_REG) = (0x0); \ +} + +#define HAL_MISC_DISABLE_ALL_SHARED_GPIO_PINS() \ +{ \ + (MISC_GPIOA_PIN_ENABLE_REG) = (0xFFFFFFFF); \ + (MISC_GPIOB_PIN_ENABLE_REG) = (0xFFFFFFFF); \ +} + + + +#endif // end of #ifndef _STAR_MISC_H_ --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/pcie.h @@ -0,0 +1,149 @@ +/******************************************************************************* + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + * + ******************************************************************************/ + +#ifndef _CNS3XXX_PCIE_H_ +#define _CNS3XXX_PCIE_H_ + +#include "mach/board.h" + +#define PCIE0_IO_SPACE_START (CNS3XXX_PCIE0_IO_BASE) +#define PCIE0_IO_SPACE_SIZE 0x01000000 /* 16MB */ +#define PCIE0_IO_SPACE_END (CNS3XXX_PCIE0_IO_BASE + PCIE0_IO_SPACE_SIZE - 1) + +#define PCIE0_MEM_SPACE_START (CNS3XXX_PCIE0_MEM_BASE) +#define PCIE0_MEM_SPACE_SIZE 0x01000000 /* 176MB */ +#define PCIE0_MEM_SPACE_END (CNS3XXX_PCIE0_MEM_BASE + PCIE0_MEM_SPACE_SIZE - 1) + +#define PCIE1_IO_SPACE_START (CNS3XXX_PCIE1_IO_BASE) +#define PCIE1_IO_SPACE_SIZE 0x01000000 /* 16MB */ +#define PCIE1_IO_SPACE_END (CNS3XXX_PCIE1_IO_BASE + PCIE1_IO_SPACE_SIZE - 1) + +#define PCIE1_MEM_SPACE_START (CNS3XXX_PCIE1_MEM_BASE) +#define PCIE1_MEM_SPACE_SIZE 0x01000000 /* 16MB */ +#define PCIE1_MEM_SPACE_END (CNS3XXX_PCIE1_MEM_BASE + PCIE1_MEM_SPACE_SIZE - 1) + +#define PCIB_MEM_MAP_VALUE(base, reg_offset) (*((u32 volatile *)(SYSVA_PCI_BRIDGE_##base##_ADDR + reg_offset))) + +/* + * define access macros + */ +#define PCI_BRIDGE_CONFIG_DATA PCIB_MEM_MAP_VALUE(CONFIG_DATA_BASE, 0x2C) +#define PCI_BRIDGE_CONFIG_ADDR PCIB_MEM_MAP_VALUE(CONFIG_ADDR_BASE, 0x28) + +#define PCI_BRIDGE_CONFIG_DATA_REG_OFFSET 0x2C +#define PCI_BRIDGE_CONFIG_ADDR_REG_OFFSET 0x28 + + +/* PCIe MISC 0 Register */ +#define CNS3XXX_PCIEPHY0_CMCTL0 (CNS3XXX_MISC_BASE_VIRT + 0x900) +#define CNS3XXX_PCIEPHY0_CMCTL1 (CNS3XXX_MISC_BASE_VIRT + 0x904) +#define CNS3XXX_PCIEPHY0_CTL1 (CNS3XXX_MISC_BASE_VIRT + 0x940) +#define CNS3XXX_PCIE0_AXIS_AWMISC (CNS3XXX_MISC_BASE_VIRT + 0x944) +#define CNS3XXX_PCIE0_AXIS_ARMISC (CNS3XXX_MISC_BASE_VIRT + 0x948) +#define CNS3XXX_PCIE0_AXIS_RMISC (CNS3XXX_MISC_BASE_VIRT + 0x94C) +#define CNS3XXX_PCIE0_AXIS_BMISC (CNS3XXX_MISC_BASE_VIRT + 0x950) +#define CNS3XXX_PCIE0_AXIM_RMISC (CNS3XXX_MISC_BASE_VIRT + 0x954) +#define CNS3XXX_PCIE0_AXIM_BMISC (CNS3XXX_MISC_BASE_VIRT + 0x958) +#define CNS3XXX_PCIE0_CTRL (CNS3XXX_MISC_BASE_VIRT + 0x95C) +#define CNS3XXX_PCIE0_PM_DEBUG (CNS3XXX_MISC_BASE_VIRT + 0x960) +#define CNS3XXX_PCIE0_RFC_DEBUG (CNS3XXX_MISC_BASE_VIRT + 0x964) +#define CNS3XXX_PCIE0_CXPL_DEBUGL (CNS3XXX_MISC_BASE_VIRT + 0x968) +#define CNS3XXX_PCIE0_CXPL_DEBUGH (CNS3XXX_MISC_BASE_VIRT + 0x96C) +#define CNS3XXX_PCIE0_DIAG (CNS3XXX_MISC_BASE_VIRT + 0x970) +#define CNS3XXX_PCIE0_INT_STATUS (CNS3XXX_MISC_BASE_VIRT + 0x974) +#define CNS3XXX_PCIE0_INT_MASK (CNS3XXX_MISC_BASE_VIRT + 0x978) + + +/* PCIe MISC 1 Register */ +#define CNS3XXX_PCIEPHY1_CMCTL0 (CNS3XXX_MISC_BASE_VIRT + 0xA00) +#define CNS3XXX_PCIEPHY1_CMCTL1 (CNS3XXX_MISC_BASE_VIRT + 0xA04) +#define CNS3XXX_PCIEPHY1_CTL1 (CNS3XXX_MISC_BASE_VIRT + 0xA40) +#define CNS3XXX_PCIE1_AXIS_AWMISC (CNS3XXX_MISC_BASE_VIRT + 0xA44) +#define CNS3XXX_PCIE1_AXIS_ARMISC (CNS3XXX_MISC_BASE_VIRT + 0xA48) +#define CNS3XXX_PCIE1_AXIS_RMISC (CNS3XXX_MISC_BASE_VIRT + 0xA4C) +#define CNS3XXX_PCIE1_AXIS_BMISC (CNS3XXX_MISC_BASE_VIRT + 0xA50) +#define CNS3XXX_PCIE1_AXIM_RMISC (CNS3XXX_MISC_BASE_VIRT + 0xA54) +#define CNS3XXX_PCIE1_AXIM_BMISC (CNS3XXX_MISC_BASE_VIRT + 0x958) +#define CNS3XXX_PCIE1_CTRL (CNS3XXX_MISC_BASE_VIRT + 0xA5C) +#define CNS3XXX_PCIE1_PM_DEBUG (CNS3XXX_MISC_BASE_VIRT + 0xA60) +#define CNS3XXX_PCIE1_RFC_DEBUG (CNS3XXX_MISC_BASE_VIRT + 0xA64) +#define CNS3XXX_PCIE1_CXPL_DEBUGL (CNS3XXX_MISC_BASE_VIRT + 0xA68) +#define CNS3XXX_PCIE1_CXPL_DEBUGH (CNS3XXX_MISC_BASE_VIRT + 0xA6C) +#define CNS3XXX_PCIE1_DIAG (CNS3XXX_MISC_BASE_VIRT + 0xA70) +#define CNS3XXX_PCIE1_INT_STATUS (CNS3XXX_MISC_BASE_VIRT + 0xA74) +#define CNS3XXX_PCIE1_INT_MASK (CNS3XXX_MISC_BASE_VIRT + 0xA78) + + +/* + * define constants macros + */ + +#define PCIB_DEVICE_ID 0x3400 +#define PCIB_VENDOR_ID 0x177D +#define PCIB_CLASS_CODE 0xFF0000 +#define PCIB_REVISION_ID 0x00 +#define PCIB_BAR0_MEMORY_SPACE_BASE 0x20000000 +#define PCIB_BAR1_IO_SPACE_BASE 0x20000000 +#define PCI_MEMORY_SPACE_BASE 0xB0000000 +#define PCI_IO_SPACE_BASE 0xA8000000 +#define PCI_MAX_BUS_NUM 0x01 +#define PCI_MAX_DEVICE_NUM 0x14 +#define PCI_MAX_FUNCTION_NUM 0x01 +#define PCI_MAX_REG_NUM 0x3C + +#define PCI_MAX_DEVICE_TYPE_NUM 0x13 +#define PCI_MAX_BAR_NUM 0x06 + +#define PCI_CSH_VENDOR_ID_REG_ADDR 0x00 +#define PCI_CSH_DEVICE_ID_REG_ADDR 0x02 +#define PCI_CSH_COMMAND_REG_ADDR 0x04 +#define PCI_CSH_STATUS_REG_ADDR 0x06 +#define PCI_CSH_REVISION_CLASS_REG_ADDR 0x08 +#define PCI_CSH_CACHE_LINE_SIZE_REG_ADDR 0x0C +#define PCI_CSH_LATENCY_TIMER_REG_ADDR 0x0D +#define PCI_CSH_HEADER_TYPE_REG_ADDR 0x0E +#define PCI_CSH_BIST_REG_ADDR 0x0F +#define PCI_CSH_BAR_REG_ADDR 0x10 + + +#define PCI_IO_SPACE_SIZE_1M 0x00 +#define PCI_IO_SPACE_SIZE_2M 0x01 +#define PCI_IO_SPACE_SIZE_4M 0x02 +#define PCI_IO_SPACE_SIZE_8M 0x03 +#define PCI_IO_SPACE_SIZE_16M 0x04 +#define PCI_IO_SPACE_SIZE_32M 0x05 +#define PCI_IO_SPACE_SIZE_64M 0x06 +#define PCI_IO_SPACE_SIZE_128M 0x07 +#define PCI_IO_SPACE_SIZE_256M 0x08 +#define PCI_IO_SPACE_SIZE_512M 0x09 +#define PCI_IO_SPACE_SIZE_1G 0x0A +#define PCI_IO_SPACE_SIZE_2G 0x0B + + +struct pcie_dbgfs_reg{ + char *name; + u32 *addr; +}; + +#endif /* end of #ifndef _STAR_PCIE_H_ */ + --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/pcm.h @@ -0,0 +1,277 @@ +/****************************************************************************** + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + * + ******************************************************************************/ + +#ifndef _STAR_PCM_H_ +#define _STAR_PCM_H_ + +/****************************************************************************** + * MODULE NAME: star_pcm.h + * PROJECT CODE: Orion + * DESCRIPTION: + * MAINTAINER: MJLIU + * DATE: 15 September 2005 + * + * SOURCE CONTROL: + * + * LICENSE: + * This source code is copyright (c) 2005 Star Semi Inc. + * All rights reserved. + * + * REVISION HISTORY: + * 15 September 2005 - MJLIU - Initial Version v1.0 + * + * + * SOURCE: + * ISSUES: + * NOTES TO USERS: + ******************************************************************************/ + +//#include + +#define PCM_BASE_ADDR (CNS3XXX_SSP_BASE_VIRT) +#define PCM_MEM_MAP_ADDR(reg_offset) (PCM_BASE_ADDR + reg_offset) +#define PCM_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)PCM_MEM_MAP_ADDR(reg_offset))) + + +/* + * define access macros + */ +#define PCM_CONFIGURATION_0_REG PCM_MEM_MAP_VALUE(0x80) +#define PCM_CONFIGURATION_1_REG PCM_MEM_MAP_VALUE(0x84) + +#define PCM_CHANNEL_0_CONFIG_REG PCM_MEM_MAP_VALUE(0x88) +#define PCM_CHANNEL_1_CONFIG_REG PCM_MEM_MAP_VALUE(0x8C) +#define PCM_CHANNEL_2_CONFIG_REG PCM_MEM_MAP_VALUE(0x90) +#define PCM_CHANNEL_3_CONFIG_REG PCM_MEM_MAP_VALUE(0x94) + +#define PCM_TX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0x98) +#define PCM_TX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0x9C) + +#define PCM_RX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0xA0) +#define PCM_RX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0xA4) + +#define PCM_INTERRUPT_STATUS_REG PCM_MEM_MAP_VALUE(0xA8) +#define PCM_INTERRUPT_ENABLE_REG PCM_MEM_MAP_VALUE(0xAC) + + + +/* + * define constants macros + */ +#define CH0_BIT_INDEX (0x1) +#define CH1_BIT_INDEX (0x2) +#define CH2_BIT_INDEX (0x4) +#define CH3_BIT_INDEX (0x8) + +#define PCM_RXBUF_FULL_FG (0x1) +#define PCM_TXBUF_EMPTY_FG (0x2) +#define PCM_RXBUF_OVERRUN_FG (0x4) +#define PCM_TXBUF_UNDERRUN_FG (0x8) + +#define PCM_ENABLE_FG (0x1 << 23) + +#define PCM_IDL_MODE (0) +#define PCM_GCI_MODE (1) + +#define PCM_DATA_BIT_8 (0) +#define PCM_DATA_BIT_16 (1) + + +/* + * Set Commands Variables + */ +#define Software_Reset (0x02) +#define Hardware_Reset (0x04) +#define Write_Transmit_Time_Slot (0x40) +#define Read_Transmit_Time_Slot (0x41) +#define Write_Receive_Time_Slot (0x42) +#define Read_Receive_Time_Slot (0x43) +#define Write_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x44) +#define Read_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x45) +#define Write_Device_Configure_Reg (0x46) +#define Read_Device_Configure_Reg (0x47) +#define Write_Channel_Enable_Operating_Mode_Reg (0x4A) +#define Read_Channel_Enable_Operating_Mode_Reg (0x4B) +#define Read_Signal_Reg (0x4D) +#define Input_Data_Reg (0x52) +#define Output_Data_Reg (0x53) +#define Input_Direction_Reg (0x54) +#define Output_Direction_Reg (0x55) +#define Write_System_State (0x56) +#define Read_System_State (0x57) +#define Write_Operating_Functon (0x60) +#define Read_Operating_Functon (0x61) +#define Write_System_State_Config (0x68) +#define Read_System_State_Config (0x69) +#define Write_Interrupt_Mask_Reg (0x6C) +#define Read_Interrupt_Mask_Reg (0x6D) +#define Write_Operating_Condition (0x70) +#define Write_Loop_Supervision_Parameter (0xC2) +#define Write_DC_Feed_Parameter (0xC6) +#define Write_Signal_A_B_Parameter (0xD2) +#define Write_Switching_Reg_Parameter (0xE4) +#define Write_Switching_Reg_Control (0xE6) + + +/* + * define data structure + */ +typedef struct _PCM_CHANNEL_OBJECT_ PCM_CHANNEL_OBJECT_T; + +struct _PCM_CHANNEL_OBJECT_ +{ + u16 channel_0_tx_data; + u16 channel_0_rx_data; + u32 channel_0_data_width; /* 0 : 8-bit, 1 : 16-bit */ + + u16 channel_1_tx_data; + u16 channel_1_rx_data; + u32 channel_1_data_width; + + u16 channel_2_tx_data; + u16 channel_2_rx_data; + u32 channel_2_data_width; + + u16 channel_3_tx_data; + u16 channel_3_rx_data; + u32 channel_3_data_width; + + u32 channel_enable_config; /* bit[0] = 0 : channel 0 disabled + [0] = 1 : channel 0 enabled + bit[1] = 0 : channel 1 disabled + [1] = 1 : channel 1 enabled + bit[2] = 0 : channel 2 disabled + [2] = 1 : channel 2 enabled + bit[3] = 0 : channel 3 disabled + [3] = 1 : channel 3 enabled */ +}; + + +typedef struct _PCM_OBJECT_ PCM_OBJECT_T; + +struct _PCM_OBJECT_ +{ + u32 config_0; + u32 config_1; + + u32 channel_0_config; + u32 channel_1_config; + u32 channel_2_config; + u32 channel_3_config; + + u32 interrupt_config; + + /* + * For interrupt setting + */ +// INTC_OBJECT_T intc_obj; +}; + + + +/* + * function declarations + */ +void Hal_Pcm_Initialize(PCM_OBJECT_T *); + + +/* + * macro declarations + */ +#define HAL_PCM_ENABLE_PCM() \ +{ \ + (PCM_CONFIGURATION_0_REG) |= ((u32)0x1 << 31); \ +} + +#define HAL_PCM_DISABLE_PCM() \ +{ \ + (PCM_CONFIGURATION_0_REG) &= ~((u32)0x1 << 31); \ +} + +#define HAL_PCM_ENABLE_DATA_SWAP() \ +{ \ + (PCM_CONFIGURATION_0_REG) |= (0x1 << 24); \ +} + +#define HAL_PCM_DISABLE_DATA_SWAP() \ +{ \ + (PCM_CONFIGURATION_0_REG) &= ~(0x1 << 24); \ +} + +#define HAL_PCM_WRITE_TX_DATA_0(tx_data_0) \ +{ \ + (PCM_TX_DATA_31_0_REG) = tx_data_0; \ +} + +#define HAL_PCM_WRITE_TX_DATA_1(tx_data_1) \ +{ \ + (PCM_TX_DATA_63_32_REG) = tx_data_1; \ +} + +#define HAL_PCM_READ_RX_DATA_0(rx_data_0) \ +{ \ + (rx_data_0) = PCM_RX_DATA_31_0_REG; \ +} + +#define HAL_PCM_READ_RX_DATA_1(rx_data_1) \ +{ \ + (rx_data_1) = PCM_RX_DATA_63_32_REG; \ +} + +#define HAL_PCM_READ_INTERRUPT_STATUS(status) \ +{ \ + (status) = PCM_INTERRUPT_STATUS_REG; \ +} + +#define HAL_PCM_CLEAR_INTERRUPT_STATUS(status) \ +{ \ + (PCM_INTERRUPT_STATUS_REG) = (status & 0xC); \ +} + +#define HAL_PCM_DISABLE_RECEIVE_BUFFER_FULL_INTERRUPT() \ +{ \ + (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \ +} + +#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_EMPTY_INTERRUPT() \ +{ \ + (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \ +} + +#define HAL_PCM_DISABLE_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \ +{ \ + (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 2); \ +} + +#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \ +{ \ + (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 3); \ +} + +#define HAL_PCM_DISABLE_ALL_INTERRUPT_SOURCES() \ +{ \ + (PCM_INTERRUPT_ENABLE_REG) = 0; \ +} + +#endif // end of #ifndef _STAR_PCM_H_ + --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/platform.h @@ -0,0 +1,297 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/platform.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (c) ARM Limited 2003. All rights reserved. + * + * 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 + */ + +#ifndef __ASM_ARCH_PLATFORM_H +#define __ASM_ARCH_PLATFORM_H + +#ifndef __ASSEMBLY__ + +#include + +/* + * SDRAM + */ +#define CNS3XXX_SDRAM_BASE 0x00000000 + +/* ------------------------------------------------------------------------ + * Cavium Networks Registers + * ------------------------------------------------------------------------ + * + */ +#define CNS3XXX_SYS_ID_OFFSET 0x00 +#define CNS3XXX_SYS_SW_OFFSET 0x04 +#define CNS3XXX_SYS_LED_OFFSET 0x08 +#define CNS3XXX_SYS_OSC0_OFFSET 0x0C + +#define CNS3XXX_SYS_OSC1_OFFSET 0x10 +#define CNS3XXX_SYS_OSC2_OFFSET 0x14 +#define CNS3XXX_SYS_OSC3_OFFSET 0x18 +#define CNS3XXX_SYS_OSC4_OFFSET 0x1C /* OSC1 for Cavium Networks/AB */ + +#define CNS3XXX_SYS_LOCK_OFFSET 0x20 +#define CNS3XXX_SYS_100HZ_OFFSET 0x24 +#define CNS3XXX_SYS_CFGDATA1_OFFSET 0x28 +#define CNS3XXX_SYS_CFGDATA2_OFFSET 0x2C +#define CNS3XXX_SYS_FLAGS_OFFSET 0x30 +#define CNS3XXX_SYS_FLAGSSET_OFFSET 0x30 +#define CNS3XXX_SYS_FLAGSCLR_OFFSET 0x34 +#define CNS3XXX_SYS_NVFLAGS_OFFSET 0x38 +#define CNS3XXX_SYS_NVFLAGSSET_OFFSET 0x38 +#define CNS3XXX_SYS_NVFLAGSCLR_OFFSET 0x3C +#define CNS3XXX_SYS_RESETCTL_OFFSET 0x40 +#define CNS3XXX_SYS_PCICTL_OFFSET 0x44 +#define CNS3XXX_SYS_MCI_OFFSET 0x48 +#define CNS3XXX_SYS_FLASH_OFFSET 0x4C +#define CNS3XXX_SYS_CLCD_OFFSET 0x50 +#define CNS3XXX_SYS_CLCDSER_OFFSET 0x54 +#define CNS3XXX_SYS_BOOTCS_OFFSET 0x58 +#define CNS3XXX_SYS_24MHz_OFFSET 0x5C +#define CNS3XXX_SYS_MISC_OFFSET 0x60 +#define CNS3XXX_SYS_IOSEL_OFFSET 0x70 +#define CNS3XXX_SYS_PROCID_OFFSET 0x84 +#define CNS3XXX_SYS_TEST_OSC0_OFFSET 0xC0 +#define CNS3XXX_SYS_TEST_OSC1_OFFSET 0xC4 +#define CNS3XXX_SYS_TEST_OSC2_OFFSET 0xC8 +#define CNS3XXX_SYS_TEST_OSC3_OFFSET 0xCC +#define CNS3XXX_SYS_TEST_OSC4_OFFSET 0xD0 + +#define CNS3XXX_SYS_BASE 0x10000000 +#define CNS3XXX_SYS_ID (CNS3XXX_SYS_BASE + CNS3XXX_SYS_ID_OFFSET) +#define CNS3XXX_SYS_SW (CNS3XXX_SYS_BASE + CNS3XXX_SYS_SW_OFFSET) +#define CNS3XXX_SYS_LED (CNS3XXX_SYS_BASE + CNS3XXX_SYS_LED_OFFSET) +#define CNS3XXX_SYS_OSC0 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_OSC0_OFFSET) +#define CNS3XXX_SYS_OSC1 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_OSC1_OFFSET) + +#define CNS3XXX_SYS_LOCK (CNS3XXX_SYS_BASE + CNS3XXX_SYS_LOCK_OFFSET) +#define CNS3XXX_SYS_100HZ (CNS3XXX_SYS_BASE + CNS3XXX_SYS_100HZ_OFFSET) +#define CNS3XXX_SYS_CFGDATA1 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_CFGDATA1_OFFSET) +#define CNS3XXX_SYS_CFGDATA2 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_CFGDATA2_OFFSET) +#define CNS3XXX_SYS_FLAGS (CNS3XXX_SYS_BASE + CNS3XXX_SYS_FLAGS_OFFSET) +#define CNS3XXX_SYS_FLAGSSET (CNS3XXX_SYS_BASE + CNS3XXX_SYS_FLAGSSET_OFFSET) +#define CNS3XXX_SYS_FLAGSCLR (CNS3XXX_SYS_BASE + CNS3XXX_SYS_FLAGSCLR_OFFSET) +#define CNS3XXX_SYS_NVFLAGS (CNS3XXX_SYS_BASE + CNS3XXX_SYS_NVFLAGS_OFFSET) +#define CNS3XXX_SYS_NVFLAGSSET (CNS3XXX_SYS_BASE + CNS3XXX_SYS_NVFLAGSSET_OFFSET) +#define CNS3XXX_SYS_NVFLAGSCLR (CNS3XXX_SYS_BASE + CNS3XXX_SYS_NVFLAGSCLR_OFFSET) +#define CNS3XXX_SYS_RESETCTL (CNS3XXX_SYS_BASE + CNS3XXX_SYS_RESETCTL_OFFSET) +#define CNS3XXX_SYS_PCICTL (CNS3XXX_SYS_BASE + CNS3XXX_SYS_PCICTL_OFFSET) +#define CNS3XXX_SYS_MCI (CNS3XXX_SYS_BASE + CNS3XXX_SYS_MCI_OFFSET) +#define CNS3XXX_SYS_FLASH (CNS3XXX_SYS_BASE + CNS3XXX_SYS_FLASH_OFFSET) +#define CNS3XXX_SYS_CLCD (CNS3XXX_SYS_BASE + CNS3XXX_SYS_CLCD_OFFSET) +#define CNS3XXX_SYS_CLCDSER (CNS3XXX_SYS_BASE + CNS3XXX_SYS_CLCDSER_OFFSET) +#define CNS3XXX_SYS_BOOTCS (CNS3XXX_SYS_BASE + CNS3XXX_SYS_BOOTCS_OFFSET) +#define CNS3XXX_SYS_24MHz (CNS3XXX_SYS_BASE + CNS3XXX_SYS_24MHz_OFFSET) +#define CNS3XXX_SYS_MISC (CNS3XXX_SYS_BASE + CNS3XXX_SYS_MISC_OFFSET) +#define CNS3XXX_SYS_IOSEL (CNS3XXX_SYS_BASE + CNS3XXX_SYS_IOSEL_OFFSET) +#define CNS3XXX_SYS_PROCID (CNS3XXX_SYS_BASE + CNS3XXX_SYS_PROCID_OFFSET) +#define CNS3XXX_SYS_TEST_OSC0 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_TEST_OSC0_OFFSET) +#define CNS3XXX_SYS_TEST_OSC1 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_TEST_OSC1_OFFSET) +#define CNS3XXX_SYS_TEST_OSC2 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_TEST_OSC2_OFFSET) +#define CNS3XXX_SYS_TEST_OSC3 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_TEST_OSC3_OFFSET) +#define CNS3XXX_SYS_TEST_OSC4 (CNS3XXX_SYS_BASE + CNS3XXX_SYS_TEST_OSC4_OFFSET) + +/* + * Values for CNS3XXX_SYS_RESET_CTRL + */ +#define CNS3XXX_SYS_CTRL_RESET_CONFIGCLR 0x01 +#define CNS3XXX_SYS_CTRL_RESET_CONFIGINIT 0x02 +#define CNS3XXX_SYS_CTRL_RESET_DLLRESET 0x03 +#define CNS3XXX_SYS_CTRL_RESET_PLLRESET 0x04 +#define CNS3XXX_SYS_CTRL_RESET_POR 0x05 +#define CNS3XXX_SYS_CTRL_RESET_DoC 0x06 + +#define CNS3XXX_SYS_CTRL_LED (1 << 0) + + +/* ------------------------------------------------------------------------ + * Cavium Networks control registers + * ------------------------------------------------------------------------ + */ + +/* + * CNS3XXX_IDFIELD + * + * 31:24 = manufacturer (0x41 = ARM) + * 23:16 = architecture (0x08 = AHB system bus, ASB processor bus) + * 15:12 = FPGA (0x3 = XVC600 or XVC600E) + * 11:4 = build value + * 3:0 = revision number (0x1 = rev B (AHB)) + */ + +/* + * CNS3XXX_SYS_LOCK + * control access to SYS_OSCx, SYS_CFGDATAx, SYS_RESETCTL, + * SYS_CLD, SYS_BOOTCS + */ +#define CNS3XXX_SYS_LOCK_LOCKED (1 << 16) +#define CNS3XXX_SYS_LOCKVAL_MASK 0xFFFF /* write 0xA05F to enable write access */ + +/* + * CNS3XXX_SYS_FLASH + */ +#define CNS3XXX_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */ + +/* + * CNS3XXX_INTREG + * - used to acknowledge and control MMCI and UART interrupts + */ +#define CNS3XXX_INTREG_WPROT 0x00 /* MMC protection status (no interrupt generated) */ +#define CNS3XXX_INTREG_RI0 0x01 /* Ring indicator UART0 is asserted, */ +#define CNS3XXX_INTREG_CARDIN 0x08 /* MMCI card in detect */ + /* write 1 to acknowledge and clear */ +#define CNS3XXX_INTREG_RI1 0x02 /* Ring indicator UART1 is asserted, */ +#define CNS3XXX_INTREG_CARDINSERT 0x03 /* Signal insertion of MMC card */ + +/* + * Cavium Networks common peripheral addresses + */ +#define CNS3XXX_SCTL_BASE 0x10001000 /* System controller */ + +/* PCI space */ +#define CNS3XXX_PCI_BASE 0x41000000 /* PCI Interface */ +#define CNS3XXX_PCI_CFG_BASE 0x42000000 +#define CNS3XXX_PCI_MEM_BASE0 0x44000000 +#define CNS3XXX_PCI_MEM_BASE1 0x50000000 +#define CNS3XXX_PCI_MEM_BASE2 0x60000000 +/* Sizes of above maps */ +#define CNS3XXX_PCI_BASE_SIZE 0x01000000 +#define CNS3XXX_PCI_CFG_BASE_SIZE 0x02000000 +#define CNS3XXX_PCI_MEM_BASE0_SIZE 0x0c000000 /* 32Mb */ +#define CNS3XXX_PCI_MEM_BASE1_SIZE 0x10000000 /* 256Mb */ +#define CNS3XXX_PCI_MEM_BASE2_SIZE 0x10000000 /* 256Mb */ + +#define CNS3XXX_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */ +#define CNS3XXX_LT_BASE 0x80000000 /* Logic Tile expansion */ + +/* + * LED settings, bits [7:0] + */ +#define CNS3XXX_SYS_LED0 (1 << 0) +#define CNS3XXX_SYS_LED1 (1 << 1) +#define CNS3XXX_SYS_LED2 (1 << 2) +#define CNS3XXX_SYS_LED3 (1 << 3) +#define CNS3XXX_SYS_LED4 (1 << 4) +#define CNS3XXX_SYS_LED5 (1 << 5) +#define CNS3XXX_SYS_LED6 (1 << 6) +#define CNS3XXX_SYS_LED7 (1 << 7) + +#define ALL_LEDS 0xFF + +#define LED_BANK CNS3XXX_SYS_LED + +/* + * Control registers + */ +#define CNS3XXX_IDFIELD_OFFSET 0x0 /* Cavium Networks build information */ +#define CNS3XXX_FLASHPROG_OFFSET 0x4 /* Flash devices */ +#define CNS3XXX_INTREG_OFFSET 0x8 /* Interrupt control */ +#define CNS3XXX_DECODE_OFFSET 0xC /* Fitted logic modules */ + +/* + * System controller bit assignment + */ +#define CNS3XXX_REFCLK 0 +#define CNS3XXX_TIMCLK 1 + +#define CNS3XXX_TIMER1_EnSel 15 +#define CNS3XXX_TIMER2_EnSel 17 +#define CNS3XXX_TIMER3_EnSel 19 +#define CNS3XXX_TIMER4_EnSel 21 + + +#define MAX_TIMER 2 +#define MAX_PERIOD 699050 +#define TICKS_PER_uSEC 1 + +/* + * These are useconds NOT ticks. + * + */ +#define mSEC_1 1000 +#define mSEC_5 (mSEC_1 * 5) +#define mSEC_10 (mSEC_1 * 10) +#define mSEC_25 (mSEC_1 * 25) +#define SEC_1 (mSEC_1 * 1000) + +#define CNS3XXX_CSR_BASE 0x10000000 +#define CNS3XXX_CSR_SIZE 0x10000000 + +/* Platform Level Setup Functions */ + +extern void cns3xxx_sys_init(void); +extern int cns3xxx_pcie_init(u8 ports); + +/* Information about built-in Ethernet MAC interfaces */ +struct eth_plat_info { + u8 ports; /* Bitmap of enabled Ports */ + u8 eth0_hwaddr[6]; + u8 eth1_hwaddr[6]; + u8 eth2_hwaddr[6]; + u8 cpu_hwaddr[6]; +}; + +// 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) + + +#endif /* __ASM_ARCH_PLATFORM_H */ +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/pm.h @@ -0,0 +1,333 @@ +/****************************************************************************** + * + * Copyright (c) 2008 Cavium Networks + * + * 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 + * + ******************************************************************************/ + +#ifndef _CNS3XXX_PM_H_ +#define _CNS3XXX_PM_H_ +#include +#define PMU_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_PM_BASE_VIRT+offset))) + +#define PM_CLK_GATE_REG PMU_REG_VALUE(0x000) +#define PM_SOFT_RST_REG PMU_REG_VALUE(0x004) +#define PM_HS_CFG_REG PMU_REG_VALUE(0x008) +#define PM_CACTIVE_STA_REG PMU_REG_VALUE(0x00C) +#define PM_PWR_STA_REG PMU_REG_VALUE(0x010) +#define PM_CLK_CTRL_REG PMU_REG_VALUE(0x014) +#define PM_PLL_LCD_I2S_CTRL_REG PMU_REG_VALUE(0x018) +#define PM_PLL_HM_PD_CTRL_REG PMU_REG_VALUE(0x01C) +#define PM_REGULAT_CTRL_REG PMU_REG_VALUE(0x020) +#define PM_WDT_CTRL_REG PMU_REG_VALUE(0x024) +#define PM_WU_CTRL0_REG PMU_REG_VALUE(0x028) +#define PM_WU_CTRL1_REG PMU_REG_VALUE(0x02C) +#define PM_CSR_REG PMU_REG_VALUE(0x030) + +/* PM_CLK_GATE_REG */ +#define PM_CLK_GATE_REG_OFFSET_SDIO (25) +#define PM_CLK_GATE_REG_OFFSET_GPU (24) +#define PM_CLK_GATE_REG_OFFSET_CIM (23) +#define PM_CLK_GATE_REG_OFFSET_LCDC (22) +#define PM_CLK_GATE_REG_OFFSET_I2S (21) +#define PM_CLK_GATE_REG_OFFSET_RAID (20) +#define PM_CLK_GATE_REG_OFFSET_SATA (19) +#define PM_CLK_GATE_REG_OFFSET_PCIE0 (17) +#define PM_CLK_GATE_REG_OFFSET_PCIE1 (18) +#define PM_CLK_GATE_REG_OFFSET_USB_HOST (16) +#define PM_CLK_GATE_REG_OFFSET_USB_OTG (15) +#define PM_CLK_GATE_REG_OFFSET_TIMER (14) +#define PM_CLK_GATE_REG_OFFSET_CRYPTO (13) +#define PM_CLK_GATE_REG_OFFSET_HCIE (12) +#define PM_CLK_GATE_REG_OFFSET_SWITCH (11) +#define PM_CLK_GATE_REG_OFFSET_GPIO (10) +#define PM_CLK_GATE_REG_OFFSET_UART3 (9) +#define PM_CLK_GATE_REG_OFFSET_UART2 (8) +#define PM_CLK_GATE_REG_OFFSET_UART1 (7) +#define PM_CLK_GATE_REG_OFFSET_RTC (5) +#define PM_CLK_GATE_REG_OFFSET_GDMA (4) +#define PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C (3) +#define PM_CLK_GATE_REG_OFFSET_SMC_NFI (1) +#define PM_CLK_GATE_REG_MASK (0x03FFFFBA) + +/* PM_SOFT_RST_REG */ +#define PM_SOFT_RST_REG_OFFST_WARM_RST_FLAG (31) +#define PM_SOFT_RST_REG_OFFST_CPU1 (29) +#define PM_SOFT_RST_REG_OFFST_CPU0 (28) +#define PM_SOFT_RST_REG_OFFST_SDIO (25) +#define PM_SOFT_RST_REG_OFFST_GPU (24) +#define PM_SOFT_RST_REG_OFFST_CIM (23) +#define PM_SOFT_RST_REG_OFFST_LCDC (22) +#define PM_SOFT_RST_REG_OFFST_I2S (21) +#define PM_SOFT_RST_REG_OFFST_RAID (20) +#define PM_SOFT_RST_REG_OFFST_SATA (19) +#define PM_SOFT_RST_REG_OFFST_PCIE1 (18) +#define PM_SOFT_RST_REG_OFFST_PCIE0 (17) +#define PM_SOFT_RST_REG_OFFST_USB_HOST (16) +#define PM_SOFT_RST_REG_OFFST_USB_OTG (15) +#define PM_SOFT_RST_REG_OFFST_TIMER (14) +#define PM_SOFT_RST_REG_OFFST_CRYPTO (13) +#define PM_SOFT_RST_REG_OFFST_HCIE (12) +#define PM_SOFT_RST_REG_OFFST_SWITCH (11) +#define PM_SOFT_RST_REG_OFFST_GPIO (10) +#define PM_SOFT_RST_REG_OFFST_UART3 (9) +#define PM_SOFT_RST_REG_OFFST_UART2 (8) +#define PM_SOFT_RST_REG_OFFST_UART1 (7) +#define PM_SOFT_RST_REG_OFFST_RTC (5) +#define PM_SOFT_RST_REG_OFFST_GDMA (4) +#define PM_SOFT_RST_REG_OFFST_SPI_PCM_I2C (3) +#define PM_SOFT_RST_REG_OFFST_DMC (2) +#define PM_SOFT_RST_REG_OFFST_SMC_NFI (1) +#define PM_SOFT_RST_REG_OFFST_GLOBAL (0) +#define PM_SOFT_RST_REG_MASK (0xF3FFFFBF) + +/* PMHS_CFG_REG */ +#define PM_HS_CFG_REG_OFFSET_SDIO (25) +#define PM_HS_CFG_REG_OFFSET_GPU (24) +#define PM_HS_CFG_REG_OFFSET_CIM (23) +#define PM_HS_CFG_REG_OFFSET_LCDC (22) +#define PM_HS_CFG_REG_OFFSET_I2S (21) +#define PM_HS_CFG_REG_OFFSET_RAID (20) +#define PM_HS_CFG_REG_OFFSET_SATA (19) +#define PM_HS_CFG_REG_OFFSET_PCIE1 (18) +#define PM_HS_CFG_REG_OFFSET_PCIE0 (17) +#define PM_HS_CFG_REG_OFFSET_USB_HOST (16) +#define PM_HS_CFG_REG_OFFSET_USB_OTG (15) +#define PM_HS_CFG_REG_OFFSET_TIMER (14) +#define PM_HS_CFG_REG_OFFSET_CRYPTO (13) +#define PM_HS_CFG_REG_OFFSET_HCIE (12) +#define PM_HS_CFG_REG_OFFSET_SWITCH (11) +#define PM_HS_CFG_REG_OFFSET_GPIO (10) +#define PM_HS_CFG_REG_OFFSET_UART3 (9) +#define PM_HS_CFG_REG_OFFSET_UART2 (8) +#define PM_HS_CFG_REG_OFFSET_UART1 (7) +#define PM_HS_CFG_REG_OFFSET_RTC (5) +#define PM_HS_CFG_REG_OFFSET_GDMA (4) +#define PM_HS_CFG_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_HS_CFG_REG_OFFSET_DMC (2) +#define PM_HS_CFG_REG_OFFSET_SMC_NFI (1) +#define PM_HS_CFG_REG_MASK (0x03FFFFBE) +#define PM_HS_CFG_REG_MASK_SUPPORT (0x01100806) + +/* PM_CACTIVE_STA_REG */ +#define PM_CACTIVE_STA_REG_OFFSET_SDIO (25) +#define PM_CACTIVE_STA_REG_OFFSET_GPU (24) +#define PM_CACTIVE_STA_REG_OFFSET_CIM (23) +#define PM_CACTIVE_STA_REG_OFFSET_LCDC (22) +#define PM_CACTIVE_STA_REG_OFFSET_I2S (21) +#define PM_CACTIVE_STA_REG_OFFSET_RAID (20) +#define PM_CACTIVE_STA_REG_OFFSET_SATA (19) +#define PM_CACTIVE_STA_REG_OFFSET_PCIE1 (18) +#define PM_CACTIVE_STA_REG_OFFSET_PCIE0 (17) +#define PM_CACTIVE_STA_REG_OFFSET_USB_HOST (16) +#define PM_CACTIVE_STA_REG_OFFSET_USB_OTG (15) +#define PM_CACTIVE_STA_REG_OFFSET_TIMER (14) +#define PM_CACTIVE_STA_REG_OFFSET_CRYPTO (13) +#define PM_CACTIVE_STA_REG_OFFSET_HCIE (12) +#define PM_CACTIVE_STA_REG_OFFSET_SWITCH (11) +#define PM_CACTIVE_STA_REG_OFFSET_GPIO (10) +#define PM_CACTIVE_STA_REG_OFFSET_UART3 (9) +#define PM_CACTIVE_STA_REG_OFFSET_UART2 (8) +#define PM_CACTIVE_STA_REG_OFFSET_UART1 (7) +#define PM_CACTIVE_STA_REG_OFFSET_RTC (5) +#define PM_CACTIVE_STA_REG_OFFSET_GDMA (4) +#define PM_CACTIVE_STA_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_CACTIVE_STA_REG_OFFSET_DMC (2) +#define PM_CACTIVE_STA_REG_OFFSET_SMC_NFI (1) +#define PM_CACTIVE_STA_REG_MASK (0x03FFFFBE) + +/* PM_PWR_STA_REG */ +#define PM_PWR_STA_REG_REG_OFFSET_SDIO (25) +#define PM_PWR_STA_REG_REG_OFFSET_GPU (24) +#define PM_PWR_STA_REG_REG_OFFSET_CIM (23) +#define PM_PWR_STA_REG_REG_OFFSET_LCDC (22) +#define PM_PWR_STA_REG_REG_OFFSET_I2S (21) +#define PM_PWR_STA_REG_REG_OFFSET_RAID (20) +#define PM_PWR_STA_REG_REG_OFFSET_SATA (19) +#define PM_PWR_STA_REG_REG_OFFSET_PCIE1 (18) +#define PM_PWR_STA_REG_REG_OFFSET_PCIE0 (17) +#define PM_PWR_STA_REG_REG_OFFSET_USB_HOST (16) +#define PM_PWR_STA_REG_REG_OFFSET_USB_OTG (15) +#define PM_PWR_STA_REG_REG_OFFSET_TIMER (14) +#define PM_PWR_STA_REG_REG_OFFSET_CRYPTO (13) +#define PM_PWR_STA_REG_REG_OFFSET_HCIE (12) +#define PM_PWR_STA_REG_REG_OFFSET_SWITCH (11) +#define PM_PWR_STA_REG_REG_OFFSET_GPIO (10) +#define PM_PWR_STA_REG_REG_OFFSET_UART3 (9) +#define PM_PWR_STA_REG_REG_OFFSET_UART2 (8) +#define PM_PWR_STA_REG_REG_OFFSET_UART1 (7) +#define PM_PWR_STA_REG_REG_OFFSET_RTC (5) +#define PM_PWR_STA_REG_REG_OFFSET_GDMA (4) +#define PM_PWR_STA_REG_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_PWR_STA_REG_REG_OFFSET_DMC (2) +#define PM_PWR_STA_REG_REG_OFFSET_SMC_NFI (1) +#define PM_PWR_STA_REG_REG_MASK (0x03FFFFBE) + +/* PM_CLK_CTRL_REG */ +#define PM_CLK_CTRL_REG_OFFSET_I2S_MCLK (31) +#define PM_CLK_CTRL_REG_OFFSET_DDR2_CHG_EN (30) +#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF1_EN (29) +#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF0_EN (28) +#define PM_CLK_CTRL_REG_OFFSET_TIMER_SIM_MODE (27) +#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_DIV (24) +#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_SEL (22) +#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_DIV (20) +#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_SEL (16) +#define PM_CLK_CTRL_REG_OFFSET_MDC_DIV (14) +#define PM_CLK_CTRL_REG_OFFSET_CRYPTO_CLK_SEL (12) +#define PM_CLK_CTRL_REG_OFFSET_CPU_PWR_MODE (9) +#define PM_CLK_CTRL_REG_OFFSET_PLL_DDR2_SEL (7) +#define PM_CLK_CTRL_REG_OFFSET_DIV_IMMEDIATE (6) +#define PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV (4) +#define PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL (0) + +#define PM_CPU_CLK_DIV(DIV) { \ + PM_CLK_CTRL_REG &= ~((0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \ + PM_CLK_CTRL_REG |= (((DIV)&0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \ +} + +#define PM_PLL_CPU_SEL(CPU) { \ + PM_CLK_CTRL_REG &= ~((0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \ + PM_CLK_CTRL_REG |= (((CPU)&0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \ +} + +/* PM_PLL_LCD_I2S_CTRL_REG */ +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_MCLK_SMC_DIV (22) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_R_SEL (17) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_P (11) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_M (3) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_S (0) + +/* PM_PLL_HM_PD_CTRL_REG */ +/* +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PCIE_PHY1 (13) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PCIE_PHY0 (12) +*/ +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1 (11) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0 (10) +/* +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_USB_PHY1 (9) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_USB_PHY0 (8) +*/ +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2SCD (6) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2S (5) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_LCD (4) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB (3) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_RGMII (2) +#define PM_PLL_HM_PD_CTRL_REG_MASK (0x00000C7C) + +/* PM_REGULAT_CTRL_REG */ + +/* PM_WDT_CTRL_REG */ +#define PM_WDT_CTRL_REG_OFFSET_RESET_CPU_ONLY (0) + +/* PM_WU_CTRL0_REG */ + +/* PM_WU_CTRL1_REG */ + +/* PM_CSR_REG - Clock Scaling Register*/ +#define PM_CSR_REG_OFFSET_CSR_EN (30) +#define PM_CSR_REG_OFFSET_CSR_NUM (0) + + +#define CNS3XXX_PWR_CLK_EN(BLOCK) (0x1< + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +/* + * We use IRQ1 as the IPI + */ +static inline void smp_cross_call(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 2); +} + +static inline void smp_cross_call_cache(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 1); +} + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/system.h @@ -0,0 +1,51 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/system.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + /* + * To reset, we hit the on-board reset register + * in the system FPGA + */ + cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(GLOBAL)); +} + +#endif --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/timex.h @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/timex.h + * + * Cavium Networks architecture timex specifications + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * + * 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 + */ + +#define CLOCK_TICK_RATE (50000000 / 16) --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/uncompress.h @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/uncompress.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * + * 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 +#include + +#include + +#define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) +#define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c)) +#define AMBA_UART_CR(base) (*(volatile unsigned char *)((base) + 0x30)) +#define AMBA_UART_FR(base) (*(volatile unsigned char *)((base) + 0x18)) + +/* + * Return the UART base address + */ +static inline unsigned long get_uart_base(void) +{ + return CNS3XXX_UART0_BASE; +} + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 5)) + barrier(); + + AMBA_UART_DR(base) = c; +} + +static inline void flush(void) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 3)) + barrier(); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h @@ -0,0 +1,26 @@ +/* + * arch/arm/mach-cns3xxx/include/mach/vmalloc.h + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Russell King. + * + * 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 + */ + +#define VMALLOC_END (PAGE_OFFSET + 0x18000000) --- /dev/null +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -0,0 +1,101 @@ +menu "CNS3XXX platform type" + depends on ARCH_CNS3XXX + +config MACH_GW2388 + bool "Support Gateworks Laguna Platform" + select ARM_GIC + help + Include support for the Cavium Networks CNS3XXX MPCore Platform Baseboard. + This is a platform with an on-board ARM11 MPCore and has support for USB, + USB-OTG, MMC/SD/SDIO and PCI-E, etc. + +config CNS3XXX_PM_API + bool "Support for CNS3XXX Power Managemnet API" + depends on ARCH_CNS3XXX + default y + help + Enable support for the CNS3XXX Power Managemnet API. + +config CNS3XXX_RAID + bool "Support for CNS3XXX RAID" + depends on ARCH_CNS3XXX + help + Enable RAID 4/5/6 Hardware accelartion in CNS3XXX. + If unsure, say N. + +config CNS3XXX_DMAC + bool "Support for CNS3XXX DMAC" + depends on ARCH_CNS3XXX + help + Enable support for the CNS3XXX DMA controllers. + +choice + prompt "PROM VERSTION" + default SILICON + help + Select the PROM interrupt ID mapping. +config SILICON + bool "CNS3XXX_SILICON" + help + Temporary option. + Interrupt + ID Source Function Trigger Type + --- ------------- ------------- ---------------- + 32 clkscale_intr PMU rising edge + 33 sdio_intr SDIO high level + 34 l2cc_intr L2CC high level + 35 rtc_intr RTC high level + 36 i2s_intr I2S high level + 37 pcm_intr_n PCM high level + 38 spi_intr_n SPI high level + 39 i2c_intr_n I2C high level + 40 cim_intr CIM high level + 41 gpu_intr GPU high level + 42 lcd_intr LCD high level + 43 gpioa_intr GPIOA programmable + 44 gpiob_intr GPIOB programmable + 45 irda0_intr UART0 high level + 46 irda1_intr UART1 high level + 47 irda2_intr UART2 high level + 48 arm11_intr ARM11 high level + 49 swsta_intr PSE Status high level + 50 tstc_r0_intr PSE R0TxComplete rising edge + 51 fstc_r0_intr PSE R0RxComplete rising edge + 52 tsqe_r0_intr PSE R0QEmpty rising edge + 53 tsqe_r0_intr PSE R0QFull rising edge + 54 tstc_r1_intr PSE R1TxComplete rising edge + 55 fstc_r1_intr PSE R1RxComplete rising edge + 56 tsqe_r1_intr PSE R1QEmpty rising edge + 57 tsqe_r1_intr PSE R1QFull rising edge + 58 hnat_intr PPE high level + 59 crypto_intr CRYPTO high level + 60 hcie_intr HCIE rising edge + 61 pcie0_intr PCIE0 Device high level + 62 pcie1_intr PCIE1 Device high level + 63 usbotg_intr USB OTG high level + 64 ehci_intr USB EHCI high level + 65 sata_intr SATA high level + 66 raid_intr_n RAID high level + 67 smc_intr_n SMC high level + 68 dmac_abort_intr DMAC high level + 86:69 dmac_intr[17:0] DMAC high level + 87 pcie0_rc_intr PCIE0 RC high level + 88 pcie1_rc_intr PCIE1 RC high level + 89 timer1_intr TIMER 1 high level + 90 timer2_intr TIMER 2 high level + 91 ochi_intr_n USB OCHI high level + 92 timer3_intr TIMER 3 high level + 93 ext_intr0 Extrenal Pin programmable + 94 ext_intr1 Extrenal Pin programmable + 95 ext_intr2 Extrenal Pin programmable + +endchoice + +config CNS3XXX_GPU_ENVIRONMENT + bool "CNS3XXX GPU(GC300 2D Acceleration) Support" + default n + help + Say Y if you want to support 2D acceleration. + +endmenu + --- /dev/null +++ b/arch/arm/mach-cns3xxx/laguna-setup.c @@ -0,0 +1,593 @@ +/* + * linux/arch/arm/mach-cns3xxx/laguna.c + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2008 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" + +struct laguna_board_info { + char model[6]; + u32 config_bitmap; + u32 config2_bitmap; + u8 nor_flash_size; + u8 spi_flash_size; +}; + +static struct laguna_board_info laguna_info __initdata; + +/* + * Cavium Networks ARM11 MPCore platform devices + */ + +static struct mtd_partition laguna_norflash_partitions[] = { + /* Bootloader */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_256K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* Bootloader params */ + { + .name = "params", + .offset = SZ_256K, + .size = SZ_128K, + .mask_flags = 0, + }, + /* linux */ + { + .name = "linux", + .offset = SZ_256K + SZ_128K, + .size = SZ_2M, + .mask_flags = 0, + }, + /* Root FS */ + { + .name = "rootfs", + .offset = SZ_256K + SZ_128K + SZ_2M, + .size = SZ_16M - SZ_256K - SZ_128K - SZ_2M, + .mask_flags = 0, + } +}; + +static struct physmap_flash_data laguna_norflash_data = { + .width = 2, + .parts = laguna_norflash_partitions, + .nr_parts = ARRAY_SIZE(laguna_norflash_partitions), +}; + +static struct resource laguna_norflash_resource = { + .start = CNS3XXX_FLASH0_BASE, + .end = CNS3XXX_FLASH0_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device laguna_norflash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &laguna_norflash_data, + }, + .num_resources = 1, + .resource = &laguna_norflash_resource, +}; + +/* UART0 */ +static struct resource laguna_uart_resources[] = { + { + .start = CNS3XXX_UART0_BASE, + .end = CNS3XXX_UART0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM + },{ + .start = CNS3XXX_UART1_BASE, + .end = CNS3XXX_UART1_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 +}; + +/* SDIO, MMC/SD */ +static struct resource laguna_sdio_resource[] = { + { + .start = CNS3XXX_SDIO_BASE, + .end = CNS3XXX_SDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + },{ + .start = IRQ_CNS3XXX_SDIO, + .end = IRQ_CNS3XXX_SDIO, + .flags = IORESOURCE_IRQ, + }, +}; + +struct cns3xxx_sdhci_platdata laguna_sdio_platform_data = { + .max_width = 4, + .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), +}; + +static u64 laguna_device_sdhci_dmamask = 0xffffffffUL; + +static struct platform_device laguna_sdio_device = { + .name = "cns3xxx-sdhci", + .id = 0, + .num_resources = ARRAY_SIZE(laguna_sdio_resource), + .resource = laguna_sdio_resource, + .dev = { + .dma_mask = &laguna_device_sdhci_dmamask, + .coherent_dma_mask = 0xffffffffUL, + .platform_data = &laguna_sdio_platform_data, + } +}; + +static struct pca953x_platform_data laguna_pca_data = { + .gpio_base = 100, +}; + +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_device = { + .name = "cns3xxx-i2c", + .num_resources = 2, + .resource = laguna_i2c_resource, +}; + +static struct resource laguna_usb_ehci_resource[] = { + { + .start = CNS3XXX_USB_BASE, + .end = CNS3XXX_USB_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, + },{ + .start = IRQ_CNS3XXX_USB_EHCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 laguna_usb_dma_mask = 0xffffffffULL; + +static struct platform_device laguna_usb_ehci_device = { + .name = "cns3xxx-ehci", + .num_resources = ARRAY_SIZE(laguna_usb_ehci_resource), + .resource = laguna_usb_ehci_resource, + .dev = { + .dma_mask = &laguna_usb_dma_mask, + .coherent_dma_mask = 0xffffffffULL, + }, +}; + +static struct resource laguna_usb_ohci_resource[] = { + { + .start = CNS3XXX_USB_OHCI_BASE, + .end = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, + },{ + .start = IRQ_CNS3XXX_USB_OHCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 laguna_usb_ohci_dma_mask = 0xffffffffULL; +static struct platform_device laguna_usb_ohci_device = { + .name = "cns3xxx-ohci", + .dev = { + .dma_mask = &laguna_usb_ohci_dma_mask, + .coherent_dma_mask = 0xffffffffULL, + }, + .num_resources = 2, + .resource = laguna_usb_ohci_resource, +}; + +static u64 laguna_usbotg_dma_mask = 0xffffffffULL; +static struct lm_device laguna_usb_otg_device = { + .dev = { + .dma_mask = &laguna_usbotg_dma_mask, + .coherent_dma_mask = 0xffffffffULL, + }, + .resource = { + .start = CNS3XXX_USBOTG_BASE, + .end = CNS3XXX_USBOTG_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, + }, + .irq = IRQ_CNS3XXX_USB_OTG, +}; + +static struct resource laguna_ahci_resource[] = { + { + .start = CNS3XXX_SATA2_BASE, + .end = CNS3XXX_SATA2_BASE + CNS3XXX_SATA2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_CNS3XXX_SATA, + .end = IRQ_CNS3XXX_SATA, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 laguna_device_ahci_dmamask = 0xffffffffUL; + +static struct platform_device laguna_ahci = { + .name = "cns3xxx_ahci", + .id = -1, + .dev = { + .dma_mask = &laguna_device_ahci_dmamask, + .coherent_dma_mask = 0xffffffffUL, + }, + .resource = laguna_ahci_resource, + .num_resources = ARRAY_SIZE(laguna_ahci_resource), +}; + +/* SPI Flash */ +static struct mtd_partition laguna_spiflash_partitions[] = { + /* Bootloader */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + }, + /* Bootloader params */ + { + .name = "params", + .offset = SZ_128K, + .size = SZ_128K, + }, + /* linux */ + { + .name = "linux", + .offset = SZ_256K, + .size = 0x180000, + .mask_flags = 0, + }, + /* FileSystem */ + { + .name = "rootfs", + .offset = SZ_256K + 0x180000, + .size = SZ_4M - SZ_256K - 0x180000, + } +}; + +static struct flash_platform_data laguna_spiflash_data = { + .parts = laguna_spiflash_partitions, + .nr_parts = ARRAY_SIZE(laguna_spiflash_partitions), +}; + +static struct spi_board_info __initdata laguna_spi_devices[] = { + { + .modalias = "m25p80", + .platform_data = &laguna_spiflash_data, + .max_speed_hz = 50000000, + .bus_num = 1, + .chip_select = 0, + }, +}; + +static struct platform_device laguna_spi_controller_device = { + .name = "cns3xxx_spi", +}; + +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, + }, +}; + +static struct gpio_led_platform_data laguna_gpio_leds_data = { + .num_leds = 2, + .leds = laguna_gpio_leds, +}; + +static struct platform_device laguna_gpio_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev.platform_data = &laguna_gpio_leds_data, +}; + +static struct eth_plat_info laguna_net_data = { + .ports = 3, // Bring Up both Eth port by Default +}; + +static struct platform_device laguna_net_device = { + .name = "cns3xxx-net", + .id = -1, + .dev.platform_data = &laguna_net_data, +}; + +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.eth0_hwaddr, buf, ETH_ALEN); + if (at24_mem_acc->read(at24_mem_acc, buf, 0x106, 6) == 6) + memcpy(&laguna_net_data.eth1_hwaddr, buf, ETH_ALEN); + if (at24_mem_acc->read(at24_mem_acc, buf, 0x10C, 6) == 6) + memcpy(&laguna_net_data.eth2_hwaddr, buf, ETH_ALEN); + if (at24_mem_acc->read(at24_mem_acc, buf, 0x112, 6) == 6) + memcpy(&laguna_net_data.cpu_hwaddr, 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, 8); + if (at24_mem_acc->read(at24_mem_acc, buf, 0x146, 4) == 4) + memcpy(&laguna_info.config2_bitmap, buf, 8); +}; + +static struct at24_platform_data laguna_eeprom_info = { + .byte_len = 1024, + .page_size = 16, + .flags = AT24_FLAG_READONLY, + .setup = at24_setup, +}; + +static struct i2c_board_info __initdata laguna_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9555", 0x23), + .platform_data = &laguna_pca_data, + }, + { + I2C_BOARD_INFO("gsp", 0x29), + }, + { + I2C_BOARD_INFO ("24c08",0x50), + .platform_data = &laguna_eeprom_info, + }, + { + I2C_BOARD_INFO("ds1672", 0x68), + }, +}; + +static void __init laguna_init(void) +{ + cns3xxx_sys_init(); + + platform_device_register(&laguna_i2c_controller_device); + + i2c_register_board_info(0, laguna_i2c_devices, ARRAY_SIZE(laguna_i2c_devices)); + + pm_power_off = cns3xxx_power_off; +} + +static int __init laguna_model_setup(void) +{ + if (!machine_is_gw2388()) + return 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 | SATA1_LOAD)) + platform_device_register(&laguna_ahci); + + if (laguna_info.config_bitmap & (PCIe0_LOAD)) + cns3xxx_pcie_init(1); + + if (laguna_info.config_bitmap & (PCIe1_LOAD)) + cns3xxx_pcie_init(2); + + if (laguna_info.config_bitmap & (USB0_LOAD)) + lm_device_register(&laguna_usb_otg_device); + + if (laguna_info.config_bitmap & (USB1_LOAD)) { + platform_device_register(&laguna_usb_ehci_device); + platform_device_register(&laguna_usb_ohci_device); + } + + if (laguna_info.config_bitmap & (SD_LOAD)) + platform_device_register(&laguna_sdio_device); + + 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_norflash_partitions[3].size = SZ_8M - SZ_256K - SZ_128K - SZ_2M; + laguna_norflash_resource.end = CNS3XXX_FLASH0_BASE + SZ_8M - 1; + break; + case 2: + laguna_norflash_partitions[3].size = SZ_16M - SZ_256K - SZ_128K - SZ_2M; + laguna_norflash_resource.end = CNS3XXX_FLASH0_BASE + SZ_16M - 1; + break; + case 3: + laguna_norflash_partitions[3].size = SZ_32M - SZ_256K - SZ_128K - SZ_2M; + laguna_norflash_resource.end = CNS3XXX_FLASH0_BASE + SZ_32M - 1; + break; + case 4: + laguna_norflash_partitions[3].size = SZ_64M - SZ_256K - SZ_128K - SZ_2M; + laguna_norflash_resource.end = CNS3XXX_FLASH0_BASE + SZ_64M - 1; + break; + case 5: + laguna_norflash_partitions[3].size = SZ_128M - SZ_256K - SZ_128K - SZ_2M; + laguna_norflash_resource.end = CNS3XXX_FLASH0_BASE + SZ_128M - 1; + break; + } + platform_device_register(&laguna_norflash_device); + } + + if (laguna_info.config2_bitmap & (SPI_FLASH_LOAD)) { + switch (laguna_info.spi_flash_size) { + case 1: + laguna_spiflash_partitions[3].size = SZ_4M - SZ_256K - 0x180000; + break; + case 2: + laguna_spiflash_partitions[3].size = SZ_8M - SZ_256K - 0x180000; + break; + case 3: + laguna_spiflash_partitions[3].size = SZ_16M - SZ_256K - 0x180000; + break; + case 4: + laguna_spiflash_partitions[3].size = SZ_32M - SZ_256K - 0x180000; + break; + case 5: + laguna_spiflash_partitions[3].size = SZ_64M - SZ_256K - 0x180000; + break; + } + spi_register_board_info(laguna_spi_devices, ARRAY_SIZE(laguna_spi_devices)); + } + + if (laguna_info.config_bitmap & (SPI0_LOAD | SPI1_LOAD)) + { + platform_device_register(&laguna_spi_controller_device); + } + + /* + * 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) + { + 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 Laguna Platform") + .phys_io = CNS3XXX_UART0_BASE, + .io_pg_offst = (CNS3XXX_UART0_BASE_VIRT >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = cns3xxx_map_io, + .init_irq = cns3xxx_init_irq, + .timer = &cns3xxx_timer, + .init_machine = laguna_init, +MACHINE_END --- /dev/null +++ b/arch/arm/mach-cns3xxx/lm.c @@ -0,0 +1,98 @@ +/* + * linux/arch/arm/mach-integrator/lm.c + * + * Copyright (C) 2003 Deep Blue Solutions 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 +#include +#include +#include +#include + +#include + +#define to_lm_device(d) container_of(d, struct lm_device, dev) +#define to_lm_driver(d) container_of(d, struct lm_driver, drv) + +static int lm_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + +static int lm_bus_probe(struct device *dev) +{ + struct lm_device *lmdev = to_lm_device(dev); + struct lm_driver *lmdrv = to_lm_driver(dev->driver); + + return lmdrv->probe(lmdev); +} + +static int lm_bus_remove(struct device *dev) +{ + struct lm_device *lmdev = to_lm_device(dev); + struct lm_driver *lmdrv = to_lm_driver(dev->driver); + + if (lmdrv->remove) + lmdrv->remove(lmdev); + return 0; +} + +static struct bus_type lm_bustype = { + .name = "logicmodule", + .match = lm_match, + .probe = lm_bus_probe, + .remove = lm_bus_remove, +}; + +static int __init lm_init(void) +{ + return bus_register(&lm_bustype); +} + +postcore_initcall(lm_init); + +int lm_driver_register(struct lm_driver *drv) +{ + drv->drv.bus = &lm_bustype; + return driver_register(&drv->drv); +} + +void lm_driver_unregister(struct lm_driver *drv) +{ + driver_unregister(&drv->drv); +} + +static void lm_device_release(struct device *dev) +{ + struct lm_device *d = to_lm_device(dev); + + kfree(d); +} + +int lm_device_register(struct lm_device *dev) +{ + int ret; + + dev->dev.release = lm_device_release; + dev->dev.bus = &lm_bustype; + + ret = dev_set_name(&dev->dev, "lm%d", dev->id); + if (ret) + return ret; + dev->resource.name = dev_name(&dev->dev); + + ret = request_resource(&iomem_resource, &dev->resource); + if (ret == 0) { + ret = device_register(&dev->dev); + if (ret) + release_resource(&dev->resource); + } + return ret; +} + +EXPORT_SYMBOL(lm_driver_register); +EXPORT_SYMBOL(lm_driver_unregister); --- /dev/null +++ b/arch/arm/mach-cns3xxx/localtimer.c @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/mach-cns3xxx/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 +#include +#include + +#include +#include +#include + +/* + * Setup the local clock events for a CPU. + */ +void __cpuinit local_timer_setup(struct clock_event_device *evt) +{ + evt->irq = IRQ_LOCALTIMER; + twd_timer_setup(evt); +} --- /dev/null +++ b/arch/arm/mach-cns3xxx/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the linux kernel. +# + +obj-y := core.o lm.o +obj-$(CONFIG_MACH_GW2388) += laguna-setup.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o +obj-$(CONFIG_PCIEPORTBUS) += pcie.o +obj-$(CONFIG_CNS3XXX_RAID) += rdma.o +obj-$(CONFIG_CNS3XXX_DMAC) += dmac.o +obj-$(CONFIG_CNS3XXX_PM_API) += pm.o + --- /dev/null +++ b/arch/arm/mach-cns3xxx/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00C00000 +kernel_phys-y := 0x00600000 --- /dev/null +++ b/arch/arm/mach-cns3xxx/platsmp.c @@ -0,0 +1,220 @@ +/* + * linux/arch/arm/mach-cns3xxx/platsmp.c + * + * Copyright (c) 2008 Cavium Networks + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "core.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; + +static void __iomem *scu_base_addr(void) +{ + return (void __iomem *)(CNS3XXX_TC11MP_SCU_BASE_VIRT); +} + +static inline unsigned int get_core_count(void) +{ + void __iomem *scu_base = scu_base_addr(); + if (scu_base) + return scu_get_core_count(scu_base); + return 1; +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + trace_hardirqs_off(); + + /* + * 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_cpu_init(0, (void __iomem *)(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT)); + set_interrupt_pri(1, 0); // set cache broadcast ipi to highest priority + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * 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. + */ + pen_release = cpu; + flush_cache_all(); + + /* + * XXX + * + * This is a later addition to the booting protocol: the + * bootMonitor now puts secondary cores into WFI, so + * poke_milo() no longer gets the cores moving; we need + * to send a soft interrupt to wake the secondary core. + * Use smp_cross_call() for this, since there's little + * point duplicating the code here + */ + smp_cross_call(cpumask_of(cpu)); + + 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; +} + +static void __init poke_milo(void) +{ + /* nobody is to be released from the pen yet */ + pen_release = -1; + + /* write the address of secondary startup into the general purpose register */ + __raw_writel(virt_to_phys(cns3xxx_secondary_startup), (void __iomem *)(0xFFF07000 + 0x0600)); + + mb(); +} + +/* + * 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) +{ + unsigned int i, ncores = get_core_count(); + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = get_core_count(); + unsigned int cpu = smp_processor_id(); + int i; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "CNS3XXX: strange CM count of 0? Default to 1\n"); + + ncores = 1; + } + + 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; + } + + smp_store_cpu_info(cpu); + + /* + * are we trying to boot more cores than exist? + */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * 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); + + /* + * Initialise the SCU if there are more than one CPU and let + * them know where to start. Note that, on modern versions of + * MILO, the "poke" doesn't actually do anything until each + * individual core is sent a soft interrupt to get it out of + * WFI + */ + if (max_cpus > 1) { + /* + * Enable the local timer or broadcast device for the + * boot CPU, but only if we have more than one CPU. + */ + percpu_timer_setup(); + + scu_enable(scu_base_addr()); + poke_milo(); + } +} --- /dev/null +++ b/arch/arm/mach-cns3xxx/pm.c @@ -0,0 +1,476 @@ +/****************************************************************************** + * + * Copyright (c) 2008 Cavium Networks + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +/* + * cns3xxx_pwr_clk_en - clock enable + * @block: bitmap for peripheral + */ +void cns3xxx_pwr_clk_en(unsigned int block) +{ + PM_CLK_GATE_REG |= (block&PM_CLK_GATE_REG_MASK); +} + +/* + * cns3xxx_pwr_soft_rst - software reset + * @block: bitmap for peripheral + */ +void cns3xxx_pwr_soft_rst_force(unsigned int block) +{ + /* bit 0, 28, 29 => program low to reset, + * the other else program low and then high + */ + if (block & 0x30000001) { + PM_SOFT_RST_REG &= ~(block&PM_SOFT_RST_REG_MASK); + } else { + PM_SOFT_RST_REG &= ~(block&PM_SOFT_RST_REG_MASK); + PM_SOFT_RST_REG |= (block&PM_SOFT_RST_REG_MASK); + } +} + +void cns3xxx_pwr_soft_rst(unsigned int block) +{ + static unsigned int soft_reset = 0; + + if(soft_reset & block) { + //Because SPI/I2C/GPIO use the same block, just only reset once... + return; + } + else { + soft_reset |= block; + } + cns3xxx_pwr_soft_rst_force(block); +} + +/* + * void cns3xxx_pwr_lp_hs - lower power handshake + * @dev: bitmap for device + * + */ +void cns3xxx_lp_hs(unsigned int dev) +{ + + if (PM_HS_CFG_REG_MASK_SUPPORT & dev) { + PM_HS_CFG_REG |= dev; + + /* TODO: disable clock */ + } +} + +/* + * cns3xxx_pwr_mode - change CPU power mode + * @pwr_mode: CPU power mode + * CNS3XXX_PWR_CPU_MODE_DFS, CNS3XXX_PWR_CPU_MODE_IDLE + * CNS3XXX_PWR_CPU_MODE_HALT, CNS3XXX_PWR_CPU_MODE_DOZE + * CNS3XXX_PWR_CPU_MODE_SLEEP, CNS3XXX_PWR_CPU_MODE_HIBERNATE + */ +static void cns3xxx_pwr_mode(unsigned int pwr_mode) +{ + if (CNS3XXX_PWR_CPU_MODE_HIBERNATE < pwr_mode) { + return; + } + + PM_CLK_CTRL_REG &= + ~(0x7<> PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL) &0xf; + old_div = (PM_CLK_CTRL_REG >> PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV) & 0x3; + + if ((cpu_sel == old_cpu) + && (div_sel == old_div)) { + return; + } + + /* 1. Set PLL_CPU_SEL */ + PM_PLL_CPU_SEL(cpu_sel); + PM_CPU_CLK_DIV(div_sel); + + /* 2. Set in DFS mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); + + /* 3. disable all interrupt except interrupt ID-32 (clkscale_intr) */ + /* disable all interrupt */ + GIC_REG_VALUE(0x184) = 0xffffffff; + GIC_REG_VALUE(0x188) = 0xffffffff; + /* enable interrupt id 32*/ + GIC_REG_VALUE(0x104) = 0x00000001; + GIC_REG_VALUE(0x108) = 0x80000000; + + /* 4. Let CPU enter into WFI state */ + asm volatile( + "mov r0, #0\n" + "mcr p15, 0, r0, c7, c0, 4\n" + ); + + +#if 0 + { + int i; + for (i=IRQ_CNS3XXX_PMU+1; i> 3); + *(volatile unsigned int *) (CNS3XXX_TIMER1_2_3_BASE_VIRT + TIMER1_AUTO_RELOAD_OFFSET) + = pclk/15*0x25000; + } + +} + + +/* + * clock_out_sel - select clock source to ClkOut pin + * This function just select pll_cpu to ClkOut pin, + * we can measure the ClkOut frequency to make sure whether pll_cpu is change + * + */ +void clock_out_sel(void) +{ + + int temp = PM_CLK_CTRL_REG; + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 26); /* Set GPIOB26 to ClkOut*/ + /* debug purpose, use ext intr 1 and 2 to generate interrupt */ + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 27); /* Set GPIOB27 to external interrupt 2*/ + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 28); /* Set GPIOB28 to external interrupt 1*/ + /* select ClkOut source as pll_cpu_clk and ClkOut divider is by 16 */ + temp &=~(0x3 << 20); + temp &=~(0xf << 16); + temp |= (0x3 << 20); + temp |= (0x1 << 16); + PM_CLK_CTRL_REG = temp; +} + +void cns3xxx_wfi(void) +{ + mb(); + asm volatile( + "mov r0, #0\n" + "mcr p15, 0, r0, c7, c10, 4\n" + "mcr p15, 0, r0, c7, c0, 4\n" + ); +} + +/* + * cns3xxx_pwr_sleep - + */ +void cns3xxx_pwr_sleep(void) +{ + /* 1. Set in sleep mode + * 2. disable all functional block + * 3. make sure that all function block are in power off state + * 4. power down all PLL + * 5. Let CPU enter into WFI state + * 6. Wait PMU to change PLL_CPU and divider and wake up CPU + */ + int i, j, count = 0; + /* 1. Set in SLEEP mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_SLEEP); + + /* 2. disable all functional block */ + i = PM_CLK_GATE_REG; + PM_CLK_GATE_REG = 0x0; + + /* 3. make sure that all function block are in power off state */ + while (0x4 != PM_PWR_STA_REG) { + count++; + if (1000 == count) { + count = PM_PWR_STA_REG; + break; + } + }; + + /* 4. power down all PLL */ + j = PM_PLL_HM_PD_CTRL_REG; + PM_PLL_HM_PD_CTRL_REG = 0x00003FFC; + +#if 0 + /* set DMC to low power hand shake */ + PM_HS_CFG_REG |= (0x1 << 2); + /* disable DMC */ + PM_CLK_GATE_REG &= ~(0x1<<2); +#endif + + /* set wake up interrupt source, use ext_intr1 to wake up*/ + PM_WU_CTRL0_REG = 0x0; PM_WU_CTRL1_REG = 0x40000000; + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 27); + + /* 5. Let CPU enter into WFI state */ + GIC_REG_VALUE(0x104) = 0x1; /* enable clock scaling interrupt */ + printk("<0>enter WFI\n"); + cns3xxx_wfi(); + PM_CLK_GATE_REG = i; + PM_PLL_HM_PD_CTRL_REG = j; + printk("<0>leave WFI\n"); + GIC_REG_VALUE(0x104) = 0xffffffff; + GIC_REG_VALUE(0x108) = 0xffffffff; + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); +} + +/* + * cns3xxx_pwr_sleep_test - enter into sleep and won't be wake up + */ +void cns3xxx_pwr_sleep_test(void) +{ + int i, j, count = 0; + /* 1. Set in SLEEP mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_SLEEP); + + /* 2. disable all functional block */ + i = PM_CLK_GATE_REG; + PM_CLK_GATE_REG = 0x0; + + /* 3. make sure that all function block are in power off state */ + while (0x4 != PM_PWR_STA_REG) { + count++; + if (1000 == count) { + count = PM_PWR_STA_REG; + break; + } + }; + /* 4. power down all PLL */ + j = PM_PLL_HM_PD_CTRL_REG; + PM_PLL_HM_PD_CTRL_REG = 0x00003FFC; + + /* set wake up interrupt source, do nothing */ + PM_WU_CTRL0_REG = 0x0; PM_WU_CTRL1_REG = 0x00000000; + + /* 5. Let CPU enter into WFI state */ + GIC_REG_VALUE(0x104) = 0x1; /* enable clock scaling interrupt */ + printk("<0>enter WFI\n"); + cns3xxx_wfi(); + PM_CLK_GATE_REG = i; + PM_PLL_HM_PD_CTRL_REG = j; + printk("<0>leave WFI, count 0x%.8x\n", count); + GIC_REG_VALUE(0x104) = 0xffffffff; + GIC_REG_VALUE(0x108) = 0xffffffff; + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); +} + +/* + * cns3xxx_pwr_doze - + */ +void cns3xxx_pwr_doze(void) +{ + /* 1. Set in doze mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DOZE); + + + /* set wake up interrupt source*/ + PM_WU_CTRL0_REG = 0x0; PM_WU_CTRL1_REG = 0x40000000; + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 27); + + /* 5. Let CPU enter into WFI state */ + GIC_REG_VALUE(0x104) = 0x1; /* enable clock scaling interrupt */ + printk("<0>enter WFI\n"); + cns3xxx_wfi(); + printk("<0>leave WFI\n"); + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); +} + +/* + * cns3xxx_pwr_idle - + * IDLE mode just turn off CPU clock. + * L2 cache, peripheral, PLL, external DRAM and chip power are still on + */ +void cns3xxx_pwr_idle(void) +{ + /* 1. Set in IDLE mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_IDLE); + +#if 1 + /* disable all interrupt except interrupt ID-32 (clkscale_intr) + * + * CPU can be wake up by any interrupt here, + * we disable all interrupt is just for testing + */ + + /* disable all interrupt */ + GIC_REG_VALUE(0x184) = 0xffffffff; GIC_REG_VALUE(0x188) = 0xffffffff; + /* enable interrupt id 32*/ + GIC_REG_VALUE(0x104) = 0x00000001; GIC_REG_VALUE(0x108) = 0x00000000; +#endif + + /* set wake up interrupt source*/ + PM_WU_CTRL0_REG = 0x0; PM_WU_CTRL1_REG = 0x40000000; + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 27); + + /* 5. Let CPU enter into WFI state */ + printk("<0>enter WFI\n"); + cns3xxx_wfi(); + printk("<0>leave WFI\n"); + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); + GIC_REG_VALUE(0x104) = 0xffffffff; + GIC_REG_VALUE(0x108) = 0xffffffff; +} + +/* + * cns3xxx_pwr_halt - + * HALT mode just turn off CPU and L2 cache clock. + * peripheral, PLL, external DRAM and chip power are still on + */ + +void cns3xxx_pwr_halt(void) +{ + /* 1. Set in HALT mode */ + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_HALT); + + /* + * CPU can be wake up by any interrupt here, + * for test, we disable all interrupt except ID-32 + */ + /* disable all interrupt */ + GIC_REG_VALUE(0x184) = 0xffffffff; GIC_REG_VALUE(0x188) = 0xffffffff; + /* enable interrupt id 32*/ + GIC_REG_VALUE(0x104) = 0x00000001; GIC_REG_VALUE(0x108) = 0x00000000; + + /* set wake up interrupt source to trigger clock scaling interrupt */ + PM_WU_CTRL0_REG = 0x0; PM_WU_CTRL1_REG = 0x40000000; + //MISC_GPIOB_PIN_ENABLE_REG |= (0x1 << 27); + + /* 5. Let CPU enter into WFI state */ + cns3xxx_wfi(); + cns3xxx_pwr_mode(CNS3XXX_PWR_CPU_MODE_DFS); + GIC_REG_VALUE(0x104) = 0xffffffff; + GIC_REG_VALUE(0x108) = 0xffffffff; +} + +/* + * cns3xxx_cpu_clock - return CPU/L2 clock + * aclk: cpu clock/2 + * hclk: cpu clock/4 + * pclk: cpu clock/8 + */ +int cns3xxx_cpu_clock(void) +{ +#define CPU_BASE 300 + int cpu, cpu_sel, div_sel; + + cpu_sel = (PM_CLK_CTRL_REG >> PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL) & 0xf; + div_sel = (PM_CLK_CTRL_REG >> PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV) & 0x3; + + cpu = (CPU_BASE + ((cpu_sel/3) * 100) + ((cpu_sel %3) *33)) >> div_sel; + return cpu; +} + +static int __init cns3xxx_pmu_init(void) +{ + return 0; +} + + +EXPORT_SYMBOL(cns3xxx_pwr_power_up); +EXPORT_SYMBOL(cns3xxx_pwr_clk_en); +EXPORT_SYMBOL(cns3xxx_pwr_soft_rst); +EXPORT_SYMBOL(cns3xxx_pwr_soft_rst_force); +EXPORT_SYMBOL(cns3xxx_cpu_clock); + +module_init(cns3xxx_pmu_init); --- /dev/null +++ b/arch/arm/mach-cns3xxx/rdma.c @@ -0,0 +1,901 @@ +/* + * rdma.c - CNS3XXX RAID-DMA h/w acceleration + * + * Revision History: arch/arm/mach-cns3xxx/ChangeLog.cns_raid.txt + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rdma.h" +#include + +int rdma_verbose; +u8 rdma_test_ptn[32] = {0}; +unsigned int dma_timeout_jiffies; +mempool_t *rdma_sg_pool = NULL; /* pool */ +rdma_chan_t *dma = NULL; /* dma channel */ + +static DEFINE_SPINLOCK(process_lock); + +/* Debug Printk */ +#define dprintk(x...) ((void)(rdma_verbose && printk(KERN_WARNING x))) +#define dump_regs(x) \ +do { \ + dprintk("pa:%08x sg:%08x bp:%08x fp:%08x st:%08x qp:%08x sz:%08x\n", \ + *((x)->cregs->para), \ + *((x)->cregs->sgad), \ + *((x)->cregs->back), \ + *((x)->cregs->frnt), \ + *((x)->cregs->stat), \ + *((x)->cregs->qpar), \ + *((x)->cregs->blsz)); \ +} while (0) + + +#define rdma_dmac_flush_range(start, bytes) \ + do { \ + dma_cache_maint(start, bytes, DMA_BIDIRECTIONAL); \ + } while (0); + +#define rdma_dmac_inv_range(start, bytes) \ + do { \ + dma_cache_maint(start, bytes, DMA_FROM_DEVICE); \ + } while (0); + +#define rdma_dmac_clean_range(start, bytes) \ + do { \ + dma_cache_maint(start, bytes, DMA_TO_DEVICE); \ + } while (0); + + + +extern void *acs_mempool_alloc(mempool_t *pool); + +/** + * rdma_timeout_handle + */ +static void rdma_timeout_handle(rdma_chan_t *rdma) +{ + printk("%s: timeout handling\n", __FUNCTION__); + spin_lock_irq(&process_lock); + + if (!list_empty(&rdma->process_q)) { + sg_t *sg_fin = list_entry(rdma->process_q.next, sg_t, lru); + list_del_init(&sg_fin->lru); + sg_fin->status = SG_STATUS_DONE; + } + + *(dma->cregs->para) = 0; + *(dma->cregs->back) = rdma->q_first_phys; + *(dma->cregs->frnt) = rdma->q_first_phys; + flush_cache_all(); + spin_unlock_irq(&process_lock); +} + +/** + * rdma_mempool_alloc - return a sg from pool + * @gfp_mask: gfp flag + * + * Return: + * sg table + */ +static void *rdma_sg_mempool_alloc(unsigned int gfp_mask) +{ + void *element; + int exception_timeout = 30; + +repeat: + element = acs_mempool_alloc(rdma_sg_pool); + if (likely(element)) + return element; + + if (!(gfp_mask & __GFP_WAIT)) { + return NULL; + } else { + msleep(1000); + exception_timeout--; + WARN_ON(exception_timeout < 0); /* Thresh check, we should check or increase if any warning */ + goto repeat; + } +} + +#define rdma_mempool_create(pool, name, size, min_nr, alloc_fn, free_fn, privp) \ +do { \ + printk("%s: pre-allocating %s: %d*%d=%d\n", \ + __FUNCTION__, (name), (min_nr), (size), (min_nr) * (size)); \ + pool = mempool_create((min_nr), (mempool_alloc_t *)(alloc_fn), free_fn, (privp)); \ + if (!pool) \ + goto abort; \ +} while(0); + +#define rdma_mempool_destroy(pool) \ +do { \ + if (pool) \ + mempool_destroy(pool); \ +} while(0); + +#define rdma_kfree_obj(obj) \ +do { \ + if (obj) \ + kfree(obj); \ +} while(0); + +/** + * rdma_sg_prealloc_fn - sg mempool pre-allocation callback + * @gfp_flags: GFP_ flags + * @data: private data, reserved + * + * Return: + * pre-alloc sg table + */ +static void *rdma_sg_prealloc_fn(int gfp_flags, void *data) +{ + sg_t *sg = NULL; + sg = kzalloc(sizeof(sg_t), gfp_flags); + INIT_LIST_HEAD(&sg->lru); + init_waitqueue_head(&sg->wait); + sg->status = SG_STATUS_FREE; + + /* Remove Debug Message */ +#if 0 + printk("%s: pre-allocating sg=0x%p, phy=0x%p\n", + __FUNCTION__, (void *)sg, (void *)virt_to_phys(sg)); +#endif + + WARN_ON(!sg); + return (void *)sg; +} + +/** + * rdma_sg_deconstruct_fn - sg mempool de-allocation callback + * @sg: sg elements + * @data: private data, reserved + */ +static void rdma_sg_deconstruct_fn(void *sg, void *data) +{ + if (sg) { + printk("%s: de-allocating sg=0x%p, phy=0x%p\n", + __FUNCTION__, (void *)sg, (void *)virt_to_phys(sg)); + kfree(sg); + } + return; +} + + + +/*-------------------------------------------------------- */ +/** + * rdma_get_sg - alloc an SG + * @dma: dma chan + */ +static sg_t *rdma_get_sg(rdma_chan_t *dma) +{ + sg_t *sg = (sg_t *)rdma_sg_mempool_alloc(GFP_KERNEL); + + /* + * No need to zero rest of un-used SG entries; + * we detect the src+dst by parameter + sg, not by zero-valued sg. + */ + // memzero(&(sg->entry[0]), SG_ENTRY_BYTES); + + sg->status = SG_STATUS_ACQUIRED; + + return sg; +} + + +/** + * rdma_queue_sg - queue an SG, wait done and put it. + * @dma: dma chan + * @sg: sg + * @q_para: parameter + * @q_blsz: block size + * @q_sgad: SG Addr + * @sg_cnt: count of (src_cnt + dst_cnt) + */ +#define QUEUE_MODE +static void rdma_queue_sg(rdma_chan_t *rdma, sg_t *sg, u32 q_para, u32 q_blsz, u32 q_sgad, int sg_cnt) +{ + cmdq_t *this_virt = NULL; + + spin_lock_irq(&process_lock); + + sg->status = SG_STATUS_SCHEDULED; + list_add_tail(&sg->lru, &rdma->process_q); + + dump_regs(rdma); + +#ifdef QUEUE_MODE + /* Setup BP */ + this_virt = (cmdq_t *)(phys_to_virt(*(rdma->cregs->back))); + this_virt->parameter = q_para; + this_virt->block_size = q_blsz; + this_virt->sg_addr = q_sgad; + this_virt->reserved = 0; + dump_regs(rdma); + + /* FP++ */ + *(rdma->cregs->frnt) = *(rdma->cregs->frnt) + 16; + dump_regs(rdma); + + /* FIXME */ + { + void *sgp = (void *)sg; + void *cqp = (void *)this_virt; + + rdma_dmac_flush_range(sgp, (sg_cnt * sizeof(u64))); + rdma_dmac_flush_range(cqp, sizeof(cmdq_t)); + } + + /* Queue Enable */ + *(rdma->cregs->stat) = REG_STAT_CMD_QUEUE_ENABLE; + dump_regs(rdma); + +#else + *(dma->cregs->blsz) = q_blsz; + *(rdma->cregs->sgad) = q_sgad; + *(rdma->cregs->para) = q_para; + dump_regs(rdma); +#endif /* QUEUE_MODE */ + + spin_unlock_irq(&process_lock); + dump_regs(rdma); + + wait_event_timeout(sg->wait, + sg->status & (SG_STATUS_DONE | SG_STATUS_ERROR), + dma_timeout_jiffies); + dump_regs(rdma); + + /* timed out */ + if (unlikely(sg->status & SG_STATUS_SCHEDULED)) { + printk("%s: operation timeout\n", __FUNCTION__); + rdma_timeout_handle(rdma); + } + + sg->status = SG_STATUS_FREE; + mempool_free(sg, rdma_sg_pool); + return; +} + + +#define R6_RECOV_PD 1 +#define R6_RECOV_DD 2 +#define R6_RECOV_DQ 3 +/** + * @src_no: source count + * @bytes: len in bytes + * @bh_ptr: srcs PA + * @w1_dst: pd: P, dd: DD1, qd: DD + * @w2_dst: pd: DD, dd: DD2, qd: Q + * @pd_dd_qd: failed layout to recover + * @w1_idx: idx of w1_dst + * @w2_idx: idx of w2_dst + * @src_idx: source index; utilize data index only. + * + * Desc: + * Recover P+DD / DD1+DD2 / DD+Q from bh_ptr + */ +void do_cns_rdma_gfgen_pd_dd_dq(unsigned int src_no, unsigned int bytes, + void **bh_ptr, void *w1_dst, void *w2_dst, + int pd_dd_qd, unsigned int w1_idx, unsigned int w2_idx, + unsigned int *src_idx) +{ + int i; + sg_t *sg = NULL; + u32 q_sgad, q_blsz, q_para; + + /* clean src/dst */ + for (i=0; i PD */ + for (i=0; i<(src_no - 1); i++) { + sg->entry[i] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (SG_READ_IDX_MASK & ((u64)src_idx[i]) << SG_IDX_SHIFT) + | (RWI_RD_D); + } + sg->entry[src_no-1] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (RWI_RD_Q); + + /* pd */ + sg->entry[src_no] = (SG_ADDR_MASK & ((u64)virt_to_phys(w1_dst))) | (RWI_W_P1); + sg->entry[src_no+1] = (SG_ADDR_MASK & ((u64)virt_to_phys(w2_dst))) | (RWI_W_D2); + + q_para = REG_PARA_ENABLE + | REG_PARA_XFER_END + | REG_PARA_CALC_P + | (REG_PARA_FAULTY_DISKS_CNT * 2) + | w2_idx * REG_PARA_FDISK_2_Q_IDX; + break; + + case R6_RECOV_DD: + /* dd...PQ -> DD */ + for (i=0; i<(src_no - 2); i++) { + sg->entry[i] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (SG_READ_IDX_MASK & ((u64)src_idx[i]) << SG_IDX_SHIFT) + | (RWI_RD_D); + } + + sg->entry[src_no-2] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (RWI_RD_P); + sg->entry[src_no-1] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i+1]))) + | (RWI_RD_Q); + + /* dd */ + sg->entry[src_no] = (SG_ADDR_MASK & ((u64)virt_to_phys(w1_dst))) | (RWI_W_D1); + sg->entry[src_no+1] = (SG_ADDR_MASK & ((u64)virt_to_phys(w2_dst))) | (RWI_W_D2); + + q_para = REG_PARA_ENABLE + | REG_PARA_XFER_END + | REG_PARA_CALC_DATA + | (REG_PARA_FAULTY_DISKS_CNT * 2) + | w1_idx * REG_PARA_FDISK_1_P_IDX + | w2_idx * REG_PARA_FDISK_2_Q_IDX; + + break; + + case R6_RECOV_DQ: + /* dd...dP -> DQ */ + for (i=0; i<(src_no - 1); i++) { + sg->entry[i] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (SG_READ_IDX_MASK & ((u64)src_idx[i]) << SG_IDX_SHIFT) + | (RWI_RD_D); + } + sg->entry[src_no-1] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (RWI_RD_P); + + /* qd */ + sg->entry[src_no] = (SG_ADDR_MASK & ((u64)virt_to_phys(w1_dst))) | (RWI_W_D1); + sg->entry[src_no+1] = (SG_ADDR_MASK & ((u64)virt_to_phys(w2_dst))) | (RWI_W_Q2); + + q_para = REG_PARA_ENABLE + | REG_PARA_XFER_END + | REG_PARA_CALC_Q + | (REG_PARA_FAULTY_DISKS_CNT * 2) + | w1_idx * REG_PARA_FDISK_1_P_IDX; + break; + + default: + BUG(); + break; + + } + + q_sgad = virt_to_phys(&(sg->entry[0])); + q_blsz = bytes & REG_BLSZ_MASK; + + if (unlikely(rdma_verbose)) { + for (i=0; ientry[i]); + printk("set-SG::DST1ptr= 0x%016llx\n", sg->entry[src_no]); + printk("set-SG::DST2ptr= 0x%016llx\n", sg->entry[src_no+1]); + } + + /* Queue SG */ + rdma_queue_sg(dma, sg, q_para, q_blsz, q_sgad, (src_no + 2)); + + /* Invalidate dst */ + rdma_dmac_inv_range(w1_dst, bytes); + rdma_dmac_inv_range(w2_dst, bytes); + +abort: + return; +} + +/** + * @src_no: source count + * @bytes: len in bytes + * @bh_ptr: srcs PA + * @p_dst: P dest PA + * @q_dst: Q dest PA + * + * Desc: + * p/q_dst = XOR/GFMUL(bh_ptr[0 ... src_no-1]), in Page Addr + */ +void do_cns_rdma_gfgen(unsigned int src_no, unsigned int bytes, void **bh_ptr, + void *p_dst, void *q_dst) // u8 *gfmr +{ + int i; + sg_t *sg = NULL; + u32 q_sgad, q_blsz, q_para; + + /* clean src/dst */ + for (i=0; ientry[i] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (SG_READ_IDX_MASK & ((u64)i + 1) << SG_IDX_SHIFT) + | (RWI_RD_D); + } + + /* Setup SG::Write::P1 + Q2 */ + sg->entry[src_no] = (SG_ADDR_MASK & ((u64)virt_to_phys(p_dst))) | (RWI_W_P1); + sg->entry[src_no+1] = (SG_ADDR_MASK & ((u64)virt_to_phys(q_dst))) | (RWI_W_Q2); + + /* Setup SGAD, BLSZ, PARAMETER */ + q_sgad = virt_to_phys(&(sg->entry[0])); + q_blsz = bytes & REG_BLSZ_MASK; + q_para = REG_PARA_ENABLE + | REG_PARA_XFER_END + | REG_PARA_CALC_PQ + | (REG_PARA_FAULTY_DISKS_CNT * 2); + + if (unlikely(rdma_verbose)) { + for (i=0; ientry[i]); + printk("set-SG::DST1ptr= 0x%016llx\n", sg->entry[src_no]); + printk("set-SG::DST2ptr= 0x%016llx\n", sg->entry[src_no+1]); + } + + /* Queue SG */ + rdma_queue_sg(dma, sg, q_para, q_blsz, q_sgad, (src_no + 2)); + + /* Invalidate dst */ + rdma_dmac_inv_range(p_dst, bytes); + rdma_dmac_inv_range(q_dst, bytes); + +abort: + return; +} + +/** + * @src_no: source count + * @bytes: len in bytes + * @bh_ptr: srcs PA + * @dst_ptr: dest PA + * + * Desc: + * dst_ptr = XOR(bh_ptr[0 ... src_no-1]), in Page Addr + */ +void do_cns_rdma_xorgen(unsigned int src_no, unsigned int bytes, void **bh_ptr, void *dst_ptr) +{ + int i; + sg_t *sg = NULL; + u32 q_sgad, q_blsz, q_para; + + /* clean src/dst */ + for (i=0; ientry[i] = (SG_ADDR_MASK & ((u64)virt_to_phys(bh_ptr[i]))) + | (SG_READ_IDX_MASK & ((u64)i + 1) << SG_IDX_SHIFT) + | (RWI_RD_D); + } + + /* Setup SG::Write::P1 */ + sg->entry[src_no] = (SG_ADDR_MASK & ((u64)virt_to_phys(dst_ptr))) + | (RWI_W_P1); + + /* Setup SGAD, BLSZ, PARAMETER */ + q_sgad = virt_to_phys(&(sg->entry[0])); + q_blsz = bytes & REG_BLSZ_MASK; + q_para = REG_PARA_ENABLE + | REG_PARA_XFER_END + | REG_PARA_CALC_P + | (REG_PARA_FAULTY_DISKS_CNT * 1); + + if (unlikely(rdma_verbose)) { + for (i=0; ientry[i]); + printk("set-SG::DST1ptr= 0x%016llx\n", sg->entry[src_no]); + } + + /* Queue SG */ + rdma_queue_sg(dma, sg, q_para, q_blsz, q_sgad, (src_no + 1)); + + /* Invalidate dst */ + rdma_dmac_inv_range(dst_ptr, bytes); + +abort: + return; +} + + +/** + * rdma_isr - rdma isr + * @irq: irq# + * @dev_id: private data + */ +static irqreturn_t rdma_isr(int irq, void *dev_id) +{ + unsigned long flags; + rdma_chan_t *this_dma = (rdma_chan_t *)dev_id; + + /* Make sure the INT is for us */ + if (unlikely(dma != this_dma)) + { + printk(KERN_ERR "Unexpected Interrupt, irq=%d, dma=%p, dev_id=%p\n", irq, dma, dev_id); + return IRQ_NONE; + } + + dprintk("%s: pstat=0x%08x\n", __FUNCTION__, *(this_dma->cregs->stat)); + + spin_lock_irqsave(&process_lock, flags); + + /* clear */ + *(this_dma->cregs->stat) = REG_STAT_XFER_COMPLETE | REG_STAT_INTERRUPT_FLAG; + + if (!list_empty(&this_dma->process_q)) { + sg_t *sg_fin = list_entry(this_dma->process_q.next, sg_t, lru); + + BUG_ON(!(sg_fin->status & SG_STATUS_SCHEDULED)); + + list_del_init(&sg_fin->lru); + sg_fin->status = SG_STATUS_DONE; // TODO: slave/decoder error handling + + /* FP rewind */ + if (*(dma->cregs->frnt) == this_dma->q_last_phys) { + *(dma->cregs->back) = this_dma->q_first_phys; + *(dma->cregs->frnt) = this_dma->q_first_phys; + } + + wake_up(&sg_fin->wait); + } + spin_unlock_irqrestore(&process_lock, flags); + + return IRQ_HANDLED; +} + +/** + * test_show - show unit test result + */ +static void test_show(void **src, unsigned int bytes, void *p, void *q, unsigned int src_cnt, int stage) +{ + int i; + char *buf; + + for (i=0; i= (MAX_ENTRIES_PER_SG - 2)) + src_cnt = MAX_ENTRIES_PER_SG - 2; + + if (src_cnt < 2) + src_cnt = 2; + + if (bytes > 65536) + bytes = 65536; + + if (bytes < 4096) + bytes = 4096; + + for (i = 0; i < MAX_ENTRIES_PER_SG; i++) { + if (i < src_cnt) { + src_ptrs[i] = kmalloc(bytes, GFP_KERNEL); + } else { + src_ptrs[i] = NULL; + } + } + p_dst = kmalloc(bytes, GFP_KERNEL); + q_dst = kmalloc(bytes, GFP_KERNEL); + + printk("%s: ACTION=%d, src_cnt=%u, bytes=%u p/w1=0x%p, q/w2=0x%p\n", + __FUNCTION__, action, src_cnt, bytes, p_dst, q_dst); + + /* Shuffle the src and dst */ + for (i = 0; i < src_cnt; i++) { + if (rdma_test_ptn[0] == 0) { + memset(src_ptrs[i], (jiffies % 240)+1, bytes); + msleep(10 + 10 * i); + } else { + memset(src_ptrs[i], rdma_test_ptn[i], bytes); + } + } + memset(p_dst, 0xff, bytes); + memset(q_dst, 0xff, bytes); + + // flush_cache_all(); + test_show(src_ptrs, bytes, p_dst, q_dst, src_cnt, 1); + + switch (action) + { + /* P */ + case 1: + printk("\n%s: XORgen\n\n", __FUNCTION__); + do_cns_rdma_xorgen(src_cnt, bytes, src_ptrs, p_dst); + break; + + /* PQ */ + case 2: + printk("\n%s: PQgen\n\n", __FUNCTION__); + do_cns_rdma_gfgen(src_cnt, bytes, src_ptrs, p_dst, q_dst); + break; + + /* PD */ + case 3: + w1_idx = src_cnt + 1; + w2_idx = 1; + cnt = 0; + + printk("read_idx: "); + for (i=1; i<=(src_cnt+2); i++) + if (i != w1_idx && i != w2_idx) { + read_idx[cnt] = i; + printk("%d ", i); + cnt++; + } + printk("\n%s: PDgen w1/w2_idx=%u/%u\n\n", __FUNCTION__, w1_idx, w2_idx); + do_cns_rdma_gfgen_pd_dd_dq(src_cnt, bytes, src_ptrs, p_dst, q_dst, + R6_RECOV_PD, w1_idx, w2_idx, read_idx); + break; + + /* DD */ + case 4: + w1_idx = 1; + w2_idx = 2; + cnt = 0; + + printk("read_idx: "); + for (i=1; i<=(src_cnt+2); i++) + if (i != w1_idx && i != w2_idx) { + read_idx[cnt] = i; + printk("%d ", i); + cnt++; + } + printk("\n%s: DDgen w1/w2_idx=%u/%u\n\n", __FUNCTION__, w1_idx, w2_idx); + do_cns_rdma_gfgen_pd_dd_dq(src_cnt, bytes, src_ptrs, p_dst, q_dst, + R6_RECOV_DD, w1_idx, w2_idx, read_idx); + break; + + /* DQ */ + case 5: + w1_idx = 1; + w2_idx = src_cnt + 2; + cnt = 0; + + printk("read_idx: "); + for (i=1; i<=(src_cnt+2); i++) + if (i != w1_idx && i != w2_idx) { + read_idx[cnt] = i; + printk("%d ", i); + cnt++; + } + printk("\n%s: DQgen w1/w2_idx=%u/%u\n\n", __FUNCTION__, w1_idx, w2_idx); + do_cns_rdma_gfgen_pd_dd_dq(src_cnt, bytes, src_ptrs, p_dst, q_dst, + R6_RECOV_DQ, w1_idx, w2_idx, read_idx); + break; + + /* Verbose */ + case 9999: + rdma_verbose = (rdma_verbose == 1 ? 0 : 1); + printk("\n%s: Setup verbose mode => %d\n\n", __FUNCTION__, rdma_verbose); + break; + + /* + * SRC Pattern Assign + * e.g. 0x00000000 <-- do not assign + * e.g. 0xbbccddee <-- 4 src: bb cc dd ee + */ + default: + rdma_test_ptn[0] = (u8)(action >> 24 & 0x000000FF); + rdma_test_ptn[1] = (u8)(action >> 16 & 0x000000FF); + rdma_test_ptn[2] = (u8)(action >> 8 & 0x000000FF); + rdma_test_ptn[3] = (u8)(action & 0x000000FF); + + printk("\n%s: Setup src test pattern => 0x%02x %02x %02x %02x\n\n", __FUNCTION__, + rdma_test_ptn[0], + rdma_test_ptn[1], + rdma_test_ptn[2], + rdma_test_ptn[3]); + break; + } + + // flush_cache_all(); + test_show(src_ptrs, bytes, p_dst, q_dst, src_cnt, 2); + + for (i = 0; i < MAX_ENTRIES_PER_SG; i++) { + rdma_kfree_obj(src_ptrs[i]); + } + rdma_kfree_obj(p_dst); + rdma_kfree_obj(q_dst); + +} + +void cns_rdma_hw_init(void){ + + cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_RAID); + cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_RAID); +} + +/** + * cns_rdma_init - module init + */ +int __init cns_rdma_init(void) +{ + int err = 0; + + printk("%s: start\n", __FUNCTION__); + + cns_rdma_hw_init(); + + rdma_test_ptn[0] = 0; + rdma_verbose = 0; + dma_timeout_jiffies = HZ; + + /* DMA chan */ + dma = (rdma_chan_t *) kzalloc(sizeof(rdma_chan_t), GFP_KERNEL); + if (dma == NULL) + goto abort; + + INIT_LIST_HEAD(&(dma->process_q)); + + //static DEFINE_SPINLOCK(dma->process_lock); + dma->irq = IRQ_CNS3XXX_RAID; + dma->irq_str = "CNS3XXX RAID acceleration"; + dma->cregs = NULL; + dma->q_virt = NULL; + + /* control register */ + dma->cregs = (struct ctrl_regs *) kzalloc(sizeof(struct ctrl_regs) + GENERIC_ALIGN, GFP_KERNEL); + dma->cregs = (struct ctrl_regs *) (((u32) dma->cregs & GENERIC_ALIGN_MASK) + GENERIC_ALIGN); + + if (dma->cregs == NULL) + goto abort; + + printk("%s: reg1: virt=0x%p\n", + __FUNCTION__, (void *)dma->cregs); + + dma->cregs->para = RDMA_REGS_VIRT(REG_PARA_OFFSET); + dma->cregs->blsz = RDMA_REGS_VIRT(REG_BLSZ_OFFSET); + dma->cregs->sgad = RDMA_REGS_VIRT(REG_SGAD_OFFSET); + dma->cregs->stat = RDMA_REGS_VIRT(REG_STAT_OFFSET); + dma->cregs->frnt = RDMA_REGS_VIRT(REG_FRNT_OFFSET); + dma->cregs->back = RDMA_REGS_VIRT(REG_BACK_OFFSET); + dma->cregs->qpar = RDMA_REGS_VIRT(REG_QPAR_OFFSET); + + /* Pre-allocate S/G table */ + rdma_mempool_create(rdma_sg_pool, "rdma_sg", sizeof(sg_t), + MAX_SG, rdma_sg_prealloc_fn, rdma_sg_deconstruct_fn, NULL); + + /* Pre-allocate Queue Cmds */ + dma->q_virt = (cmdq_t *) kzalloc(sizeof(cmdq_t) * CURR_Q_DEPTH + CURR_Q_DEPTH_ALIGN, GFP_KERNEL); + dma->q_virt = (cmdq_t *) (((u32) dma->q_virt & CURR_Q_DEPTH_ALIGN_MASK) + CURR_Q_DEPTH_ALIGN); + + if (dma->q_virt == NULL) + goto abort; + + dma->q_first_phys = virt_to_phys((void *)dma->q_virt); + dma->q_last_phys = dma->q_first_phys + sizeof(cmdq_t) * (CURR_Q_DEPTH - 1); + + printk("%s: q1: virt=0x%p, phy=0x%x -> 0x%x\n", + __FUNCTION__, (void *)dma->q_virt, dma->q_first_phys, dma->q_last_phys); + + *(dma->cregs->qpar) = REG_QPAR_DEPTH_32; + *(dma->cregs->back) = dma->q_first_phys; + *(dma->cregs->frnt) = dma->q_first_phys; + + /* Register IRQ */ + err = request_irq(dma->irq, rdma_isr, 0, dma->irq_str, dma); + if (err) { + printk("%s: request irq failed\n", __FUNCTION__); + goto abort; + } + + /* Clear 31 & 0 */ + *(dma->cregs->stat) = REG_STAT_INTERRUPT_FLAG; + + err = 0; + goto done; + +abort: + rdma_mempool_destroy(rdma_sg_pool); + rdma_kfree_obj(dma->cregs); + rdma_kfree_obj(dma); + + +done: + printk("%s: done, err=%d\n", __FUNCTION__, err); + return err; +} + +/** + * cns_rdma_exit - module exit + */ +void cns_rdma_exit(void) +{ + printk("%s: start\n", __FUNCTION__); + + rdma_mempool_destroy(rdma_sg_pool); + rdma_kfree_obj(dma->cregs); + rdma_kfree_obj(dma); + printk("%s: done\n", __FUNCTION__); +} + +//module_init(cns_rdma_init); +//module_exit(cns_rdma_exit); --- /dev/null +++ b/arch/arm/mach-cns3xxx/rdma.h @@ -0,0 +1,178 @@ +/* + * rdma.h - CNS3xxx hardware RAID acceleration + */ +#ifndef _CNS3XXX_RDMA_H_ +#define _CNS3XXX_RDMA_H_ + +#include + +#define RDMA_REGS_PHYS(x) ((u32)(CNS3XXX_RAID_BASE + (x))) +#define RDMA_REGS_VIRT(x) ((u32 volatile *)(CNS3XXX_RAID_BASE_VIRT + (x))) +#define RDMA_REGS_VALUE(x) (*((u32 volatile *)(CNS3XXX_RAID_BASE_VIRT + (x)))) + + +#define GENERIC_ALIGN 0x8 /* 64-bits */ +#define GENERIC_ALIGN_MASK 0xFFFFFFF8UL +#define QUEUE_DEPTH_ALIGN_MUL 0x10 /* 16 bytes; ALIGNMENT == QDEPTH * 16 bytes */ + + +/* Register Offset */ +#define REG_PARA_OFFSET 0x00UL /* Parameter */ +#define REG_BLSZ_OFFSET 0x04UL /* Block Size */ +#define REG_SGAD_OFFSET 0x08UL /* SG Address */ +#define REG_STAT_OFFSET 0x0CUL /* Status */ +#define REG_FRNT_OFFSET 0x10UL /* FP */ +#define REG_BACK_OFFSET 0x14UL /* BP */ +#define REG_QPAR_OFFSET 0x18UL /* Queue Parameter */ + + +/* 0x00: PARA */ +#define REG_PARA_ENABLE 0x80000000UL /* 31 */ +#define REG_PARA_XFER_END 0x40000000UL /* 30 */ +#define REG_PARA_MEMORY_WR_DISABLE 0x20000000UL /* 29 */ +#define REG_PARA_FAULTY_DISKS_CNT 0x08000000UL /* 28:27 */ + +#define REG_PARA_CALC 0x01000000UL /* 26:24 */ + #define REG_PARA_CALC_DATA 0x00000000UL + #define REG_PARA_CALC_P 0x01000000UL + #define REG_PARA_CALC_Q 0x02000000UL + #define REG_PARA_CALC_R 0x04000000UL + #define REG_PARA_CALC_PQ 0x03000000UL + #define REG_PARA_CALC_PR 0x05000000UL + #define REG_PARA_CALC_QR 0x06000000UL + #define REG_PARA_CALC_PQR 0x07000000UL + +#define REG_PARA_FDISK_3_R_IDX 0x00010000UL /* 23:16 */ +#define REG_PARA_FDISK_2_Q_IDX 0x00000100UL /* 15:8 */ +#define REG_PARA_FDISK_1_P_IDX 0x00000001UL /* 7:0 */ + +/* 0x04: BLSZ */ +#define REG_BLSZ_SHIFT 3 /* 19:3 */ +#define REG_BLSZ_MASK 0x000FFFF8UL /* N * 8bytes */ + +/* 0x08: SGAD */ +#define REG_SGAD_SHIFT 0 + +/* 0x0C: STAT */ +#define REG_STAT_XFER_COMPLETE 0x80000000UL /* 31 */ +#define REG_STAT_SLAVE_ERROR 0x40000000UL /* 30 */ +#define REG_STAT_DECODER_ERROR 0x20000000UL /* 29 */ +#define REG_STAT_R_FLAG 0x00080000UL /* 19 */ +#define REG_STAT_Q_FLAG 0x00040000UL /* 18 */ +#define REG_STAT_P_FLAG 0x00020000UL /* 17 */ +#define REG_STAT_CMD_QUEUE_ENABLE 0x00000002UL /* 1 */ +#define REG_STAT_INTERRUPT_FLAG 0x00000001UL /* 0 */ + +/* 0x10/14: FRNT/BACK */ +#define REG_FRNT_SHIFT 0 +#define REG_BACK_SHIFT 0 + +/* 0x18: QPAR */ +#define MAX_Q_DEPTH 256 +#define REG_QPAR_DEPTH_256 0xFF +#define REG_QPAR_DEPTH_128 0x7F +#define REG_QPAR_DEPTH_64 0x3F +#define REG_QPAR_DEPTH_32 0x1F +#define REG_QPAR_DEPTH_16 0xF +#define REG_QPAR_DEPTH_8 0x7 +#define REG_QPAR_DEPTH_4 0x3 +#define REG_QPAR_DEPTH_2 0x1 + +/* len = 32 */ +#define CURR_Q_DEPTH (REG_QPAR_DEPTH_32 + 1) +#define CURR_Q_DEPTH_ALIGN ((CURR_Q_DEPTH) * (QUEUE_DEPTH_ALIGN_MUL)) /* 0x200 */ +#define CURR_Q_DEPTH_ALIGN_MASK 0xFFFFFE00UL + + +#define MAX_SG 32 // cf. CURR_Q_DEPTH or MAX_Q_DEPTH +#define MAX_ENTRIES_PER_SG 32 + +/* SG Table */ +#define SG_ADDR_MASK 0x00000000FFFFFFFFULL + +#define SG_READ_IDX_MASK 0x000000FF00000000ULL +#define SG_IDX_SHIFT 32 + +// ---------------------- 7654321076543210 +#define SG_RW_MASK 0x00000F0000000000ULL +#define RWI_RD_D 0x0000000000000000ULL +#define RWI_RD_P 0x0000010000000000ULL +#define RWI_RD_Q 0x0000020000000000ULL +#define RWI_RD_R 0x0000030000000000ULL +#define RWI_W_D1 0x0000040000000000ULL +#define RWI_W_P1 0x0000050000000000ULL +#define RWI_W_Q1 0x0000060000000000ULL +#define RWI_W_R1 0x0000070000000000ULL +#define RWI_W_D2 0x0000080000000000ULL +#define RWI_W_P2 0x0000090000000000ULL +#define RWI_W_Q2 0x00000A0000000000ULL +#define RWI_W_R2 0x00000B0000000000ULL +#define RWI_W_D3 0x00000C0000000000ULL +#define RWI_W_P3 0x00000D0000000000ULL +#define RWI_W_Q3 0x00000E0000000000ULL +#define RWI_W_R3 0x00000F0000000000ULL + + +#define SG_STATUS_FREE 0x00000001UL +#define SG_STATUS_ACQUIRED 0x00000002UL +#define SG_STATUS_SCHEDULED 0x00000004UL +#define SG_STATUS_DONE 0x00000008UL +#define SG_STATUS_ERROR 0x00000010UL + +#define SG_ENTRY_BYTES (8 * MAX_ENTRIES_PER_SG) + +typedef struct rdma_sgtable sg_t; +struct rdma_sgtable { + u64 entry[MAX_ENTRIES_PER_SG]; + + struct list_head lru; /* list_add_tail/list_del to/from process_q when schedule or isr */ + wait_queue_head_t wait; + + u32 status; +}; + +/* Command Queue: cmdq_t */ +typedef struct rdma_cmdq cmdq_t; +struct rdma_cmdq { + volatile u32 parameter; + volatile u32 block_size; + volatile u32 sg_addr; + volatile u32 reserved; +}; + +struct ctrl_regs { + volatile u32 *para; + volatile u32 *blsz; + volatile u32 *sgad; + volatile u32 *stat; + volatile u32 *frnt; + volatile u32 *back; + volatile u32 *qpar; +}; + +/* channel */ +#define RDMA_CHANNEL_COUNT 1 +typedef struct rdma_channel rdma_chan_t; +struct rdma_channel +{ + struct list_head process_q; + spinlock_t process_lock; /* process queue lock */ + + int irq; + const char *irq_str; + + /* cmd queue start address */ + volatile cmdq_t *q_virt; + volatile u32 q_first_phys; + volatile u32 q_last_phys; + + /* control regs */ + struct ctrl_regs *cregs; + + // wait_queue_head_t wait; +}; + +int __init cns_rdma_init(void); + +#endif + --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -146,6 +146,7 @@ machine-$(CONFIG_ARCH_ORION5X) := orion machine-$(CONFIG_ARCH_PNX4008) := pnx4008 machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_REALVIEW) := realview +machine-$(CONFIG_ARCH_CNS3XXX) := cns3xxx machine-$(CONFIG_ARCH_RPC) := rpc machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 --- /dev/null +++ b/arch/arm/mm/cache-l2cc.c @@ -0,0 +1,218 @@ +/******************************************************************************* + * + * arch/arm/mm/cache-l2cc.c - L2 cache controller support + * + * Copyright (c) 2008 Cavium Networks + * + * 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 +#include + +#include +#include +#include + +#define CACHE_LINE_SIZE 32 + +static void __iomem *cns3xxx_l2_base; +static DEFINE_SPINLOCK(cns3xxx_l2_lock); + +static inline void cache_wait(void __iomem *reg, unsigned long mask) +{ +#ifndef CONFIG_L2CC_NO_WAIT + /* wait for the operation to complete */ + while (readl(reg) & mask); +#endif +} + +static inline void sync_writel(unsigned long val, unsigned long reg, + unsigned long complete_mask) +{ + unsigned long flags; + + spin_lock_irqsave(&cns3xxx_l2_lock, flags); + writel(val, cns3xxx_l2_base + reg); + /* wait for the operation to complete */ + while (readl(cns3xxx_l2_base + reg) & complete_mask) + ; + spin_unlock_irqrestore(&cns3xxx_l2_lock, flags); +} + +static inline void cache_sync(void) +{ + sync_writel(0, L2CC_CACHE_SYNC, 1); +} + +static inline void cns3xxx_l2_inv_all(void) +{ + /* invalidate all ways */ + sync_writel(0xffff, L2CC_INV_WAY, 0xffff); + cache_sync(); +} + +static void cns3xxx_l2_inv_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + writel(start, cns3xxx_l2_base + L2CC_CLEAN_INV_LINE_PA); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + writel(end, cns3xxx_l2_base + L2CC_CLEAN_INV_LINE_PA); + } + + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + writel(addr, cns3xxx_l2_base + L2CC_INV_LINE_PA); + + cache_sync(); +} + +static void cns3xxx_l2_clean_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(CACHE_LINE_SIZE - 1); + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + writel(addr, cns3xxx_l2_base + L2CC_CLEAN_LINE_PA); + + cache_wait(cns3xxx_l2_base + L2CC_CLEAN_LINE_PA, 1); + cache_sync(); +} + +static void cns3xxx_l2_flush_range(unsigned long start, unsigned long end) +{ + unsigned long addr; + + start &= ~(CACHE_LINE_SIZE - 1); + for (addr = start; addr < end; addr += CACHE_LINE_SIZE) + writel(addr, cns3xxx_l2_base + L2CC_CLEAN_INV_LINE_PA); + + cache_wait(cns3xxx_l2_base + L2CC_CLEAN_INV_LINE_PA, 1); + cache_sync(); +} + +void __init l2cc_init(void __iomem *base) +{ + __u32 aux, prefetch, tag, data; + + printk(KERN_INFO "Initializing CNS3XXX L2 cache controller... "); + + cns3xxx_l2_base = base; + + /* disable L2CC */ + writel(0, cns3xxx_l2_base + L2CC_CTRL); + + /* + * Auxiliary control register + * + * bit[22] - shared attribute internally ignored + * bit[21] - parity enabled + * bit[20] - + * bit[19:17] - 32kB way size + * bit[16] - way associative + * bit[12] - exclusive cache disabled + * + */ + aux = readl(cns3xxx_l2_base + L2CC_AUX_CTRL); + aux &= 0xfe000fff; +#ifdef CONFIG_CACHE_L2_I_PREFETCH + aux |= 0x20000000; /* bit[29]: Instruction prefetching enable, bit[29]: Data prefetching enable */ +#endif +#ifdef CONFIG_CACHE_L2_D_PREFETCH + aux |= 0x10000000; /* bit[28]: Instruction prefetching enable, bit[28]: Data prefetching enable */ +#endif + aux |= 0x00540000; /* ...010..., 32KB, 8-way, Parity Disable*/ + writel(aux, cns3xxx_l2_base + L2CC_AUX_CTRL); + + prefetch = readl(cns3xxx_l2_base + 0xF60); + prefetch |= 0x00000008; /* prefetch offset, bit[4..0] */ +#ifdef CONFIG_CACHE_L2_I_PREFETCH + prefetch |= 0x20000000; +#endif +#ifdef CONFIG_CACHE_L2_D_PREFETCH + prefetch |= 0x10000000; +#endif + writel(prefetch, cns3xxx_l2_base + 0xF60); + + /* Tag RAM Control register + * + * bit[10:8] - 1 cycle of write accesses latency + * bit[6:4] - 1 cycle of read accesses latency + * bit[3:0] - 1 cycle of setup latency + * + * 1 cycle of latency for setup, read and write accesses + */ + tag = readl(cns3xxx_l2_base + L2CC_TAG_RAM_LATENCY_CTRL); + tag &= 0xfffff888; + tag |= 0x00000000; + writel(tag, cns3xxx_l2_base + L2CC_TAG_RAM_LATENCY_CTRL); + + /* Data RAM Control register + * + * bit[10:8] - 1 cycles of write accesses latency + * bit[6:4] - 1 cycles of read accesses latency + * bit[3:0] - 1 cycle of setup latency + * + * 1 cycle of setup latency, 2 cycles of read and write accesses latency + */ + data = readl(cns3xxx_l2_base + L2CC_DATA_RAM_LATENCY_CTRL); + data &= 0xfffff888; + data |= 0x00000000; + writel(data, cns3xxx_l2_base + L2CC_DATA_RAM_LATENCY_CTRL); + + cns3xxx_l2_inv_all(); + + /* lockdown required ways for different effective size of the L2 cache */ +#ifdef CONFIG_CACHE_L2CC_32KB + /* 32KB, lock way7..1 */ + writel(0xfe, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_D); + writel(0xfe, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_I); + printk(KERN_INFO "CNS3XXX L2 cache lock down : way7..1\n"); +#elif defined(CONFIG_CACHE_L2CC_64KB) + /* 64KB, lock way7..2 */ + writel(0xfc, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_D); + writel(0xfc, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_I); + printk(KERN_INFO "CNS3XXX L2 cache lock down : way7..2\n"); +#elif defined(CONFIG_CACHE_L2CC_96KB) + /* 96KB, lock way7..3 */ + writel(0xf8, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_D); + writel(0xf8, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_I); + printk(KERN_INFO "CNS3XXX L2 cache lock down : way7..3\n"); +#elif defined(CONFIG_CACHE_L2CC_128KB) + /* 128KB, lock way7..4 */ + writel(0xf0, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_D); + writel(0xf0, cns3xxx_l2_base + L2CC_LOCKDOWN_0_WAY_I); + printk(KERN_INFO "CNS3XXX L2 cache lock down : way7..4\n"); +#endif + + /* enable L2CC */ + writel(1, cns3xxx_l2_base + L2CC_CTRL); + + outer_cache.inv_range = cns3xxx_l2_inv_range; + outer_cache.clean_range = cns3xxx_l2_clean_range; + outer_cache.flush_range = cns3xxx_l2_flush_range; + + printk("done.\n"); +} --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -109,6 +109,25 @@ void __init l2x0_init(void __iomem *base l2x0_inv_all(); + /* lockdown required ways for different effective size of the L2 cache */ +#ifdef CONFIG_CACHE_L2X0_128KB + /* 128KB, lock way7..1 */ + writel(0xfe, l2x0_base + L2X0_LOCKDOWN_WAY_D); + writel(0xfe, l2x0_base + L2X0_LOCKDOWN_WAY_I); +#elif defined(CONFIG_CACHE_L2X0_256KB) + /* 256KB, lock way7..2 */ + writel(0xfc, l2x0_base + L2X0_LOCKDOWN_WAY_D); + writel(0xfc, l2x0_base + L2X0_LOCKDOWN_WAY_I); +#elif defined(CONFIG_CACHE_L2X0_512KB) + /* 512KB, lock way7..3 */ + writel(0xf8, l2x0_base + L2X0_LOCKDOWN_WAY_D); + writel(0xf8, l2x0_base + L2X0_LOCKDOWN_WAY_I); +#elif defined(CONFIG_CACHE_L2X0_1MB) + /* 1MB, lock way7..4 */ + writel(0xf0, l2x0_base + L2X0_LOCKDOWN_WAY_D); + writel(0xf0, l2x0_base + L2X0_LOCKDOWN_WAY_I); +#endif + /* enable L2X0 */ writel(1, l2x0_base + L2X0_CTRL); --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -29,7 +29,8 @@ #error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" #endif -#define CONSISTENT_END (0xffe00000) +//#define CONSISTENT_END (0xffe00000) +#define CONSISTENT_END (0xf2000000) #define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE) #define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) @@ -208,7 +209,7 @@ __dma_alloc(struct device *dev, size_t s { void *ptr = page_address(page); memset(ptr, 0, size); - dmac_flush_range(ptr, ptr + size); + smp_dma_flush_range(ptr, ptr + size); outer_flush_range(__pa(ptr), __pa(ptr) + size); } @@ -498,15 +499,15 @@ void dma_cache_maint(const void *start, switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - inner_op = dmac_inv_range; + inner_op = smp_dma_inv_range; outer_op = outer_inv_range; break; case DMA_TO_DEVICE: /* writeback only */ - inner_op = dmac_clean_range; + inner_op = smp_dma_clean_range; outer_op = outer_clean_range; break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - inner_op = dmac_flush_range; + inner_op = smp_dma_flush_range; outer_op = outer_flush_range; break; default: @@ -528,15 +529,15 @@ static void dma_cache_maint_contiguous(s switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - inner_op = dmac_inv_range; + inner_op = smp_dma_inv_range; outer_op = outer_inv_range; break; case DMA_TO_DEVICE: /* writeback only */ - inner_op = dmac_clean_range; + inner_op = smp_dma_clean_range; outer_op = outer_clean_range; break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - inner_op = dmac_flush_range; + inner_op = smp_dma_flush_range; outer_op = outer_flush_range; break; default: --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -391,7 +391,7 @@ config CPU_FEROCEON_OLD_ID # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_CNS3XXX || MACH_REALVIEW_PBX select CPU_32v6 select CPU_ABRT_EV6 select CPU_PABRT_NOIFAR @@ -516,6 +516,16 @@ config CPU_CACHE_VIPT config CPU_CACHE_FA bool +config CPU_NO_CACHE_BCAST + bool + depends on SMP + default y if CPU_V6 + +config CPU_NO_CACHE_BCAST_DEBUG + bool + depends on SMP + default y if CPU_V6 + if MMU # The copy-page model config CPU_COPY_V3 @@ -759,11 +769,84 @@ config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX - default y + default n select OUTER_CACHE help This option enables the L2x0 PrimeCell. +choice + prompt "L2 Cache Size" + depends on CACHE_L2X0 + default CACHE_L2X0_1MB + +config CACHE_L2X0_128KB + bool "128KB" + help + 16KB/way, 8-way, evmon/parity/share enabled + +config CACHE_L2X0_256KB + bool "256KB" + help + 32KB/way, 8-way, evmon/parity/share enabled + +config CACHE_L2X0_512KB + bool "512KB" + help + 64KB/way, 8-way, evmon/parity/share enabled + +config CACHE_L2X0_1MB + bool "1MB" + help + 128KB/way, 8-way, evmon/parity/share enabled +endchoice + +config CACHE_L2CC + bool "Enable the L2 outer cache controller" + depends on ARCH_CNS3XXX + default n + select OUTER_CACHE + help + This option enables the L2 cache controller. + +choice + prompt "L2 Cache Size" + depends on CACHE_L2CC + default CACHE_L2CC_256KB + +config CACHE_L2CC_32KB + bool "32KB" + help + 4KB/way, 8-way, evmon/share enabled + +config CACHE_L2CC_64KB + bool "64KB" + help + 8KB/way, 8-way, evmon/share enabled + +config CACHE_L2CC_96KB + bool "96KB" + help + 12KB/way, 8-way, evmon/share enabled + +config CACHE_L2CC_128KB + bool "128KB" + help + 16KB/way, 8-way, evmon/share enabled + +config CACHE_L2CC_256KB + bool "256KB" + help + 32KB/way, 8-way, evmon/share enabled + +endchoice + +config CACHE_L2_I_PREFETCH + bool "Enable the L2 instruction prefetching" + depends on CACHE_L2CC + default y + help + This option enables instruction prefetching. + config CACHE_XSC3L2 bool "Enable the L2 cache on XScale3" depends on CPU_XSC3 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -82,5 +82,6 @@ obj-$(CONFIG_CPU_V7) += proc-v7.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o +obj-$(CONFIG_CACHE_L2CC) += cache-l2cc.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -687,7 +687,7 @@ __early_param("vmalloc=", early_vmalloc) static void __init sanity_check_meminfo(void) { - int i, j, highmem = 0; + int i, j; for (i = 0, j = 0; i < meminfo.nr_banks; i++) { struct membank *bank = &meminfo.bank[j]; --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2668,3 +2668,5 @@ #define PCI_DEVICE_ID_RME_DIGI32 0x9896 #define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 #define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 + +#define PCI_VENDOR_ID_CAVIUM 0x177d --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sat Jun 20 22:28:39 2009 +# Last update: Wed Jun 9 02:11:30 2010 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -928,7 +928,7 @@ palmt5 MACH_PALMT5 PALMT5 917 palmtc MACH_PALMTC PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 mxc30030evb MACH_MXC30030EVB MXC30030EVB 920 -rea_2d MACH_REA_2D REA_2D 921 +rea_cpu2 MACH_REA_2D REA_2D 921 eti3e524 MACH_TI3E524 TI3E524 922 ateb9200 MACH_ATEB9200 ATEB9200 923 auckland MACH_AUCKLAND AUCKLAND 924 @@ -1319,7 +1319,7 @@ mistral MACH_MISTRAL MISTRAL 1315 msm MACH_MSM MSM 1316 ct5910 MACH_CT5910 CT5910 1317 ct5912 MACH_CT5912 CT5912 1318 -hynet_ine MACH_HYNET_INE HYNET_INE 1319 +argonst_foundation MACH_HYNET_INE HYNET_INE 1319 hynet_app MACH_HYNET_APP HYNET_APP 1320 msm7200 MACH_MSM7200 MSM7200 1321 msm7600 MACH_MSM7600 MSM7600 1322 @@ -1638,7 +1638,7 @@ mx35evb MACH_MX35EVB MX35EVB 1643 aml_m8050 MACH_AML_M8050 AML_M8050 1644 mx35_3ds MACH_MX35_3DS MX35_3DS 1645 mars MACH_MARS MARS 1646 -ntosd_644xa MACH_NTOSD_644XA NTOSD_644XA 1647 +neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647 badger MACH_BADGER BADGER 1648 trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649 trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650 @@ -1654,7 +1654,7 @@ vf10xx MACH_VF10XX VF10XX 1659 zoran43xx MACH_ZORAN43XX ZORAN43XX 1660 sonix926 MACH_SONIX926 SONIX926 1661 celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662 -cc9m2443 MACH_CC9M2443 CC9M2443 1663 +cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663 tw5334 MACH_TW5334 TW5334 1664 omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665 nal_hlite MACH_NAL_HLITE NAL_HLITE 1666 @@ -1769,14 +1769,15 @@ mx31cicada MACH_MX31CICADA MX31CICADA mi424wr MACH_MI424WR MI424WR 1778 axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 -davinci_da8xx_evm MACH_DAVINCI_DA8XX_EVM DAVINCI_DA8XX_EVM 1781 +davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781 ep9302 MACH_EP9302 EP9302 1782 at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 cybook3 MACH_CYBOOK3 CYBOOK3 1784 wdg002 MACH_WDG002 WDG002 1785 sg560adsl MACH_SG560ADSL SG560ADSL 1786 nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787 -marvell_newdb MACH_MARVELL_NEWDB MARVELL_NEWDB 1789 +dove_db MACH_DOVE_DB DOVE_DB 1788 +dove_avng MACH_MARVELL_NEWDB MARVELL_NEWDB 1789 vandihud MACH_VANDIHUD VANDIHUD 1790 magx_e8 MACH_MAGX_E8 MAGX_E8 1791 magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792 @@ -1802,7 +1803,7 @@ ccw9p9215js MACH_CCW9P9215JS CCW9P9215J rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812 sifmain MACH_SIFMAIN SIFMAIN 1813 sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814 -cc9m2443js MACH_CC9M2443JS CC9M2443JS 1815 +cc9m2443 MACH_CC9M2443 CC9M2443 1815 xaria300 MACH_XARIA300 XARIA300 1816 it9200 MACH_IT9200 IT9200 1817 rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818 @@ -1962,7 +1963,7 @@ ethernut5 MACH_ETHERNUT5 ETHERNUT5 19 arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 -cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 +eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 cheflux MACH_CHEFLUX CHEFLUX 1976 eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 opcotec MACH_OPCOTEC OPCOTEC 1978 @@ -2249,14 +2250,14 @@ omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_ darwin MACH_DARWIN DARWIN 2262 oratiscomu MACH_ORATISCOMU ORATISCOMU 2263 rtsbc20 MACH_RTSBC20 RTSBC20 2264 -i780 MACH_I780 I780 2265 +sgh_i780 MACH_I780 I780 2265 gemini324 MACH_GEMINI324 GEMINI324 2266 oratislan MACH_ORATISLAN ORATISLAN 2267 oratisalog MACH_ORATISALOG ORATISALOG 2268 oratismadi MACH_ORATISMADI ORATISMADI 2269 oratisot16 MACH_ORATISOT16 ORATISOT16 2270 oratisdesk MACH_ORATISDESK ORATISDESK 2271 -v2p_ca9 MACH_V2P_CA9 V2P_CA9 2272 +vexpress MACH_VEXPRESS VEXPRESS 2272 sintexo MACH_SINTEXO SINTEXO 2273 cm3389 MACH_CM3389 CM3389 2274 omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275 @@ -2280,3 +2281,615 @@ htcrhodium MACH_HTCRHODIUM HTCRHODIUM htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293 matrix504 MACH_MATRIX504 MATRIX504 2294 mrfsa MACH_MRFSA MRFSA 2295 +sc_p270 MACH_SC_P270 SC_P270 2296 +atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297 +pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298 +dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299 +leonardo MACH_LEONARDO LEONARDO 2300 +zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301 +dp6xx MACH_DP6XX DP6XX 2302 +bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303 +mahimahi MACH_MAHIMAHI MAHIMAHI 2304 +clickc MACH_CLICKC CLICKC 2305 +zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306 +tazcard MACH_TAZCARD TAZCARD 2307 +tazdev MACH_TAZDEV TAZDEV 2308 +annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309 +annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310 +cerebric MACH_CEREBRIC CEREBRIC 2311 +orca MACH_ORCA ORCA 2312 +pc9260 MACH_PC9260 PC9260 2313 +ems285a MACH_EMS285A EMS285A 2314 +gec2410 MACH_GEC2410 GEC2410 2315 +gec2440 MACH_GEC2440 GEC2440 2316 +mw903 MACH_ARCH_MW903 ARCH_MW903 2317 +mw2440 MACH_MW2440 MW2440 2318 +ecac2378 MACH_ECAC2378 ECAC2378 2319 +tazkiosk MACH_TAZKIOSK TAZKIOSK 2320 +whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321 +sbox9263 MACH_SBOX9263 SBOX9263 2322 +oreo_camera MACH_OREO OREO 2323 +smdk6442 MACH_SMDK6442 SMDK6442 2324 +openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 +incredible MACH_INCREDIBLE INCREDIBLE 2326 +incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 +heroct MACH_HEROCT HEROCT 2328 +mmnet1000 MACH_MMNET1000 MMNET1000 2329 +devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330 +devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331 +mx31txtr MACH_MX31TXTR MX31TXTR 2332 +u380 MACH_U380 U380 2333 +oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334 +npcmx50 MACH_NPCMX50 NPCMX50 2335 +mx51_lange51 MACH_MX51_LANGE51 MX51_LANGE51 2336 +mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337 +riom MACH_RIOM RIOM 2338 +comcas MACH_COMCAS COMCAS 2339 +wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340 +cm_t35 MACH_CM_T35 CM_T35 2341 +net2big MACH_NET2BIG NET2BIG 2342 +motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343 +igep0020 MACH_IGEP0020 IGEP0020 2344 +igep0010 MACH_IGEP0010 IGEP0010 2345 +mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346 +scat100 MACH_SCAT100 SCAT100 2347 +sanmina MACH_SANMINA SANMINA 2348 +momento MACH_MOMENTO MOMENTO 2349 +nuc9xx MACH_NUC9XX NUC9XX 2350 +nuc910evb MACH_NUC910EVB NUC910EVB 2351 +nuc920evb MACH_NUC920EVB NUC920EVB 2352 +nuc950evb MACH_NUC950EVB NUC950EVB 2353 +nuc945evb MACH_NUC945EVB NUC945EVB 2354 +nuc960evb MACH_NUC960EVB NUC960EVB 2355 +nuc932evb MACH_NUC932EVB NUC932EVB 2356 +nuc900 MACH_NUC900 NUC900 2357 +sd1soc MACH_SD1SOC SD1SOC 2358 +ln2440bc MACH_LN2440BC LN2440BC 2359 +rsbc MACH_RSBC RSBC 2360 +openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 +hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 +wayland MACH_WAYLAND WAYLAND 2363 +acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 +hwat91 MACH_HWAT91 HWAT91 2365 +at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366 +csb732 MACH_CSB732 CSB732 2367 +u8500 MACH_U8500 U8500 2368 +huqiu MACH_HUQIU HUQIU 2369 +mx51_kunlun MACH_MX51_KUNLUN MX51_KUNLUN 2370 +pmt1g MACH_PMT1G PMT1G 2371 +htcelf MACH_HTCELF HTCELF 2372 +armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373 +armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374 +u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375 +csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376 +dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377 +hy9307 MACH_HY9307 HY9307 2378 +aspire_easystore MACH_A_ES A_ES 2379 +davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380 +agama9263 MACH_AGAMA9263 AGAMA9263 2381 +marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382 +flint MACH_FLINT FLINT 2383 +tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384 +sch_m490 MACH_SCH_M490 SCH_M490 2386 +rbl01 MACH_RBL01 RBL01 2387 +omnifi MACH_OMNIFI OMNIFI 2388 +otavalo MACH_OTAVALO OTAVALO 2389 +siena MACH_SIENNA SIENNA 2390 +htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391 +htc_opal MACH_HTC_OPAL HTC_OPAL 2392 +touchbook MACH_TOUCHBOOK TOUCHBOOK 2393 +latte MACH_LATTE LATTE 2394 +xa200 MACH_XA200 XA200 2395 +nimrod MACH_NIMROD NIMROD 2396 +cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397 +cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398 +tk71 MACH_TK71 TK71 2399 +comham3525 MACH_COMHAM3525 COMHAM3525 2400 +mx31erebus MACH_MX31EREBUS MX31EREBUS 2401 +mcardmx27 MACH_MCARDMX27 MCARDMX27 2402 +paradise MACH_PARADISE PARADISE 2403 +tide MACH_TIDE TIDE 2404 +wzl2440 MACH_WZL2440 WZL2440 2405 +sdrdemo MACH_SDRDEMO SDRDEMO 2406 +ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407 +ecmimg20 MACH_ECMIMG20 ECMIMG20 2408 +omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409 +halo MACH_HALO HALO 2410 +huangshan MACH_HUANGSHAN HUANGSHAN 2411 +vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412 +raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 +raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 +raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 +multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416 +multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417 +tnetv107x MACH_TNETV107X TNETV107X 2418 +snake MACH_SNAKE SNAKE 2419 +cwmx27 MACH_CWMX27 CWMX27 2420 +sch_m480 MACH_SCH_M480 SCH_M480 2421 +platypus MACH_PLATYPUS PLATYPUS 2422 +pss2 MACH_PSS2 PSS2 2423 +davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424 +str9100 MACH_STR9100 STR9100 2425 +net5big MACH_NET5BIG NET5BIG 2426 +seabed9263 MACH_SEABED9263 SEABED9263 2427 +mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428 +octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429 +klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430 +klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431 +klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432 +supersonic MACH_SUPERSONIC SUPERSONIC 2433 +liberty MACH_LIBERTY LIBERTY 2434 +mh355 MACH_MH355 MH355 2435 +pc7802 MACH_PC7802 PC7802 2436 +gnet_sgc MACH_GNET_SGC GNET_SGC 2437 +einstein15 MACH_EINSTEIN15 EINSTEIN15 2438 +cmpd MACH_CMPD CMPD 2439 +davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440 +lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441 +ea313x MACH_EA313X EA313X 2442 +fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443 +fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444 +pelco_moe MACH_PELCO_MOE PELCO_MOE 2445 +minimix27 MACH_MINIMIX27 MINIMIX27 2446 +omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447 +passionc MACH_PASSIONC PASSIONC 2448 +mx27amata MACH_MX27AMATA MX27AMATA 2449 +bgat1 MACH_BGAT1 BGAT1 2450 +buzz MACH_BUZZ BUZZ 2451 +mb9g20 MACH_MB9G20 MB9G20 2452 +yushan MACH_YUSHAN YUSHAN 2453 +lizard MACH_LIZARD LIZARD 2454 +omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455 +smdkv210 MACH_SMDKV210 SMDKV210 2456 +bravo MACH_BRAVO BRAVO 2457 +siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458 +siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459 +sm3k MACH_SM3K SM3K 2460 +acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461 +sst61vc010_dev MACH_SST61VC010_DEV SST61VC010_DEV 2462 +glittertind MACH_GLITTERTIND GLITTERTIND 2463 +omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464 +omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465 +cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466 +torino_s MACH_TORINO_S TORINO_S 2467 +havana MACH_HAVANA HAVANA 2468 +beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469 +vanguard MACH_VANGUARD VANGUARD 2470 +s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471 +cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472 +aster MACH_ASTER ASTER 2473 +voguesv210 MACH_VOGUESV210 VOGUESV210 2474 +acm500x MACH_ACM500X ACM500X 2475 +km9260 MACH_KM9260 KM9260 2476 +nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477 +ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478 +smartq7 MACH_SMARTQ7 SMARTQ7 2479 +at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480 +asusp527 MACH_ASUSP527 ASUSP527 2481 +at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482 +topasa900 MACH_TOPASA900 TOPASA900 2483 +electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484 +mx51grb MACH_MX51GRB MX51GRB 2485 +xea300 MACH_XEA300 XEA300 2486 +htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487 +lima MACH_LIMA LIMA 2488 +csb740 MACH_CSB740 CSB740 2489 +usb_s8815 MACH_USB_S8815 USB_S8815 2490 +watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491 +milkyway MACH_MILKYWAY MILKYWAY 2492 +g4evm MACH_G4EVM G4EVM 2493 +picomod6 MACH_PICOMOD6 PICOMOD6 2494 +omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495 +ip6000 MACH_IP6000 IP6000 2496 +ip6010 MACH_IP6010 IP6010 2497 +utm400 MACH_UTM400 UTM400 2498 +omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499 +wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500 +sx560 MACH_SX560 SX560 2501 +ts41x MACH_TS41X TS41X 2502 +elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503 +rhobot MACH_RHOBOT RHOBOT 2504 +mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505 +ls9260 MACH_LS9260 LS9260 2506 +shank MACH_SHANK SHANK 2507 +qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508 +at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509 +hiram MACH_HIRAM HIRAM 2510 +phy3250 MACH_PHY3250 PHY3250 2511 +ea3250 MACH_EA3250 EA3250 2512 +fdi3250 MACH_FDI3250 FDI3250 2513 +htcwhitestone MACH_WHITESTONE WHITESTONE 2514 +at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515 +ccmx51 MACH_CCMX51 CCMX51 2516 +ccmx51js MACH_CCMX51JS CCMX51JS 2517 +ccwmx51 MACH_CCWMX51 CCWMX51 2518 +ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519 +mini6410 MACH_MINI6410 MINI6410 2520 +tiny6410 MACH_TINY6410 TINY6410 2521 +nano6410 MACH_NANO6410 NANO6410 2522 +at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523 +htcleo MACH_HTCLEO HTCLEO 2524 +avp13 MACH_AVP13 AVP13 2525 +xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526 +vpnext MACH_VPNEXT VPNEXT 2527 +swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528 +tx51 MACH_TX51 TX51 2529 +dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530 +mx28evk MACH_MX28EVK MX28EVK 2531 +phoenix260 MACH_PHOENIX260 PHOENIX260 2532 +uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533 +smartq5 MACH_SMARTQ5 SMARTQ5 2534 +all3078 MACH_ALL3078 ALL3078 2535 +ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536 +siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537 +epb5000 MACH_EPB5000 EPB5000 2538 +hy9263 MACH_HY9263 HY9263 2539 +acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540 +acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541 +acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542 +acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543 +acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544 +bonnell MACH_BONNELL BONNELL 2545 +oht_mx27 MACH_OHT_MX27 OHT_MX27 2546 +htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547 +davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 +c3ax03 MACH_C3AX03 C3AX03 2549 +mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 +esyx MACH_ESYX ESYX 2551 +dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552 +bulldog MACH_BULLDOG BULLDOG 2553 +derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554 +bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555 +bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556 +bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557 +bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558 +bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559 +bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560 +bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561 +bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562 +bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563 +bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564 +bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565 +acer_s200 MACH_ACER_S200 ACER_S200 2566 +bt270 MACH_BT270 BT270 2567 +iseo MACH_ISEO ISEO 2568 +cezanne MACH_CEZANNE CEZANNE 2569 +lucca MACH_LUCCA LUCCA 2570 +supersmart MACH_SUPERSMART SUPERSMART 2571 +arm11_board MACH_CS_MISANO CS_MISANO 2572 +magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573 +emxx MACH_EMXX EMXX 2574 +outlaw MACH_OUTLAW OUTLAW 2575 +riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 +riot_vox MACH_RIOT_VOX RIOT_VOX 2577 +riot_x37 MACH_RIOT_X37 RIOT_X37 2578 +mega25mx MACH_MEGA25MX MEGA25MX 2579 +benzina2 MACH_BENZINA2 BENZINA2 2580 +ignite MACH_IGNITE IGNITE 2581 +foggia MACH_FOGGIA FOGGIA 2582 +arezzo MACH_AREZZO AREZZO 2583 +leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584 +jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585 +gts_nova MACH_GTS_NOVA GTS_NOVA 2586 +p3600 MACH_P3600 P3600 2587 +dlt2 MACH_DLT2 DLT2 2588 +df3120 MACH_DF3120 DF3120 2589 +ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590 +nautel_lpc3240 MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591 +glacier MACH_GLACIER GLACIER 2592 +phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593 +omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594 +pca101 MACH_PCA101 PCA101 2595 +buzzc MACH_BUZZC BUZZC 2596 +sasie2 MACH_SASIE2 SASIE2 2597 +davinci_dm6467_cio MACH_DAVINCI_CIO DAVINCI_CIO 2598 +smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599 +wzl6410 MACH_WZL6410 WZL6410 2600 +wzl6410m MACH_WZL6410M WZL6410M 2601 +wzl6410f MACH_WZL6410F WZL6410F 2602 +wzl6410i MACH_WZL6410I WZL6410I 2603 +spacecom1 MACH_SPACECOM1 SPACECOM1 2604 +pingu920 MACH_PINGU920 PINGU920 2605 +bravoc MACH_BRAVOC BRAVOC 2606 +cybo2440 MACH_CYBO2440 CYBO2440 2607 +vdssw MACH_VDSSW VDSSW 2608 +romulus MACH_ROMULUS ROMULUS 2609 +omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610 +eltd100 MACH_ELTD100 ELTD100 2611 +capc7117 MACH_CAPC7117 CAPC7117 2612 +swan MACH_SWAN SWAN 2613 +veu MACH_VEU VEU 2614 +rm2 MACH_RM2 RM2 2615 +tt2100 MACH_TT2100 TT2100 2616 +venice MACH_VENICE VENICE 2617 +pc7323 MACH_PC7323 PC7323 2618 +masp MACH_MASP MASP 2619 +fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620 +fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621 +lexikon MACH_LEXIKON LEXIKON 2622 +mini2440v2 MACH_MINI2440V2 MINI2440V2 2623 +icontrol MACH_ICONTROL ICONTROL 2624 +sheevad MACH_SHEEVAD SHEEVAD 2625 +qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626 +qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627 +bee MACH_BEE BEE 2628 +mx23evk MACH_MX23EVK MX23EVK 2629 +ap4evb MACH_AP4EVB AP4EVB 2630 +stockholm MACH_STOCKHOLM STOCKHOLM 2631 +lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632 +stingray MACH_STINGRAY STINGRAY 2633 +kraken MACH_KRAKEN KRAKEN 2634 +gw2388 MACH_GW2388 GW2388 2635 +jadecpu MACH_JADECPU JADECPU 2636 +carlisle MACH_CARLISLE CARLISLE 2637 +lux_sf9 MACH_LUX_SFT9 LUX_SFT9 2638 +nemid_tb MACH_NEMID_TB NEMID_TB 2639 +terrier MACH_TERRIER TERRIER 2640 +turbot MACH_TURBOT TURBOT 2641 +sanddab MACH_SANDDAB SANDDAB 2642 +mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643 +ghi2703d MACH_GHI2703D GHI2703D 2644 +lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645 +lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646 +lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647 +hw90240 MACH_HW90240 HW90240 2648 +dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649 +mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650 +scat110 MACH_SCAT110 SCAT110 2651 +acer_a1 MACH_ACER_A1 ACER_A1 2652 +cmcontrol MACH_CMCONTROL CMCONTROL 2653 +pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654 +rfp43 MACH_RFP43 RFP43 2655 +sk86r0301 MACH_SK86R0301 SK86R0301 2656 +ctpxa MACH_CTPXA CTPXA 2657 +epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658 +guruplug MACH_GURUPLUG GURUPLUG 2659 +spear310 MACH_SPEAR310 SPEAR310 2660 +spear320 MACH_SPEAR320 SPEAR320 2661 +robotx MACH_ROBOTX ROBOTX 2662 +lsxhl MACH_LSXHL LSXHL 2663 +smartlite MACH_SMARTLITE SMARTLITE 2664 +cws2 MACH_CWS2 CWS2 2665 +m619 MACH_M619 M619 2666 +smartview MACH_SMARTVIEW SMARTVIEW 2667 +lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668 +kizbox MACH_KIZBOX KIZBOX 2669 +htccharmer MACH_HTCCHARMER HTCCHARMER 2670 +guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671 +pm9g45 MACH_PM9G45 PM9G45 2672 +htcpanther MACH_HTCPANTHER HTCPANTHER 2673 +htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674 +reb01 MACH_REB01 REB01 2675 +aquila MACH_AQUILA AQUILA 2676 +spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677 +sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 +msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 +micro2440 MACH_MICRO2440 MICRO2440 2680 +am2440 MACH_AM2440 AM2440 2681 +tq2440 MACH_TQ2440 TQ2440 2682 +lpc2478oem MACH_LPC2478OEM LPC2478OEM 2683 +ak880x MACH_AK880X AK880X 2684 +cobra3530 MACH_COBRA3530 COBRA3530 2685 +pmppb MACH_PMPPB PMPPB 2686 +u6715 MACH_U6715 U6715 2687 +axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688 +g30_dvb MACH_G30_DVB G30_DVB 2689 +vc088x MACH_VC088X VC088X 2690 +mioa702 MACH_MIOA702 MIOA702 2691 +hpmin MACH_HPMIN HPMIN 2692 +ak880xak MACH_AK880XAK AK880XAK 2693 +arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694 +lkevm MACH_LKEVM LKEVM 2695 +mw6410 MACH_MW6410 MW6410 2696 +terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697 +cpu8000e MACH_CPU8000E CPU8000E 2698 +catania MACH_CATANIA CATANIA 2699 +tokyo MACH_TOKYO TOKYO 2700 +msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701 +msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702 +msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703 +msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704 +msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705 +msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706 +msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707 +qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708 +qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709 +qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710 +qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711 +qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712 +adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713 +mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714 +mobikt MACH_MOBIKT MOBIKT 2715 +mx53_evk MACH_MX53_EVK MX53_EVK 2716 +igep0030 MACH_IGEP0030 IGEP0030 2717 +axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718 +dtcommod MACH_DTCOMMOD DTCOMMOD 2719 +gould MACH_GOULD GOULD 2720 +siberia MACH_SIBERIA SIBERIA 2721 +sbc3530 MACH_SBC3530 SBC3530 2722 +qarm MACH_QARM QARM 2723 +mips MACH_MIPS MIPS 2724 +mx27grb MACH_MX27GRB MX27GRB 2725 +sbc8100 MACH_SBC8100 SBC8100 2726 +saarb MACH_SAARB SAARB 2727 +omap3mini MACH_OMAP3MINI OMAP3MINI 2728 +cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729 +catan MACH_CATAN CATAN 2730 +harmony MACH_HARMONY HARMONY 2731 +tonga MACH_TONGA TONGA 2732 +cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733 +htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734 +epc_g45 MACH_EPC_G45 EPC_G45 2735 +epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736 +mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737 +rtw1000 MACH_RTW1000 RTW1000 2738 +bobcat MACH_BOBCAT BOBCAT 2739 +trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740 +msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741 +nedap9263 MACH_NEDAP9263 NEDAP9263 2742 +netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743 +bmx MACH_BMX BMX 2744 +netstream MACH_NETSTREAM NETSTREAM 2745 +vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746 +vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747 +bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748 +sgarm10 MACH_SGARM10 SGARM10 2749 +cm_t3517 MACH_CM_T3517 CM_T3517 2750 +omap3_cps MACH_OMAP3_CPS OMAP3_CPS 2751 +axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752 +wbd222 MACH_WBD222 WBD222 2753 +mt65xx MACH_MT65XX MT65XX 2754 +msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755 +msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756 +vmc300 MACH_VMC300 VMC300 2757 +tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758 +nanos MACH_NANOS NANOS 2759 +stamp9g10 MACH_STAMP9G10 STAMP9G10 2760 +stamp9g45 MACH_STAMP9G45 STAMP9G45 2761 +h6053 MACH_H6053 H6053 2762 +smint01 MACH_SMINT01 SMINT01 2763 +prtlvt2 MACH_PRTLVT2 PRTLVT2 2764 +ap420 MACH_AP420 AP420 2765 +htcclio MACH_HTCSHIFT HTCSHIFT 2766 +davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767 +msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768 +msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769 +esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770 +sbc35 MACH_SBC35 SBC35 2771 +mpx6446 MACH_MPX6446 MPX6446 2772 +oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773 +kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774 +ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775 +cns3420vb MACH_CNS3420VB CNS3420VB 2776 +lpc_evo MACH_LPC2 LPC2 2777 +olympus MACH_OLYMPUS OLYMPUS 2778 +vortex MACH_VORTEX VORTEX 2779 +s5pc200 MACH_S5PC200 S5PC200 2780 +ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781 +smdkc200 MACH_SMDKC200 SMDKC200 2782 +emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783 +apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784 +songshan MACH_SONGSHAN SONGSHAN 2785 +tianshan MACH_TIANSHAN TIANSHAN 2786 +vpx500 MACH_VPX500 VPX500 2787 +am3517sam MACH_AM3517SAM AM3517SAM 2788 +skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789 +skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790 +omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791 +df7220 MACH_DF7220 DF7220 2792 +nemini MACH_NEMINI NEMINI 2793 +t8200 MACH_T8200 T8200 2794 +apf51 MACH_APF51 APF51 2795 +dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796 +bordeaux MACH_BORDEAUX BORDEAUX 2797 +catania_b MACH_CATANIA_B CATANIA_B 2798 +mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799 +ti8168evm MACH_TI8168EVM TI8168EVM 2800 +neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801 +withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802 +dbps MACH_DBPS DBPS 2803 +at91sam9261 MACH_SBC9261 SBC9261 2804 +pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805 +speedy MACH_SPEEDY SPEEDY 2806 +chrysaor MACH_CHRYSAOR CHRYSAOR 2807 +tango MACH_TANGO TANGO 2808 +synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809 +hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810 +hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811 +hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812 +iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813 +irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814 +irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815 +teton_bga MACH_TETON_BGA TETON_BGA 2816 +snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817 +tam3517 MACH_TAM3517 TAM3517 2818 +pdc100 MACH_PDC100 PDC100 2819 +eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25 EUKREA_CPUIMX25 2820 +eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35 EUKREA_CPUIMX35 2821 +eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 +eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 +p565 MACH_P565 P565 2824 +acer_a4 MACH_ACER_A4 ACER_A4 2825 +davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826 +eshare MACH_ESHARE ESHARE 2827 +hw_omapl138_europa MACH_HW_OMAPL138_EUROPA HW_OMAPL138_EUROPA 2828 +wlbargn MACH_WLBARGN WLBARGN 2829 +bm170 MACH_BM170 BM170 2830 +netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831 +netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832 +siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833 +elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834 +mcu1 MACH_MCU1 MCU1 2835 +omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836 +omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837 +smdkc210 MACH_SMDKC210 SMDKC210 2838 +omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839 +spyplug MACH_SPYPLUG SPYPLUG 2840 +ginger MACH_GINGER GINGER 2841 +tny_t3530 MACH_TNY_T3530 TNY_T3530 2842 +pca102 MACH_PCA102 PCA102 2843 +spade MACH_SPADE SPADE 2844 +mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845 +t5325 MACH_T5325 T5325 2846 +gw2361 MACH_GW2361 GW2361 2847 +elog MACH_ELOG ELOG 2848 +income MACH_INCOME INCOME 2849 +bcm589x MACH_BCM589X BCM589X 2850 +etna MACH_ETNA ETNA 2851 +hawks MACH_HAWKS HAWKS 2852 +meson MACH_MESON MESON 2853 +xsbase255 MACH_XSBASE255 XSBASE255 2854 +pvm2030 MACH_PVM2030 PVM2030 2855 +mioa502 MACH_MIOA502 MIOA502 2856 +vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857 +vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858 +vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859 +htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860 +mx257sx MACH_MX257SX MX257SX 2861 +goni MACH_GONI GONI 2862 +msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863 +msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864 +quickstep MACH_QUICKSTEP QUICKSTEP 2865 +dmw96 MACH_DMW96 DMW96 2866 +hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867 +trident MACH_TRIDENT TRIDENT 2868 +lightning MACH_LIGHTNING LIGHTNING 2869 +iconnect MACH_ICONNECT ICONNECT 2870 +autobot MACH_AUTOBOT AUTOBOT 2871 +coconut MACH_COCONUT COCONUT 2872 +durian MACH_DURIAN DURIAN 2873 +cayenne MACH_CAYENNE CAYENNE 2874 +fuji MACH_FUJI FUJI 2875 +synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876 +em1sy MACH_EM1SY EM1SY 2877 +m502 MACH_M502 M502 2878 +matrix518 MACH_MATRIX518 MATRIX518 2879 +tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880 +spear1310 MACH_SPEAR1310 SPEAR1310 2881 +bv07 MACH_BV07 BV07 2882 +mxt_td61 MACH_MXT_TD61 MXT_TD61 2883 +openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884 +devixp MACH_DEVIXP DEVIXP 2885 +miccpt MACH_MICCPT MICCPT 2886 +mic256 MACH_MIC256 MIC256 2887 +as1167 MACH_AS1167 AS1167 2888 +omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889 +u5500 MACH_U5500 U5500 2890 +davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891 +mecha MACH_MECHA MECHA 2892 +bubba3 MACH_BUBBA3 BUBBA3 2893 +pupitre MACH_PUPITRE PUPITRE 2894 +tegra_harmony MACH_TEGRA_HARMONY TEGRA_HARMONY 2895 +tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896 +tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897 +simplenet MACH_SIMPLENET SIMPLENET 2898 +ec4350tbm MACH_EC4350TBM EC4350TBM 2899 +pec_tc MACH_PEC_TC PEC_TC 2900 +pec_hc2 MACH_PEC_HC2 PEC_HC2 2901 +esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902 +esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903 +esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904 +esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905 +unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906 +blueshark MACH_BLUESHARK BLUESHARK 2907 +e10 MACH_E10 E10 2908 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct t extern void iwmmxt_task_release(struct thread_info *); extern void iwmmxt_task_switch(struct thread_info *); -extern void vfp_sync_state(struct thread_info *thread); +extern void vfp_sync_hwstate(struct thread_info *); +extern void vfp_flush_hwstate(struct thread_info *); #endif --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -663,7 +663,7 @@ static int ptrace_getvfpregs(struct task union vfp_state *vfp = &thread->vfpstate; struct user_vfp __user *ufp = data; - vfp_sync_state(thread); + vfp_sync_hwstate(thread); /* copy the floating point registers */ if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, @@ -686,7 +686,7 @@ static int ptrace_setvfpregs(struct task union vfp_state *vfp = &thread->vfpstate; struct user_vfp __user *ufp = data; - vfp_sync_state(thread); + vfp_sync_hwstate(thread); /* copy the floating point registers */ if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, @@ -697,6 +697,8 @@ static int ptrace_setvfpregs(struct task if (get_user(vfp->hard.fpscr, &ufp->fpscr)) return -EFAULT; + vfp_flush_hwstate(thread); + return 0; } #endif --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -42,6 +42,7 @@ ENTRY(vfp_null_entry) mov pc, lr ENDPROC(vfp_null_entry) + .align 2 .LCvfp: .word vfp_vector @@ -61,6 +62,7 @@ ENTRY(vfp_testing_entry) mov pc, r9 @ we have handled the fault ENDPROC(vfp_testing_entry) + .align 2 VFP_arch_address: .word VFP_arch --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -209,40 +209,55 @@ ENDPROC(vfp_save_state) last_VFP_context_address: .word last_VFP_context -ENTRY(vfp_get_float) - add pc, pc, r0, lsl #3 + .macro tbl_branch, base, tmp, shift +#ifdef CONFIG_THUMB2_KERNEL + adr \tmp, 1f + add \tmp, \tmp, \base, lsl \shift + mov pc, \tmp +#else + add pc, pc, \base, lsl \shift mov r0, r0 +#endif +1: + .endm + +ENTRY(vfp_get_float) + tbl_branch r0, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0 +1: mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0 mov pc, lr - mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1 + .org 1b + 8 +1: mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1 mov pc, lr + .org 1b + 8 .endr ENDPROC(vfp_get_float) ENTRY(vfp_put_float) - add pc, pc, r1, lsl #3 - mov r0, r0 + tbl_branch r1, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0 +1: mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0 mov pc, lr - mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1 + .org 1b + 8 +1: mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1 mov pc, lr + .org 1b + 8 .endr ENDPROC(vfp_put_float) ENTRY(vfp_get_double) - add pc, pc, r0, lsl #3 - mov r0, r0 + tbl_branch r0, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - fmrrd r0, r1, d\dr +1: fmrrd r0, r1, d\dr mov pc, lr + .org 1b + 8 .endr #ifdef CONFIG_VFPv3 @ d16 - d31 registers .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr +1: mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr mov pc, lr + .org 1b + 8 .endr #endif @@ -253,17 +268,18 @@ ENTRY(vfp_get_double) ENDPROC(vfp_get_double) ENTRY(vfp_put_double) - add pc, pc, r2, lsl #3 - mov r0, r0 + tbl_branch r2, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - fmdrr d\dr, r0, r1 +1: fmdrr d\dr, r0, r1 mov pc, lr + .org 1b + 8 .endr #ifdef CONFIG_VFPv3 @ d16 - d31 registers .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr +1: mcrr p11, 3, r0, r1, c\dr @ fmdrr r0, r1, d\dr mov pc, lr + .org 1b + 8 .endr #endif ENDPROC(vfp_put_double) --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -38,16 +38,75 @@ union vfp_state *last_VFP_context[NR_CPU */ unsigned int VFP_arch; +/* + * Per-thread VFP initialization. + */ +static void vfp_thread_flush(struct thread_info *thread) +{ + union vfp_state *vfp = &thread->vfpstate; + unsigned int cpu; + + memset(vfp, 0, sizeof(union vfp_state)); + + vfp->hard.fpexc = FPEXC_EN; + vfp->hard.fpscr = FPSCR_ROUND_NEAREST; + + /* + * Disable VFP to ensure we initialize it first. We must ensure + * that the modification of last_VFP_context[] and hardware disable + * are done for the same CPU and without preemption. + */ + cpu = get_cpu(); + if (last_VFP_context[cpu] == vfp) + last_VFP_context[cpu] = NULL; + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + put_cpu(); +} + +static void vfp_thread_exit(struct thread_info *thread) +{ + /* release case: Per-thread VFP cleanup. */ + union vfp_state *vfp = &thread->vfpstate; + unsigned int cpu = get_cpu(); + + if (last_VFP_context[cpu] == vfp) + last_VFP_context[cpu] = NULL; + put_cpu(); +} + +/* + * When this function is called with the following 'cmd's, the following + * is true while this function is being run: + * THREAD_NOFTIFY_SWTICH: + * - the previously running thread will not be scheduled onto another CPU. + * - the next thread to be run (v) will not be running on another CPU. + * - thread->cpu is the local CPU number + * - not preemptible as we're called in the middle of a thread switch + * THREAD_NOTIFY_FLUSH: + * - the thread (v) will be running on the local CPU, so + * v === current_thread_info() + * - thread->cpu is the local CPU number at the time it is accessed, + * but may change at any time. + * - we could be preempted if tree preempt rcu is enabled, so + * it is unsafe to use thread->cpu. + * THREAD_NOTIFY_EXIT + * - the thread (v) will be running on the local CPU, so + * v === current_thread_info() + * - thread->cpu is the local CPU number at the time it is accessed, + * but may change at any time. + * - we could be preempted if tree preempt rcu is enabled, so + * it is unsafe to use thread->cpu. + */ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { struct thread_info *thread = v; - union vfp_state *vfp; - __u32 cpu = thread->cpu; if (likely(cmd == THREAD_NOTIFY_SWITCH)) { u32 fpexc = fmrx(FPEXC); #ifdef CONFIG_SMP + unsigned int cpu = thread->cpu; + /* * On SMP, if VFP is enabled, save the old state in * case the thread migrates to a different CPU. The @@ -74,25 +133,10 @@ static int vfp_notifier(struct notifier_ return NOTIFY_DONE; } - vfp = &thread->vfpstate; - if (cmd == THREAD_NOTIFY_FLUSH) { - /* - * Per-thread VFP initialisation. - */ - memset(vfp, 0, sizeof(union vfp_state)); - - vfp->hard.fpexc = FPEXC_EN; - vfp->hard.fpscr = FPSCR_ROUND_NEAREST; - - /* - * Disable VFP to ensure we initialise it first. - */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); - } - - /* flush and release case: Per-thread VFP cleanup. */ - if (last_VFP_context[cpu] == vfp) - last_VFP_context[cpu] = NULL; + if (cmd == THREAD_NOTIFY_FLUSH) + vfp_thread_flush(thread); + else + vfp_thread_exit(thread); return NOTIFY_DONE; } @@ -153,10 +197,13 @@ static void vfp_raise_exceptions(u32 exc } /* - * Update the FPSCR with the additional exception flags. + * If any of the status flags are set, update the FPSCR. * Comparison instructions always return at least one of * these flags set. */ + if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) + fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); + fpscr |= exceptions; fmxr(FPSCR, fpscr); @@ -381,54 +428,60 @@ static void vfp_pm_init(void) static inline void vfp_pm_init(void) { } #endif /* CONFIG_PM */ -/* - * Synchronise the hardware VFP state of a thread other than current with the - * saved one. This function is used by the ptrace mechanism. - */ -#ifdef CONFIG_SMP -void vfp_sync_state(struct thread_info *thread) +void vfp_sync_hwstate(struct thread_info *thread) { + unsigned int cpu = get_cpu(); + /* - * On SMP systems, the VFP state is automatically saved at every - * context switch. We mark the thread VFP state as belonging to a - * non-existent CPU so that the saved one will be reloaded when - * needed. + * If the thread we're interested in is the current owner of the + * hardware VFP state, then we need to save its state. */ - thread->vfpstate.hard.cpu = NR_CPUS; + if (last_VFP_context[cpu] == &thread->vfpstate) { + u32 fpexc = fmrx(FPEXC); + + /* + * Save the last VFP state on this CPU. + */ + fmxr(FPEXC, fpexc | FPEXC_EN); + vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); + fmxr(FPEXC, fpexc); + } + + put_cpu(); } -#else -void vfp_sync_state(struct thread_info *thread) + +void vfp_flush_hwstate(struct thread_info *thread) { unsigned int cpu = get_cpu(); - u32 fpexc = fmrx(FPEXC); /* - * If VFP is enabled, the previous state was already saved and - * last_VFP_context updated. + * If the thread we're interested in is the current owner of the + * hardware VFP state, then we need to save its state. */ - if (fpexc & FPEXC_EN) - goto out; + if (last_VFP_context[cpu] == &thread->vfpstate) { + u32 fpexc = fmrx(FPEXC); - if (!last_VFP_context[cpu]) - goto out; + fmxr(FPEXC, fpexc & ~FPEXC_EN); - /* - * Save the last VFP state on this CPU. - */ - fmxr(FPEXC, fpexc | FPEXC_EN); - vfp_save_state(last_VFP_context[cpu], fpexc); - fmxr(FPEXC, fpexc); + /* + * Set the context to NULL to force a reload the next time + * the thread uses the VFP. + */ + last_VFP_context[cpu] = NULL; + } +#ifdef CONFIG_SMP /* - * Set the context to NULL to force a reload the next time the thread - * uses the VFP. + * For SMP we still have to take care of the case where the thread + * migrates to another CPU and then back to the original CPU on which + * the last VFP user is still the same thread. Mark the thread VFP + * state as belonging to a non-existent CPU so that the saved one will + * be reloaded in the above case. */ - last_VFP_context[cpu] = NULL; - -out: + thread->vfpstate.hard.cpu = NR_CPUS; +#endif put_cpu(); } -#endif #include @@ -481,7 +534,7 @@ static int __init vfp_init(void) */ elf_hwcap |= HWCAP_VFP; #ifdef CONFIG_VFPv3 - if (VFP_arch >= 3) { + if (VFP_arch >= 2) { elf_hwcap |= HWCAP_VFPv3; /* --- /dev/null +++ b/arch/arm/mach-cns3xxx/pcie.c @@ -0,0 +1,360 @@ +/******************************************************************************* + * + * Copyright (c) 2008 Cavium Networks + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_SPINLOCK(pci_config_lock); + +static int pcie_linked[2] = {0, 0}; // if 1, mean link ok. + +u32 cns3xxx_pcie0_irqs[2] = { IRQ_CNS3XXX_PCIE0_RC, IRQ_CNS3XXX_PCIE0_DEVICE, }; +u32 cns3xxx_pcie1_irqs[2] = { IRQ_CNS3XXX_PCIE1_RC, IRQ_CNS3XXX_PCIE1_DEVICE, }; + +static u32 access_base[2][3] = { + { CNS3XXX_PCIE0_HOST_BASE_VIRT, CNS3XXX_PCIE0_CFG0_BASE_VIRT, CNS3XXX_PCIE0_CFG1_BASE_VIRT}, + { CNS3XXX_PCIE1_HOST_BASE_VIRT, CNS3XXX_PCIE1_CFG0_BASE_VIRT, CNS3XXX_PCIE1_CFG1_BASE_VIRT}, +}; + +static int cns3xxx_pci_cfg_base(struct pci_bus *bus, + unsigned int devfn, int where) +{ + int domain = pci_domain_nr(bus); + int slot = PCI_SLOT(devfn); + u32 base; + + if ((!pcie_linked[domain]) && (bus->number || slot)) + return 0; + + if (!(bus->number)) { + if (slot > 1) + return 0; + // CFG0 Type + base = access_base[domain][slot]; + } else { + // CFG1 Type + base = access_base[domain][2]; + } + base += (((bus->number & 0xf) << 20)| (devfn << 12) | (where & 0xfc)); + return base; +} + +static int cns3xxx_pci_read_config(struct pci_bus *bus, + unsigned int devfn, int where, int size, + u32 * val) +{ + u32 v = 0xffffffff; + u32 base; + u32 mask = (0x1ull << (size * 8)) - 1; + int shift = (where % 4) * 8; + + base = cns3xxx_pci_cfg_base(bus, devfn, where); + if (!base) { + *val = 0xFFFFFFFF; + return PCIBIOS_SUCCESSFUL; + } + + v = __raw_readl(base); + if (bus->number == 0 && devfn == 0 && + (where & 0xffc) == PCI_CLASS_REVISION) { + /* RC's class is 0xb, but Linux PCI driver needs 0x604 for a PCIe bridge. */ + /* So we must dedicate the class code to 0x604 here */ + v &= 0xff; + v |= (0x604 << 16); + } + + *val = (v >> shift) & mask; + return PCIBIOS_SUCCESSFUL; +} + +static int cns3xxx_pci_write_config(struct pci_bus *bus, + unsigned int devfn, int where, int size, + u32 val) +{ + u32 v; + u32 base; + u32 mask = (0x1ull << (size * 8)) - 1; + int shift = (where % 4) * 8; + + base = cns3xxx_pci_cfg_base(bus, devfn, where); + if (!base) + return PCIBIOS_SUCCESSFUL; + + v = __raw_readl(base); + v &= ~(mask << shift); + v |= (val & mask) << shift; + __raw_writel(v, base); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops cns3xxx_pcie_ops = { + .read = cns3xxx_pci_read_config, + .write = cns3xxx_pci_write_config, +}; + +static struct resource cns3xxx_pcie0_io = { + .name = "PCIe0 I/O space", + .start = PCIE0_IO_SPACE_START, + .end = PCIE0_IO_SPACE_END, + .flags = IORESOURCE_IO, +}; + +static struct resource cns3xxx_pcie1_io = { + .name = "PCIe1 I/O space", + .start = PCIE1_IO_SPACE_START, + .end = PCIE1_IO_SPACE_END, + .flags = IORESOURCE_IO, +}; + +static struct resource cns3xxx_pcie0_mem = { + .name = "PCIe0 non-prefetchable", + .start = PCIE0_MEM_SPACE_START, + .end = PCIE0_MEM_SPACE_END, + .flags = IORESOURCE_MEM, +}; + +static struct resource cns3xxx_pcie1_mem = { + .name = "PCIe1 non-prefetchable", + .start = PCIE1_MEM_SPACE_START, + .end = PCIE1_MEM_SPACE_END, + .flags = IORESOURCE_MEM, +}; + +static int __init cns3xxx_pci_setup_resources(int nr, struct resource **resource) +{ + if(nr==0){ + BUG_ON(request_resource(&iomem_resource, &cns3xxx_pcie0_io) || + request_resource(&iomem_resource, &cns3xxx_pcie0_mem)); + resource[0] = &cns3xxx_pcie0_io; + resource[1] = &cns3xxx_pcie0_mem; + }else{ + BUG_ON(request_resource(&iomem_resource, &cns3xxx_pcie1_io) || + request_resource(&iomem_resource, &cns3xxx_pcie1_mem)); + resource[0] = &cns3xxx_pcie1_io; + resource[1] = &cns3xxx_pcie1_mem; + } + return 0; +} + +int __init cns3xxx_pci_setup(int nr, struct pci_sys_data *sys) +{ + BUG_ON(cns3xxx_pci_setup_resources(sys->domain,sys->resource)); + return 1; +} + +struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys) +{ + struct pci_bus *ret; + ret = pci_scan_bus(sys->busnr, &cns3xxx_pcie_ops, sys); + pci_assign_unassigned_resources(); + return ret; +} + +/* + * CNS3XXX PCIe device don't support hotplugin, and we will check the link at start up. + * + */ +static void cns3xxx_pcie_check_link(int port) +{ + + u32 reg; + u32 time; + + time = jiffies; /* set the start time for the receive */ + while (1) { + reg = __raw_readl( port == 0 ? CNS3XXX_PCIE0_PM_DEBUG : CNS3XXX_PCIE1_PM_DEBUG); /* check link up */ + reg = __raw_readl( port == 0 ? CNS3XXX_PCIE0_PM_DEBUG : CNS3XXX_PCIE1_PM_DEBUG); + if (reg & 0x1) { + pcie_linked[port]++; + break; + } else if (time_after(jiffies, (unsigned long)(time + 50))) { + break; + } + } + +} + +static void cns3xxx_pcie_hw_init(int port){ + struct pci_bus bus; + struct pci_sys_data sd; + u32 devfn = 0; + u8 pri_bus, sec_bus, sub_bus; + u8 cp, u8tmp; + u16 u16tmp,pos,dc; + u32 mem_base, host_base, io_base, cfg0_base; + + bus.number = 0; + bus.ops = &cns3xxx_pcie_ops; + sd.domain = port; + bus.sysdata = &sd; + + mem_base = ( port == 0 ? CNS3XXX_PCIE0_MEM_BASE : CNS3XXX_PCIE1_MEM_BASE ); + mem_base = mem_base >> 16; + + io_base = ( port == 0 ? CNS3XXX_PCIE0_IO_BASE : CNS3XXX_PCIE1_IO_BASE ); + io_base = io_base >> 16; + + host_base = ( port == 0 ? CNS3XXX_PCIE0_HOST_BASE_VIRT : CNS3XXX_PCIE1_HOST_BASE_VIRT ); + host_base = ( host_base -1 ) >> 16; + + cfg0_base = ( port == 0 ? CNS3XXX_PCIE0_CFG0_BASE_VIRT : CNS3XXX_PCIE1_CFG0_BASE_VIRT ); + cfg0_base = ( cfg0_base -1 ) >> 16; + + pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0); + pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1); + pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1); + + pci_bus_read_config_byte(&bus, devfn, PCI_PRIMARY_BUS, &pri_bus); + pci_bus_read_config_byte(&bus, devfn, PCI_SECONDARY_BUS, &sec_bus); + pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &sub_bus); + + pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base); + pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, host_base); + pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base); + pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, cfg0_base); + + pci_bus_read_config_byte(&bus, devfn, PCI_CAPABILITY_LIST, &cp); + while (cp != 0) { + pci_bus_read_config_byte(&bus, devfn, cp, &u8tmp); + // Read Next ID + pci_bus_read_config_word(&bus, devfn, cp, &u16tmp); + cp = (u16tmp & 0xFF00) >> 8; + } + + /* Modify device's Max_Read_Request size */ + devfn = PCI_DEVFN(1,0); + if (!pcie_linked[port]) + return; + + pci_bus_read_config_byte(&bus, devfn, PCI_CAPABILITY_LIST, &cp); + while (cp != 0) { + pci_bus_read_config_byte(&bus, devfn, cp, &u8tmp); + // Read Next ID + pci_bus_read_config_word(&bus, devfn, cp, &u16tmp); + cp = (u16tmp & 0xFF00) >> 8; + } + + /* Set Device Max_Read_Request_Size to 128 byte */ + pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP); + pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc); + dc &= ~(0x3 << 12); /* Clear Device Control Register [14:12] */ + pci_bus_write_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, dc); + pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc); + + if (!port) { + /* Disable PCIe0 Interrupt Mask INTA to INTD */ + __raw_writel(~0x3FFF, CNS3XXX_MISC_BASE_VIRT + 0x978); + } else { + /* Disable PCIe1 Interrupt Mask INTA to INTD */ + __raw_writel(~0x3FFF, CNS3XXX_MISC_BASE_VIRT + 0xA78); + } +} + + +void __init cns3xxx_pcie0_preinit(void) +{ + cns3xxx_pcie_check_link(0); + cns3xxx_pcie_hw_init(0); +} + +void __init cns3xxx_pcie1_preinit(void) +{ + cns3xxx_pcie_check_link(1); + cns3xxx_pcie_hw_init(1); +} + +/* + * map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this. + */ + +static int __init cns3xxx_pcie0_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return cns3xxx_pcie0_irqs[slot]; +} + +static int __init cns3xxx_pcie1_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return cns3xxx_pcie1_irqs[slot]; +} + +static struct hw_pci cns3xxx_pcie[2] __initdata = { + { + .swizzle = pci_std_swizzle, + .map_irq = cns3xxx_pcie0_map_irq, + .nr_controllers = 1, + .nr_domains = 0, + .setup = cns3xxx_pci_setup, + .scan = cns3xxx_pci_scan_bus, + .preinit = cns3xxx_pcie0_preinit, + }, + { + .swizzle = pci_std_swizzle, + .map_irq = cns3xxx_pcie1_map_irq, + .nr_controllers = 1, + .nr_domains = 1, + .setup = cns3xxx_pci_setup, + .scan = cns3xxx_pci_scan_bus, + .preinit = cns3xxx_pcie1_preinit, + } +}; + +static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) +{ + if (fsr & (1 << 10)) + regs->ARM_pc += 4; + return 0; +} + +//extern void pci_common_init(struct hw_pci *); +int cns3xxx_pcie_init(u8 ports) +{ + hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, "imprecise external abort"); + + if (ports & 0x1) + pci_common_init(&cns3xxx_pcie[0]); + if (ports & 0x2) + pci_common_init(&cns3xxx_pcie[1]); + + return 0; +} + +//device_initcall(cns3xxx_pcie_init);